From 1702ce6ce430a66bb7af51644b91b7c196e719d9 Mon Sep 17 00:00:00 2001 From: Alexander Date: Wed, 29 Jun 2022 11:03:02 +0300 Subject: =?UTF-8?q?=D0=A1=D0=BE=D0=B7=D0=B4=D0=B0=D1=8E=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D1=8B=D0=B9=20=D1=80=D0=B5=D0=BF=D0=BE=D0=B7=D0=B8=D1=82?= =?UTF-8?q?=D0=BE=D1=80=D0=B8=D0=B9.=20=D0=9F=D1=80=D0=BE=D0=B3=D1=80?= =?UTF-8?q?=D0=B0=D0=BC=D0=BC=D0=B0=20=D0=B4=D0=BB=D1=8F=20=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D1=81=D0=B8=D0=B8=20NixieClock=5Fv2.=20=D0=A0=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D0=B0=D0=B5=D1=82,=20=D1=87=D0=B0=D1=81?= =?UTF-8?q?=D1=8B=20=D1=82=D0=B8=D0=BA=D0=B0=D1=8E=D1=82.=20=D0=95=D1=81?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BF=D1=80=D0=BE=D0=B1=D0=BB=D0=B5=D0=BC=D0=B0?= =?UTF-8?q?,=20=D1=87=D1=82=D0=BE=20=D1=81=D0=BA=D0=B0=D1=87=D0=B5=D1=82?= =?UTF-8?q?=20=D0=B2=D1=82=D0=BE=D1=80=D0=B0=D1=8F=20=D1=81=D0=B5=D0=BD?= =?UTF-8?q?=D0=BE=D1=81=D1=80=D0=BD=D0=B0=D1=8F=20=D0=BA=D0=BD=D0=BE=D0=BF?= =?UTF-8?q?=D0=BA=D0=B0=20(=D0=BE=D0=BD=D0=B0=20=D0=B2=20=D0=B4=D1=80?= =?UTF-8?q?=D1=83=D0=B3=D0=BE=D0=BC=20=D0=BA=D0=B0=D0=BD=D0=B0=D0=BB=D0=B5?= =?UTF-8?q?).=20=D0=9F=D0=BE=D1=8D=D1=82=D0=BE=D0=BC=D1=83=20=D0=BD=D0=B0?= =?UTF-8?q?=20=D0=BD=D0=B5=D0=B5=20=D1=81=D0=BE=D0=B1=D0=B8=D1=80=D0=B0?= =?UTF-8?q?=D1=8E=D1=81=D1=8C=20=D1=81=D0=B4=D0=B5=D0=BB=D0=B0=D1=82=D1=8C?= =?UTF-8?q?=20=D0=B0=D0=BD=D1=82=D0=B8=D0=B4=D1=80=D0=B5=D0=B1=D0=B5=D0=B7?= =?UTF-8?q?=D0=B3.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Libraries/Indicate/indicate_modes_task.c | 331 +++++++++++++++++++++++++++++++ 1 file changed, 331 insertions(+) create mode 100644 Libraries/Indicate/indicate_modes_task.c (limited to 'Libraries/Indicate/indicate_modes_task.c') diff --git a/Libraries/Indicate/indicate_modes_task.c b/Libraries/Indicate/indicate_modes_task.c new file mode 100644 index 0000000..ef237b1 --- /dev/null +++ b/Libraries/Indicate/indicate_modes_task.c @@ -0,0 +1,331 @@ +#include "indicate_modes_task.h" +#include "nixie_driver_process.h" +#include "ltimers.h" + +// FreeRTOS includes +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + + +typedef enum { + + STATE_BLINK_START_OFF, + STATE_BLINK_TIMER_OFF, + STATE_BLINK_TIMER_ON + +} IndicModesBlinkStates_t; + +static IndicModesBlinkStates_t state_blink = STATE_BLINK_TIMER_OFF; + +static IndicModesNums_t curr_indic_mode = INDIC_MODE_STANDART; + +QueueHandle_t queue_data_to_indic; +QueueHandle_t queue_data_to_blink_mode; +extern QueueHandle_t queue_switch_indic_mode; + + +// Прототипы функций меню +static void IndicMode_Standart ( void ); +static void IndicMode_Blink ( void ); + +void DataCopyToArray ( uint8_t *data_arr, DataToIndicate_t *data_struct ); +void DataCopyToStruct ( DataToIndicate_t *data_struct, uint8_t *data_arr ); +void WriteOffByte ( uint8_t *array, uint8_t mask ); + + +// Массив указателей на функции-меню +typedef void ( *IndicModes_t ) ( void ); +static const IndicModes_t IndicModes[MAX_INDIC_MODES] = { + + IndicMode_Standart, + IndicMode_Blink + +}; + + +// ---------------------------------------------------------------------------- +// +// ---------------------------------------------------------------------------- +void IndicateModesInit ( void ) +{ + queue_data_to_indic = xQueueCreate ( 1, sizeof (DataToIndicate_t) ); + configASSERT( queue_data_to_indic ); + + queue_data_to_blink_mode = xQueueCreate ( 1, sizeof (IndicModesMsgBlink_t) ); + configASSERT( queue_data_to_indic ); +} + + +// ---------------------------------------------------------------------------- +// Режим инжикации "Стандартный", когда время выводится без эффектов +// ---------------------------------------------------------------------------- +static void IndicMode_Standart ( void ) +{ + ; + + // Важное замечание! + // При передаче указателя массива через очередь ОС нужно передавать весь + // массив целиком, чтобы полученный экземпляр данных не менялся. Для передачи + // шести байт можно сделать небольшую структуру + + // - тут проверяем сообщение из очереди ОС на обновление выводимых данных + // и если они изменились, то отправляем их в модуль Никси + + static DataToIndicate_t data_struct; + + if ( pdPASS == xQueueReceive ( queue_data_to_indic, &data_struct, 0 ) ) + { + NixieDriver_SendValue2 ( data_struct ); + } +} + + +// ---------------------------------------------------------------------------- +// Режим "моргания" индикаторов +// В сообщении из очереди принимаются данные, которые нужно вывести, и +// маска-байт, которая соответствует номеру индикатора, который должен +// моргать. Если байт установлен, то индикатор моргает. Могут моргать сразу +// несколько индикаторов. Моргание синхронное. +// Останавливать задачу в этих функция нельзя +// - тут лучше было бы сделать ожидание завершения фазы моргания +// ---------------------------------------------------------------------------- +static void IndicMode_Blink ( void ) +{ + ; + // - принимаем сообщение с данными и маской, и на номер установленного + // байта записываем пустой символ, запоминая его. Затем запускаем таймер + // и отправляем массив данных с "дыркой" на вывод. После таймера + // записываем сохраненное значение и выводим с таймером "чистые" значения + +//#if 0 + + static const uint32_t TIME_BLINK_OFF = 250; // ms + static const uint32_t TIME_BLINK_ON = 250; // ms + + static DataToIndicate_t data_struct; + static IndicModesMsgBlink_t data_new_struct; + + static uint8_t indic_data_off [MAX_TUBES]; + static uint8_t prev_indic_data_off [MAX_TUBES]; + static uint8_t new_indic_data_off [MAX_TUBES]; + + static uint8_t prev_mask_byte = 0; + static uint8_t is_blink_tube = 0; + + + if ( pdPASS == xQueueReceive ( queue_data_to_blink_mode, &data_new_struct, 0 ) ) + { + DataCopyToArray ( &new_indic_data_off[0], &data_new_struct.data ); + + DataCopyToArray ( &indic_data_off[0], &data_new_struct.data ); + WriteOffByte ( &indic_data_off[0], data_new_struct.mask_byte ); // теперь можно вместо пустой цифры отправлять точку + DataCopyToStruct ( &data_struct, &indic_data_off[0] ); + + // Если изменилась только маска байта, то начинаем моргать с отрицательной + // фазы + if ( prev_mask_byte != data_new_struct.mask_byte ) + { + prev_mask_byte = data_new_struct.mask_byte; + NixieDriver_SendValue2 ( data_struct ); + StartLTimer ( LTIMER_INDIC_MODE_BLINK_OFF ); + state_blink = STATE_BLINK_TIMER_OFF; + } + else + { + // А если изменились данные моргающей лампы, то начинать с + // положительной фазы + for ( uint8_t tube_num = 0; tube_num < MAX_TUBES; tube_num++ ) + { + if ( (prev_indic_data_off[tube_num] != new_indic_data_off[tube_num]) )// В этой лампе данные не равны? + { + if ( data_new_struct.mask_byte & ( 32 >> tube_num ) ) // И эта лампа моргающая? + { + is_blink_tube = 1; + break; + } + } + } // end for + + if ( is_blink_tube == 1 ) + { + NixieDriver_SendValue2 ( data_new_struct.data ); + StartLTimer ( LTIMER_INDIC_MODE_BLINK_ON ); + state_blink = STATE_BLINK_TIMER_ON; + is_blink_tube = 0; + } + else + { + if ( state_blink == STATE_BLINK_TIMER_OFF ) + { + NixieDriver_SendValue2 ( data_struct ); + } + else + { + NixieDriver_SendValue2 ( data_new_struct.data ); + } + } + } + + DataCopyToArray ( &prev_indic_data_off[0], &data_new_struct.data ); + } + + switch ( state_blink ) + { +// case STATE_BLINK_START_OFF: +// +// for ( uint8_t tube_num = 0; tube_num < MAX_TUBES; tube_num++ ) +// { +// if ( data_new_struct.mask_byte & ( 32 >> tube_num ) ) +// { +// indic_data_off [tube_num] = TUBE_EMPTY_VALUE; // - тут цифра 10 это TUBE_DIGIT_EMPTY +// } +// } +// +// DataCopyToStruct ( &data_struct, &indic_data_off[0] ); +// +// NixieDriver_SendValue2 ( data_struct ); +// +// state_blink = STATE_BLINK_TIMER_OFF; +// StartLTimer ( LTIMER_INDIC_MODE_BLINK_OFF ); +// +// break; + + case STATE_BLINK_TIMER_OFF: + + if ( GetLTimer ( LTIMER_INDIC_MODE_BLINK_OFF ) >= TIME_BLINK_OFF ) + { + NixieDriver_SendValue2 ( data_new_struct.data ); + state_blink = STATE_BLINK_TIMER_ON; + StartLTimer ( LTIMER_INDIC_MODE_BLINK_ON ); + } + + break; + + case STATE_BLINK_TIMER_ON: + + if ( GetLTimer ( LTIMER_INDIC_MODE_BLINK_ON ) >= TIME_BLINK_ON ) + { + NixieDriver_SendValue2 ( data_struct ); + state_blink = STATE_BLINK_TIMER_OFF; + StartLTimer ( LTIMER_INDIC_MODE_BLINK_OFF ); + } + + break; + } + +//#endif +} + + +// ---------------------------------------------------------------------------- +// +// ---------------------------------------------------------------------------- +void DataCopyToStruct ( DataToIndicate_t *data_struct, uint8_t *data_arr ) +{ + data_struct->indic_1 = data_arr[0]; + data_struct->indic_2 = data_arr[1]; + data_struct->indic_3 = data_arr[2]; + data_struct->indic_4 = data_arr[3]; + data_struct->indic_5 = data_arr[4]; + data_struct->indic_6 = data_arr[5]; +} + + +// ---------------------------------------------------------------------------- +// +// ---------------------------------------------------------------------------- +void DataCopyToArray ( uint8_t *data_arr, DataToIndicate_t *data_struct ) +{ + data_arr[0] = data_struct->indic_1; + data_arr[1] = data_struct->indic_2; + data_arr[2] = data_struct->indic_3; + data_arr[3] = data_struct->indic_4; + data_arr[4] = data_struct->indic_5; + data_arr[5] = data_struct->indic_6; +} + + +// ---------------------------------------------------------------------------- +// Ф-я записи в массив "темной" лампы +// ---------------------------------------------------------------------------- +void WriteOffByte ( uint8_t *array, uint8_t mask ) +{ + for ( uint8_t tube_num = 0; tube_num < MAX_TUBES; tube_num++ ) + { + if ( mask & ( 32 >> tube_num ) ) + { + //array [tube_num] = TUBE_EMPTY_VALUE; // - тут цифра 10 это TUBE_DIGIT_EMPTY + // Можно поробовать здесь отправлять точку вместо пустого символа + array [tube_num] = 12; // Шлем номер значения цифры из массива tube_digits [MAX_DIGITS] + } + } +} + + +// ---------------------------------------------------------------------------- +// Режимы работы индикации (моргать, плавно переключаться и тд.) +// ---------------------------------------------------------------------------- +void ProcessFSM_IndicateModes ( void ) +{ + // - тут нужно принимать сообщения из модуля Меню и переходить в нужный режим + // индикации + // При этом нужно помнить, что режим индикации может иметь много состояний, + // поэтому нужно сбрасывать это состояние и, возможно, другие переменные + // перед переключением в другой режим. + + IndicModesNums_t indic_mode_num; + + if ( pdPASS == xQueueReceive ( queue_switch_indic_mode, &indic_mode_num, 0 ) ) + { + // Сначала переведем состояние отключаемого режима в начальное + switch ( curr_indic_mode ) + { + case INDIC_MODE_STANDART: + + break; + + case INDIC_MODE_BLINK: + state_blink = STATE_BLINK_TIMER_OFF; + break; + } + + curr_indic_mode = indic_mode_num; + } + + IndicModes [curr_indic_mode](); + taskYIELD(); +} + + +// ---------------------------------------------------------------------------- +// Задача ОС, реализующая головную задачу программы NixieClockSimply +// ---------------------------------------------------------------------------- +void IndicateModes_Task ( void *pvParameters ) +{ + while(1)ProcessFSM_IndicateModes (); + //vTaskDelete(NULL); +} + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3