Impelement edge event detection

This commit is contained in:
Drahoslav 2018-06-04 14:46:15 +02:00
parent f6236e5866
commit 2ec057fd07

71
rpio.go
View File

@ -76,6 +76,7 @@ type Mode uint8
type Pin uint8 type Pin uint8
type State uint8 type State uint8
type Pull uint8 type Pull uint8
type Edge uint8
// Memory offsets for gpio, see the spec for more details // Memory offsets for gpio, see the spec for more details
const ( const (
@ -121,6 +122,14 @@ const (
PullUp PullUp
) )
// Edge events
const (
NoEdge Edge = iota
RiseEdge
FallEdge
AnyEdge = RiseEdge | FallEdge
)
// Arrays for 8 / 32 bit access to memory and a semaphore for write locking // Arrays for 8 / 32 bit access to memory and a semaphore for write locking
var ( var (
memlock sync.Mutex memlock sync.Mutex
@ -212,6 +221,16 @@ func (pin Pin) PullOff() {
PullMode(pin, PullOff) PullMode(pin, PullOff)
} }
// Enable edge event detection on pin
func (pin Pin) Detect(edge Edge) {
DetectEdge(pin, edge)
}
// Check edge event on pin
func (pin Pin) EdgeDetected() bool {
return EdgeDetected(pin)
}
// PinMode sets the mode (direction) of a given pin (Input, Output, Clock or Pwm) // PinMode sets the mode (direction) of a given pin (Input, Output, Clock or Pwm)
// //
// Clock is possible only for pins 4, 5, 6, 20, 21. // Clock is possible only for pins 4, 5, 6, 20, 21.
@ -262,7 +281,6 @@ func PinMode(pin Pin, mode Mode) {
// WritePin sets a given pin High or Low // WritePin sets a given pin High or Low
// by setting the clear or set registers respectively // by setting the clear or set registers respectively
func WritePin(pin Pin, state State) { func WritePin(pin Pin, state State) {
p := uint8(pin) p := uint8(pin)
// Clear register, 10 / 11 depending on bank // Clear register, 10 / 11 depending on bank
@ -278,7 +296,6 @@ func WritePin(pin Pin, state State) {
} else { } else {
gpioMem[setReg] = 1 << (p & 31) gpioMem[setReg] = 1 << (p & 31)
} }
} }
// Read the state of a pin // Read the state of a pin
@ -304,6 +321,50 @@ func TogglePin(pin Pin) {
} }
} }
// Enable edge event detection on pin
//
// Call with RiseEdge followed by call with FallEdge has the same effect as call with AnyEdge,
// to disable previously enabled event call it with NoEdge.
//
// Combine with pin.EdgeDetected() to check whether event occured.
//
// It also clears previously detected events of this pin if any.
func DetectEdge(pin Pin, edge Edge) {
p := uint8(pin)
// Rising edge detect enable register (19/20 depending on bank)
// Falling edge detect enable register (22/23 depending on bank)
renReg := p/32 + 19
fenReg := p/32 + 23
if edge == NoEdge { // clear bits
gpioMem[renReg] = gpioMem[renReg] &^ (1 << (p&31))
gpioMem[fenReg] = gpioMem[fenReg] &^ (1 << (p&31))
}
if edge & RiseEdge > 0 { // set bit
gpioMem[renReg] = gpioMem[renReg] | (1 << (p&31))
}
if edge & FallEdge > 0 { // set bit
gpioMem[fenReg] = gpioMem[fenReg] | (1 << (p&31))
}
EdgeDetected(pin) // to clear outdated detection
}
// Check whether edge event occured
//
// Event detection has to be enabled first, by pin.Detect(edge)
func EdgeDetected(pin Pin) bool {
p := uint8(pin)
// Event detect status register (16/17)
edsReg := p/32 + 16
test := gpioMem[edsReg] & (1 << (p&31))
gpioMem[edsReg] = test // set bit to clear it
return test > 0
}
func PullMode(pin Pin, pull Pull) { func PullMode(pin Pin, pull Pull) {
// Pull up/down/off register has offset 38 / 39, pull is 37 // Pull up/down/off register has offset 38 / 39, pull is 37
pullClkReg := pin/32 + 38 pullClkReg := pin/32 + 38
@ -315,7 +376,7 @@ func PullMode(pin Pin, pull Pull) {
switch pull { switch pull {
case PullDown, PullUp: case PullDown, PullUp:
gpioMem[pullReg] = gpioMem[pullReg]&^3 | uint32(pull) gpioMem[pullReg] = gpioMem[pullReg] &^ 3 | uint32(pull)
case PullOff: case PullOff:
gpioMem[pullReg] = gpioMem[pullReg] &^ 3 gpioMem[pullReg] = gpioMem[pullReg] &^ 3
} }
@ -343,7 +404,7 @@ func PullMode(pin Pin, pull Pull) {
// changing frequency for one pin will change it also for all pins within a group. // changing frequency for one pin will change it also for all pins within a group.
// The groups are: // The groups are:
// gp_clk0: pins 4, 20, 32, 34 // gp_clk0: pins 4, 20, 32, 34
// gp_clk1: pins 5, 21, 42, 43 // gp_clk1: pins 5, 21, 42, 44
// gp_clk2: pins 6 and 43 // gp_clk2: pins 6 and 43
// pwm_clk: pins 12, 13, 18, 19, 40, 41, 45 // pwm_clk: pins 12, 13, 18, 19, 40, 41, 45
func SetFreq(pin Pin, freq int) { func SetFreq(pin Pin, freq int) {
@ -452,7 +513,7 @@ func SetDutyCycle(pin Pin, dutyLen, cycleLen uint32) {
const msen = 1 << 7 // use M/S transition instead of pwm algorithm const msen = 1 << 7 // use M/S transition instead of pwm algorithm
// reset settings // reset settings
pwmMem[pwmCtlReg] = pwmMem[pwmCtlReg]&^(ctlMask<<shift) | msen<<shift | pwen <<shift pwmMem[pwmCtlReg] = pwmMem[pwmCtlReg]&^(ctlMask<<shift) | msen<<shift | pwen<<shift
// set duty cycle // set duty cycle
pwmMem[pwmDatReg] = dutyLen pwmMem[pwmDatReg] = dutyLen
pwmMem[pwmRngReg] = cycleLen pwmMem[pwmRngReg] = cycleLen