Loading projects/step-up/battery.c 0 → 100644 +89 −0 Original line number Original line Diff line number Diff line #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; } projects/step-up/buttons.c 0 → 100644 +133 −0 Original line number Original line Diff line number Diff line #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 } Loading
projects/step-up/battery.c 0 → 100644 +89 −0 Original line number Original line Diff line number Diff line #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; }
projects/step-up/buttons.c 0 → 100644 +133 −0 Original line number Original line Diff line number Diff line #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 }