From: Jan "Yenya" Kasprzak Date: Wed, 1 May 2013 22:19:53 +0000 (+0200) Subject: Added missing source files battery.c and buttons.c X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=commitdiff_plain;h=287f589eb6aee0d3aa9726106c6782c41c81ec6a;p=tinyboard.git Added missing source files battery.c and buttons.c --- diff --git a/projects/step-up/battery.c b/projects/step-up/battery.c new file mode 100644 index 0000000..ceb53cb --- /dev/null +++ b/projects/step-up/battery.c @@ -0,0 +1,89 @@ +#include + +#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 index 0000000..4101a2f --- /dev/null +++ b/projects/step-up/buttons.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include // 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 +} +