]> www.fi.muni.cz Git - bike-lights.git/blobdiff - lights.c
pins.txt: pin-out modifications
[bike-lights.git] / lights.c
index aa018d977d61d8156b43e3f64e29a837d388b8b7..d05fa1cf45c06f17b19306624cabd99ead2c004b 100644 (file)
--- a/lights.c
+++ b/lights.c
 #include <avr/sleep.h>
 #include <avr/interrupt.h>
 
-uint16_t pwmee EEMEM;
 volatile uint16_t adcval;
+unsigned char led_is_on = 0;
+volatile unsigned char adccount = 0;
 
-volatile struct
+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()
 {
-  uint8_t tmr_int: 1;
-  uint8_t adc_int: 1;
-  uint8_t rx_int: 1;
+        DDRB |= _BV( PB5 );
+       PORTA |=  _BV( PA0 );
+       led_is_on = 1;
 }
-intflags;
 
+static void inline led_off()
+{
+       led_is_on = 0;
+        DDRB &= ~_BV( PB5 );
+       PORTA &=~  _BV( PA0 );
+//        ADCSRA &= ~(_BV(ADIE) | _BV(ADIF));
+}
 
-unsigned char debug EEMEM = 1;
+/* ------------ Logging/Debugging ----------- */
 
-ISR(ADC_vect)
+unsigned char debug_state EEMEM;
+
+static void inline debug_setstate(unsigned char val)
 {
-       adcval = ADCW;
-       ADCSRA &= ~_BV(ADIE);         /* disable ADC interrupt */
-       intflags.adc_int = 1;
+       eeprom_write_byte(&debug_state, val);
 }
 
-ISR(TIMER1_OVF_vect)
+#define LOG_BUFFER 64
+uint16_t log_buffer[LOG_BUFFER] EEMEM;
+unsigned char log_buffer_count;
+uint16_t log_buffer2[LOG_BUFFER];
+volatile unsigned char stop = 0;
+
+static void inline init_log()
 {
-       TIMSK &= ~_BV(TOIE1);
-       intflags.tmr_int = 1;
+       debug_setstate(1);
+       log_buffer_count = 0;
 }
 
-int main(void)
+static void log_word(uint16_t word) {
+       if (log_buffer_count >= LOG_BUFFER)
+               return;
+       
+       // eeprom_write_word(&log_buffer[log_buffer_count], word);
+       log_buffer2[log_buffer_count] = word;
+       log_buffer_count++;
+
+       if (log_buffer_count == LOG_BUFFER) {
+               unsigned char i;
+               for (i=0; i < LOG_BUFFER; i++) {
+                       eeprom_write_word(&log_buffer[i],
+                               log_buffer2[i]);
+               }
+               debug_setstate(0x42);
+       }
+}
+
+/* ------------ Timer ----------- */
+
+volatile uint16_t jiffies = 0;
+
+static void inline init_tmr()
+{
+       TCCR0A = _BV(WGM00);
+       TCCR0B = _BV(CS02) | _BV(CS00); // 1 kHz
+       OCR0A = 12; // 100 Hz
+       TIMSK |= _BV(OCIE0A);
+       DDRA |= _BV( PA0 );
+
+       jiffies = 0;
+}
+
+static void inline tmr_handler()
+{
+       unsigned char c = jiffies & 0x0F;
+       unsigned char c1 = jiffies & 0x7F;
+
+       ++jiffies;
+
+#if 0
+       if (c == 1)
+               led_on();
+
+       if (c == 9)
+               led_off();
+#endif
+
+       if (c == 0x02 || c == 0x08)
+               led_on();
+               
+       if (c == 0x05 || c == 0x0b)
+               led_off();
+
+#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) {
+               adcval = 0xFFEE;
+
+               ADCSRA |= _BV(ADIF) | _BV(ADIE) | _BV(ADSC);
+       }
+#endif
+}
+
+ISR(TIMER0_COMPA_vect)
+{
+       tmr_handler();
+}
+
+/* ------------ PWM ----------- */
+
+static void inline init_pwm()
 {
-       char seen = 0;
+       /* Async clock */
+       PLLCSR = _BV(LSM) | _BV(PLLE);
+       _delay_ms(1);
+       while (PLLCSR & _BV(PLOCK) == 0)
+               ;
+       PLLCSR |= _BV(PCKE);
 
        TCCR1C = _BV(COM1D0) | _BV(COM1D1) | _BV(PWM1D);
        TCCR1A = _BV(COM1A0) | _BV(COM1A1) | _BV(COM1B0) | _BV(COM1B1) | _BV(PWM1A) | _BV(PWM1B);
-       TCCR1B = 0x80| _BV(CS13) | _BV(CS10);
-       TC1H  = 0x03;
-       OCR1C = 0xFF;
-       OCR1D = OCR1B = OCR1A = 0x40;
-       TCNT1 = 0;
-       DDRB |= _BV( PB5 ) | _BV( PB1 ) | _BV( PB3 );
+       // TCCR1B = 0x80| _BV(CS13) | _BV(CS11);
+       TCCR1B = _BV(7)                         // PWM1X: PWM inversion mode
+               | _BV(CS10)                     // no clock prescaling
+               ;
+       OCR1C = 0xFF;                           // TOP value
+       OCR1D = OCR1B = OCR1A = 0;
+       // OCR1D = 0;
+       DDRB |= _BV( PB5 );
        PORTB &= ~(_BV( PB5 ) | _BV( PB1 ) | _BV( PB3 ));
-       TIMSK = _BV(TOIE1);
 
-       ADCSRA = _BV(ADEN) | _BV(ADATE) | _BV(ADPS1) | _BV(ADPS0);
-       ADMUX = _BV(REFS1) | _BV(MUX0);
+       // led_off();
+       // TIMSK |= _BV(TOIE1);
+}
+
+#if 0
+static void inline pwm_handler()
+{
+       // TIMSK &= ~_BV(TOIE1);
+       // OCR1D = pwmval;
+}
+
+ISR(TIMER1_OVF_vect)
+{
+       pwm_handler();
+}
+#endif
+
+/* ------------ A/D Converter ----------- */
+
+static void inline init_adc()
+{
+       ADCSRA = _BV(ADEN)                      // enable
+               | _BV(ADPS1) | _BV(ADPS0)       // CLK/8 = 125 kHz
+               // | _BV(ADPS2)                 // CLK/16 = 62.5 kHz
+               ;
+       ADMUX = _BV(REFS1)                      // 1.1V internal reference
+               | _BV(MUX4)|_BV(MUX3)   // port ADC5-6, gain 1
+               ;
        // ADCSRB = _BV(REFS2); 
-       DIDR0 = _BV(ADC1D) | _BV(AREFD);
+       ADCSRB |= _BV(GSEL); 
+       // Disable digital input on all bits used by ADC
+       DIDR0 = _BV(ADC5D)|_BV(ADC6D) | _BV(AREFD);
+       ADCSRA |= _BV(ADIE);
+}
 
