]> www.fi.muni.cz Git - bike-lights.git/commitdiff
firmware: buttons + hall probe via ADC
authorJan "Yenya" Kasprzak <kas@fi.muni.cz>
Fri, 8 Mar 2013 21:52:16 +0000 (22:52 +0100)
committerJan "Yenya" Kasprzak <kas@fi.muni.cz>
Fri, 8 Mar 2013 21:52:16 +0000 (22:52 +0100)
firmware/adc.c
firmware/buttons.c
firmware/control.c
firmware/lights.h

index 0ec32af77c0a54db8bbc4b0f8a6ac8476086e15f..b82bc097136d3c70a63defb3290829ecaf3678d3 100644 (file)
@@ -6,8 +6,9 @@
 #define AMBIENT_ADC N_PWMLEDS
 #define BATTERY_ADC (N_PWMLEDS + 1)
 #define ADC1_GAIN20 (N_PWMLEDS + 2)
+#define BUTTON_ADC  (N_PWMLEDS + 2)
 
-#define NUM_ADCS 6
+#define NUM_ADCS 7
 volatile static unsigned char current_adc;
 static uint16_t adc_sum;
 static unsigned char sum_shift;
@@ -42,6 +43,10 @@ static void inline setup_mux(unsigned char n)
        case 5: // gain stage offset: 1.1V, ADC1,1, gain 20
                ADMUX = _BV(REFS1) | _BV(MUX3) | _BV(MUX2) | _BV(MUX0);
                sum_shift = 0; // 1 measurement
+       case 6: // buttons: 1.1V, ADC3, single-ended
+               PORTA |= _BV(PA3); // +5V to the voltage splitter
+               ADMUX = _BV(REFS1) | _BV(MUX1) | _BV(MUX0);
+               sum_shift = 0;
                break;
        }
 
@@ -94,7 +99,7 @@ void init_adc()
        // ADCSRB |= _BV(GSEL); // gain 8 or 32
 
        // Disable digital input on all bits used by ADC
-       DIDR0 = _BV(ADC0D) | _BV(ADC1D) | _BV(ADC2D)
+       DIDR0 = _BV(ADC0D) | _BV(ADC1D) | _BV(ADC2D) | _BV(ADC3D)
                | _BV(ADC4D) | _BV(ADC5D) | _BV(ADC6D);
 
        // 1.1V, ADC1,1, gain 20
@@ -160,6 +165,8 @@ ISR(ADC_vect) { // IRQ handler
                ambient_adc(adc_sum);
        if (current_adc == BATTERY_ADC)
                battery_adc(adcval);
+       if (current_adc == BUTTON_ADC)
+               button_adc(adcval);
        
        start_next_adc();
 }
index 2e80142b3be896c0bbf2ffa9961c1b2c48127a58..be3a86581f477f825cbbaaa9728bcc0bdc282cdb 100644 (file)
@@ -7,8 +7,15 @@
 #include "lights.h"
 
 #define WAKEUP_LIMIT   5       // times 100 ms
-static uint16_t button_start[N_BUTTONS];
-static unsigned char prev_pin;
+static uint16_t button_start[3];
+union {
+       unsigned char all;
+       struct {
+               unsigned char btn1 : 1;
+               unsigned char btn2 : 1;
+               unsigned char brake : 1;
+       };
+} button_state, prev_state;
 
 static unsigned char user_params[MAX_USER_PARAMS] = { 0, 0, 0 };
 static unsigned char user_params_max[MAX_USER_PARAMS] = { 3, 2, 2 };
@@ -31,8 +38,8 @@ unsigned char buttons_setup_in_progress()
 {
        if (user_params_state // setup in progress ...
                // or at least one button is pressed:
-               || !(prev_pin & _BV(PA3))
-               || !(prev_pin & _BV(PA4)))
+               || prev_state.btn1
+               || prev_state.btn2)
                return 1;
        return 0;
 }
