b15f/firmware/pwm.cpp

40 lines
955 B
C++
Raw Normal View History

2019-05-28 09:12:58 +00:00
#include "pwm.h"
2019-05-28 10:32:31 +00:00
const uint16_t PWM::PRESCALERS[] = {0, 1, 8, 64, 256, 1024};
const uint8_t PWM::PRESCALER_COUNT = sizeof(PRESCALERS) / sizeof(uint16_t);
2019-05-28 09:12:58 +00:00
2019-05-28 10:32:31 +00:00
void PWM::init() const volatile
2019-05-28 09:12:58 +00:00
{
2019-05-28 10:32:31 +00:00
// fast pwm mode, top = OCR0A, non inverting mode
2019-12-03 06:41:20 +00:00
TCCR0A = _BV(WGM00) | _BV(WGM01);
TCCR0B = _BV(WGM02);
2019-05-28 09:12:58 +00:00
2019-05-28 10:32:31 +00:00
// output signal on PB4
DDRB |= _BV(PB4);
}
void PWM::setFrequency(uint32_t freq) const volatile
{
2019-05-28 09:12:58 +00:00
uint16_t p_ideal = ceil(float(F_CPU) / (freq * 0x100));
2019-05-28 10:32:31 +00:00
for(int8_t i = PRESCALER_COUNT - 1; i >= 0 && PRESCALERS[i] >= p_ideal; i--)
TCCR0B = (TCCR0B & 0xF8) | i; // set prescaler
2019-05-28 09:12:58 +00:00
if(p_ideal)
2019-05-28 10:32:31 +00:00
OCR0A = (uint8_t) (float(F_CPU) / (freq * PRESCALERS[TCCR0B & 0x07]));
2019-05-28 09:12:58 +00:00
}
2019-05-28 10:32:31 +00:00
void PWM::setValue(uint8_t value) const volatile
2019-05-28 09:12:58 +00:00
{
2019-12-03 06:41:20 +00:00
if(value)
{
OCR0B = value;
TCCR0A |= _BV(COM0B1);
} else
{
TCCR0A &= ~_BV(COM0B1);
}
2019-05-28 09:12:58 +00:00
}
2019-05-28 10:32:31 +00:00
uint8_t PWM::getTop() const volatile
{
return OCR0A;
}