#include #include #include #include "lights.h" void init_pwm() { /* Async clock */ PLLCSR = _BV(PLLE); /* Synchronize to the phase lock */ _delay_ms(1); while ((PLLCSR & _BV(PLOCK)) == 0) ; PLLCSR |= _BV(PCKE); // 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; // PWM3 is inverted OCR1D = PWM_MAX & 0xFF; TC1H = 0x00; 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 } void susp_pwm() { DDRB &= ~(_BV( PB1 ) | _BV( PB3 ) | _BV( PB5 )); TCCR1D = TCCR1C = TCCR1B = TCCR1A = 0; TIMSK = 0; TIFR = 0; } void pwm_off(unsigned char n) { switch (n) { case 0: DDRB &= ~_BV(PB1); break; case 1: DDRB &= ~_BV(PB3); break; case 2: DDRB &= ~_BV(PB5); break; } } void pwm_set(unsigned char n, uint16_t stride) { unsigned char hi, lo; if (stride > PWM_MAX) stride = PWM_MAX; if (n == 2) stride = PWM_MAX - stride; hi = stride >> 8; lo = stride & 0xFF; switch (n) { case 0: TC1H = hi; OCR1A = lo; DDRB |= _BV(PB1); break; case 1: TC1H = hi; OCR1B = lo; DDRB |= _BV(PB3); break; case 2: TC1H = hi; OCR1D = lo; DDRB |= _BV(PB5); break; } } #if 0 static void inline pwm_handler() { OCR1A = pwmval[0]; OCR1B = pwmval[1]; OCR1D = pwmval[2]; TIMSK &= ~_BV(TOIE1); } ISR(TIMER1_OVF_vect) { pwm_handler(); } #endif