aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/machine/machine_avrtiny.go
blob: 78168f47b3d72f22b4d32b7b0db6d3a32bd69ef1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
//go:build avrtiny

package machine

import (
	"device/avr"
	"runtime/volatile"
	"unsafe"
)

const deviceName = avr.DEVICE

const (
	PinInput PinMode = iota
	PinInputPullup
	PinOutput
)

// Configure sets the pin to input or output.
func (p Pin) Configure(config PinConfig) {
	port, mask := p.getPortMask()

	if config.Mode == PinOutput {
		// set output bit
		port.DIRSET.Set(mask)

		// Note: the output state (high or low) is as it was before.
	} else {
		// 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()
	if high {
		port.OUTSET.Set(mask)
	} else {
		port.OUTCLR.Set(mask)
	}
}