some fixes for PWM, but the resolution in the lower end still sucks.
authorsimimeie <simimeie>
Sun, 8 Aug 2010 17:06:11 +0000 (17:06 +0000)
committersimimeie <simimeie>
Sun, 8 Aug 2010 17:06:11 +0000 (17:06 +0000)
will try something completely different next.

ledpwm.c

index d4aa5e298c46edb4c2752ff74aad95f53e0e267d..dc8b7bddf5e894308dd4c061d72a5139271861d3 100644 (file)
--- 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();
 }
This page took 0.097503 seconds and 4 git commands to generate.