machine: refactor PWM support

This commit refactors PWM support in the machine package to be more
flexible. The new API can be used to produce tones at a specific
frequency and control servos in a portable way, by abstracting over
counter widths and prescalers.
This commit is contained in:
Ayke van Laethem
2020-05-19 22:30:46 +02:00
committed by Ron Evans
parent f880950c3e
commit 72acda22b0
20 changed files with 1565 additions and 758 deletions
+43 -54
View File
@@ -11,60 +11,49 @@ import "device/sam"
const HSRAM_SIZE = 0x00030000
// InitPWM initializes the PWM interface.
func InitPWM() {
// turn on timer clocks used for PWM
sam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC0_ | sam.MCLK_APBBMASK_TCC1_)
sam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TCC2_ | sam.MCLK_APBCMASK_TCC3_)
sam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_TCC4_)
// This chip has five TCC peripherals, which have PWM as one feature.
var (
TCC0 = (*TCC)(sam.TCC0)
TCC1 = (*TCC)(sam.TCC1)
TCC2 = (*TCC)(sam.TCC2)
TCC3 = (*TCC)(sam.TCC3)
TCC4 = (*TCC)(sam.TCC4)
)
//use clock generator 0
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC0].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) |
sam.GCLK_PCHCTRL_CHEN)
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC2].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) |
sam.GCLK_PCHCTRL_CHEN)
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC4].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) |
sam.GCLK_PCHCTRL_CHEN)
}
// getTimer returns the timer to be used for PWM on this pin
func (pwm PWM) getTimer() *sam.TCC_Type {
switch pwm.Pin {
case PA14:
return sam.TCC2
case PA15:
return sam.TCC2
case PA16:
return sam.TCC1
case PA17:
return sam.TCC1
case PA18:
return sam.TCC1
case PA19:
return sam.TCC1
case PA20:
return sam.TCC0
case PA21:
return sam.TCC0
case PA22:
return sam.TCC0
case PA23:
return sam.TCC0
case PB12:
return sam.TCC3
case PB13:
return sam.TCC3
case PB14:
return sam.TCC4
case PB15:
return sam.TCC4
case PB16:
return sam.TCC0
case PB17:
return sam.TCC0
case PB31:
return sam.TCC4
default:
return nil // not supported on this pin
func (tcc *TCC) configureClock() {
// Turn on timer clocks used for the TCC and use generic clock generator 0.
switch tcc.timer() {
case sam.TCC0:
sam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC0_)
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC0].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)
case sam.TCC1:
sam.MCLK.APBBMASK.SetBits(sam.MCLK_APBBMASK_TCC1_)
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC1].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)
case sam.TCC2:
sam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TCC2_)
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC2].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)
case sam.TCC3:
sam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TCC3_)
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC3].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)
case sam.TCC4:
sam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_TCC4_)
sam.GCLK.PCHCTRL[sam.PCHCTRL_GCLK_TCC4].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)
}
}
func (tcc *TCC) timerNum() uint8 {
switch tcc.timer() {
case sam.TCC0:
return 0
case sam.TCC1:
return 1
case sam.TCC2:
return 2
case sam.TCC3:
return 3
case sam.TCC4:
return 4
default:
return 0x0f // should not happen
}
}