diff options
author | Oxore <oxore@protonmail.com> | 2023-03-05 20:20:45 +0300 |
---|---|---|
committer | Oxore <oxore@protonmail.com> | 2023-03-05 20:20:45 +0300 |
commit | ea807de65b0485ac58b6eae576209c64d4d5c4e9 (patch) | |
tree | b4264d20e1d700cfd9e0ece9d847a825dd1dfc03 /app/nixie_driver/nixie_driver_process.c | |
parent | dd01e7ed22cea652061f0d12cecf929e04b285e9 (diff) |
Split app code and third party libraries
Diffstat (limited to 'app/nixie_driver/nixie_driver_process.c')
-rw-r--r-- | app/nixie_driver/nixie_driver_process.c | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/app/nixie_driver/nixie_driver_process.c b/app/nixie_driver/nixie_driver_process.c new file mode 100644 index 0000000..219494e --- /dev/null +++ b/app/nixie_driver/nixie_driver_process.c @@ -0,0 +1,346 @@ +#include "nixie_driver_process.h" +#include "nixie_driver_config.h" +#include "indicate_modes_task.h" +#include "light_sensor_task.h" + +#include <stdint.h> + +// FreeRTOS includes +#include "FreeRTOS.h" +#include "task.h" +#include "queue.h" +#include "semphr.h" + +// - массив для цифр дешифратора +// - массив для номера лампы +// - счетчик номера текущей лампы +// - таймер1 для времени горения +// - таймер2 для времени затухания + +#define TUBE_HEATING_UP 0 + +static const uint16_t tube_off_digit = 0; // Символ для дешифратора, чтобы лампа не горела + +// Массив значений цифр для дешифратора. Если старший байт вперед. +// И учтено, что все значения сдвинуты на 1 влево +const uint16_t tube_digits [MAX_DIGITS] = { + // Цифра на лампе + TUBE_DIGIT_0, // 0 + TUBE_DIGIT_1, // 1 + TUBE_DIGIT_2, // 2 + TUBE_DIGIT_3, // 3 + TUBE_DIGIT_4, // 4 + TUBE_DIGIT_5, // 5 + TUBE_DIGIT_6, // 6 + TUBE_DIGIT_7, // 7 + TUBE_DIGIT_8, // 8 + TUBE_DIGIT_9, // 9 + TUBE_DIGIT_DP1, // dp1 + TUBE_DIGIT_DP2, // dp2 + TUBE_DIGIT_EMPTY, // лампа не горит +}; + +// Лампы на плате идут слева направо. Значение ячейки массива с учетом, если +// старший байт идет вперед в SPI +// И учтено, что все значения сдвинуты на 1 влево +static const uint16_t tube_num [ MAX_TUBES ] = { + TUBE_NUM_1, // 1-я лампа + TUBE_NUM_2, // 2-я лампа + TUBE_NUM_3, // 3-я лампа + TUBE_NUM_4, // 4-я лампа + TUBE_NUM_5, // 5-я лампа + TUBE_NUM_6, // 6-я лампа +}; + + +// Текущий буфер с данными-цифрами на лампы +static uint16_t curr_tube_bufer [ MAX_TUBES ] = { + TUBE_DIGIT_1, // 0 + TUBE_DIGIT_1, // 1 + TUBE_DIGIT_1, // 2 + TUBE_DIGIT_1, // 3 + TUBE_DIGIT_1, // 4 + TUBE_DIGIT_1, // 5 +}; + + +// Яркость ------------------------------------------------------------------ // + +// горит / не горит +// time1 / time2 +// 1 9 +// 2 8 +// 3 7 +// 4 6 +// 5 6 +// 6 4 +// 7 3 +// 8 2 +// 9 1 +// 10 0 + +#define TIME_PERIOD_TCONST (uint32_t)80 // Время полного периода частоты работы ламп. Единица измерения зависит от настройки + // таймера. В данном случае таймер тикает раз в 100 мкс, значит Т = 80 => T = 80*100 = 8000мкс = 8мс +#define TIME_MIN (uint32_t)1 // Минимальный шаг времени таймера = 100 мкс. Минимальное время горения лампы + +// - добавить состояния DARK и LIGHT +// (по сути это только комбинации TIME_ON и TIME_OFF) +#define TIME_ON 2//5//20 +#define TIME_OFF 23//22 +// Время паузы после вкл/выкл всез ламп поочереди +#define TIME_OFF_BRIGHT 0 +#define TIME_OFF_DARK 100 + +#define TIME_TEST 10000 + +static uint32_t time_on = TIME_ON; // Время горения лампы +static uint32_t time_off = TIME_OFF; // Время на угасание лампы ( чтобы она успела погаснуть полностью ) +static uint32_t time_off2 = TIME_OFF_DARK; + +// Сообщения очереди ОСРВ +QueueHandle_t queue_new_value; +QueueHandle_t queue_new_data; +static LightSensorState_t light_sensor_state; +extern QueueHandle_t queue_light_sensor; + + +// Прототипы функций файла -------------------------------------------------- // +// Открытые +void NixieDriver_SendValue ( uint8_t *value_arr ); +// Закрытые +static void SwitchOnTube ( uint8_t tube_nbr ); +static void SwitchOffTube ( uint8_t tube_nbr ); + +static uint8_t LoadNextValueToTubes ( void ); + +static void UpdateValueForClock ( void ); +static void CheckLightSensor (void); + + +// ---------------------------------------------------------------------------- +// +// ---------------------------------------------------------------------------- +void NixieDriverInitProcess ( void ) +{ + queue_new_value = xQueueCreate ( 1, sizeof (uint8_t*) ); + configASSERT( queue_new_value ); + queue_new_data = xQueueCreate ( 1, sizeof (DataToIndicate_t) ); + configASSERT( queue_new_value ); +} + + +// ---------------------------------------------------------------------------- +// Ф-я, реализующая беспрерывный процесс динамической индикации ламп Nixie +// Ф-я вызывается из прерывания таймера, настроенного на 100 мкс +// ---------------------------------------------------------------------------- +void ProcessNixieDriverFromISR ( void ) +{ + static uint8_t process_indic_state = 0; + static uint32_t timer = TIME_ON; + static uint8_t curr_tube_num = 0; + timer++; +#if TUBE_HEATING_UP == 0 + switch ( process_indic_state ) + { + case 0: + if ( timer >= time_off ) // Ждем время горения лампы + { + curr_tube_num = LoadNextValueToTubes (); + SwitchOnTube ( curr_tube_num ); + timer = 0; + process_indic_state = 1; + } + break; + case 1: + if ( timer >= time_on ) + { + SwitchOffTube ( curr_tube_num ); + timer = 0; + process_indic_state = 0; + + if ( curr_tube_num == (MAX_TUBES - 1) ) + { + UpdateValueForClock (); + CheckLightSensor(); + + SwitchOffTube ( curr_tube_num ); + process_indic_state = 2; + timer = 0; + + } + } + break; + case 2: + if ( timer >= time_off2 ) + { + timer = time_off; + process_indic_state = 0; + } + break; + } // end switch +#endif +} + +// ---------------------------------------------------------------------------- +// Ф-я подготовки и запуска передачи байт по SPI в сдвиговые регистры +// управеления динамической индикацией. По сути включает нужную лампу +// Ф-я принимает текущий номер лампы, для которой будет формироваться +// пакет-кадр +// ---------------------------------------------------------------------------- +static void SwitchOnTube ( uint8_t tube_nbr ) +{ + // - сначала отправляем пару байт с номером лампы + // - затем отправляем пару байт с номером цифры + static uint16_t temp; + temp = 0; + temp = tube_num [ tube_nbr ]; + temp |= curr_tube_bufer [ tube_nbr ]; + NIX_DRIVER_RESET_ST_PIN; + // Т.к. точки на лампах управляются напрямую с МК через GPIO, + // то нужно проверять вручную идет ли в пакете точка + // Маленький нюанс: + // Если мы выставим сигнал на точки раньше, чем передадим пакет на включение ламп по SPI, + // то по идее точки включатся раньше, чем подастся сигнал ST + if (curr_tube_bufer [ tube_nbr ] & TUBE_DIGIT_DP1) + { + NIX_DRIVER_SET_TUB_DP1_PIN; + } + else + { + NIX_DRIVER_RESET_TUB_DP1_PIN; + } + if (curr_tube_bufer [ tube_nbr ] & TUBE_DIGIT_DP2) + { + NIX_DRIVER_SET_TUB_DP2_PIN; + } + else + { + NIX_DRIVER_RESET_TUB_DP2_PIN; + } + SPI_I2S_SendData16 ( NIX_SPIx, temp ); + SPI_I2S_ITConfig ( NIX_SPIx, SPI_I2S_IT_TXE, ENABLE ); +} + +// ---------------------------------------------------------------------------- +// Ф-я отключает лампу +// ---------------------------------------------------------------------------- +static void SwitchOffTube ( uint8_t tube_nbr ) +{ + NIX_DRIVER_RESET_ST_PIN; + NIX_DRIVER_RESET_TUB_DP1_PIN; + NIX_DRIVER_RESET_TUB_DP2_PIN; + SPI_I2S_SendData16 ( NIX_SPIx, tube_off_digit ); + SPI_I2S_ITConfig ( NIX_SPIx, SPI_I2S_IT_TXE, ENABLE ); +} + +#if TUBE_HEATING_UP == 1 +// ---------------------------------------------------------------------------- +// Временная ф-я для прогрева каждой лампы по каждому катоду +// ---------------------------------------------------------------------------- +static uint8_t LoadNextValueToTubes ( void ) +{ + static uint8_t curr_tube_num = 0; + static uint8_t curr_digit = 0; + if ( curr_digit == 10 ) + { + if ( curr_tube_num == 5 ) + { + curr_tube_num = 0; + } + else + { + curr_tube_num++; + if ( curr_tube_num == 1 ) { curr_tube_num++; } + } + curr_digit = 0; + } + + curr_tube_bufer [ curr_tube_num ] = tube_digits [ curr_digit ]; + curr_digit++; + + return curr_tube_num; +} + +#else + +static uint8_t LoadNextValueToTubes ( void ) +{ + static uint8_t curr_tube_num = 5; + if ( curr_tube_num == 5 ) + { + curr_tube_num = 0; + } + else + { + curr_tube_num++; + } + return curr_tube_num; +} + +#endif + +// ---------------------------------------------------------------------------- +// Обновления значения выводимого на индикаторы +// Ф-я вызывается из ф-ии ProcessNixieDriverFromISR () после вывода одного +// цикла ( то есть 6-ти индикаторов ) +// ---------------------------------------------------------------------------- + +// - внимание! нужно сделать два буфера, из которых в прерывании берутся +// данные на передачу в лампы в SPI. Это нужно, чтобы не тратить время на +// заполнение данных буфера. Сделать флаг или семафор. Пока из одного +// буфера данные уходят, то в другой заполняют новые данные. А когда они +// заполнятся, то просто поменять указатель на массив. + +// - сделать защиту от выхода за границы массива tube_digits [10] +// (не больше 10) + +static void UpdateValueForClock ( void ) +{ + // - проверяем сообщение очереди с новыми данными для отображения + // если есть, то заполняем буфер curr_tube_bufer [] новыми значениями + DataToIndicate_t data_struct; + + if ( pdPASS == xQueueReceive ( queue_new_data, &data_struct, 0 ) ) + { + curr_tube_bufer [0] = tube_digits [ data_struct.indic_1 ]; + curr_tube_bufer [1] = tube_digits [ data_struct.indic_2 ]; + curr_tube_bufer [2] = tube_digits [ data_struct.indic_3 ]; + curr_tube_bufer [3] = tube_digits [ data_struct.indic_4 ]; + curr_tube_bufer [4] = tube_digits [ data_struct.indic_5 ]; + curr_tube_bufer [5] = tube_digits [ data_struct.indic_6 ]; + } +} + + +// ---------------------------------------------------------------------------- +// +// ---------------------------------------------------------------------------- +static void CheckLightSensor (void) +{ + //LightSensorState_t light_sensor_state; + if ( pdPASS == xQueueReceive ( queue_light_sensor, &light_sensor_state, 0 ) ) + { + if (light_sensor_state == LIGHT_SENSOR_STATE_LIGHT ) + { + time_on = TIME_OFF; + time_off = TIME_ON; + time_off2 = TIME_OFF_BRIGHT;//TIME_OFF_DARK; + } + else + { + time_on = TIME_ON; + time_off = TIME_OFF; + time_off2 = TIME_OFF_DARK;//TIME_OFF_BRIGHT; + } + } +} + + +// ---------------------------------------------------------------------------- +// Ф-я кладет сообщение в очередь ОС и передает указатель на массив с данными +// Размер массива всегда 6 (количество ламп) +// ---------------------------------------------------------------------------- +void NixieDriver_SendValue ( uint8_t *value_arr ) +{ + xQueueSend ( queue_new_value, &value_arr, 0 ); +} |