summaryrefslogtreecommitdiff
path: root/app/button
diff options
context:
space:
mode:
Diffstat (limited to 'app/button')
-rw-r--r--app/button/button_handler.c209
-rw-r--r--app/button/button_handler.h18
-rw-r--r--app/button/button_task.c229
-rw-r--r--app/button/button_task.h8
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