Merge pull request #12827 from maribu/atmega_pwm
cpu/atmega_common/periph/pwm: Minor fix & cleanup
This commit is contained in:
commit
cc44992abe
@ -29,6 +29,8 @@
|
|||||||
#define WGM0 0
|
#define WGM0 0
|
||||||
#define WGM1 1
|
#define WGM1 1
|
||||||
#define WGM2 3
|
#define WGM2 3
|
||||||
|
#define COMB0 4
|
||||||
|
#define COMB1 5
|
||||||
#define COMA0 6
|
#define COMA0 6
|
||||||
#define COMA1 7
|
#define COMA1 7
|
||||||
|
|
||||||
@ -38,7 +40,7 @@ static struct {
|
|||||||
uint8_t res;
|
uint8_t res;
|
||||||
} state[PWM_NUMOF];
|
} state[PWM_NUMOF];
|
||||||
|
|
||||||
static inline unsigned get_prescaler(pwm_t dev, uint32_t *scale)
|
static inline uint8_t get_prescaler(pwm_t dev, uint32_t *scale)
|
||||||
{
|
{
|
||||||
uint16_t divmask = pwm_conf[dev].div;
|
uint16_t divmask = pwm_conf[dev].div;
|
||||||
uint32_t target = *scale;
|
uint32_t target = *scale;
|
||||||
@ -58,6 +60,38 @@ static inline unsigned get_prescaler(pwm_t dev, uint32_t *scale)
|
|||||||
return pre;
|
return pre;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void compute_cra_and_crb(pwm_t dev, uint8_t pre)
|
||||||
|
{
|
||||||
|
uint8_t cra = (1 << WGM1) | (1 << WGM0);
|
||||||
|
uint8_t crb = pre;
|
||||||
|
|
||||||
|
if (pwm_conf[dev].pin_ch[0] != GPIO_UNDEF) {
|
||||||
|
cra |= (1 << COMA1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
crb |= (1 << WGM2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pwm_conf[dev].pin_ch[1] != GPIO_UNDEF) {
|
||||||
|
cra |= (1 << COMB1);
|
||||||
|
}
|
||||||
|
|
||||||
|
state[dev].CRA = cra;
|
||||||
|
state[dev].CRB = crb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void apply_config(pwm_t dev)
|
||||||
|
{
|
||||||
|
pwm_conf[dev].dev->CRA = state[dev].CRA;
|
||||||
|
pwm_conf[dev].dev->CRB = state[dev].CRB;
|
||||||
|
|
||||||
|
if (pwm_conf[dev].pin_ch[0] == GPIO_UNDEF) {
|
||||||
|
/* If channel 0 is not used, variable resolutions can be used for
|
||||||
|
* channel 1 */
|
||||||
|
pwm_conf[dev].dev->OCR[0] = state[dev].res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t pwm_init(pwm_t dev, pwm_mode_t mode, uint32_t freq, uint16_t res)
|
uint32_t pwm_init(pwm_t dev, pwm_mode_t mode, uint32_t freq, uint16_t res)
|
||||||
{
|
{
|
||||||
(void)mode;
|
(void)mode;
|
||||||
@ -82,36 +116,25 @@ uint32_t pwm_init(pwm_t dev, pwm_mode_t mode, uint32_t freq, uint16_t res)
|
|||||||
|
|
||||||
/* find out prescaler */
|
/* find out prescaler */
|
||||||
uint32_t scale = (CLOCK_CORECLOCK / (freq * (uint32_t)res));
|
uint32_t scale = (CLOCK_CORECLOCK / (freq * (uint32_t)res));
|
||||||
unsigned pre = get_prescaler(dev, &scale);
|
uint8_t pre = get_prescaler(dev, &scale);
|
||||||
freq = (CLOCK_CORECLOCK / (scale * (uint32_t)res));
|
freq = (CLOCK_CORECLOCK / (scale * (uint32_t)res));
|
||||||
|
|
||||||
/* compute register values and enable pins */
|
/* Compute configuration and store it in the state. (The state is needed
|
||||||
uint8_t cra = _BV(WGM1) | _BV(WGM0);
|
* for later calls to pwm_poweron().)*/
|
||||||
uint8_t crb = 0;
|
compute_cra_and_crb(dev, pre);
|
||||||
|
state[dev].res = res - 1;
|
||||||
|
|
||||||
res -= 1;
|
/* Apply configuration stored in state */
|
||||||
/* configure pins and resolution. Output must be low at initialization.
|
apply_config(dev);
|
||||||
* Force the pin low to avoid flickering. */
|
|
||||||
|
/* Enable outputs */
|
||||||
if (pwm_conf[dev].pin_ch[0] != GPIO_UNDEF) {
|
if (pwm_conf[dev].pin_ch[0] != GPIO_UNDEF) {
|
||||||
gpio_init(pwm_conf[dev].pin_ch[0], GPIO_OUT);
|
gpio_init(pwm_conf[dev].pin_ch[0], GPIO_OUT);
|
||||||
gpio_clear(pwm_conf[dev].pin_ch[0]);
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
crb |= _BV(WGM2);
|
|
||||||
pwm_conf[dev].dev->OCR[0] = (uint8_t)res;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pwm_conf[dev].pin_ch[1] != GPIO_UNDEF) {
|
if (pwm_conf[dev].pin_ch[1] != GPIO_UNDEF) {
|
||||||
gpio_init(pwm_conf[dev].pin_ch[1], GPIO_OUT);
|
gpio_init(pwm_conf[dev].pin_ch[1], GPIO_OUT);
|
||||||
gpio_clear(pwm_conf[dev].pin_ch[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pwm_conf[dev].dev->CRA = cra;
|
|
||||||
pwm_conf[dev].dev->CRB = crb | (pre);
|
|
||||||
state[dev].CRA = cra;
|
|
||||||
state[dev].CRB = crb | (pre);
|
|
||||||
state[dev].res = res;
|
|
||||||
|
|
||||||
/* return real frequency */
|
/* return real frequency */
|
||||||
return freq;
|
return freq;
|
||||||
}
|
}
|
||||||
@ -133,21 +156,11 @@ uint8_t pwm_channels(pwm_t dev)
|
|||||||
void pwm_set(pwm_t dev, uint8_t ch, uint16_t value)
|
void pwm_set(pwm_t dev, uint8_t ch, uint16_t value)
|
||||||
{
|
{
|
||||||
assert(dev < PWM_NUMOF && ch <= 1 && pwm_conf[dev].pin_ch[ch] != GPIO_UNDEF);
|
assert(dev < PWM_NUMOF && ch <= 1 && pwm_conf[dev].pin_ch[ch] != GPIO_UNDEF);
|
||||||
|
if (value > state[dev].res) {
|
||||||
/* output flickers when duty cycle is 0 or 100%. Simply force the pin
|
pwm_conf[dev].dev->OCR[ch] = state[dev].res;
|
||||||
* low or high respectively to have a clean output. */
|
|
||||||
uint8_t bit = (_BV(COMA1) >> (ch << 1));
|
|
||||||
if (value >= state[dev].res) {
|
|
||||||
pwm_conf[dev].dev->CRA &= ~bit;
|
|
||||||
gpio_set(pwm_conf[dev].pin_ch[ch]);
|
|
||||||
}
|
|
||||||
else if (value == 0) {
|
|
||||||
pwm_conf[dev].dev->CRA &= ~bit;
|
|
||||||
gpio_clear(pwm_conf[dev].pin_ch[ch]);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pwm_conf[dev].dev->OCR[ch] = value;
|
pwm_conf[dev].dev->OCR[ch] = value;
|
||||||
pwm_conf[dev].dev->CRA |= bit;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,8 +174,8 @@ void pwm_poweron(pwm_t dev)
|
|||||||
else {
|
else {
|
||||||
power_timer0_enable();
|
power_timer0_enable();
|
||||||
}
|
}
|
||||||
pwm_conf[dev].dev->CRA = state[dev].CRA;
|
|
||||||
pwm_conf[dev].dev->CRB = state[dev].CRB;
|
apply_config(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pwm_poweroff(pwm_t dev)
|
void pwm_poweroff(pwm_t dev)
|
||||||
@ -170,7 +183,7 @@ void pwm_poweroff(pwm_t dev)
|
|||||||
assert(dev < PWM_NUMOF);
|
assert(dev < PWM_NUMOF);
|
||||||
pwm_conf[dev].dev->CRA = 0x00;
|
pwm_conf[dev].dev->CRA = 0x00;
|
||||||
pwm_conf[dev].dev->CRB = 0x00;
|
pwm_conf[dev].dev->CRB = 0x00;
|
||||||
/* disable power reduction */
|
/* disable timers to lower power consumption */
|
||||||
if (dev) {
|
if (dev) {
|
||||||
power_timer2_disable();
|
power_timer2_disable();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user