rgb-led-string: Christmas tree mod after real-world testing
[tinyboard.git] / projects / step-up / battery.c
1 #include <avr/io.h>
2
3 #include "lights.h"
4
5 #define BATTERY_ADC_SHIFT       2
6 #define RESISTOR_HI     1500    // kOhm
7 #define RESISTOR_LO      100    // kOhm
8 /*
9  * The internal 1.1V reference has tolerance from 1.0 to 1.2V
10  * (datasheet, section 19.6). We have to measure the actual value
11  * of our part.
12  */
13 #define AREF_1100MV     1060    // mV
14
15 static volatile uint16_t battery_adcval;
16 static unsigned char initial_readings = 0;
17
18 void init_battery()
19 {
20         battery_adcval = 0;
21         initial_readings = 5;
22 }
23
24 unsigned char battery_100mv()
25 {
26         /*
27          * This is tricky: we need to maintain precision, so we first
28          * multiply adcval by as big number as possible to fit uint16_t,
29          * then divide to get the final value,
30          * and finally type-cast it to unsigned char.
31          * We don't do running average, as the required precision
32          * is coarse (0.1 V).
33          */
34         return (unsigned char)
35                 ((uint16_t)(
36                 (battery_adcval >> BATTERY_ADC_SHIFT)
37                 * (11                                      // 1.1V
38                 * (RESISTOR_HI+RESISTOR_LO)/RESISTOR_LO    // resistor ratio
39                 / 4)) >> 8);                               // divide by 1024
40 }
41
42 void battery_adc(uint16_t adcval)
43 {
44         if (initial_readings) {
45                 initial_readings--;
46                 battery_adcval = adcval << BATTERY_ADC_SHIFT;
47         } else if (battery_adcval == 0) {
48                 battery_adcval = adcval << BATTERY_ADC_SHIFT;
49         } else { // running average
50                 battery_adcval += (adcval
51                         - (battery_adcval >> BATTERY_ADC_SHIFT));
52         }
53 #if 0
54         log_byte(battery_100mv());
55         log_flush();
56 #endif
57 }
58
59 unsigned char battery_gauge()
60 {
61         unsigned char b8 = battery_100mv();
62         unsigned char rv;
63
64         if        (b8 < 70) {
65                 rv = 1;
66         } else if (b8 < 75) {
67                 rv = 2;
68         } else if (b8 < 80) {
69                 rv = 3;
70         } else if (b8 < 85) {
71                 rv = 4;
72         } else if (b8 < 90) {
73                 rv = 5;
74         } else if (b8 < 95) {
75                 rv = 6;
76         } else {
77                 rv = 7;
78         }
79
80 #if 0
81         if (rv == 1 && !initial_readings)
82                 set_error(ERR_BATTERY);
83 #endif
84
85 #if 0
86         log_byte(0xbb);
87         log_byte(rv);
88         log_flush();
89 #endif
90         return rv;
91 }