From: simimeie Date: Sun, 8 Aug 2010 17:06:11 +0000 (+0000) Subject: some fixes for PWM, but the resolution in the lower end still sucks. X-Git-Url: http://git.rrze.uni-erlangen.de/gitweb/?p=moodlight.git;a=commitdiff_plain;h=6c58993de6a9677e0503810e2481f0ecf97e6640 some fixes for PWM, but the resolution in the lower end still sucks. will try something completely different next. --- diff --git a/ledpwm.c b/ledpwm.c index d4aa5e2..dc8b7bd 100644 --- a/ledpwm.c +++ b/ledpwm.c @@ -1,4 +1,4 @@ -/* $Id: ledpwm.c,v 1.4 2010/07/25 20:40:44 simimeie Exp $ +/* $Id: ledpwm.c,v 1.5 2010/08/08 17:06:11 simimeie Exp $ * Functions for led brightness control via PWM (pulse width modulation). */ @@ -33,12 +33,22 @@ volatile uint16_t ledpwm_curoreg = 0; * For a 16-bit read, the low byte must be read before the high byte */ static void ledpwm_programnextstep(void) { uint16_t nextval = 0xffff; + uint16_t tmp1 = ledpwm_curoreg; /* Copy so the compiler can place it into + * a register despite the volatile. */ uint8_t i; for (i = 0; i < 3; i++) { - if ((ledpwm_val[i] > ledpwm_curoreg) && (ledpwm_val[i] <= nextval)) { + if ((ledpwm_val[i] > tmp1) && (ledpwm_val[i] <= nextval)) { nextval = ledpwm_val[i]; } } + /* tmp1 now reused */ + tmp1 = TCNT1L; + tmp1 |= (uint16_t)TCNT1H << 8; + if ((tmp1 + 30) > nextval) { /* 30 cycles is more or less a guess. + * This needs to be set to the number of cycles the code takes from + * here until the iret. */ + nextval = tmp1 + 30; + } OCR1AH = nextval >> 8; OCR1AL = nextval & 0xff; ledpwm_curoreg = nextval; @@ -64,15 +74,17 @@ void ledpwm_TIMER1OVF_hook(void) { /* Called on compare match */ ISR(TIMER1_COMPA_vect) { - if (ledpwm_val[LEDPWM_REDLED] <= ledpwm_curoreg) { - LEDPORT &= (uint8_t)~_BV(LEDPINR); + uint8_t orval = 0x00; + if (ledpwm_val[LEDPWM_REDLED] > ledpwm_curoreg) { + orval |= _BV(LEDPINR); } - if (ledpwm_val[LEDPWM_GREENLED] <= ledpwm_curoreg) { - LEDPORT &= (uint8_t)~_BV(LEDPING); + if (ledpwm_val[LEDPWM_GREENLED] > ledpwm_curoreg) { + orval |= _BV(LEDPING); } - if (ledpwm_val[LEDPWM_BLUELED] <= ledpwm_curoreg) { - LEDPORT &= (uint8_t)~_BV(LEDPINB); + if (ledpwm_val[LEDPWM_BLUELED] > ledpwm_curoreg) { + orval |= _BV(LEDPINB); } + LEDPORT = (LEDPORT & (uint8_t)~(_BV(LEDPINR) | _BV(LEDPING) | _BV(LEDPINB))) | orval; ledpwm_programnextstep(); } @@ -83,18 +95,15 @@ void ledpwm_init(void) { * timers.c already does that. */ /* Enable TIMER1 output compare interrupt A */ TIMSK1 |= _BV(OCIE1A); - ledpwm_programnextstep(); } void ledpwm_setled(uint8_t led, uint16_t val) { if (led > 2) { return; /* ignore invalid values */ } ledpwm_val[led] = val; - ledpwm_programnextstep(); } void ledpwm_set(uint8_t red, uint8_t green, uint8_t blue, uint8_t br) { ledpwm_val[LEDPWM_REDLED] = red * br; ledpwm_val[LEDPWM_GREENLED] = green * br; ledpwm_val[LEDPWM_BLUELED] = blue * br; - ledpwm_programnextstep(); }