#include #include "batmon.h" #include "systick.h" static uint8_t vbat = 0; void batmon_init() { TCCR0A = 0; TCCR0B = (1 << CS02); TIMSK0 = (1 << TOIE0); ADCSRA = (1 << ADPS2) | (1 << ADPS1); // 125 kHz ADC clock ADMUX = ADC_CHANNEL | (1 << REFS0) | (1 << REFS1) | (1 << ADLAR); // Internal 1.2V bandgap, left adj. ADCSRB = 0; #if ADC_CHANNEL < 7 DIDR0 = (1 << ADC_CHANNEL); // Disconnect digital channel #endif // Enable voltage divider PORT_ADCC(DDR) |= PIN_ADCC; PORT_ADCC(PORT) &= ~PIN_ADCC; // Enable ADC ADCSRA |= (1 << ADEN); ADCSRA |= (1 << ADSC); // Configure charging indicator pin PORT_CHI(DDR) &= ~(1 << PIN_CHI); PORT_CHI(PORT) &= ~(1 << PIN_CHI); } uint8_t batmon_proc() { static uint16_t sum = 0; static uint8_t cnt = 0; if (ADCSRA & (1 << ADIF)) { sum += ADCH; if (!(++cnt)) { vbat = sum >> 8; sum = 0; if (vbat < BAT_THRES_POWER_OFF) return 1; } ADCSRA &= ~(1 << ADIF); ADCSRA |= (1 << ADSC); // TODO: I want this to work off TIMER0 } return 0; } inline uint8_t batmon_get_voltage() { return vbat; } static uint8_t batmon_get_voltage_sync() { uint16_t sum = 0; uint8_t cnt = 255; ADCSRA |= (1 << ADSC); do { if (ADCSRA & (1 << ADIF)) { sum += ADCH; ADCSRA &= ~(1 << ADIF); ADCSRA |= (1 << ADSC); cnt--; } } while (cnt); return (sum >> 8); } // Note: Call batmon_init() after using this function before using batmon_proc() again inline uint8_t batmon_ok_to_boot() { return (batmon_get_voltage_sync() > BAT_THRES_POWER_ON); } inline uint8_t batmon_is_charging() { return !(PORT_CHI(PIN) & PIN_CHI); }