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() {}