#include "twi.h" #include "ssd1306.h" #include "sevenseg.h" #include "adc.h" #include "iopins.h" #include const uint16_t adc_target16_acceptable = 900; const uint16_t adc_target16 = 972; //const uint8_t adc_target8 = 243; static bool g_pwm_on = false; static volatile uint16_t tick_counter = 0; static volatile bool tick_counter_changed = false; // Tick ISR(INT0_vect) { tick_counter++; tick_counter_changed = true; } static void init_isr() { as_input(D2); // using INT0 - arduino pin D2 EICRA = _BV(ISC01) | _BV(ISC00); // rising edge EIMSK = _BV(INT0); } static void init_pwm_out() { // Output is OC0A as_output(D5); // initialize the timer // Fast PWM mode, Output to OC0A // clock is 16MHz, presc /64, counting to 80 -> freq 3125Hz // Duty cycle = appx. 60% OCR0A = 80; OCR0B = 46; TCCR0A = _BV(WGM00) | _BV(WGM01); TCCR0B = _BV(CS01) | _BV(CS00) | _BV(WGM02); } static void pwm_on() { TCCR0A |= _BV(COM0B1); g_pwm_on = true; } static void pwm_off() { TCCR0A &= ~_BV(COM0B1); g_pwm_on = false; } void main() { TWI_Init(); adc_init(); init_pwm_out(); ssd1306_128x32_i2c_init(); ssd1306_clearScreen(); struct SevenSeg sseg = { .x0 = 0, .y0 = 0, .charwidth = 17, .thick = 3, //.charwidth = 16, //.thick = 1, .spacing = 4, }; init_isr(); sei(); // TODO show loading icon sseg_number(&sseg, 0, 5, 0); // request ADC meas adc_async_start_measure_word(0); // uint16_t cnt = 0; uint16_t analog; uint16_t count_boost_fail = 0; for (;;) { if (adc_async_ready()) { analog = adc_async_get_result_word(); adc_async_start_measure_word(0); bool good_voltage = analog >= adc_target16; if (g_pwm_on) { if (good_voltage) { pwm_off(); count_boost_fail = 0; } else { count_boost_fail++; } } else if (!good_voltage) { pwm_on(); } // If fail to reach target voltage in reasonable time, // show weak battery icon and stop trying. if (count_boost_fail > 50000 && analog < adc_target16_acceptable) { // TODO weak battery icon sseg_number(&sseg, 9999, 5, 0); pwm_off(); for(;;) {} } // TODO synchronization? if (tick_counter_changed) { tick_counter_changed = false; sseg_number(&sseg, tick_counter, 5, 0); } // if (++cnt > 10000) { // sseg_number(&sseg, analog, 5, 0); // cnt = 0; // } } } }