]> www.fi.muni.cz Git - bike-lights.git/commitdiff
multi-mode light
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Thu, 23 Aug 2012 08:54:50 +0000 (10:54 +0200)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Thu, 23 Aug 2012 08:55:06 +0000 (10:55 +0200)
lights.c

index 78bd2e1b2198427f3ebc62aabcbfc9335a89fd4e..d05fa1cf45c06f17b19306624cabd99ead2c004b 100644 (file)
--- a/lights.c
+++ b/lights.c
@@ -5,22 +5,25 @@
 #include <avr/interrupt.h>
 
 volatile uint16_t adcval;
-unsigned char pwmval = 0x10;
-volatile uint16_t adc_exp = 0x10;
 unsigned char led_is_on = 0;
 volatile unsigned char adccount = 0;
 
-volatile struct
-{
-  uint8_t pwm_int: 1;
-  uint8_t adc_int: 1;
-  uint8_t tmr_int: 1;
-}
-intflags;
+typedef struct {
+       unsigned char pwmval, expected;
+} led_level_t;
+
+led_level_t led_modes[2] = {
+       { 0x50, 0x38 },
+       { 0x38, 0x04 },
+};
+
+unsigned char led_mode = 0;
+unsigned char led_mode_changed = 0;
 
 static void inline led_on()
 {
         DDRB |= _BV( PB5 );
+       PORTA |=  _BV( PA0 );
        led_is_on = 1;
 }
 
@@ -28,6 +31,7 @@ static void inline led_off()
 {
        led_is_on = 0;
         DDRB &= ~_BV( PB5 );
+       PORTA &=~  _BV( PA0 );
 //        ADCSRA &= ~(_BV(ADIE) | _BV(ADIF));
 }
 
@@ -72,7 +76,7 @@ static void log_word(uint16_t word) {
 
 /* ------------ Timer ----------- */
 
-volatile uint16_t clock = 0;
+volatile uint16_t jiffies = 0;
 
 static void inline init_tmr()
 {
@@ -82,35 +86,42 @@ static void inline init_tmr()
        TIMSK |= _BV(OCIE0A);
        DDRA |= _BV( PA0 );
 
-       clock = 0;
+       jiffies = 0;
 }
 
 static void inline tmr_handler()
 {
-       unsigned char c = clock & 0x1F;
-       unsigned char c1 = clock & 0xFF;
+       unsigned char c = jiffies & 0x0F;
+       unsigned char c1 = jiffies & 0x7F;
+
+       ++jiffies;
 
-       ++clock;
 #if 0
-       if (c == 10 || c == 30) 
+       if (c == 1)
                led_on();
 
-       if (c == 20 || c == 40)
+       if (c == 9)
                led_off();
 #endif
 
        if (c == 0x02 || c == 0x08)
                led_on();
+               
        if (c == 0x05 || c == 0x0b)
                led_off();
 
-       if ((clock & 0x7F) == 0x1F) {
-               if (c1 < 0x80) {
-                       adc_exp = 0x80;
-               } else {
-                       adc_exp = 0x20;
-               }
+#if 1
+       if (c1 == 0x10) {
+               led_mode = 0;
+               led_mode_changed = 1;
+               OCR1D = led_modes[led_mode].pwmval;
+       } else if (c1 == 0x70) {
+               led_mode = 1;
+               led_mode_changed = 1;
+               OCR1D = led_modes[led_mode].pwmval;
        }
+#endif
+
        ADCSRA |= _BV(ADSC);
 #if 0
        if (led_is_on && adcval != 0xFFEE) {
@@ -144,9 +155,9 @@ static void inline init_pwm()
                | _BV(CS10)                     // no clock prescaling
                ;
        OCR1C = 0xFF;                           // TOP value
-       OCR1D = OCR1B = OCR1A = pwmval;
+       OCR1D = OCR1B = OCR1A = 0;
        // OCR1D = 0;
-       // DDRB |= _BV( PB5 );
+       DDRB |= _BV( PB5 );
        PORTB &= ~(_BV( PB5 ) | _BV( PB1 ) | _BV( PB3 ));
 
        // led_off();
@@ -186,32 +197,35 @@ static void inline init_adc()
 
 static void inline adc_handler()
 {
-       uint16_t new_pwm = pwmval;
-       uint16_t old_pwm = pwmval;
-       uint16_t old_adc = adcval;
+       uint16_t new_pwm = led_modes[led_mode].pwmval;
+       uint16_t old_pwm = new_pwm;
+       uint16_t adc_exp = led_modes[led_mode].expected;
+
        adcval = ADCW;
        adccount++;
 
        // log_word(((adcval & 0x3FC) << 6) | pwmval);
-       log_word(((adcval & 0xFF) << 8) | pwmval);
 
        if (!led_is_on)
                return;
-       // adcval = (adcval + 3*old_adc)/4;
 
        // ADCSRA &= ~(_BV(ADIE) | _BV(ADIF));
 
-       if (adcval < 1) {
-               adcval = 1;
-       } else if (adcval > adc_exp) {
-               new_pwm = old_pwm*adc_exp/adcval;
-       } else if (adcval < adc_exp && 2 * adcval > adc_exp) {
-               new_pwm = old_pwm*adc_exp/adcval;
-       } else if (adcval < adc_exp) {
-               new_pwm = 2 * old_pwm;
+       if (led_mode_changed) {
+               led_mode_changed = 0;
+               goto set_pwm;
+       }
+
+       log_word(((adcval & 0xFF) << 8) | old_pwm);
+
+       if (2*adcval > 5*adc_exp) { // >2.5x expected, lower significantly
+               new_pwm = 2*old_pwm/3;
+       } else if (3*adcval > 4*adc_exp) { // >1.33x expected, lower a bit
+               new_pwm = old_pwm - 1;
+       } else if (4*adcval < 3*adc_exp) { // 0.75x expected, raise a bit
+               new_pwm = old_pwm + 1;
        }
 
-       new_pwm = (3*old_pwm + new_pwm) / 4;
        if (new_pwm > 0x60) { // odpojeno?
                new_pwm = 0x60;
        }
@@ -219,10 +233,11 @@ static void inline adc_handler()
                new_pwm = 2;
        }
 
-       // if (new_pwm < 15*old_pwm/16 || new_pwm > 17*old_pwm/16) {
-               pwmval = new_pwm;
-               OCR1D = pwmval;
-       // }
+set_pwm:
+       if (new_pwm != old_pwm) {
+               led_modes[led_mode].pwmval = new_pwm;
+               OCR1D = new_pwm;
+       }
        // ADCSRA |= _BV(ADSC);
 }
 
@@ -233,24 +248,26 @@ ISR(ADC_vect)
 
 int main(void)
 {
+       _delay_ms(1500);
        init_log();
 
        init_pwm();
        init_adc();
        init_tmr();
 
-       debug_setstate(2);
+       led_on();
+       debug_setstate(3);
 
        sei();
        while (1)
-               ;// sleep_mode();
+               ; // sleep_mode();
 
 #if 0
-    DDRA |= _BV( PA0 );
-    while( 1 ) { 
-        PORTA |=  _BV( PA0 );
-        _delay_ms(200);
-        PORTA &=~ _BV( PA0 );
-    }
+       while (1) {
+               PORTA |=  _BV( PA0 );
+               _delay_ms(200);
+               PORTA &=~ _BV( PA0 );
+               _delay_ms(200);
+       }
 #endif
 }