2 #include <util/delay.h>
9 void battery_init(void)
12 battery_led(LED_ON); _delay_ms(500);
13 battery_led(LED_OFF); _delay_ms(500);
14 battery_led(LED_ON); _delay_ms(500);
15 battery_led(LED_OFF); _delay_ms(500);
16 // LED indicates charger status
17 battery_led(LED_CHARGER);
19 // ADC setting for voltage monitor
20 // Ref:2.56V band-gap, Input:ADC0(PF0), Prescale:128(16MHz/128=125KHz)
21 ADMUX = (1<<REFS1) | (1<<REFS0);
22 ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);
26 // Indicator for battery
27 void battery_led(battery_led_t val)
29 if (val == LED_TOGGLE) {
33 } else if (val == LED_ON) {
34 // On overriding charger status
37 } else if (val == LED_OFF) {
38 // Off overriding charger status
42 // Display charger status
48 bool battery_charging(void)
50 if (!(USBSTA&(1<<VBUS))) return false;
53 // MCP73831 MCP73832 LTC4054 Status
54 // Hi-Z Hi-Z Hi-Z Shutdown/No Battery
55 // Low Low Low Charging
56 // Hi Hi-Z Hi-Z Charged
58 // preserve last register status
59 uint8_t ddrf_prev = DDRF;
60 uint8_t portf_prev = PORTF;
66 bool charging = PINF&(1<<5) ? false : true;
68 // restore last register status
69 DDRF = (DDRF&~(1<<5)) | (ddrf_prev&(1<<5));
70 PORTF = (PORTF&~(1<<5)) | (portf_prev&(1<<5));
72 // TODO: With MCP73831 this can not get stable status when charging.
73 // LED is powered from PSEL line(USB or Lipo)
74 // due to weak low output of STAT pin?
75 // due to pull-up'd via resitor and LED?
79 // Returns voltage in mV
80 uint16_t battery_voltage(void)
82 volatile uint16_t bat;
83 //ADCSRA |= (1<<ADEN);
85 // discard first result
87 while (ADCSRA & (1<<ADSC)) ;
90 // discard second result
92 while (ADCSRA & (1<<ADSC)) ;
96 while (ADCSRA & (1<<ADSC)) ;
99 //ADCSRA &= ~(1<<ADEN);
101 return (bat - BATTERY_ADC_OFFSET) * BATTERY_ADC_RESOLUTION;
104 static bool low_voltage(void) {
105 static bool low = false;
106 uint16_t v = battery_voltage();
107 if (v < BATTERY_VOLTAGE_LOW_LIMIT) {
109 } else if (v > BATTERY_VOLTAGE_LOW_RECOVERY) {
115 battery_status_t battery_status(void)
117 if (USBSTA&(1<<VBUS)) {
119 return battery_charging() ? CHARGING : FULL_CHARGED;
122 return low_voltage() ? LOW_VOLTAGE : DISCHARGING;