diff options
Diffstat (limited to 'app/button')
-rw-r--r-- | app/button/button_handler.c | 209 | ||||
-rw-r--r-- | app/button/button_handler.h | 18 | ||||
-rw-r--r-- | app/button/button_task.c | 229 | ||||
-rw-r--r-- | app/button/button_task.h | 8 |
4 files changed, 464 insertions, 0 deletions
diff --git a/app/button/button_handler.c b/app/button/button_handler.c new file mode 100644 index 0000000..7c3ea91 --- /dev/null +++ b/app/button/button_handler.c @@ -0,0 +1,209 @@ +#include "button_handler.h" +#include "ltimers.h" + +#include "nixie_driver_process.h" + +// FreeRTOS includes +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" + +// Обработчик нажатий представляет собой конечный автомат для обработки +// результата работы сенсорной библиотеки, обработки комбинаций и времени +// нажатий и выдачи результата во внешнюю программу + + +#define TIME_BUTTON_LONG_PRESS 1000 // 3 секунды для долгого жмака + + +// Состояние конечного автомата обработчика нажатий +typedef enum { + BUTTON_STATE_START = 0, + BUTTON_STATE_ONE_BUT_IS_PRESSING_NOW, + BUTTON_STATE_TWO_BUTS_AND_TIMER, + BUTTON_STATE_TWO_BUTS_AFTER_TIMER +} Button_FSMStates_t; + +// Комбнации нажатостей кнопушек (нажата одна, зажаты две и тд.) +enum { + BUT_COMB_NONE = 0, + BUT_COMB_BUT1 = 1, + BUT_COMB_BUT2 = 2, + BUT_COMB_BOTH = 3 +} ; + +QueueHandle_t queue_but_comb; + +// - сделать в обработчике вывода индикации ламп на нижнем уровне, +// чтобы ты отправлял цифру на индикатор, а он сам уже преобразовывал + + +// ---------------------------------------------------------------------------- +// +// ---------------------------------------------------------------------------- +void ButtonInit ( void ) +{ + queue_but_comb = xQueueCreate ( 1, sizeof (ButtonCombName_t) ); + configASSERT( queue_but_comb ); +} + + +// ---------------------------------------------------------------------------- +// Конечный автомат-обработчик нажатий кнопушек +// Note: +// Антидребезг в данном автомате не нужен, т.к. обработчик сенсорной библиотеки +// уже все сделал (а вот не сделал, возможно от микродребезга есть защита, +// а вот от крупного дребезга нет защиты) +// ---------------------------------------------------------------------------- +void Button_ProcessFSM ( void ) +{ + static Button_FSMStates_t state_fsm_button = BUTTON_STATE_START; + static uint8_t still_pushed = 0; + + static uint8_t prev_button_comb; + static uint8_t curr_button_comb; + static ButtonCombName_t msg_but_comb_name; + + switch ( state_fsm_button ) + { + // ------------------------------------------------------------------------- + case BUTTON_STATE_START: + + curr_button_comb = Button_GetCurrButtons(); + + if ( curr_button_comb != BUT_COMB_NONE ) + { + prev_button_comb = curr_button_comb; + state_fsm_button = BUTTON_STATE_ONE_BUT_IS_PRESSING_NOW; + still_pushed = 0; + } + + break; + // ------------------------------------------------------------------------- + case BUTTON_STATE_ONE_BUT_IS_PRESSING_NOW: + // - 1 отпустили + // - 2 нажали вторую + // - 3 вторая кнопка, но такого не должно быть(ошибка) + + curr_button_comb = Button_GetCurrButtons(); + + // Сначала проверим, вдруг кнопушку отпустили + if ( (curr_button_comb == BUT_COMB_NONE) && (still_pushed == 0) ) + { + // - сообщ.: "Одиночный обратный жмак" + + switch ( prev_button_comb ) + { + case BUT_COMB_BUT1: + xQueueReceive ( queue_but_comb, &msg_but_comb_name, 0 ); + msg_but_comb_name = BUTTON_SINGLE_FORWARD; + xQueueSend ( queue_but_comb, &msg_but_comb_name, 0 ); + break; + case BUT_COMB_BUT2: + xQueueReceive ( queue_but_comb, &msg_but_comb_name, 0 ); + msg_but_comb_name = BUTTON_SINGLE_BACKWARD; + xQueueSend ( queue_but_comb, &msg_but_comb_name, 0 ); + break; + default: + break; + } + + state_fsm_button = BUTTON_STATE_START; + + return; + } + + if ( (curr_button_comb == BUT_COMB_NONE) && (still_pushed == 1) ) + { + state_fsm_button = BUTTON_STATE_START; + return; + } + + switch ( prev_button_comb ) + { + case BUT_COMB_BUT1: + + if ( curr_button_comb == BUT_COMB_BOTH ) + { + // - тогда сообщ.: "Зажатый прямой жмак вперед" + xQueueReceive ( queue_but_comb, &msg_but_comb_name, 0 ); + //msg_but_comb_name = BUTTON_HOLD_FORWARD; + msg_but_comb_name = BUTTON_HOLD_BACKWARD; + xQueueSend ( queue_but_comb, &msg_but_comb_name, 0 ); + StartLTimer ( LTIMER_BUTTON_LONG_PRESS ); + state_fsm_button = BUTTON_STATE_TWO_BUTS_AND_TIMER; + still_pushed = 1; + } + + break; + + case BUT_COMB_BUT2: + + if ( curr_button_comb == BUT_COMB_BOTH ) + { + // - тогда сообщ.: "Зажатый прямой жмак назад" + xQueueReceive ( queue_but_comb, &msg_but_comb_name, 0 ); + //msg_but_comb_name = BUTTON_HOLD_BACKWARD; + msg_but_comb_name = BUTTON_HOLD_FORWARD; + xQueueSend ( queue_but_comb, &msg_but_comb_name, 0 ); + + StartLTimer ( LTIMER_BUTTON_LONG_PRESS ); + state_fsm_button = BUTTON_STATE_TWO_BUTS_AND_TIMER; + still_pushed = 1; + } + + break; + + default: + state_fsm_button = BUTTON_STATE_START; + break; + } + + break; + + // ------------------------------------------------------------------------- + case BUTTON_STATE_TWO_BUTS_AND_TIMER: + + curr_button_comb = Button_GetCurrButtons(); + + if ( curr_button_comb == BUT_COMB_BOTH ) + { + if ( GetLTimer (LTIMER_BUTTON_LONG_PRESS) == TIME_BUTTON_LONG_PRESS ) + { + // - сообщ.: "Две долго" + xQueueReceive ( queue_but_comb, &msg_but_comb_name, 0 ); + msg_but_comb_name = BUTTON_LONG; + xQueueSend ( queue_but_comb, &msg_but_comb_name, 0 ); + + state_fsm_button = BUTTON_STATE_TWO_BUTS_AFTER_TIMER; + } + } + else + { + prev_button_comb = curr_button_comb; + state_fsm_button = BUTTON_STATE_ONE_BUT_IS_PRESSING_NOW; + } + + break; + + // ------------------------------------------------------------------------- + case BUTTON_STATE_TWO_BUTS_AFTER_TIMER: + + curr_button_comb = Button_GetCurrButtons(); + + if ( curr_button_comb == BUT_COMB_NONE ) + { + state_fsm_button = BUTTON_STATE_START; + } + else if ( curr_button_comb != BUT_COMB_BOTH ) + { + prev_button_comb = curr_button_comb; + state_fsm_button = BUTTON_STATE_ONE_BUT_IS_PRESSING_NOW; + } + + break; + + default: + break; + } +} diff --git a/app/button/button_handler.h b/app/button/button_handler.h new file mode 100644 index 0000000..86118fa --- /dev/null +++ b/app/button/button_handler.h @@ -0,0 +1,18 @@ +#ifndef BUTTON_HANDLER_INCLUDED +#define BUTTON_HANDLER_INCLUDED + +#include <stdint.h> + +typedef enum { + BUTTON_SINGLE_FORWARD, + BUTTON_SINGLE_BACKWARD, + BUTTON_HOLD_FORWARD, + BUTTON_HOLD_BACKWARD, + BUTTON_LONG +} ButtonCombName_t; + +void ButtonInit ( void ); +uint8_t Button_GetCurrButtons ( void ); +void Button_ProcessFSM ( void ); + +#endif //BUTTON_HANDLER_INCLUDED diff --git a/app/button/button_task.c b/app/button/button_task.c new file mode 100644 index 0000000..cc0a73f --- /dev/null +++ b/app/button/button_task.c @@ -0,0 +1,229 @@ +#include "head_task.h" +#include "tsl_user.h" +#include "nixie_driver_process.h" + +#include "button_handler.h" +#include "ltimers.h" + +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +#define TKEY_NUM_1 0 +#define TKEY_NUM_2 1 + +#define TIME_SENSOR_BUT_DEBOUNCE 50 //ms + +// Эти определения пойдут в модуль обработки кнопушек уровня пользователя - Button_Module + +#define TEST_TKEY(NB) ((MyTKeys[(NB)].p_Data->StateId == TSL_STATEID_DETECT) ||\ + (MyTKeys[(NB)].p_Data->StateId == TSL_STATEID_DEB_RELEASE_DETECT)) + +#define TEST_LINROT(NB) ((MyLinRots[(NB)].p_Data->StateId == TSL_STATEID_DETECT) ||\ + (MyLinRots[(NB)].p_Data->StateId == TSL_STATEID_DEB_RELEASE_DETECT)) + +// For debug purpose with STMStudio +uint8_t DS[TSLPRM_TOTAL_TKEYS + TSLPRM_TOTAL_LNRTS]; // To store the States (one per object) +int16_t DD[TSLPRM_TOTAL_TKEYS + (TSLPRM_TOTAL_LNRTS * 3)]; // To store the Deltas (one per channel) + +// Битовая переменная, в которой будут устанавливаться соответствующие +// номерам нажатых кнопушек биты +static volatile uint8_t tkey_buttons_bits = 0; + + +static void ProcessSensors ( void ); +static void TkeyDebounce ( void ); + + +// ---------------------------------------------------------------------------- +// Ф-я которая будет возвращать значение битовой переменной +// и вызываться из модуля button_handler.c (ф-я Button_ProcessFSM ();) +// ---------------------------------------------------------------------------- +uint8_t Button_GetCurrButtons ( void ) +{ + uint8_t curr_buts_bits = tkey_buttons_bits; + return curr_buts_bits; +} + +// ---------------------------------------------------------------------------- +// +// ---------------------------------------------------------------------------- +void ProcessFSM_ButtonTask ( void ) +{ + /* Execute STMTouch Driver state machine */ + if (TSL_user_Action () == TSL_STATUS_OK) + { + ProcessSensors (); // Execute sensors related tasks + + // Обработчик нажатий кнопушек (автомат) + //Button_ProcessFSM (); + } + Button_ProcessFSM (); + taskYIELD(); +} + + +/** + * @brief Manage the activity on sensors when touched/released (example) + * @param None + * @retval None + */ +static void ProcessSensors ( void ) +{ + uint32_t idx; + uint32_t idx_ds = 0; + uint32_t idx_dd = 0; +#if USE_LCD > 0 + static uint32_t started = 0; +#endif + +#if TSLPRM_TOTAL_TKEYS > 0 + // Read all TKeys + for (idx = 0; idx < TSLPRM_TOTAL_TKEYS; idx++) + { + // STMStudio debug + DS[idx_ds++] = MyTKeys[idx].p_Data->StateId; + DD[idx_dd++] = MyTKeys[idx].p_ChD->Delta; + } +#endif + +#if TSLPRM_TOTAL_LNRTS > 0 + uint32_t idxch; + // Read all Linear and Rotary sensors + for (idx = 0; idx < TSLPRM_TOTAL_LNRTS; idx++) + { + // STMStudio debug + DS[idx_ds++] = MyLinRots[idx].p_Data->StateId; + for (idxch = 0; idxch < MyLinRots[idx].NbChannels; idxch++) + { + DD[idx_dd++] = MyLinRots[idx].p_ChD[idxch].Delta; + } + } +#endif + + // Сделаем обработчик антидребезга (вроде он есть в библе сенсорных кнопок, + // но GROUP5 почему-то сильно дергается) + + TkeyDebounce(); + + // Тут можно поменять кнопки местами +} + +/** + * @brief Executed when a sensor is in Off state + * @param None + * @retval None + */ +void MyTKeys_OffStateProcess(void) +{ + /* Add here your own processing when a sensor is in Off state */ +} + +void MyLinRots_OffStateProcess(void) +{ + /* Add here your own processing when a sensor is in Off state */ +} + +/** + * @brief Executed at each timer interruption (option must be enabled) + * @param None + * @retval None + */ +void TSL_CallBack_TimerTick(void) +{ +} + +/** + * @brief Executed when a sensor is in Error state + * @param None + * @retval None + */ +void MyTKeys_ErrorStateProcess(void) +{ + /* Add here your own processing when a sensor is in Error state */ + TSL_tkey_SetStateOff (); + while(1) + { + } +} + +void MyLinRots_ErrorStateProcess(void) +{ + /* Add here your own processing when a sensor is in Error state */ + TSL_linrot_SetStateOff(); + while(1) + { + } +} + + +// ---------------------------------------------------------------------------- +// Ф-я антидребезга для сенсорных кнопок +// ---------------------------------------------------------------------------- +void TkeyDebounce ( void ) +{ + static uint8_t tkey_db_state = 1; + static uint8_t tkey_code = 0; + static uint8_t _tkey_code = 1; // предыдущее состояние кнопок + + if (TEST_TKEY(TKEY_NUM_2)) + { + tkey_code |= 1 << TKEY_NUM_1; + } + else + { + tkey_code &= ~(1 << TKEY_NUM_1); + } + + if (TEST_TKEY(TKEY_NUM_1)) + { + tkey_code |= 1 << TKEY_NUM_2; + } + else + { + tkey_code &= ~(1 << TKEY_NUM_2); + } + + switch (tkey_db_state) + { + case 1: + if ( tkey_code != _tkey_code ) // если нажата любая сенсорная кнопушка + { + _tkey_code = tkey_code; + tkey_db_state = 2; + StartLTimer (LTIMER_SENSOR_BUT_DEBOUNCE); + } + break; + + case 2: + if( GetLTimer( LTIMER_SENSOR_BUT_DEBOUNCE ) >= TIME_SENSOR_BUT_DEBOUNCE ) + { + tkey_db_state = 3; + } + break; + + case 3: + if( _tkey_code == tkey_code ) + { + tkey_db_state = 1; + tkey_buttons_bits = _tkey_code; + + } + else { tkey_db_state = 1; } + break; + + default: + break; + } // end switch +} + + +// ---------------------------------------------------------------------------- +// Задача ОС, реализующая обработку нажатий кнопушек +// Здесь обрабатывается уже результат обработки сенсорных нажатий +// ---------------------------------------------------------------------------- +void Button_Task ( void *pvParameters ) +{ + while(1)ProcessFSM_ButtonTask (); +} diff --git a/app/button/button_task.h b/app/button/button_task.h new file mode 100644 index 0000000..c55f8c3 --- /dev/null +++ b/app/button/button_task.h @@ -0,0 +1,8 @@ +#ifndef BUTTON_TASK_INCLUDED +#define BUTTON_TASK_INCLUDED + +#include "stm32f0xx.h" + +void Button_Task ( void *pvParameters ); + +#endif //BUTTON_TASK_INCLUDED
\ No newline at end of file |