X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;f=lights.c;h=78bd2e1b2198427f3ebc62aabcbfc9335a89fd4e;hb=88f407272caa26d8c63fded44d38d26972c11300;hp=653e8d4f7e7b3dcd1e550120f637652b7d82f2e4;hpb=b1355d3cdba26fe18c5a69fc6d94c93478559788;p=bike-lights.git diff --git a/lights.c b/lights.c index 653e8d4..78bd2e1 100644 --- a/lights.c +++ b/lights.c @@ -4,57 +4,253 @@ #include #include -uint16_t pwmee EEMEM; +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; -int main(void) +volatile struct +{ + uint8_t pwm_int: 1; + uint8_t adc_int: 1; + uint8_t tmr_int: 1; +} +intflags; + +static void inline led_on() +{ + DDRB |= _BV( PB5 ); + led_is_on = 1; +} + +static void inline led_off() +{ + led_is_on = 0; + DDRB &= ~_BV( PB5 ); +// ADCSRA &= ~(_BV(ADIE) | _BV(ADIF)); +} + +/* ------------ Logging/Debugging ----------- */ + +unsigned char debug_state EEMEM; + +static void inline debug_setstate(unsigned char val) +{ + eeprom_write_byte(&debug_state, val); +} + +#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() +{ + debug_setstate(1); + log_buffer_count = 0; +} + +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 clock = 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 ); + + clock = 0; +} + +static void inline tmr_handler() +{ + unsigned char c = clock & 0x1F; + unsigned char c1 = clock & 0xFF; + + ++clock; +#if 0 + if (c == 10 || c == 30) + led_on(); + + if (c == 20 || c == 40) + 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; + } + } + 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(PWM1A) | _BV(PWM1B); - TCCR1B = 0x80| _BV(CS13) | _BV(CS11); - TC1H = 0x03; - OCR1C = 0xFF; - OCR1D = 0x20; - TCNT1 = 0; - DDRB |= _BV( PB5 ); - PORTB &= ~_BV( PB5 ); - - ADCSRA = _BV(ADEN) | _BV(ADATE) | _BV(ADPS1) | _BV(ADPS0); - ADMUX = _BV(REFS1) | _BV(MUX0); + TCCR1A = _BV(COM1A0) | _BV(COM1A1) | _BV(COM1B0) | _BV(COM1B1) | _BV(PWM1A) | _BV(PWM1B); + // 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 = pwmval; + // OCR1D = 0; + // DDRB |= _BV( PB5 ); + PORTB &= ~(_BV( PB5 ) | _BV( PB1 ) | _BV( PB3 )); + + // 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); +} - while (1) { - uint16_t pwm; - unsigned char pwmhi, pwmlo; +static void inline adc_handler() +{ + uint16_t new_pwm = pwmval; + uint16_t old_pwm = pwmval; + uint16_t old_adc = adcval; + adcval = ADCW; + adccount++; - ADCSRA |= _BV(ADSC); + // log_word(((adcval & 0x3FC) << 6) | pwmval); + log_word(((adcval & 0xFF) << 8) | pwmval); - _delay_ms(100); + if (!led_is_on) + return; + // adcval = (adcval + 3*old_adc)/4; - pwm = ADCW; - if (!seen) { - seen = 1; - eeprom_write_word(&pwmee, pwm); - } - if (pwm > 0x3C0) - pwm = 0x3C0; - if (pwm < 1) - pwm = 1; - pwmhi = pwm >> 8; - pwmlo = pwm & 0xFF; - - TC1H = pwmhi; - OCR1D = pwmlo; + // 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; } - sleep_mode(); + new_pwm = (3*old_pwm + new_pwm) / 4; + if (new_pwm > 0x60) { // odpojeno? + new_pwm = 0x60; + } + if (new_pwm < 2) { // zkrat? + new_pwm = 2; + } + + // if (new_pwm < 15*old_pwm/16 || new_pwm > 17*old_pwm/16) { + pwmval = new_pwm; + OCR1D = pwmval; + // } + // ADCSRA |= _BV(ADSC); +} + +ISR(ADC_vect) +{ + adc_handler(); +} + +int main(void) +{ + init_log(); + + init_pwm(); + init_adc(); + init_tmr(); + + debug_setstate(2); + + sei(); + while (1) + ;// sleep_mode(); + +#if 0 DDRA |= _BV( PA0 ); while( 1 ) { PORTA |= _BV( PA0 ); - _delay_ms(2000); + _delay_ms(200); PORTA &=~ _BV( PA0 ); - _delay_ms(2000); } +#endif }