1// +build stm32,!stm32f103xx
2
3package machine
4
5import (
6	"device/stm32"
7)
8
9// GPIO for the stm32 families except the stm32f1xx which uses a simpler but
10//  less flexible mechanism. Extend the +build directive above to exclude other
11//  models in the stm32f1xx series as necessary
12
13const (
14	// Mode Flag
15	PinOutput        PinMode = 0
16	PinInput         PinMode = PinInputFloating
17	PinInputFloating PinMode = 1
18	PinInputPulldown PinMode = 2
19	PinInputPullup   PinMode = 3
20
21	// for UART
22	PinModeUARTTX PinMode = 4
23	PinModeUARTRX PinMode = 5
24
25	// for I2C
26	PinModeI2CSCL PinMode = 6
27	PinModeI2CSDA PinMode = 7
28
29	// for SPI
30	PinModeSPICLK PinMode = 8
31	PinModeSPISDO PinMode = 9
32	PinModeSPISDI PinMode = 10
33
34	// for analog/ADC
35	PinInputAnalog PinMode = 11
36
37	// for PWM
38	// TBD
39)
40
41// Configure this pin with the given configuration
42func (p Pin) Configure(config PinConfig) {
43	// Use the default system alternate function; this
44	//  will only be used if you try to call this with
45	//  one of the peripheral modes instead of vanilla GPIO.
46	p.ConfigureAltFunc(config, stm32.AF0_SYSTEM)
47}
48
49// Configure this pin with the given configuration including alternate
50//  function mapping if necessary.
51func (p Pin) ConfigureAltFunc(config PinConfig, altFunc stm32.AltFunc) {
52	// Configure the GPIO pin.
53	p.enableClock()
54	port := p.getPort()
55	pin := uint8(p) % 16
56	pos := pin * 2
57
58	switch config.Mode {
59
60	// GPIO
61	case PinInputFloating:
62		port.MODER.ReplaceBits(stm32.GPIOModeInput, 0x3, pos)
63		port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
64	case PinInputPulldown:
65		port.MODER.ReplaceBits(stm32.GPIOModeInput, 0x3, pos)
66		port.PUPDR.ReplaceBits(stm32.GPIOPUPDRPullDown, 0x3, pos)
67	case PinInputPullup:
68		port.MODER.ReplaceBits(stm32.GPIOModeInput, 0x3, pos)
69		port.PUPDR.ReplaceBits(stm32.GPIOPUPDRPullUp, 0x3, pos)
70	case PinOutput:
71		port.MODER.ReplaceBits(stm32.GPIOModeOutputGeneral, 0x3, pos)
72		port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedHigh, 0x3, pos)
73
74	// UART
75	case PinModeUARTTX:
76		port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
77		port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedHigh, 0x3, pos)
78		port.PUPDR.ReplaceBits(stm32.GPIOPUPDRPullUp, 0x3, pos)
79		p.SetAltFunc(altFunc)
80	case PinModeUARTRX:
81		port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
82		port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
83		p.SetAltFunc(altFunc)
84
85	// I2C
86	case PinModeI2CSCL:
87		port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
88		port.OTYPER.ReplaceBits(stm32.GPIOOutputTypeOpenDrain, 0x1, pos)
89		port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedLow, 0x3, pos)
90		port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
91		p.SetAltFunc(altFunc)
92	case PinModeI2CSDA:
93		port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
94		port.OTYPER.ReplaceBits(stm32.GPIOOutputTypeOpenDrain, 0x1, pos)
95		port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedLow, 0x3, pos)
96		port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
97		p.SetAltFunc(altFunc)
98
99	// SPI
100	case PinModeSPICLK:
101		port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
102		port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedLow, 0x3, pos)
103		port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
104		p.SetAltFunc(altFunc)
105	case PinModeSPISDO:
106		port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
107		port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedLow, 0x3, pos)
108		port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
109		p.SetAltFunc(altFunc)
110	case PinModeSPISDI:
111		port.MODER.ReplaceBits(stm32.GPIOModeOutputAltFunc, 0x3, pos)
112		port.OSPEEDR.ReplaceBits(stm32.GPIOSpeedLow, 0x3, pos)
113		port.PUPDR.ReplaceBits(stm32.GPIOPUPDRFloating, 0x3, pos)
114		p.SetAltFunc(altFunc)
115	}
116}
117
118// SetAltFunc maps the given alternative function to the I/O pin
119func (p Pin) SetAltFunc(af stm32.AltFunc) {
120	port := p.getPort()
121	pin := uint8(p) % 16
122	pos := (pin % 8) * 4
123	if pin < 8 {
124		port.AFRL.ReplaceBits(uint32(af), 0xf, pos)
125	} else {
126		port.AFRH.ReplaceBits(uint32(af), 0xf, pos)
127	}
128}
129