@@ -115,8 +122,10 @@ static inline void long_press(unsigned char button)
 
 void init_buttons()
 {
-       DDRA &= ~(_BV(PA3) | _BV(PA4)); // set as input
-       PORTA |=  _BV(PA3) | _BV(PA4);  // enable internal pull-ups
+       DDRA &= ~_BV(PA4); // set as input
+       DDRA |= _BV(PA3); // output
+       PORTA &= ~(_BV(PA3) | _BV(PA4));  // PA4 disable internal pull-up
+                                       // PA3 set to zero
 
        GIMSK &= ~(_BV(PCIE0) | _BV(PCIE1)); // disable pin-change IRQs
        PCMSK0 = 0; // disable pin-change IRQs on all pins of port A
@@ -124,39 +133,42 @@ void init_buttons()
 
        button_start[0] = 0;
        button_start[1] = 0;
-       prev_pin = _BV(PA3) | _BV(PA4);
+       button_start[2] = 0;
+
+       prev_state.all    = 0;
+       button_state.all  = 0;
        user_params_state = 0;
 }
 
 void susp_buttons()
 {
        DDRA &= ~(_BV(PA3) | _BV(PA4)); // set as input
-       PORTA |=  _BV(PA3) | _BV(PA4);  // enable internal pull-ups
+       PORTA |= _BV(PA4);  // enable internal pull-up
+       PORTA &= ~_BV(PA3); // disable pull-up
 
        GIMSK &= ~_BV(PCIE0);
        GIMSK |= _BV(PCIE1);
 
-       PCMSK0 = _BV(PCINT3) | _BV(PCINT4);
-               // disable pin-change IRQs on all pins except PA3,PA4
+       PCMSK0 = _BV(PCINT4);
+               // disable pin-change IRQs on all pins except PA4
        PCMSK1 = 0; // disable pin-change IRQs on all pins of port B
 }
 
 static void handle_button(unsigned char button, unsigned char cur,
        unsigned char prev)
 {
-       // BEWARE: pins are at _zero_ when pressed!
-       if (!cur && prev) {                   // --- just pressed ---
+       if (cur && !prev) {                   // --- just pressed ---
                button_start[button] = jiffies;
                set_status_led(button, NULL);
 
-       } else if (!cur && !prev) {           // --- is still pressed ---
+       } else if (cur && prev) {           // --- is still pressed ---
                uint16_t duration = jiffies - button_start[button];
 
                if (duration > 160) {
                        set_status_led(button, on1_pattern);
                                // acknowledge long press
                }
-       } else if (cur && !prev) {            // --- just released ---
+       } else if (!cur && prev) {            // --- just released ---
                uint16_t duration = jiffies - button_start[button];
 
                if (duration > 6 && duration < 60) {
@@ -169,14 +181,29 @@ static void handle_button(unsigned char button, unsigned char cur,
        }
 }
 
-void timer_check_buttons()
+static void handle_brake(unsigned char cur, unsigned char prev)
 {
-       unsigned char pin = PINA & (_BV(PA3) | _BV(PA4));
+       if (cur && !prev) {                   // --- just pressed ---
+               button_start[2] = jiffies;
+       } else if (cur && prev) {           // --- is still pressed ---
+               uint16_t duration = jiffies - button_start[2];
+
+               if (duration > 6) {
+                       brake_on();
+                       button_start[2] = jiffies - 7; // avoid overflow
+               }
+       } else if (!cur && prev) {            // --- just released ---
+               brake_off();
+       }
+}
 
-       handle_button(0, pin & _BV(PA3), prev_pin & _BV(PA3));
-       handle_button(1, pin & _BV(PA4), prev_pin & _BV(PA4));
+void timer_check_buttons()
+{
+       handle_button(0, button_state.btn1, prev_state.btn1);
+       handle_button(1, button_state.btn2, prev_state.btn2);
+       handle_brake(button_state.brake, prev_state.brake);
 
-       prev_pin = pin;
+       prev_state.all = button_state.all;
 
        if (user_params_state && jiffies - user_params_starttime > 1000) {
                user_params_state = 0;
@@ -196,13 +223,44 @@ unsigned char buttons_wait_for_release()
 
                _delay_ms(100);
 
-               pin = PINA & (_BV(PA3) | _BV(PA4));
-       } while (!(pin & _BV(PA3)) || !(pin & _BV(PA4)));
+               pin = PINA & _BV(PA4);
+       } while (!(pin & _BV(PA4)));
 
        gpio_set(0, 0);
 
        return wake_count > WAKEUP_LIMIT;
+}
+
+void button_adc(uint16_t adcval)
+{
+#if 0
+       static unsigned char count=250;
+#endif
+       PORTA &= ~_BV(PA3); // disable +5V to the hall probe
+               // adc.c will re-enable it again
+
+       button_state.all = 0;
+       if (adcval == 0x3FF) {
+               button_state.brake = 1;
+       } else if (adcval > 0x240) {
+               button_state.brake = 1;
+               button_state.btn2 = 1;
+       } else if (adcval > 0x180) {
+               // nothing
+       } else if (adcval > 0xc0) {
+               button_state.btn2 = 1;
+       } else {
+               button_state.btn1 = 1;
+       }
+
+#if 0
+       if (--count)
+               return;
 
+       count = 250;
+       log_word(adcval);
+       log_flush();
+#endif
 }
 
 ISR(PCINT_vect)
index 7a8d4473c9cf52da0640e3e3870f88cd2de69711..007a0c2883ff87d494c58192048e05615846b22f 100644 (file)
@@ -98,7 +98,7 @@ static pattern_t slow3_pattern[] = {
        PATTERN_END
 };
 
-static unsigned char dim_mode, towbar_mode;
+static unsigned char dim_mode, towbar_mode, braking;
 
 void init_control()
 {
@@ -106,6 +106,22 @@ void init_control()
        towbar_mode = 0;
 }
 
+void brake_on()
+{
+       braking = 1;
+       gpio_set(0, 1);
+       led_set_pattern(N_PWMLEDS, status_led_pattern_select());
+       // TODO brighten rear light
+}
+
+void brake_off()
+{
+       braking = 0;
+       gpio_set(0, 0);
+       led_set_pattern(N_PWMLEDS, status_led_pattern_select());
+       // TODO dim rear light
+}
+
 void toggle_dim_mode()
 {
        dim_mode = !dim_mode;
@@ -187,6 +203,9 @@ pattern_t *pwmled2_pattern_select()
 
 pattern_t *status_led_pattern_select()
 {
+       if (braking)
+               return on1_pattern;
+
        if (buttons_setup_in_progress())
                return buttons_setup_status0_pattern_select();
 
index 1abc8a756a08fe2c3720fede0953d8f2458fa4e8..8fce475ace0f77de596ae7539ffa3fdae9fa04b0 100644 (file)
@@ -80,6 +80,7 @@ void pattern_reload();
 void init_buttons();
 void susp_buttons();
 void timer_check_buttons();
+void button_adc(uint16_t adcval);
 unsigned char get_user_param(unsigned char param);
 unsigned char buttons_wait_for_release();
 unsigned char buttons_setup_in_progress();
@@ -96,6 +97,8 @@ unsigned char battery_gauge();
 extern pattern_t on1_pattern[];
 
 void init_control();
+void brake_on();
+void brake_off();
 void toggle_dim_mode();
 void set_panic_mode();
 pattern_t *pwmled0_pattern_select();