]> git.donarmstrong.com Git - tmk_firmware.git/blob - keyboard/hhkb_rn42/rn42/battery.c
32de86448136bca3fd3539631ae87413d0aebe60
[tmk_firmware.git] / keyboard / hhkb_rn42 / rn42 / battery.c
1 #include <avr/io.h>
2 #include <util/delay.h>
3 #include "battery.h"
4
5
6 /*
7  * Battery
8  */
9 void battery_init(void)
10 {
11     // blink 
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);
18
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);
23     ADCSRA |= (1<<ADEN);
24 }
25
26 // Indicator for battery
27 void battery_led(battery_led_t val)
28 {
29     if (val == LED_TOGGLE) {
30         // Toggle LED
31         DDRF  |=  (1<<5);
32         PINF  |=  (1<<5);
33     } else if (val == LED_ON) {
34         // On overriding charger status
35         DDRF  |=  (1<<5);
36         PORTF &= ~(1<<5);
37     } else if (val == LED_OFF) {
38         // Off overriding charger status
39         DDRF  |=  (1<<5);
40         PORTF |=  (1<<5);
41     } else {
42         // Display charger status
43         DDRF  &= ~(1<<5);
44         PORTF &= ~(1<<5);
45     }
46 }
47
48 bool battery_charging(void)
49 {
50     if (!(USBSTA&(1<<VBUS))) return false;
51
52     // MCP73831:STAT
53     //   HiZ:    Shutdown/No Battery
54     //   Low:    Charging
55     //   Hi:     Charged
56
57     // preserve last register status
58     uint8_t ddrf_prev  = DDRF;
59     uint8_t portf_prev = PORTF;
60
61     // Input with pullup
62     DDRF  &= ~(1<<5);
63     PORTF |=  (1<<5);
64     _delay_ms(1);
65     bool charging = PINF&(1<<5) ? false : true;
66
67     // restore last register status
68     DDRF  = (DDRF&~(1<<5))  | (ddrf_prev&(1<<5));
69     PORTF = (PORTF&~(1<<5)) | (portf_prev&(1<<5));
70
71     return charging;
72 }
73
74 // Returns voltage in mV
75 uint16_t battery_voltage(void)
76 {
77     volatile uint16_t bat;
78     //ADCSRA |= (1<<ADEN);
79
80     // discard first result
81     ADCSRA |= (1<<ADSC);
82     while (ADCSRA & (1<<ADSC)) ;
83     bat = ADC;
84
85     // discard second result
86     ADCSRA |= (1<<ADSC);
87     while (ADCSRA & (1<<ADSC)) ;
88     bat = ADC;
89
90     ADCSRA |= (1<<ADSC);
91     while (ADCSRA & (1<<ADSC)) ;
92     bat = ADC;
93
94     //ADCSRA &= ~(1<<ADEN);
95
96     return (bat - BATTERY_ADC_OFFSET) * BATTERY_ADC_RESOLUTION;
97 }
98
99 static bool low_voltage(void) {
100     static bool low = false;
101     uint16_t v = battery_voltage();
102     if (v < BATTERY_VOLTAGE_LOW_LIMIT) {
103         low = true;
104     } else if (v > BATTERY_VOLTAGE_LOW_RECOVERY) {
105         low = false;
106     }
107     return low;
108 }
109
110 battery_status_t battery_status(void)
111 {
112     if (USBSTA&(1<<VBUS)) {
113         /* powered */
114         return battery_charging() ? CHARGING : FULL_CHARGED;
115     } else {
116         /* not powered */
117         return low_voltage() ? LOW_VOLTAGE : DISCHARGING;
118     }
119 }