summaryrefslogtreecommitdiff
path: root/app/nixie_driver/nixie_driver_process.c
diff options
context:
space:
mode:
authorOxore <oxore@protonmail.com>2023-03-05 20:20:45 +0300
committerOxore <oxore@protonmail.com>2023-03-05 20:20:45 +0300
commitea807de65b0485ac58b6eae576209c64d4d5c4e9 (patch)
treeb4264d20e1d700cfd9e0ece9d847a825dd1dfc03 /app/nixie_driver/nixie_driver_process.c
parentdd01e7ed22cea652061f0d12cecf929e04b285e9 (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.c346
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 );
+}