From: sjlongland Date: Thu, 24 Sep 2015 08:11:57 +0000 (+0000) Subject: sm1000_main: Allow forward-back movement of mode selection. X-Git-Url: http://git.whiteaudio.com/gitweb/?a=commitdiff_plain;h=d6bb35010e40e713f2881a823f6ec8776c97f118;p=freetel-svn-tracking.git sm1000_main: Allow forward-back movement of mode selection. Beginnings of menu navigation, this implements a new switch debouncer and allows bi-directional movement. git-svn-id: https://svn.code.sf.net/p/freetel/code@2361 01035d8c-6547-0410-b346-abe4f91aad63 --- diff --git a/codec2-dev/stm32/src/sm1000_main.c b/codec2-dev/stm32/src/sm1000_main.c index 3f860a7e..8b7f983b 100644 --- a/codec2-dev/stm32/src/sm1000_main.c +++ b/codec2-dev/stm32/src/sm1000_main.c @@ -43,36 +43,73 @@ #define FREEDV_NSAMPLES_16K (2*FREEDV_NSAMPLES) -#define FIFTY_MS 50 +#define DEBOUNCE_DELAY 500 #define ANNOUNCE_DELAY 300000 /* Supposed to be msec, seems not */ + #define MAX_MODES 3 #define ANALOG 0 #define DV 1 #define TONE 2 -#define SS_IDLE 0 -#define SS_DEBOUNCE_DOWN 1 -#define SS_WAIT_BUTTON_UP 2 -#define SS_DEBOUNCE_UP 3 +#define SW_STEADY 0 /*!< Switch is in steady-state */ +#define SW_DEBOUNCE 1 /*!< Switch is being debounced */ + +/*! Switch debounce and logic handling */ +struct switch_t { + /*! Debounce/hold timer */ + uint32_t timer; + /*! Current/debounced observed switch state */ + uint8_t sw; + /*! Raw observed switch state (during debounce) */ + uint8_t raw; + /*! Last steady-state switch state */ + uint8_t last; + /*! Debouncer state */ + uint8_t state; +}; + +struct switch_t sw_select; /*!< Switch driver for SELECT button */ +struct switch_t sw_back; /*!< Switch driver for BACK button */ +struct switch_t sw_ptt; /*!< Switch driver for PTT buttons */ + +/*! + * Count the tick timers on the switches. + */ +static void switch_tick(struct switch_t* const sw); + +/*! + * Update the state of a switch + */ +static void switch_update(struct switch_t* const sw, uint8_t state); + +/*! Return how long the switch has been pressed in ticks. */ +static uint32_t switch_pressed(const struct switch_t* const sw); + +/*! Return non-zero if the switch has been released. */ +static int switch_released(const struct switch_t* const sw); -typedef struct { - int state; - int mode; -} SWITCH_STATE; +/*! Acknowledge the current state of the switch */ +static void switch_ack(struct switch_t* const sw); -unsigned int downTicker = 0; unsigned int announceTicker = 0; +/*! + * User preferences + */ +static struct prefs_t { + /*! Operating mode */ + uint8_t op_mode; + /* TODO: more to come */ +} prefs; + struct tone_gen_t tone_gen; struct sfx_player_t sfx_player; struct morse_player_t morse_player; void SysTick_Handler(void); -void iterate_select_state_machine(SWITCH_STATE *ss); int main(void) { struct freedv *f; - SWITCH_STATE ss; int nin, nout, i; int n_samples, n_samples_16k; @@ -102,6 +139,11 @@ int main(void) { for(i=0; i 0) { - downTicker--; - } + switch_tick(&sw_select); + switch_tick(&sw_back); + switch_tick(&sw_ptt); if (announceTicker > 0) { announceTicker--; } } -/* Select button state machine. Debounces switches and enables cycling - through ANALOG-DV-TONE modes */ +static void switch_tick(struct switch_t* const sw) +{ + if (sw->sw != sw->raw) { + /* State transition, reset timer */ + if (sw->state == SW_STEADY) + sw->last = sw->sw; + sw->state = SW_DEBOUNCE; + sw->timer = DEBOUNCE_DELAY; + sw->sw = sw->raw; + } else if (sw->state == SW_DEBOUNCE) { + if (sw->timer > 0) { + /* Steady so far, keep waiting */ + sw->timer--; + } else { + /* Steady state reached */ + sw->state = SW_STEADY; + } + } else if (sw->sw) { + /* Hold state. Yes this will wrap, but who cares? */ + sw->timer++; + } +} -void iterate_select_state_machine(SWITCH_STATE *ss) { - int next_state; +static void switch_update(struct switch_t* const sw, uint8_t state) +{ + sw->raw = state; + if (sw->raw == sw->sw) + return; + + if (sw->state == SW_STEADY) + sw->last = sw->sw; + sw->timer = DEBOUNCE_DELAY; + sw->sw = sw->raw; + sw->state = SW_DEBOUNCE; +} - next_state = ss->state; - switch(ss->state) { - case SS_IDLE: - if (switch_select() == 0) { - downTicker = FIFTY_MS; - next_state = SS_DEBOUNCE_DOWN; - } - break; - case SS_DEBOUNCE_DOWN: - if (downTicker == 0) { - ss->mode++; - sfx_play(&sfx_player, sound_click); - if (ss->mode >= MAX_MODES) - ss->mode = 0; - if (ss->mode == ANALOG) - morse_play(&morse_player, "ANALOG"); - else if (ss->mode == DV) - morse_play(&morse_player, "DV"); - else if (ss->mode == TONE) - morse_play(&morse_player, "TONE"); - next_state = SS_WAIT_BUTTON_UP; - } - break; - case SS_WAIT_BUTTON_UP: - if (switch_select() == 1) { - downTicker = FIFTY_MS; - next_state = SS_DEBOUNCE_UP; - } - break; - case SS_DEBOUNCE_UP: - if (downTicker == 0) { - next_state = SS_IDLE; - } - break; - } - ss->state = next_state; +static uint32_t switch_pressed(const struct switch_t* const sw) +{ + if ((sw->state == SW_STEADY) && sw->sw) + return sw->timer; + return 0; } +static int switch_released(const struct switch_t* const sw) +{ + if (sw->state != SW_STEADY) + return 0; + if (!sw->last) + return 0; + if (sw->sw) + return 0; + return 1; +} + +static void switch_ack(struct switch_t* const sw) +{ + if (sw->state == SW_STEADY) + sw->last = sw->sw; +}