diff options
author | Ayke van Laethem <[email protected]> | 2023-05-21 02:40:58 +0200 |
---|---|---|
committer | Ron Evans <[email protected]> | 2023-05-21 10:44:02 +0200 |
commit | da81784ee98e3eb5dcd5288564db9ed0de4f042c (patch) | |
tree | bf539e8fd66717a97cfa22dcd9b0efee8e50ff8b | |
parent | 481f60c5ea3a06a295f6a34bcee5754563358e28 (diff) | |
download | tinygo-da81784ee98e3eb5dcd5288564db9ed0de4f042c.tar.gz tinygo-da81784ee98e3eb5dcd5288564db9ed0de4f042c.zip |
attiny1616: implement Pin.Get()
I didn't add this method in the initial PR.
Also, I found that a few of my assumptions were incorrect. I've changed
the code that configures the pin to make input (floating and pullup)
actually work. These chips really are quite different from all the older
AVRs.
-rw-r--r-- | src/machine/machine_avrtiny.go | 52 |
1 files changed, 27 insertions, 25 deletions
diff --git a/src/machine/machine_avrtiny.go b/src/machine/machine_avrtiny.go index 02393700c..78168f47b 100644 --- a/src/machine/machine_avrtiny.go +++ b/src/machine/machine_avrtiny.go @@ -2,7 +2,11 @@ package machine -import "device/avr" +import ( + "device/avr" + "runtime/volatile" + "unsafe" +) const deviceName = avr.DEVICE @@ -20,35 +24,33 @@ func (p Pin) Configure(config PinConfig) { // set output bit port.DIRSET.Set(mask) - // Note: if the pin was PinInputPullup before, it'll now be high. - // Otherwise it will be low. + // Note: the output state (high or low) is as it was before. } else { - // configure input: clear output bit - port.DIRCLR.Set(mask) - - if config.Mode == PinInput { - // No pullup (floating). - // The transition may be one of the following: - // output high -> input pullup -> input (safe: output high and input pullup are similar) - // output low -> input -> input (safe: no extra transition) - port.OUTCLR.Set(mask) - } else { - // Pullup. - // The transition may be one of the following: - // output high -> input pullup -> input pullup (safe: no extra transition) - // output low -> input -> input pullup (possibly problematic) - // For the last transition (output low -> input -> input pullup), - // the transition may be problematic in some cases because there is - // an intermediate floating state (which may cause irratic - // interrupts, for example). If this is a problem, the application - // should set the pin high before configuring it as PinInputPullup. - // We can't do that here because setting it to high as an - // intermediate state may have other problems. - port.OUTSET.Set(mask) + // Configure the pin as an input. + // First set up the configuration that will be used when it is an input. + pinctrl := uint8(0) + if config.Mode == PinInputPullup { + pinctrl |= avr.PORT_PIN0CTRL_PULLUPEN } + // Find the PINxCTRL register for this pin. + ctrlAddress := (*volatile.Register8)(unsafe.Add(unsafe.Pointer(&port.PIN0CTRL), p%8)) + ctrlAddress.Set(pinctrl) + + // Configure the pin as input (if it wasn't an input pin before). + port.DIRCLR.Set(mask) } } +// Get returns the current value of a GPIO pin when the pin is configured as an +// input or as an output. +func (p Pin) Get() bool { + port, mask := p.getPortMask() + // As noted above, the PINx register is always two registers below the PORTx + // register, so we can find it simply by subtracting two from the PORTx + // register address. + return (port.IN.Get() & mask) > 0 +} + // Set changes the value of the GPIO pin. The pin must be configured as output. func (p Pin) Set(high bool) { port, mask := p.getPortMask() |