-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpwm.cpp
68 lines (56 loc) · 1.8 KB
/
pwm.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include "clocks.hpp"
#include "pwm.hpp"
std::uint8_t pwm::portPinNum[pwm::dutyCycleArrSize];
void pwm::init(std::uint32_t frequency)
{
// Initialize TCC0 clocks
clk::initTmr(clk::tmr::tTCC0, GCLK_CLKCTRL_GEN_GCLK0_Val, 48000000U);
TCC0->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM;
while (TCC0->SYNCBUSY.bit.WAVE);
// Set frequency
const auto ticks = 48000000U / frequency;
TCC0->PER.reg = ticks;
while (TCC0->SYNCBUSY.bit.PER);
// Start timer
TCC0->CTRLA.bit.ENABLE = 1;
while (TCC0->SYNCBUSY.bit.ENABLE);
}
void pwm::add(std::uint8_t idx, std::uint8_t pin, std::uint8_t defDuty)
{
pin = ARDUINO_PIN_TO_PORT_PIN(pin);
const auto apin = pin;
const auto grp = PGrp(pin);
pin &= 0x1F;
// Enable peripheral multiplexer
PORT->Group[grp].PINCFG[pin].reg |= PORT_PINCFG_PMUXEN;
const auto pmuxIdx = pin / 2;
/* Function E:
* PA04, PA05, PA08, PA09
*/
/* Function F:
* PA10, PA11, PB10, PB11, PA12, PA13, PA14, PA15, PA16, PA17, PA18, PA19, PA20, PA21, PA22, PA23
*/
// Select function
auto function = (!grp && (pin <= 9) && (bool[10]){ 0, 0, 0, 0, 1, 1, 0, 0, 1, 1 }[pin]) ? PORT_PMUX_PMUXO_E_Val : PORT_PMUX_PMUXO_F_Val;
// Even/odd function selection shifting
function = (pin % 2) ? (function << PORT_PMUX_PMUXO_Pos) : (function << PORT_PMUX_PMUXE_Pos);
// Set pin function
PORT->Group[grp].PMUX[pmuxIdx].reg |= function;
// CC0 -> WO[0], WO[4]
// CC1 -> WO[1], WO[5]
// CC2 -> WO[2], WO[6]
// CC3 -> WO[3], WO[7]
pwm::portPinNum[idx] = apin;
pwm::duty(idx, defDuty);
}
void pwm::duty(std::uint8_t idx, std::uint8_t duty)
{
TCC0->CCB[idx].reg = (TCC0->PER.reg * std::uint32_t(duty)) / 255U;
while (TCC0->SYNCBUSY.vec.CCB);
}
void pwm::remove(std::uint8_t idx)
{
const auto pin = pwm::portPinNum[idx];
// Disable wave output on pin
PORT->Group[PGrp(pin)].PINCFG[pin & 0x1F].reg &= ~PORT_PINCFG_PMUXEN;
}