]> www.fi.muni.cz Git - tinyboard.git/blobdiff - projects/step-up/battery.c
Added missing source files battery.c and buttons.c
[tinyboard.git] / projects / step-up / battery.c
diff --git a/projects/step-up/battery.c b/projects/step-up/battery.c
new file mode 100644 (file)
index 0000000..ceb53cb
--- /dev/null
@@ -0,0 +1,89 @@
+#include <avr/io.h>
+
+#include "lights.h"
+
+#define BATTERY_ADC_SHIFT      2
+#define RESISTOR_HI    1500    // kOhm
+#define RESISTOR_LO     100    // kOhm
+/*
+ * The internal 1.1V reference has tolerance from 1.0 to 1.2V
+ * (datasheet, section 19.6). We have to measure the actual value
+ * of our part.
+ */
+#define AREF_1100MV    1060    // mV
+
+static volatile uint16_t battery_adcval;
+static unsigned char initial_readings = 0;
+
+void init_battery()
+{
+       battery_adcval = 0;
+       initial_readings = 5;
+}
+
+unsigned char battery_100mv()
+{
+       /*
+        * This is tricky: we need to maintain precision, so we first
+        * multiply adcval by as big number as possible to fit uint16_t,
+        * then divide to get the final value,
+        * and finally type-cast it to unsigned char.
+        * We don't do running average, as the required precision
+        * is coarse (0.1 V).
+        */
+       return (unsigned char)
+               ((uint16_t)(
+               (battery_adcval >> BATTERY_ADC_SHIFT)
+               * (11                                      // 1.1V
+               * (RESISTOR_HI+RESISTOR_LO)/RESISTOR_LO    // resistor ratio
+               / 4)) >> 8);                               // divide by 1024
+}
+
+void battery_adc(uint16_t adcval)
+{
+       if (initial_readings) {
+               initial_readings--;
+               battery_adcval = adcval << BATTERY_ADC_SHIFT;
+       } else if (battery_adcval == 0) {
+               battery_adcval = adcval << BATTERY_ADC_SHIFT;
+       } else { // running average
+               battery_adcval += (adcval
+                       - (battery_adcval >> BATTERY_ADC_SHIFT));
+       }
+#if 0
+       log_byte(battery_100mv());
+       log_flush();
+#endif
+}
+
+unsigned char battery_gauge()
+{
+       unsigned char b8 = battery_100mv();
+       unsigned char rv;
+
+       if        (b8 < 70) {
+               rv = 1;
+       } else if (b8 < 75) {
+               rv = 2;
+       } else if (b8 < 80) {
+               rv = 3;
+       } else if (b8 < 85) {
+               rv = 4;
+       } else if (b8 < 90) {
+               rv = 5;
+       } else if (b8 < 95) {
+               rv = 6;
+       } else {
+               rv = 7;
+       }
+
+       if (rv == 1 && !initial_readings)
+               set_error(ERR_BATTERY);
+
+#if 0
+       log_byte(0xbb);
+       log_byte(rv);
+       log_flush();
+#endif
+       return rv;
+}