#include #include #include #include #include volatile uint16_t adcval; unsigned char pwmval = 0x28; uint16_t pwmints = 0; 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 ); } static void inline led_off() { DDRB &= ~_BV( PB5 ); } /* ------------ Logging/Debugging ----------- */ unsigned char debug_state EEMEM; static void inline debug_setstate(unsigned char val) { eeprom_write_byte(&debug_state, val); } #define LOG_BUFFER 192 uint16_t log_buffer[LOG_BUFFER] EEMEM; uint16_t log_buffer_count; 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) { 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) { tmr_handler(); } /* ------------ 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); TCCR1B = 0x80 | _BV(CS10); OCR1C = 0xFF; OCR1D = OCR1B = OCR1A = pwmval; TCNT1 = 0; DDRB |= _BV( PB5 ); PORTB &= ~(_BV( PB5 ) | _BV( PB1 ) | _BV( PB3 )); 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); ADMUX = _BV(REFS1) | _BV(MUX0); // ADCSRB = _BV(REFS2); DIDR0 = _BV(ADC1D) | _BV(AREFD); } static void inline adc_handler() { static unsigned char last_pwmval = 0; static unsigned char counter = 0; uint16_t tmp = pwmval; static uint16_t discard = 5; adcval = ADCW; ADCSRA &= ~_BV(ADIE); /* disable ADC interrupt */ #if 0 if (--discard > 0) goto out; 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++; if (tmp > 0xFF) tmp = 0xFF; if (tmp == 0) tmp = 1; 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); } } last_pwmval = pwmval; pwmval = tmp; if (pwmval != last_pwmval) { TIMSK |= _BV(TOIE1); discard = 1000; } else { discard = 0; } out: //TIMSK |= _BV(TOIE1); ADCSRA |= _BV(ADIE) | _BV(ADSC); #endif } ISR(ADC_vect) { adc_handler(); } #if 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); } } #endif int main(void) { char seen = 0; char pcount, ppos; unsigned char adcidx = 0; uint16_t adcvals[16]; 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(200); PORTA &=~ _BV( PA0 ); } }