]> git.gir.st - tmk_keyboard.git/blob - keyboard/hhkb_rn42/rn42/battery.c
Add battery management
[tmk_keyboard.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 }
Imprint / Impressum