aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYurii Soldak <[email protected]>2023-07-24 02:13:38 +0200
committerRon Evans <[email protected]>2023-07-27 18:15:22 +0200
commit00d46bd25dbc92970d70d88fefde303688ffe72f (patch)
treec7bb3938d5c1a913a7f653e773ffc302988bc007
parent01d2ef327d0b3a629ed3808f113f18bd16d81034 (diff)
downloadtinygo-00d46bd25dbc92970d70d88fefde303688ffe72f.tar.gz
tinygo-00d46bd25dbc92970d70d88fefde303688ffe72f.zip
avr: pin change interrupt
-rw-r--r--src/examples/pininterrupt/arduino.go11
-rw-r--r--src/examples/pininterrupt/circuitplay-express.go1
-rw-r--r--src/examples/pininterrupt/pca10040.go1
-rw-r--r--src/examples/pininterrupt/pininterrupt.go3
-rw-r--r--src/examples/pininterrupt/stm32.go1
-rw-r--r--src/examples/pininterrupt/wioterminal.go1
-rw-r--r--src/machine/machine_atmega328p.go104
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)
+}