github.com/aykevl/tinygo@v0.5.0/src/machine/machine_atmega.go (about) 1 // +build avr,atmega 2 3 package machine 4 5 import ( 6 "device/avr" 7 ) 8 9 // Configure sets the pin to input or output. 10 func (p GPIO) Configure(config GPIOConfig) { 11 if config.Mode == GPIO_OUTPUT { // set output bit 12 if p.Pin < 8 { 13 *avr.DDRD |= 1 << p.Pin 14 } else { 15 *avr.DDRB |= 1 << (p.Pin - 8) 16 } 17 } else { // configure input: clear output bit 18 if p.Pin < 8 { 19 *avr.DDRD &^= 1 << p.Pin 20 } else { 21 *avr.DDRB &^= 1 << (p.Pin - 8) 22 } 23 } 24 } 25 26 // Get returns the current value of a GPIO pin. 27 func (p GPIO) Get() bool { 28 if p.Pin < 8 { 29 val := *avr.PIND & (1 << p.Pin) 30 return (val > 0) 31 } else { 32 val := *avr.PINB & (1 << (p.Pin - 8)) 33 return (val > 0) 34 } 35 } 36 37 func (p GPIO) getPortMask() (*avr.RegValue, uint8) { 38 if p.Pin < 8 { 39 return avr.PORTD, 1 << p.Pin 40 } else { 41 return avr.PORTB, 1 << (p.Pin - 8) 42 } 43 } 44 45 // InitPWM initializes the registers needed for PWM. 46 func InitPWM() { 47 // use waveform generation 48 *avr.TCCR0A |= avr.TCCR0A_WGM00 49 50 // set timer 0 prescale factor to 64 51 *avr.TCCR0B |= avr.TCCR0B_CS01 | avr.TCCR0B_CS00 52 53 // set timer 1 prescale factor to 64 54 *avr.TCCR1B |= avr.TCCR1B_CS11 55 56 // put timer 1 in 8-bit phase correct pwm mode 57 *avr.TCCR1A |= avr.TCCR1A_WGM10 58 59 // set timer 2 prescale factor to 64 60 *avr.TCCR2B |= avr.TCCR2B_CS22 61 62 // configure timer 2 for phase correct pwm (8-bit) 63 *avr.TCCR2A |= avr.TCCR2A_WGM20 64 } 65 66 // Configure configures a PWM pin for output. 67 func (pwm PWM) Configure() { 68 if pwm.Pin < 8 { 69 *avr.DDRD |= 1 << pwm.Pin 70 } else { 71 *avr.DDRB |= 1 << (pwm.Pin - 8) 72 } 73 } 74 75 // Set turns on the duty cycle for a PWM pin using the provided value. On the AVR this is normally a 76 // 8-bit value ranging from 0 to 255. 77 func (pwm PWM) Set(value uint16) { 78 value8 := value >> 8 79 switch pwm.Pin { 80 case 3: 81 // connect pwm to pin on timer 2, channel B 82 *avr.TCCR2A |= avr.TCCR2A_COM2B1 83 *avr.OCR2B = avr.RegValue(value8) // set pwm duty 84 case 5: 85 // connect pwm to pin on timer 0, channel B 86 *avr.TCCR0A |= avr.TCCR0A_COM0B1 87 *avr.OCR0B = avr.RegValue(value8) // set pwm duty 88 case 6: 89 // connect pwm to pin on timer 0, channel A 90 *avr.TCCR0A |= avr.TCCR0A_COM0A1 91 *avr.OCR0A = avr.RegValue(value8) // set pwm duty 92 case 9: 93 // connect pwm to pin on timer 1, channel A 94 *avr.TCCR1A |= avr.TCCR1A_COM1A1 95 // this is a 16-bit value, but we only currently allow the low order bits to be set 96 *avr.OCR1AL = avr.RegValue(value8) // set pwm duty 97 case 10: 98 // connect pwm to pin on timer 1, channel B 99 *avr.TCCR1A |= avr.TCCR1A_COM1B1 100 // this is a 16-bit value, but we only currently allow the low order bits to be set 101 *avr.OCR1BL = avr.RegValue(value8) // set pwm duty 102 case 11: 103 // connect pwm to pin on timer 2, channel A 104 *avr.TCCR2A |= avr.TCCR2A_COM2A1 105 *avr.OCR2A = avr.RegValue(value8) // set pwm duty 106 default: 107 panic("Invalid PWM pin") 108 } 109 } 110 111 // I2CConfig is used to store config info for I2C. 112 type I2CConfig struct { 113 Frequency uint32 114 } 115 116 // Configure is intended to setup the I2C interface. 117 func (i2c I2C) Configure(config I2CConfig) { 118 // Default I2C bus speed is 100 kHz. 119 if config.Frequency == 0 { 120 config.Frequency = TWI_FREQ_100KHZ 121 } 122 123 // Activate internal pullups for twi. 124 *avr.PORTC |= (avr.DIDR0_ADC4D | avr.DIDR0_ADC5D) 125 126 // Initialize twi prescaler and bit rate. 127 *avr.TWSR |= (avr.TWSR_TWPS0 | avr.TWSR_TWPS1) 128 129 // twi bit rate formula from atmega128 manual pg. 204: 130 // SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) 131 // NOTE: TWBR should be 10 or higher for master mode. 132 // It is 72 for a 16mhz board with 100kHz TWI 133 *avr.TWBR = avr.RegValue(((CPU_FREQUENCY / config.Frequency) - 16) / 2) 134 135 // Enable twi module. 136 *avr.TWCR = avr.TWCR_TWEN 137 } 138 139 // Tx does a single I2C transaction at the specified address. 140 // It clocks out the given address, writes the bytes in w, reads back len(r) 141 // bytes and stores them in r, and generates a stop condition on the bus. 142 func (i2c I2C) Tx(addr uint16, w, r []byte) error { 143 if len(w) != 0 { 144 i2c.start(uint8(addr), true) // start transmission for writing 145 for _, b := range w { 146 i2c.writeByte(b) 147 } 148 } 149 if len(r) != 0 { 150 i2c.start(uint8(addr), false) // re-start transmission for reading 151 for i := range r { // read each char 152 r[i] = i2c.readByte() 153 } 154 } 155 if len(w) != 0 || len(r) != 0 { 156 // Stop the transmission after it has been started. 157 i2c.stop() 158 } 159 return nil 160 } 161 162 // start starts an I2C communication session. 163 func (i2c I2C) start(address uint8, write bool) { 164 // Clear TWI interrupt flag, put start condition on SDA, and enable TWI. 165 *avr.TWCR = (avr.TWCR_TWINT | avr.TWCR_TWSTA | avr.TWCR_TWEN) 166 167 // Wait till start condition is transmitted. 168 for (*avr.TWCR & avr.TWCR_TWINT) == 0 { 169 } 170 171 // Write 7-bit shifted peripheral address. 172 address <<= 1 173 if !write { 174 address |= 1 // set read flag 175 } 176 i2c.writeByte(address) 177 } 178 179 // stop ends an I2C communication session. 180 func (i2c I2C) stop() { 181 // Send stop condition. 182 *avr.TWCR = (avr.TWCR_TWEN | avr.TWCR_TWINT | avr.TWCR_TWSTO) 183 184 // Wait for stop condition to be executed on bus. 185 for (*avr.TWCR & avr.TWCR_TWSTO) == 0 { 186 } 187 } 188 189 // writeByte writes a single byte to the I2C bus. 190 func (i2c I2C) writeByte(data byte) { 191 // Write data to register. 192 *avr.TWDR = avr.RegValue(data) 193 194 // Clear TWI interrupt flag and enable TWI. 195 *avr.TWCR = (avr.TWCR_TWEN | avr.TWCR_TWINT) 196 197 // Wait till data is transmitted. 198 for (*avr.TWCR & avr.TWCR_TWINT) == 0 { 199 } 200 } 201 202 // readByte reads a single byte from the I2C bus. 203 func (i2c I2C) readByte() byte { 204 // Clear TWI interrupt flag and enable TWI. 205 *avr.TWCR = (avr.TWCR_TWEN | avr.TWCR_TWINT | avr.TWCR_TWEA) 206 207 // Wait till read request is transmitted. 208 for (*avr.TWCR & avr.TWCR_TWINT) == 0 { 209 } 210 211 return byte(*avr.TWDR) 212 } 213 214 // UART on the AVR. 215 type UART struct { 216 Buffer *RingBuffer 217 } 218 219 // Configure the UART on the AVR. Defaults to 9600 baud on Arduino. 220 func (uart UART) Configure(config UARTConfig) { 221 if config.BaudRate == 0 { 222 config.BaudRate = 9600 223 } 224 225 // Set baud rate based on prescale formula from 226 // https://www.microchip.com/webdoc/AVRLibcReferenceManual/FAQ_1faq_wrong_baud_rate.html 227 // ((F_CPU + UART_BAUD_RATE * 8L) / (UART_BAUD_RATE * 16L) - 1) 228 ps := ((CPU_FREQUENCY+config.BaudRate*8)/(config.BaudRate*16) - 1) 229 *avr.UBRR0H = avr.RegValue(ps >> 8) 230 *avr.UBRR0L = avr.RegValue(ps & 0xff) 231 232 // enable RX, TX and RX interrupt 233 *avr.UCSR0B = avr.UCSR0B_RXEN0 | avr.UCSR0B_TXEN0 | avr.UCSR0B_RXCIE0 234 235 // 8-bits data 236 *avr.UCSR0C = avr.UCSR0C_UCSZ01 | avr.UCSR0C_UCSZ00 237 } 238 239 // WriteByte writes a byte of data to the UART. 240 func (uart UART) WriteByte(c byte) error { 241 // Wait until UART buffer is not busy. 242 for (*avr.UCSR0A & avr.UCSR0A_UDRE0) == 0 { 243 } 244 *avr.UDR0 = avr.RegValue(c) // send char 245 return nil 246 } 247 248 //go:interrupt USART_RX_vect 249 func handleUSART_RX() { 250 // Read register to clear it. 251 data := *avr.UDR0 252 253 // Ensure no error. 254 if (*avr.UCSR0A & (avr.UCSR0A_FE0 | avr.UCSR0A_DOR0 | avr.UCSR0A_UPE0)) == 0 { 255 // Put data from UDR register into buffer. 256 UART0.Receive(byte(data)) 257 } 258 }