X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=firmware%2Fpwm.c;h=56fb0884e125113a6885a3deb45cba9efe5ad6c8;hb=8650676310d5304199ffe174b45a9a396c9610a7;hp=da9fe3df679b9feb1faede1ed11205773890a824;hpb=64a3d3a699cd60b7a6b4b06c5c38689975a3d460;p=bike-lights.git diff --git a/firmware/pwm.c b/firmware/pwm.c index da9fe3d..56fb088 100644 --- a/firmware/pwm.c +++ b/firmware/pwm.c @@ -1,29 +1,35 @@ #include #include #include +#include #include "lights.h" static uint16_t pwm[N_PWMLEDS]; static volatile unsigned char step; -void init_pwm() +static void enable_pll() { - int i; - - step = 0; - - for (i = 0; i < N_PWMLEDS; i++) - pwm[n] = 0; - /* Async clock */ PLLCSR = _BV(PLLE); /* Synchronize to the phase lock */ - _delay_ms(1); + _delay_us(100); while ((PLLCSR & _BV(PLOCK)) == 0) ; PLLCSR |= _BV(PCKE); +} + +void init_pwm() +{ + int i; + + step = 0; + + for (i = 0; i < N_PWMLEDS; i++) + pwm[i] = 0; + + enable_pll(); // PWM channel D is inverted, ... TCCR1C = _BV(COM1D1) | _BV(COM1D0) | _BV(PWM1D); @@ -56,16 +62,20 @@ void susp_pwm() TCCR1D = TCCR1C = TCCR1B = TCCR1A = 0; TIMSK = 0; TIFR = 0; + + PLLCSR &= ~(_BV(PLLE) | _BV(PCKE)); } void pwm_off(unsigned char n) { - pwm[n] = 0; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { + pwm[n] = 0; - switch (n) { - case 0: DDRB &= ~_BV(PB1); break; - case 1: DDRB &= ~_BV(PB3); break; - case 2: DDRB &= ~_BV(PB5); break; + switch (n) { + case 0: DDRB &= ~_BV(PB1); break; + case 1: DDRB &= ~_BV(PB3); break; + case 2: DDRB &= ~_BV(PB5); break; + } } } @@ -84,17 +94,14 @@ static void pwm_update_hw(unsigned char 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; } } @@ -104,8 +111,17 @@ void pwm_set(unsigned char n, uint16_t stride) if (((stride + (1 << PWM_STEP_SHIFT)) >> PWM_STEP_SHIFT) >= PWM_MAX) stride = PWM_MAX << PWM_STEP_SHIFT; - pwm[n] = stride; - pwm_update_hw(n); + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { + pwm[n] = stride; + + pwm_update_hw(n); + + switch(n) { + case 0: DDRB |= _BV(PB1); break; + case 1: DDRB |= _BV(PB3); break; + case 2: DDRB |= _BV(PB5); break; + } + } } void pwm_timer() @@ -116,22 +132,7 @@ void pwm_timer() step = 0; for (i = 0; i < N_PWMLEDS; i++) - if (pwm[n]) - pwm_update_hw(n); -} - -#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(); + if (pwm[i]) + pwm_update_hw(i); } -#endif