github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_atmega.go (about) 1 //go:build avr && atmega 2 3 package machine 4 5 import ( 6 "device/avr" 7 "runtime/interrupt" 8 "runtime/volatile" 9 "unsafe" 10 ) 11 12 // I2C on AVR. 13 type I2C struct { 14 srReg *volatile.Register8 15 brReg *volatile.Register8 16 crReg *volatile.Register8 17 drReg *volatile.Register8 18 19 srPS0 byte 20 srPS1 byte 21 crEN byte 22 crINT byte 23 crSTO byte 24 crEA byte 25 crSTA byte 26 } 27 28 // I2CConfig is used to store config info for I2C. 29 type I2CConfig struct { 30 Frequency uint32 31 } 32 33 // Configure is intended to setup the I2C interface. 34 func (i2c *I2C) Configure(config I2CConfig) error { 35 // Default I2C bus speed is 100 kHz. 36 if config.Frequency == 0 { 37 config.Frequency = 100 * KHz 38 } 39 40 // Activate internal pullups for twi. 41 avr.PORTC.SetBits((avr.DIDR0_ADC4D | avr.DIDR0_ADC5D)) 42 43 return i2c.SetBaudRate(config.Frequency) 44 } 45 46 // SetBaudRate sets the communication speed for I2C. 47 func (i2c *I2C) SetBaudRate(br uint32) error { 48 // Initialize twi prescaler and bit rate. 49 i2c.srReg.SetBits((i2c.srPS0 | i2c.srPS1)) 50 51 // twi bit rate formula from atmega128 manual pg. 204: 52 // SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) 53 // NOTE: TWBR should be 10 or higher for controller mode. 54 // It is 72 for a 16mhz board with 100kHz TWI 55 i2c.brReg.Set(uint8(((CPUFrequency() / br) - 16) / 2)) 56 57 // Enable twi module. 58 i2c.crReg.Set(i2c.crEN) 59 60 return nil 61 } 62 63 // Tx does a single I2C transaction at the specified address. 64 // It clocks out the given address, writes the bytes in w, reads back len(r) 65 // bytes and stores them in r, and generates a stop condition on the bus. 66 func (i2c *I2C) Tx(addr uint16, w, r []byte) error { 67 if len(w) != 0 { 68 i2c.start(uint8(addr), true) // start transmission for writing 69 for _, b := range w { 70 i2c.writeByte(b) 71 } 72 } 73 if len(r) != 0 { 74 i2c.start(uint8(addr), false) // re-start transmission for reading 75 for i := range r { // read each char 76 r[i] = i2c.readByte() 77 } 78 } 79 if len(w) != 0 || len(r) != 0 { 80 // Stop the transmission after it has been started. 81 i2c.stop() 82 } 83 return nil 84 } 85 86 // start starts an I2C communication session. 87 func (i2c *I2C) start(address uint8, write bool) { 88 // Clear TWI interrupt flag, put start condition on SDA, and enable TWI. 89 i2c.crReg.Set((i2c.crINT | i2c.crSTA | i2c.crEN)) 90 91 // Wait till start condition is transmitted. 92 for !i2c.crReg.HasBits(i2c.crINT) { 93 } 94 95 // Write 7-bit shifted peripheral address. 96 address <<= 1 97 if !write { 98 address |= 1 // set read flag 99 } 100 i2c.writeByte(address) 101 } 102 103 // stop ends an I2C communication session. 104 func (i2c *I2C) stop() { 105 // Send stop condition. 106 i2c.crReg.Set(i2c.crEN | i2c.crINT | i2c.crSTO) 107 108 // Wait for stop condition to be executed on bus. 109 for !i2c.crReg.HasBits(i2c.crSTO) { 110 } 111 } 112 113 // writeByte writes a single byte to the I2C bus. 114 func (i2c *I2C) writeByte(data byte) error { 115 // Write data to register. 116 i2c.drReg.Set(data) 117 118 // Clear TWI interrupt flag and enable TWI. 119 i2c.crReg.Set(i2c.crEN | i2c.crINT) 120 121 // Wait till data is transmitted. 122 for !i2c.crReg.HasBits(i2c.crINT) { 123 } 124 return nil 125 } 126 127 // readByte reads a single byte from the I2C bus. 128 func (i2c *I2C) readByte() byte { 129 // Clear TWI interrupt flag and enable TWI. 130 i2c.crReg.Set(i2c.crEN | i2c.crINT | i2c.crEA) 131 132 // Wait till read request is transmitted. 133 for !i2c.crReg.HasBits(i2c.crINT) { 134 } 135 136 return byte(i2c.drReg.Get()) 137 } 138 139 // Always use UART0 as the serial output. 140 var DefaultUART = UART0 141 142 // UART 143 var ( 144 // UART0 is the hardware serial port on the AVR. 145 UART0 = &_UART0 146 _UART0 = UART{ 147 Buffer: NewRingBuffer(), 148 149 dataReg: avr.UDR0, 150 baudRegH: avr.UBRR0H, 151 baudRegL: avr.UBRR0L, 152 statusRegA: avr.UCSR0A, 153 statusRegB: avr.UCSR0B, 154 statusRegC: avr.UCSR0C, 155 } 156 ) 157 158 func init() { 159 // Register the UART interrupt. 160 interrupt.New(irq_USART0_RX, _UART0.handleInterrupt) 161 } 162 163 // UART on the AVR. 164 type UART struct { 165 Buffer *RingBuffer 166 167 dataReg *volatile.Register8 168 baudRegH *volatile.Register8 169 baudRegL *volatile.Register8 170 171 statusRegA *volatile.Register8 172 statusRegB *volatile.Register8 173 statusRegC *volatile.Register8 174 } 175 176 // Configure the UART on the AVR. Defaults to 9600 baud on Arduino. 177 func (uart *UART) Configure(config UARTConfig) { 178 if config.BaudRate == 0 { 179 config.BaudRate = 9600 180 } 181 182 // Prescale formula for u2x mode from AVR MiniCore source code. 183 // Same as formula from specification but taking into account rounding error. 184 ps := (CPUFrequency()/4/config.BaudRate - 1) / 2 185 uart.statusRegA.SetBits(avr.UCSR0A_U2X0) 186 187 // Hardcoded exception for 57600 for compatibility with older bootloaders. 188 // Also, prescale cannot be > 4095, so switch back to non-u2x mode if the baud rate is too low. 189 if (CPUFrequency() == 16000000 && config.BaudRate == 57600) || ps > 0xfff { 190 ps = (CPUFrequency()/8/config.BaudRate - 1) / 2 191 uart.statusRegA.ClearBits(avr.UCSR0A_U2X0) 192 } 193 194 uart.baudRegH.Set(uint8(ps >> 8)) 195 uart.baudRegL.Set(uint8(ps & 0xff)) 196 197 // enable RX, TX and RX interrupt 198 uart.statusRegB.Set(avr.UCSR0B_RXEN0 | avr.UCSR0B_TXEN0 | avr.UCSR0B_RXCIE0) 199 200 // 8-bits data 201 uart.statusRegC.Set(avr.UCSR0C_UCSZ01 | avr.UCSR0C_UCSZ00) 202 } 203 204 func (uart *UART) handleInterrupt(intr interrupt.Interrupt) { 205 // Read register to clear it. 206 data := uart.dataReg.Get() 207 208 // Ensure no error. 209 if !uart.statusRegA.HasBits(avr.UCSR0A_FE0 | avr.UCSR0A_DOR0 | avr.UCSR0A_UPE0) { 210 // Put data from UDR register into buffer. 211 uart.Receive(byte(data)) 212 } 213 } 214 215 // WriteByte writes a byte of data to the UART. 216 func (uart *UART) writeByte(c byte) error { 217 // Wait until UART buffer is not busy. 218 for !uart.statusRegA.HasBits(avr.UCSR0A_UDRE0) { 219 } 220 uart.dataReg.Set(c) // send char 221 return nil 222 } 223 224 func (uart *UART) flush() {} 225 226 // SPIConfig is used to store config info for SPI. 227 type SPIConfig struct { 228 Frequency uint32 229 LSBFirst bool 230 Mode uint8 231 } 232 233 // SPI is for the Serial Peripheral Interface 234 // Data is taken from http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf page 169 and following 235 type SPI struct { 236 // The registers for the SPIx port set by the chip 237 spcr *volatile.Register8 238 spdr *volatile.Register8 239 spsr *volatile.Register8 240 241 spcrR0 byte 242 spcrR1 byte 243 spcrCPHA byte 244 spcrCPOL byte 245 spcrDORD byte 246 spcrSPE byte 247 spcrMSTR byte 248 249 spsrI2X byte 250 spsrSPIF byte 251 252 // The io pins for the SPIx port set by the chip 253 sck Pin 254 sdi Pin 255 sdo Pin 256 cs Pin 257 } 258 259 // Configure is intended to setup the SPI interface. 260 func (s SPI) Configure(config SPIConfig) error { 261 262 // This is only here to help catch a bug with the configuration 263 // where a machine missed a value. 264 if s.spcr == (*volatile.Register8)(unsafe.Pointer(uintptr(0))) || 265 s.spsr == (*volatile.Register8)(unsafe.Pointer(uintptr(0))) || 266 s.spdr == (*volatile.Register8)(unsafe.Pointer(uintptr(0))) || 267 s.sck == 0 || s.sdi == 0 || s.sdo == 0 || s.cs == 0 { 268 return errSPIInvalidMachineConfig 269 } 270 271 // Make the defaults meaningful 272 if config.Frequency == 0 { 273 config.Frequency = 4000000 274 } 275 276 // Default all port configuration bits to 0 for simplicity 277 s.spcr.Set(0) 278 s.spsr.Set(0) 279 280 // Setup pins output configuration 281 s.sck.Configure(PinConfig{Mode: PinOutput}) 282 s.sdi.Configure(PinConfig{Mode: PinInput}) 283 s.sdo.Configure(PinConfig{Mode: PinOutput}) 284 285 // Prevent CS glitches if the pin is enabled Low (0, default) 286 s.cs.High() 287 // If the CS pin is not configured as output the SPI port operates in 288 // slave mode. 289 s.cs.Configure(PinConfig{Mode: PinOutput}) 290 291 frequencyDivider := CPUFrequency() / config.Frequency 292 293 switch { 294 case frequencyDivider >= 128: 295 s.spcr.SetBits(s.spcrR0 | s.spcrR1) 296 case frequencyDivider >= 64: 297 s.spcr.SetBits(s.spcrR1) 298 case frequencyDivider >= 32: 299 s.spcr.SetBits(s.spcrR1) 300 s.spsr.SetBits(s.spsrI2X) 301 case frequencyDivider >= 16: 302 s.spcr.SetBits(s.spcrR0) 303 case frequencyDivider >= 8: 304 s.spcr.SetBits(s.spcrR0) 305 s.spsr.SetBits(s.spsrI2X) 306 case frequencyDivider >= 4: 307 // The clock is already set to all 0's. 308 default: // defaults to fastest which is /2 309 s.spsr.SetBits(s.spsrI2X) 310 } 311 312 switch config.Mode { 313 case Mode1: 314 s.spcr.SetBits(s.spcrCPHA) 315 case Mode2: 316 s.spcr.SetBits(s.spcrCPHA) 317 case Mode3: 318 s.spcr.SetBits(s.spcrCPHA | s.spcrCPOL) 319 default: // default is mode 0 320 } 321 322 if config.LSBFirst { 323 s.spcr.SetBits(s.spcrDORD) 324 } 325 326 // enable SPI, set controller, set clock rate 327 s.spcr.SetBits(s.spcrSPE | s.spcrMSTR) 328 329 return nil 330 } 331 332 // Transfer writes the byte into the register and returns the read content 333 func (s SPI) Transfer(b byte) (byte, error) { 334 s.spdr.Set(uint8(b)) 335 336 for !s.spsr.HasBits(s.spsrSPIF) { 337 } 338 339 return byte(s.spdr.Get()), nil 340 }