]> git.donarmstrong.com Git - qmk_firmware.git/blob - keyboard/hhkb_rn42/rn42/battery.c
Disable input buffer for ADC
[qmk_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     // 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 }