github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_esp8266.go (about) 1 //go:build esp8266 2 3 package machine 4 5 import ( 6 "device/esp" 7 "runtime/volatile" 8 ) 9 10 const deviceName = esp.Device 11 12 func CPUFrequency() uint32 { 13 return 80000000 // 80MHz 14 } 15 16 const ( 17 PinOutput PinMode = iota 18 PinInput 19 ) 20 21 // Hardware pin numbers 22 const ( 23 GPIO0 Pin = iota 24 GPIO1 25 GPIO2 26 GPIO3 27 GPIO4 28 GPIO5 29 GPIO6 30 GPIO7 31 GPIO8 32 GPIO9 33 GPIO10 34 GPIO11 35 GPIO12 36 GPIO13 37 GPIO14 38 GPIO15 39 GPIO16 40 ) 41 42 // Pins that are fixed by the chip. 43 const ( 44 UART_TX_PIN Pin = 1 45 UART_RX_PIN Pin = 3 46 ) 47 48 // Pin functions are not trivial. The below array maps a pin number (GPIO 49 // number) to the pad as used in the IO mux. 50 // Tables with the mapping: 51 // https://www.esp8266.com/wiki/doku.php?id=esp8266_gpio_pin_allocations#pin_functions 52 // https://www.espressif.com/sites/default/files/documentation/ESP8266_Pin_List_0.xls 53 var pinPadMapping = [...]uint8{ 54 12: 0, 55 13: 1, 56 14: 2, 57 15: 3, 58 3: 4, 59 1: 5, 60 6: 6, 61 7: 7, 62 8: 8, 63 9: 9, 64 10: 10, 65 11: 11, 66 0: 12, 67 2: 13, 68 4: 14, 69 5: 15, 70 } 71 72 // getPad returns the pad number and the register to configure this pad. 73 func (p Pin) getPad() (uint8, *volatile.Register32) { 74 pad := pinPadMapping[p] 75 var reg *volatile.Register32 76 switch pad { 77 case 0: 78 reg = &esp.IO_MUX.IO_MUX_MTDI 79 case 1: 80 reg = &esp.IO_MUX.IO_MUX_MTCK 81 case 2: 82 reg = &esp.IO_MUX.IO_MUX_MTMS 83 case 3: 84 reg = &esp.IO_MUX.IO_MUX_MTDO 85 case 4: 86 reg = &esp.IO_MUX.IO_MUX_U0RXD 87 case 5: 88 reg = &esp.IO_MUX.IO_MUX_U0TXD 89 case 6: 90 reg = &esp.IO_MUX.IO_MUX_SD_CLK 91 case 7: 92 reg = &esp.IO_MUX.IO_MUX_SD_DATA0 93 case 8: 94 reg = &esp.IO_MUX.IO_MUX_SD_DATA1 95 case 9: 96 reg = &esp.IO_MUX.IO_MUX_SD_DATA2 97 case 10: 98 reg = &esp.IO_MUX.IO_MUX_SD_DATA3 99 case 11: 100 reg = &esp.IO_MUX.IO_MUX_SD_CMD 101 case 12: 102 reg = &esp.IO_MUX.IO_MUX_GPIO0 103 case 13: 104 reg = &esp.IO_MUX.IO_MUX_GPIO2 105 case 14: 106 reg = &esp.IO_MUX.IO_MUX_GPIO4 107 case 15: 108 reg = &esp.IO_MUX.IO_MUX_GPIO5 109 } 110 return pad, reg 111 } 112 113 // Configure sets the given pin as output or input pin. 114 func (p Pin) Configure(config PinConfig) { 115 switch config.Mode { 116 case PinInput, PinOutput: 117 pad, reg := p.getPad() 118 if pad >= 12 { // pin 0, 2, 4, 5 119 reg.Set(0 << 4) // function 0 at bit position 4 120 } else { 121 reg.Set(3 << 4) // function 3 at bit position 4 122 } 123 if config.Mode == PinOutput { 124 esp.GPIO.GPIO_ENABLE_W1TS.Set(1 << p) 125 } else { 126 esp.GPIO.GPIO_ENABLE_W1TC.Set(1 << p) 127 } 128 } 129 } 130 131 // Get returns the current value of a GPIO pin when the pin is configured as an 132 // input or as an output. 133 func (p Pin) Get() bool { 134 // See this document for details 135 // https://www.espressif.com/sites/default/files/documentation/esp8266-technical_reference_en.pdf 136 137 return esp.GPIO.GPIO_IN.Get()&(1<<p) != 0 138 } 139 140 // Set sets the output value of this pin to high (true) or low (false). 141 func (p Pin) Set(value bool) { 142 if value { 143 esp.GPIO.GPIO_OUT_W1TS.Set(1 << p) 144 } else { 145 esp.GPIO.GPIO_OUT_W1TC.Set(1 << p) 146 } 147 } 148 149 // Return the register and mask to enable a given GPIO pin. This can be used to 150 // implement bit-banged drivers. 151 // 152 // Warning: only use this on an output pin! 153 func (p Pin) PortMaskSet() (*uint32, uint32) { 154 return &esp.GPIO.GPIO_OUT_W1TS.Reg, 1 << p 155 } 156 157 // Return the register and mask to disable a given GPIO pin. This can be used to 158 // implement bit-banged drivers. 159 // 160 // Warning: only use this on an output pin! 161 func (p Pin) PortMaskClear() (*uint32, uint32) { 162 return &esp.GPIO.GPIO_OUT_W1TC.Reg, 1 << p 163 } 164 165 var DefaultUART = UART0 166 167 // UART0 is a hardware UART that supports both TX and RX. 168 var UART0 = &_UART0 169 var _UART0 = UART{Buffer: NewRingBuffer()} 170 171 type UART struct { 172 Buffer *RingBuffer 173 } 174 175 // Configure the UART baud rate. TX and RX pins are fixed by the hardware so 176 // cannot be modified and will be ignored. 177 func (uart *UART) Configure(config UARTConfig) { 178 if config.BaudRate == 0 { 179 config.BaudRate = 115200 180 } 181 esp.UART0.UART_CLKDIV.Set(CPUFrequency() / config.BaudRate) 182 } 183 184 // writeByte writes a single byte to the output buffer. Note that the hardware 185 // includes a buffer of 128 bytes which will be used first. 186 func (uart *UART) writeByte(c byte) error { 187 for (esp.UART0.UART_STATUS.Get()>>16)&0xff >= 128 { 188 // Wait until the TX buffer has room. 189 } 190 esp.UART0.UART_FIFO.Set(uint32(c)) 191 return nil 192 } 193 194 func (uart *UART) flush() {}