diff --git a/rpio.go b/rpio.go index 62109ce..59b9ae4 100644 --- a/rpio.go +++ b/rpio.go @@ -76,6 +76,7 @@ type Mode uint8 type Pin uint8 type State uint8 type Pull uint8 +type Edge uint8 // Memory offsets for gpio, see the spec for more details const ( @@ -121,6 +122,14 @@ const ( 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 var ( memlock sync.Mutex @@ -212,6 +221,16 @@ func (pin 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) // // 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 // by setting the clear or set registers respectively func WritePin(pin Pin, state State) { - p := uint8(pin) // Clear register, 10 / 11 depending on bank @@ -278,7 +296,6 @@ func WritePin(pin Pin, state State) { } else { gpioMem[setReg] = 1 << (p & 31) } - } // 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) { // Pull up/down/off register has offset 38 / 39, pull is 37 pullClkReg := pin/32 + 38 @@ -315,7 +376,7 @@ func PullMode(pin Pin, pull Pull) { switch pull { case PullDown, PullUp: - gpioMem[pullReg] = gpioMem[pullReg]&^3 | uint32(pull) + gpioMem[pullReg] = gpioMem[pullReg] &^ 3 | uint32(pull) case PullOff: 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. // The groups are: // 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 // pwm_clk: pins 12, 13, 18, 19, 40, 41, 45 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 // reset settings - pwmMem[pwmCtlReg] = pwmMem[pwmCtlReg]&^(ctlMask<