#include "lights.h"
+#define PWM_MAX 0x1FF
+
void init_pwm()
{
/* Async clock */
;
PLLCSR |= _BV(PCKE);
- TCCR1C = _BV(COM1D0) | _BV(COM1D1) | _BV(PWM1D);
- TCCR1A = _BV(COM1A0) | _BV(COM1A1) | _BV(COM1B0) | _BV(COM1B1) | _BV(PWM1A) | _BV(PWM1B);
- TCCR1B = _BV(7) // PWM1X: PWM inversion mode
- | _BV(CS10) // no clock prescaling
- ;
- TC1H = 0x01;
- OCR1C = 0xFF; // TOP value
+ // PWM channel D is inverted, ...
+ TCCR1C = _BV(COM1D1) | _BV(COM1D0) | _BV(PWM1D);
+ // PWM channels A and B are not
+ TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(PWM1A) | _BV(PWM1B);
+ TCCR1D = 0;
+ TCCR1B = _BV(CS10); // no clock prescaling
+ TC1H = PWM_MAX >> 8;
+ OCR1C = PWM_MAX & 0xFF; // TOP value
+
+ TC1H = PWM_MAX >> 8;
+ OCR1D = PWM_MAX & 0xFF;
TC1H = 0x00;
- OCR1D = OCR1B = OCR1A = 0; // initial stride is 0
+ OCR1B = OCR1A = 0; // initial stride is 0
DDRB &= ~(_BV( PB1 ) | _BV( PB3 ) | _BV( PB5 )); // tristate it
PORTB &= ~(_BV( PB1 ) | _BV( PB3 ) | _BV( PB5 )); // set to zero
switch (n) {
case 0: OCR1A = stride; break;
case 1: OCR1B = stride; break;
- case 2: OCR1D = stride; break;
+ case 2: {
+ uint16_t s16 = PWM_MAX - (uint16_t)stride;
+ volatile unsigned char hi, lo;
+ hi = s16 >> 8;
+ lo = s16 & 0xFF;
+ TC1H = hi;
+ OCR1D = lo;
+ }
+ break;
}
}