]> git.gir.st - tmk_keyboard.git/blob - keyboard/hhkb_rn42/rn42/battery.c
Disable input buffer for ADC
[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 // digital input buffer disable(24.9.5)
25 DIDR0 = (1<<ADC0D) | (1<<ADC4D) | (1<<ADC5D) | (1<<ADC7D);
26 DIDR1 = (1<<AIN0D);
27 DIDR2 = (1<<ADC8D) | (1<<ADC9D) | (1<<ADC11D) | (1<<ADC12D) | (1<<ADC13D);
28
29 // ADC disable voltate divider(PF4)
30 DDRF |= (1<<4);
31 PORTF &= ~(1<<4);
32 }
33
34 // Indicator for battery
35 void battery_led(battery_led_t val)
36 {
37 if (val == LED_TOGGLE) {
38 // Toggle LED
39 DDRF |= (1<<5);
40 PINF |= (1<<5);
41 } else if (val == LED_ON) {
42 // On overriding charger status
43 DDRF |= (1<<5);
44 PORTF &= ~(1<<5);
45 } else if (val == LED_OFF) {
46 // Off overriding charger status
47 DDRF |= (1<<5);
48 PORTF |= (1<<5);
49 } else {
50 // Display charger status
51 DDRF &= ~(1<<5);
52 PORTF &= ~(1<<5);
53 }
54 }
55
56 bool battery_charging(void)
57 {
58 if (!(USBSTA&(1<<VBUS))) return false;
59
60 // Charger Status:
61 // MCP73831 MCP73832 LTC4054 Status
62 // Hi-Z Hi-Z Hi-Z Shutdown/No Battery
63 // Low Low Low Charging
64 // Hi Hi-Z Hi-Z Charged
65
66 // preserve last register status
67 uint8_t ddrf_prev = DDRF;
68 uint8_t portf_prev = PORTF;
69
70 // Input with pullup
71 DDRF &= ~(1<<5);
72 PORTF |= (1<<5);
73 _delay_ms(1);
74 bool charging = PINF&(1<<5) ? false : true;
75
76 // restore last register status
77 DDRF = (DDRF&~(1<<5)) | (ddrf_prev&(1<<5));
78 PORTF = (PORTF&~(1<<5)) | (portf_prev&(1<<5));
79
80 // TODO: With MCP73831 this can not get stable status when charging.
81 // LED is powered from PSEL line(USB or Lipo)
82 // due to weak low output of STAT pin?
83 // due to pull-up'd via resitor and LED?
84 return charging;
85 }
86
87 // Returns voltage in mV
88 uint16_t battery_voltage(void)
89 {
90 // ADC disable voltate divider(PF4)
91 DDRF |= (1<<4);
92 PORTF |= (1<<4);
93
94 volatile uint16_t bat;
95 //ADCSRA |= (1<<ADEN);
96
97 // discard first result
98 ADCSRA |= (1<<ADSC);
99 while (ADCSRA & (1<<ADSC)) ;
100 bat = ADC;
101
102 // discard second result
103 ADCSRA |= (1<<ADSC);
104 while (ADCSRA & (1<<ADSC)) ;
105 bat = ADC;
106
107 ADCSRA |= (1<<ADSC);
108 while (ADCSRA & (1<<ADSC)) ;
109 bat = ADC;
110
111 //ADCSRA &= ~(1<<ADEN);
112
113 // ADC disable voltate divider(PF4)
114 DDRF |= (1<<4);
115 PORTF &= ~(1<<4);
116
117 return (bat - BATTERY_ADC_OFFSET) * BATTERY_ADC_RESOLUTION;
118 }
119
120 static bool low_voltage(void) {
121 static bool low = false;
122 uint16_t v = battery_voltage();
123 if (v < BATTERY_VOLTAGE_LOW_LIMIT) {
124 low = true;
125 } else if (v > BATTERY_VOLTAGE_LOW_RECOVERY) {
126 low = false;
127 }
128 return low;
129 }
130
131 battery_status_t battery_status(void)
132 {
133 if (USBSTA&(1<<VBUS)) {
134 /* powered */
135 return battery_charging() ? CHARGING : FULL_CHARGED;
136 } else {
137 /* not powered */
138 return low_voltage() ? LOW_VOLTAGE : DISCHARGING;
139 }
140 }
Imprint / Impressum