tinygo/src/machine/machine_atmega328p.go
Ayke van Laethem da505a6b17 avr: unify GPIO pin/port code
All the AVRs that I've looked at had the same pin/port structure, with
the possible states being input/floating, input/pullup, low, and high
(with the same PORT/DDR registers). The main difference is the number of
available ports and pins. To reduce the amount of code and avoid
duplication (and thus errors) I decided to centralize this, following
the design used by the atmega2560 but while using a trick to save
tracking a few registers.

In the process, I noticed that the Pin.Get() function was incorrect on
the atmega2560 implementation. It is now fixed in the unified code.
2020-05-22 13:17:04 +02:00

90 строки
2,5 КиБ
Go

// +build avr,atmega328p
package machine
import (
"device/avr"
"runtime/volatile"
)
const irq_USART0_RX = avr.IRQ_USART_RX
// getPortMask returns the PORTx register and mask for the pin.
func (p Pin) getPortMask() (*volatile.Register8, uint8) {
switch {
case p >= PB0 && p <= PB7: // port B
return avr.PORTB, 1 << uint8(p-portB)
case p >= PC0 && p <= PC7: // port C
return avr.PORTC, 1 << uint8(p-portC)
default: // port D
return avr.PORTD, 1 << uint8(p-portD)
}
}
// InitPWM initializes the registers needed for PWM.
func InitPWM() {
// use waveform generation
avr.TCCR0A.SetBits(avr.TCCR0A_WGM00)
// set timer 0 prescale factor to 64
avr.TCCR0B.SetBits(avr.TCCR0B_CS01 | avr.TCCR0B_CS00)
// set timer 1 prescale factor to 64
avr.TCCR1B.SetBits(avr.TCCR1B_CS11)
// put timer 1 in 8-bit phase correct pwm mode
avr.TCCR1A.SetBits(avr.TCCR1A_WGM10)
// set timer 2 prescale factor to 64
avr.TCCR2B.SetBits(avr.TCCR2B_CS22)
// configure timer 2 for phase correct pwm (8-bit)
avr.TCCR2A.SetBits(avr.TCCR2A_WGM20)
}
// Configure configures a PWM pin for output.
func (pwm PWM) Configure() error {
switch pwm.Pin / 8 {
case 0: // port B
avr.DDRB.SetBits(1 << uint8(pwm.Pin))
case 2: // port D
avr.DDRD.SetBits(1 << uint8(pwm.Pin-16))
}
return nil
}
// Set turns on the duty cycle for a PWM pin using the provided value. On the AVR this is normally a
// 8-bit value ranging from 0 to 255.
func (pwm PWM) Set(value uint16) {
value8 := uint8(value >> 8)
switch pwm.Pin {
case PD3:
// connect pwm to pin on timer 2, channel B
avr.TCCR2A.SetBits(avr.TCCR2A_COM2B1)
avr.OCR2B.Set(value8) // set pwm duty
case PD5:
// connect pwm to pin on timer 0, channel B
avr.TCCR0A.SetBits(avr.TCCR0A_COM0B1)
avr.OCR0B.Set(value8) // set pwm duty
case PD6:
// connect pwm to pin on timer 0, channel A
avr.TCCR0A.SetBits(avr.TCCR0A_COM0A1)
avr.OCR0A.Set(value8) // set pwm duty
case PB1:
// connect pwm to pin on timer 1, channel A
avr.TCCR1A.SetBits(avr.TCCR1A_COM1A1)
// this is a 16-bit value, but we only currently allow the low order bits to be set
avr.OCR1AL.Set(value8) // set pwm duty
case PB2:
// connect pwm to pin on timer 1, channel B
avr.TCCR1A.SetBits(avr.TCCR1A_COM1B1)
// this is a 16-bit value, but we only currently allow the low order bits to be set
avr.OCR1BL.Set(value8) // set pwm duty
case PB3:
// connect pwm to pin on timer 2, channel A
avr.TCCR2A.SetBits(avr.TCCR2A_COM2A1)
avr.OCR2A.Set(value8) // set pwm duty
default:
panic("Invalid PWM pin")
}
}