diff options
author | Yurii Soldak <[email protected]> | 2023-07-24 02:13:38 +0200 |
---|---|---|
committer | Ron Evans <[email protected]> | 2023-07-27 18:15:22 +0200 |
commit | 00d46bd25dbc92970d70d88fefde303688ffe72f (patch) | |
tree | c7bb3938d5c1a913a7f653e773ffc302988bc007 | |
parent | 01d2ef327d0b3a629ed3808f113f18bd16d81034 (diff) | |
download | tinygo-00d46bd25dbc92970d70d88fefde303688ffe72f.tar.gz tinygo-00d46bd25dbc92970d70d88fefde303688ffe72f.zip |
avr: pin change interrupt
-rw-r--r-- | src/examples/pininterrupt/arduino.go | 11 | ||||
-rw-r--r-- | src/examples/pininterrupt/circuitplay-express.go | 1 | ||||
-rw-r--r-- | src/examples/pininterrupt/pca10040.go | 1 | ||||
-rw-r--r-- | src/examples/pininterrupt/pininterrupt.go | 3 | ||||
-rw-r--r-- | src/examples/pininterrupt/stm32.go | 1 | ||||
-rw-r--r-- | src/examples/pininterrupt/wioterminal.go | 1 | ||||
-rw-r--r-- | src/machine/machine_atmega328p.go | 104 |
7 files changed, 120 insertions, 2 deletions
diff --git a/src/examples/pininterrupt/arduino.go b/src/examples/pininterrupt/arduino.go new file mode 100644 index 000000000..aefdacf96 --- /dev/null +++ b/src/examples/pininterrupt/arduino.go @@ -0,0 +1,11 @@ +//go:build arduino + +package main + +import "machine" + +const ( + button = machine.D2 + buttonMode = machine.PinInputPullup + buttonPinChange = machine.PinRising +) diff --git a/src/examples/pininterrupt/circuitplay-express.go b/src/examples/pininterrupt/circuitplay-express.go index e03655064..54339c916 100644 --- a/src/examples/pininterrupt/circuitplay-express.go +++ b/src/examples/pininterrupt/circuitplay-express.go @@ -5,6 +5,7 @@ package main import "machine" const ( + button = machine.BUTTON buttonMode = machine.PinInputPulldown buttonPinChange = machine.PinFalling ) diff --git a/src/examples/pininterrupt/pca10040.go b/src/examples/pininterrupt/pca10040.go index e4a9d6feb..35bb7a866 100644 --- a/src/examples/pininterrupt/pca10040.go +++ b/src/examples/pininterrupt/pca10040.go @@ -5,6 +5,7 @@ package main import "machine" const ( + button = machine.BUTTON buttonMode = machine.PinInputPullup buttonPinChange = machine.PinRising ) diff --git a/src/examples/pininterrupt/pininterrupt.go b/src/examples/pininterrupt/pininterrupt.go index f693f1172..e13ba5eb3 100644 --- a/src/examples/pininterrupt/pininterrupt.go +++ b/src/examples/pininterrupt/pininterrupt.go @@ -12,8 +12,7 @@ import ( ) const ( - button = machine.BUTTON - led = machine.LED + led = machine.LED ) func main() { diff --git a/src/examples/pininterrupt/stm32.go b/src/examples/pininterrupt/stm32.go index 24d7e5f7b..02f2fb94e 100644 --- a/src/examples/pininterrupt/stm32.go +++ b/src/examples/pininterrupt/stm32.go @@ -5,6 +5,7 @@ package main import "machine" const ( + button = machine.BUTTON buttonMode = machine.PinInputPulldown buttonPinChange = machine.PinRising | machine.PinFalling ) diff --git a/src/examples/pininterrupt/wioterminal.go b/src/examples/pininterrupt/wioterminal.go index 90443537a..da5291db1 100644 --- a/src/examples/pininterrupt/wioterminal.go +++ b/src/examples/pininterrupt/wioterminal.go @@ -5,6 +5,7 @@ package main import "machine" const ( + button = machine.BUTTON buttonMode = machine.PinInput buttonPinChange = machine.PinFalling ) diff --git a/src/machine/machine_atmega328p.go b/src/machine/machine_atmega328p.go index ed832e6d3..0987a145c 100644 --- a/src/machine/machine_atmega328p.go +++ b/src/machine/machine_atmega328p.go @@ -466,3 +466,107 @@ var SPI0 = SPI{ sdo: PB3, sdi: PB4, cs: PB2} + +// Pin Change Interrupts +type PinChange uint8 + +const ( + PinRising PinChange = 1 << iota + PinFalling + PinToggle = PinRising | PinFalling +) + +func (pin Pin) SetInterrupt(pinChange PinChange, callback func(Pin)) (err error) { + + switch { + case pin >= PB0 && pin <= PB7: + // PCMSK0 - PCINT0-7 + pinStates[0] = avr.PINB.Get() + pinIndex := pin - PB0 + if pinChange&PinRising > 0 { + pinCallbacks[0][pinIndex][0] = callback + } + if pinChange&PinFalling > 0 { + pinCallbacks[0][pinIndex][1] = callback + } + if callback != nil { + avr.PCMSK0.SetBits(1 << pinIndex) + } else { + avr.PCMSK0.ClearBits(1 << pinIndex) + } + avr.PCICR.SetBits(avr.PCICR_PCIE0) + interrupt.New(avr.IRQ_PCINT0, handlePCINT0Interrupts) + case pin >= PC0 && pin <= PC7: + // PCMSK1 - PCINT8-14 + pinStates[1] = avr.PINC.Get() + pinIndex := pin - PC0 + if pinChange&PinRising > 0 { + pinCallbacks[1][pinIndex][0] = callback + } + if pinChange&PinFalling > 0 { + pinCallbacks[1][pinIndex][1] = callback + } + if callback != nil { + avr.PCMSK1.SetBits(1 << pinIndex) + } else { + avr.PCMSK1.ClearBits(1 << pinIndex) + } + avr.PCICR.SetBits(avr.PCICR_PCIE1) + interrupt.New(avr.IRQ_PCINT1, handlePCINT1Interrupts) + case pin >= PD0 && pin <= PD7: + // PCMSK2 - PCINT16-23 + pinStates[2] = avr.PIND.Get() + pinIndex := pin - PD0 + if pinChange&PinRising > 0 { + pinCallbacks[2][pinIndex][0] = callback + } + if pinChange&PinFalling > 0 { + pinCallbacks[2][pinIndex][1] = callback + } + if callback != nil { + avr.PCMSK2.SetBits(1 << pinIndex) + } else { + avr.PCMSK2.ClearBits(1 << pinIndex) + } + avr.PCICR.SetBits(avr.PCICR_PCIE2) + interrupt.New(avr.IRQ_PCINT2, handlePCINT2Interrupts) + default: + return ErrInvalidInputPin + } + + return nil +} + +var pinCallbacks [3][8][2]func(Pin) +var pinStates [3]uint8 + +func handlePCINTInterrupts(intr uint8, port *volatile.Register8) { + current := port.Get() + change := pinStates[intr] ^ current + pinStates[intr] = current + for i := uint8(0); i < 8; i++ { + if (change>>i)&0x01 != 0x01 { + continue + } + pin := Pin(intr*8 + i) + value := pin.Get() + if value && pinCallbacks[intr][i][0] != nil { + pinCallbacks[intr][i][0](pin) + } + if !value && pinCallbacks[intr][i][1] != nil { + pinCallbacks[intr][i][1](pin) + } + } +} + +func handlePCINT0Interrupts(intr interrupt.Interrupt) { + handlePCINTInterrupts(0, avr.PINB) +} + +func handlePCINT1Interrupts(intr interrupt.Interrupt) { + handlePCINTInterrupts(1, avr.PINC) +} + +func handlePCINT2Interrupts(intr interrupt.Interrupt) { + handlePCINTInterrupts(2, avr.PIND) +} |