]> www.fi.muni.cz Git - tinyboard.git/commitdiff
Added missing source files battery.c and buttons.c
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Wed, 1 May 2013 22:19:53 +0000 (00:19 +0200)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Wed, 1 May 2013 22:19:53 +0000 (00:19 +0200)
projects/step-up/battery.c [new file with mode: 0644]
projects/step-up/buttons.c [new file with mode: 0644]

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;
+}
diff --git a/projects/step-up/buttons.c b/projects/step-up/buttons.c
new file mode 100644 (file)
index 0000000..4101a2f
--- /dev/null
@@ -0,0 +1,133 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/sleep.h>
+#include <util/delay.h>
+#include <stdlib.h> // for NULL
+
+#include "lights.h"
+
+#define WAKEUP_LIMIT   5       // times 100 ms
+#define SHORT_PRESS_MIN        10      // in jiffies (100 Hz ticks)
+#define SHORT_PRESS_MAX 50
+#define LONG_PRESS_MIN 100
+static uint16_t button_start;
+static unsigned char prev_state;
+
+void status_led_on_off(unsigned char mode)
+{
+       if (mode)
+               PORTB |= _BV(PORTB0);
+       else
+               PORTB &= ~_BV(PORTB0);
+}
+
+void init_buttons()
+{
+       DDRB &= ~_BV(DDB1);
+       DDRB |= _BV(DDB0);
+       PORTB |= _BV(PORTB1); // enable internal pull-up
+       PORTB &= ~_BV(PORTB0); // status led off
+       GIMSK &= ~_BV(PCIE); // disable pin-change IRQs
+       PCMSK = 0; // disable pin-change IRQs on all pins of port B
+
+       button_start = 0;
+       prev_state   = 0;
+}
+
+void susp_buttons()
+{
+       DDRB &= ~(_BV(DDB1)); // set as input
+       PORTB |= _BV(PORTB1);  // enable internal pull-up
+       PORTB &= ~_BV(PORTB0); // set to zero
+
+       GIMSK |= _BV(PCIE);
+
+       PCMSK = _BV(PCINT1);
+               // disable pin-change IRQs on all pins except PB1
+}
+
+void timer_check_buttons()
+{
+       unsigned char cur = !(PINB & _BV(PINB1));
+       unsigned char prev = prev_state;
+
+       prev_state = cur;
+
+       if (cur && !prev) {                   // --- just pressed ---
+               button_start = jiffies;
+               // set_status_led(button, NULL);
+
+       } else if (cur && prev) {           // --- is still pressed ---
+               uint16_t duration = jiffies - button_start;
+
+               if (duration > LONG_PRESS_MIN) {
+                       long_press_start();
+                               // acknowledge long press
+               }
+       } else if (!cur && prev) {            // --- just released ---
+               uint16_t duration = jiffies - button_start;
+
+               if (duration > SHORT_PRESS_MIN && duration < SHORT_PRESS_MAX) {
+                       short_press();
+               } else if (duration > LONG_PRESS_MIN) {
+                       // set_status_led(button, NULL);
+                       long_press();
+               }
+               // ignore other button-press durations
+       }
+}
+
+#if 0
+static void handle_brake(unsigned char cur, unsigned char prev)
+{
+       if (cur && !prev) {                   // --- just pressed ---
+               button_start[2] = jiffies;
+       } else if (!cur && prev) {            // --- just released ---
+               button_start[2] = jiffies;
+       } else {                              // --- no change ---
+               uint16_t duration = jiffies - button_start[2];
+
+               if (duration > 6) {
+                       if (cur) {
+                               if (button_state.brake_working
+                                       && !button_state.brake_reported) {
+                                       button_state.brake_reported = 1;
+                                       brake_on();
+                               }
+                       } else {
+                               button_state.brake_working = 1;
+                               if (button_state.brake_reported) {
+                                       button_state.brake_reported = 0;
+                                       brake_off();
+                               }
+                       }
+                       button_start[2] = jiffies - 7; // avoid overflow
+               }
+       }
+}
+#endif
+
+unsigned char buttons_wait_for_release()
+{
+       uint16_t wake_count = 0;
+       unsigned char pin;
+
+       do {
+               if (wake_count++ > WAKEUP_LIMIT)
+                       status_led_on_off(1); // inform the user
+
+               _delay_ms(100);
+
+               pin = PINB & _BV(PINB1);
+       } while (!(pin & _BV(PINB1)));
+
+       status_led_on_off(0);
+
+       return wake_count > WAKEUP_LIMIT;
+}
+
+ISR(PCINT0_vect)
+{
+       // empty - let it wake us from sleep, but do nothing else
+}
+