-/* $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).
*/
* 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;
/* 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();
}
* 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();
}