From a16af64fe34410052a668c2e0ee87c9eb6876e43 Mon Sep 17 00:00:00 2001 From: "Jan \"Yenya\" Kasprzak" Date: Tue, 12 Jun 2012 23:20:15 +0200 Subject: [PATCH] PWM + ADC + code cleanups --- lights.c | 272 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 189 insertions(+), 83 deletions(-) diff --git a/lights.c b/lights.c index 6d78e23..635b249 100644 --- a/lights.c +++ b/lights.c @@ -4,8 +4,9 @@ #include #include -uint16_t pwmee EEMEM; volatile uint16_t adcval; +unsigned char pwmval = 0x28; +uint16_t pwmints = 0; volatile struct { @@ -15,46 +16,127 @@ volatile struct } intflags; +static void inline led_on() +{ + DDRB |= _BV( PB5 ); +} + +static void inline led_off() +{ + DDRB &= ~_BV( PB5 ); +} -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 192 +uint16_t log_buffer[LOG_BUFFER] EEMEM; +uint16_t log_buffer_count; + +static void inline init_log() { - TIMSK &= ~_BV(TOIE1); - intflags.pwm_int = 1; + debug_setstate(1); + log_buffer_count = 0; +} + +static void log_word(uint16_t word) { + if (log_buffer_count == LOG_BUFFER) { + debug_setstate(0x42); + log_buffer_count++; + } + if (log_buffer_count >= LOG_BUFFER) + return; + + eeprom_write_word(&log_buffer[log_buffer_count], word); + log_buffer_count++; +} + +/* ------------ Timer ----------- */ + +uint16_t clock = 0; + +static void inline init_tmr() +{ + TCCR0A = _BV(WGM00); + TCCR0B = _BV(CS02) | _BV(CS00); // 1 kHz + OCR0A = 10; // 100 Hz + TIMSK |= _BV(OCIE0A); + DDRA |= _BV( PA0 ); + + clock = 0; +} + +static void inline tmr_handler() +{ + unsigned char c = clock & 0x7F; + ++clock; + + if (c == 10 || c == 30) + led_on(); + + if (c == 20 || c == 40) + led_off(); + + log_word(adcval); + if (adcval != 0xFFEE) { + adcval = 0xFFEE; + + ADCSRA |= _BV(ADIE) | _BV(ADSC); + } } ISR(TIMER0_COMPA_vect) { - intflags.tmr_int = 1; + tmr_handler(); } -struct { - unsigned char intensity :2; - unsigned char length :6; -} pattern[] = { {1, 2}, {0, 4}, { 1, 2 }, {0, 15}, {0, 0} }; - +/* ------------ PWM ----------- */ + static void inline init_pwm() { + /* 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(CS11); - TC1H = 0x03; + // TCCR1B = 0x80| _BV(CS13) | _BV(CS11); + TCCR1B = 0x80 | _BV(CS10); OCR1C = 0xFF; - OCR1D = OCR1B = OCR1A = 0x40; + OCR1D = OCR1B = OCR1A = pwmval; TCNT1 = 0; - DDRB |= _BV( PB5 ) | _BV( PB1 ) | _BV( PB3 ); + DDRB |= _BV( PB5 ); PORTB &= ~(_BV( PB5 ) | _BV( PB1 ) | _BV( PB3 )); - TIMSK |= _BV(TOIE1); + + led_off(); + // TIMSK |= _BV(TOIE1); } +#if 0 +static void inline pwm_handler() +{ + TCNT1 = 0; + OCR1D = pwmval; +} + +ISR(TIMER1_OVF_vect) +{ + TIMSK &= ~_BV(TOIE1); + pwm_handler(); +} +#endif + +/* ------------ A/D Converter ----------- */ + static void inline init_adc() { ADCSRA = _BV(ADEN) | _BV(ADATE) | _BV(ADPS1) | _BV(ADPS0); @@ -63,94 +145,118 @@ static void inline init_adc() DIDR0 = _BV(ADC1D) | _BV(AREFD); } -static void inline init_tmr() +static void inline adc_handler() { - TCCR0A = _BV(WGM00); - TCCR0B = _BV(CS02); // | _BV(CS00); - OCR0A = 0x80; - TIMSK |= _BV(OCIE0A); - DDRA |= _BV( PA0 ); -} + static unsigned char last_pwmval = 0; + static unsigned char counter = 0; + uint16_t tmp = pwmval; + static uint16_t discard = 5; -int main(void) -{ - char seen = 0; - char pcount, ppos; - - init_pwm(); - init_adc(); - init_tmr(); + adcval = ADCW; + ADCSRA &= ~_BV(ADIE); /* disable ADC interrupt */ +#if 0 + if (--discard > 0) + goto out; - ppos = 0; - pcount = pattern[ppos].length; - if (pattern[ppos].intensity) { - PORTA |= _BV( PA0 ); - } + if (adcval > 0x300) + tmp = 3*tmp/4; + else if (adcval > 0x280) + tmp = 7*tmp/8; + else if (adcval > 0x201) + tmp--; + else if (adcval < 0x100) + tmp = 5*tmp/4; + else if (adcval < 0x180) + tmp = 9*tmp/8; + else if (adcval < 0x1ff) + tmp++; - while (1) { - unsigned char pwmhi, pwmlo; + if (tmp > 0xFF) + tmp = 0xFF; + if (tmp == 0) + tmp = 1; - if (intflags.adc_int) { - intflags.adc_int = 0; + counter++; + if ((last_pwmval > tmp && last_pwmval - tmp > 10) + || (last_pwmval < tmp && tmp - last_pwmval > 10) + || (counter > 2)) { + counter = 0; + + if (rv_count < BUFFER-1) { + eeprom_write_word(&readval[rv_count++], adcval); + eeprom_write_word(&readval[rv_count++], pwmval); + if (rv_count >= BUFFER) + eeprom_write_byte(&debug, 42); + } + } - if (adcval > 0x3C0) - adcval = 0x3C0; - if (adcval < 1) - adcval = 1; - pwmhi = adcval >> 8; - pwmlo = adcval & 0xFF; + last_pwmval = pwmval; + pwmval = tmp; - TC1H = pwmhi; - OCR1D = pwmlo; + if (pwmval != last_pwmval) { + TIMSK |= _BV(TOIE1); + + discard = 1000; + } else { + discard = 0; + } - TC1H = pwmhi; - OCR1B = pwmlo; +out: + //TIMSK |= _BV(TOIE1); + ADCSRA |= _BV(ADIE) | _BV(ADSC); +#endif +} - TC1H = pwmhi; - OCR1A = pwmlo; +ISR(ADC_vect) +{ + adc_handler(); +} - TIMSK |= _BV(TOIE1); +#if 0 + if (--pcount == 0) { + ppos++; + pcount = pattern[ppos].length; + if (!pcount) { + ppos = 0; + pcount = pattern[ppos].length; } - - if (intflags.pwm_int) { - intflags.pwm_int = 0; - ADCSRA |= _BV(ADIE) | _BV(ADSC); + if (pattern[ppos].intensity) { + PORTA |= _BV(PA0); + } else { + PORTA &= ~_BV(PA0); } + } +#endif - if (intflags.tmr_int) { - intflags.tmr_int = 0; - if (--pcount == 0) { - ppos++; - pcount = pattern[ppos].length; - if (!pcount) { - ppos = 0; - pcount = pattern[ppos].length; - } - if (pattern[ppos].intensity) { - PORTA |= _BV(PA0); - } else { - PORTA &= ~_BV(PA0); - } - } - } +int main(void) +{ + char seen = 0; + char pcount, ppos; + unsigned char adcidx = 0; + uint16_t adcvals[16]; - sei(); - sleep_mode(); - cli(); + init_log(); + init_pwm(); + init_adc(); + init_tmr(); + + debug_setstate(2); + + sei(); + while (1) + ; //sleep_mode(); #if 0 if (!seen) { seen = 1; eeprom_write_byte(&debug, 2); } #endif - } DDRA |= _BV( PA0 ); while( 1 ) { PORTA |= _BV( PA0 ); - _delay_ms(2000); + _delay_ms(200); PORTA &=~ _BV( PA0 ); - _delay_ms(2000); } } -- 2.39.3