-       sei();
-       while (1) {
-               unsigned char pwmhi, pwmlo;
+static void inline adc_handler()
+{
+       uint16_t new_pwm = led_modes[led_mode].pwmval;
+       uint16_t old_pwm = new_pwm;
+       uint16_t adc_exp = led_modes[led_mode].expected;
 
-               if (intflags.adc_int) {
-                       intflags.adc_int = 0;
+       adcval = ADCW;
+       adccount++;
 
-                       if (adcval > 0x3C0)
-                               adcval = 0x3C0;
-                       if (adcval < 1)
-                               adcval = 1;
-                       pwmhi = adcval >> 8;
-                       pwmlo = adcval & 0xFF;
+       // log_word(((adcval & 0x3FC) << 6) | pwmval);
 
-                       TC1H = pwmhi;
-                       OCR1D = pwmlo;
+       if (!led_is_on)
+               return;
 
-                       TC1H = pwmhi;
-                       OCR1B = pwmlo;
+       // ADCSRA &= ~(_BV(ADIE) | _BV(ADIF));
 
-                       TC1H = pwmhi;
-                       OCR1A = pwmlo;
+       if (led_mode_changed) {
+               led_mode_changed = 0;
+               goto set_pwm;
+       }
 
-                       TIMSK |= _BV(TOIE1);
-               }
+       log_word(((adcval & 0xFF) << 8) | old_pwm);
 
-               if (intflags.tmr_int) {
-                       intflags.tmr_int = 0;
-                       ADCSRA |= _BV(ADIE) | _BV(ADSC);
-               }
+       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;
+       }
 
-               sleep_mode();
+       if (new_pwm > 0x60) { // odpojeno?
+               new_pwm = 0x60;
+       }
+       if (new_pwm < 2) { // zkrat?
+               new_pwm = 2;
+       }
 
-#if 0
-               if (!seen) {
-                       seen = 1;
-                       eeprom_write_byte(&debug, 2);
-               }
-#endif
+set_pwm:
+       if (new_pwm != old_pwm) {
+               led_modes[led_mode].pwmval = new_pwm;
+               OCR1D = new_pwm;
        }
+       // ADCSRA |= _BV(ADSC);
+}
 
-    DDRA |= _BV( PA0 );
-    while( 1 ) { 
-        PORTA |=  _BV( PA0 );
-        _delay_ms(2000);
-        PORTA &=~ _BV( PA0 );
-        _delay_ms(2000);
-    }
+ISR(ADC_vect)
+{
+       adc_handler();
+}
+
+int main(void)
+{
+       _delay_ms(1500);
+       init_log();
+
+       init_pwm();
+       init_adc();
+       init_tmr();
+
+       led_on();
+       debug_setstate(3);
+
+       sei();
+       while (1)
+               ; // sleep_mode();
+
+#if 0
+       while (1) {
+               PORTA |=  _BV( PA0 );
+               _delay_ms(200);
+               PORTA &=~ _BV( PA0 );
+               _delay_ms(200);
+       }
+#endif
 }