Subversion Repositories DashDisplay

Rev

Rev 59 | Rev 61 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /* USER CODE BEGIN Header */
  2. /**
  3.  ******************************************************************************
  4.  * @file           : main.c
  5.  * @brief          : Main program body
  6.  ******************************************************************************
  7.  * @attention
  8.  *
  9.  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
  10.  * All rights reserved.</center></h2>
  11.  *
  12.  * This software component is licensed by ST under BSD 3-Clause license,
  13.  * the "License"; You may not use this file except in compliance with the
  14.  * License. You may obtain a copy of the License at:
  15.  *                        opensource.org/licenses/BSD-3-Clause
  16.  *
  17.  ******************************************************************************
  18.  */
  19. /* USER CODE END Header */
  20. /* Includes ------------------------------------------------------------------*/
  21. #include "main.h"
  22.  
  23. /* Private includes ----------------------------------------------------------*/
  24. /* USER CODE BEGIN Includes */
  25.  
  26. #include "libPLX/plx.h"
  27. #include "libSerial/serial.H"
  28. #include "libSmallPrintf/small_printf.h"
  29. #include "libNMEA/nmea.h"
  30. #include "switches.h"
  31.  
  32. /* USER CODE END Includes */
  33.  
  34. /* Private typedef -----------------------------------------------------------*/
  35. /* USER CODE BEGIN PTD */
  36.  
  37. /* USER CODE END PTD */
  38.  
  39. /* Private define ------------------------------------------------------------*/
  40. /* USER CODE BEGIN PD */
  41. /* USER CODE END PD */
  42.  
  43. /* Private macro -------------------------------------------------------------*/
  44. /* USER CODE BEGIN PM */
  45.  
  46. /* USER CODE END PM */
  47.  
  48. /* Private variables ---------------------------------------------------------*/
  49. SPI_HandleTypeDef hspi1;
  50.  
  51. TIM_HandleTypeDef htim2;
  52. TIM_HandleTypeDef htim3;
  53. TIM_HandleTypeDef htim9;
  54.  
  55. UART_HandleTypeDef huart4;
  56. UART_HandleTypeDef huart1;
  57. UART_HandleTypeDef huart2;
  58. UART_HandleTypeDef huart3;
  59.  
  60. /* USER CODE BEGIN PV */
  61. /* Private variables ---------------------------------------------------------*/
  62.  
  63. context_t contexts[MAX_DISPLAYS];
  64.  
  65. /* timeout when the ignition is switched off */
  66. #define IGNITION_OFF_TIMEOUT 30000UL
  67.  
  68. #define LOGGER_INTERVAL 500UL
  69.  
  70. const int DialTimeout = 10000; // about 10 seconds after twiddle, save the dial position.
  71.  
  72. nvram_info_t dial_nvram[MAX_DISPLAYS] __attribute__((section(".NVRAM_Data")));
  73.  
  74. info_t Info[MAXRDG];
  75.  
  76. /// \brief storage for incoming data
  77. data_t Data;
  78.  
  79. int PLXItems;
  80.  
  81. uint32_t Latch_Timer = IGNITION_OFF_TIMEOUT;
  82.  
  83. // location for GPS data
  84. Location loc;
  85.  
  86. /* USER CODE END PV */
  87.  
  88. /* Private function prototypes -----------------------------------------------*/
  89. void SystemClock_Config(void);
  90. static void MX_GPIO_Init(void);
  91. static void MX_SPI1_Init(void);
  92. static void MX_USART1_UART_Init(void);
  93. static void MX_USART2_UART_Init(void);
  94. static void MX_USART3_UART_Init(void);
  95. static void MX_TIM3_Init(void);
  96. static void MX_TIM9_Init(void);
  97. static void MX_TIM2_Init(void);
  98. static void MX_UART4_Init(void);
  99. /* USER CODE BEGIN PFP */
  100.  
  101. // the dial is the switch number we are using.
  102. // suppress is the ItemIndex we wish to suppress on this display
  103. int DisplayCurrent(int dial, int suppress)
  104. {
  105.   if (contexts[dial].knobPos < 0)
  106.     return -1;
  107.   return cc_display(dial, suppress);
  108. }
  109.  
  110. void sendString(usart_ctl *ctl, char *string, int length)
  111. {
  112.   int i;
  113.   for (i = 0; i < length; i++)
  114.     PutCharSerial(ctl, string[i]);
  115. }
  116.  
  117. /// \note this code doesnt work so it leaves speed as 9600.
  118. /// \brief Setup Bluetooth module
  119. void initModule(usart_ctl *ctl, uint32_t baudRate)
  120. {
  121.   char initBuf[30];
  122.   // switch to command mode
  123.   HAL_GPIO_WritePin(BT_BUTTON_GPIO_Port, BT_BUTTON_Pin, GPIO_PIN_RESET);
  124.   HAL_Delay(500);
  125.   int initLen = small_sprintf(initBuf, "AT+UART=%ul,1,2\n", baudRate);
  126.   setBaud(ctl, 38400);
  127.   sendString(ctl, initBuf, initLen);
  128.   TxWaitEmpty(ctl);
  129.   // switch back to normal comms at new baud rate
  130.  
  131.   HAL_GPIO_WritePin(BT_BUTTON_GPIO_Port, BT_BUTTON_Pin, GPIO_PIN_SET);
  132.   setBaud(ctl, baudRate);
  133.   HAL_Delay(100);
  134. }
  135.  
  136. // workspace for RMC data read from GPS module.
  137. uint8_t rmc_buff[80];
  138. uint16_t rmc_length;
  139.  
  140. uint8_t rmc_callback(uint8_t *data, uint16_t length)
  141. {
  142.   rmc_length = length;
  143.   memcpy(rmc_buff, data, length);
  144. }
  145.  
  146. /* USER CODE END PFP */
  147.  
  148. /* Private user code ---------------------------------------------------------*/
  149. /* USER CODE BEGIN 0 */
  150.  
  151. /* USER CODE END 0 */
  152.  
  153. /**
  154.  * @brief  The application entry point.
  155.  * @retval int
  156.  */
  157. int main(void)
  158. {
  159.   /* USER CODE BEGIN 1 */
  160.   __HAL_RCC_SPI1_CLK_ENABLE();
  161.   __HAL_RCC_USART1_CLK_ENABLE(); // PLX main port
  162.   __HAL_RCC_USART2_CLK_ENABLE(); // debug port
  163.   __HAL_RCC_USART3_CLK_ENABLE(); // Bluetooth port
  164.   __HAL_RCC_UART4_CLK_ENABLE(); // NMEA0183 port
  165.  
  166.   __HAL_RCC_TIM3_CLK_ENABLE();
  167.  
  168.   __HAL_RCC_TIM9_CLK_ENABLE();
  169.  
  170.   /* USER CODE END 1 */
  171.  
  172.   /* MCU Configuration--------------------------------------------------------*/
  173.  
  174.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  175.   HAL_Init();
  176.  
  177.   /* USER CODE BEGIN Init */
  178.  
  179.   /* USER CODE END Init */
  180.  
  181.   /* Configure the system clock */
  182.   SystemClock_Config();
  183.  
  184.   /* USER CODE BEGIN SysInit */
  185.   // Switch handler called on sysTick interrupt.
  186.   InitSwitches();
  187.  
  188.   /* USER CODE END SysInit */
  189.  
  190.   /* Initialize all configured peripherals */
  191.   MX_GPIO_Init();
  192.   MX_SPI1_Init();
  193.   MX_USART1_UART_Init();
  194.   MX_USART2_UART_Init();
  195.   MX_USART3_UART_Init();
  196.   MX_TIM3_Init();
  197.   MX_TIM9_Init();
  198.   MX_TIM2_Init();
  199.   MX_UART4_Init();
  200.   /* USER CODE BEGIN 2 */
  201.  
  202.   /* Turn on USART1 IRQ */
  203.   HAL_NVIC_SetPriority(USART1_IRQn, 2, 0);
  204.   HAL_NVIC_EnableIRQ(USART1_IRQn);
  205.  
  206.   /* Turn on USART2 IRQ  */
  207.   HAL_NVIC_SetPriority(USART2_IRQn, 4, 0);
  208.   HAL_NVIC_EnableIRQ(USART2_IRQn);
  209.  
  210.   /* turn on USART3 IRQ */
  211.   HAL_NVIC_SetPriority(USART3_IRQn, 4, 0);
  212.   HAL_NVIC_EnableIRQ(USART3_IRQn);
  213.  
  214.   /* turn on UART4 IRQ */
  215.   HAL_NVIC_SetPriority(UART4_IRQn, 4, 0);
  216.   HAL_NVIC_EnableIRQ(UART4_IRQn);
  217.  
  218.   /* setup the USART control blocks */
  219.   init_usart_ctl(&uc1, &huart1);
  220.   init_usart_ctl(&uc2, &huart2);
  221.   init_usart_ctl(&uc3, &huart3);
  222.   init_usart_ctl(&uc4, &huart4);
  223.  
  224.   EnableSerialRxInterrupt(&uc1);
  225.   EnableSerialRxInterrupt(&uc2);
  226.   EnableSerialRxInterrupt(&uc3);
  227.   EnableSerialRxInterrupt(&uc4);
  228.  
  229.   HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
  230.  
  231.   HAL_TIM_Encoder_Start(&htim9, TIM_CHANNEL_ALL);
  232.  
  233.   initModule(&uc3, 9600);
  234.  
  235.   // Initialise UART for 4800 baud NMEA
  236.   setBaud(&uc2, 4800);
  237.  
  238.   // Initialuse UART4 for 4800 baud NMEA.
  239.   setBaud(&uc4, 4800);
  240.  
  241.   cc_init();
  242.  
  243.   int i;
  244.   for (i = 0; i < 2; i++)
  245.   {
  246.     dial_pos[i] = 0; // default to items 0 and 1
  247.     contexts[i].knobPos = -1;
  248.   }
  249.  
  250.   /* reset the display timeout, latch on power from accessories */
  251.   Latch_Timer = IGNITION_OFF_TIMEOUT;
  252.   HAL_GPIO_WritePin(POWER_LATCH_GPIO_Port, POWER_LATCH_Pin, GPIO_PIN_RESET);
  253.  
  254.   setRmcCallback(&rmc_callback);
  255.  
  256.   /* USER CODE END 2 */
  257.  
  258.   /* Infinite loop */
  259.   /* USER CODE BEGIN WHILE */
  260.   while (1)
  261.   {
  262.  
  263.     /* while ignition is on, keep resetting power latch timer */
  264.     if (HAL_GPIO_ReadPin(IGNITION_GPIO_Port, IGNITION_Pin) == GPIO_PIN_RESET)
  265.     {
  266.       Latch_Timer = HAL_GetTick() + IGNITION_OFF_TIMEOUT;
  267.     }
  268.     else
  269.     {
  270.       /* if the ignition has been off for a while, then turn off power */
  271.       if (HAL_GetTick() > Latch_Timer)
  272.       {
  273.         HAL_GPIO_WritePin(POWER_LATCH_GPIO_Port, POWER_LATCH_Pin,
  274.                           GPIO_PIN_RESET);
  275.       }
  276.     }
  277.  
  278.     uint32_t timeout = 0; //
  279.  
  280.     uint32_t nextTick = HAL_GetTick() + LOGGER_INTERVAL;
  281.     uint8_t log = 0;
  282.     // PLX decoder protocols
  283.     char PLXPacket = 0;
  284.     for (i = 0; i < MAXRDG; i++)
  285.     {
  286.       Info[i].Max = 0;
  287.       Info[i].Min = 0xFFF; // 12 bit max value
  288.     }
  289.  
  290.     int PLXPtr = 0;
  291.  
  292.     while (1)
  293.     {
  294.  
  295.       // poll GPS Position/time on UART4
  296.       bool stat = updateLocation(&loc, &uc4);
  297.       if (loc.good)
  298.       {
  299.  
  300.         loc.good = false;
  301.       }
  302.       if (loc.valid == 'V')
  303.         memset(loc.time, '-', 6);
  304.  
  305.       // Handle the bluetooth pairing / reset function by pressing both buttons.
  306.       if ((push_pos[0] == 1) && (push_pos[1] == 1))
  307.       {
  308.         HAL_GPIO_WritePin(BT_BUTTON_GPIO_Port, BT_BUTTON_Pin,
  309.                           GPIO_PIN_RESET);
  310.       }
  311.       else
  312.       {
  313.         HAL_GPIO_WritePin(BT_BUTTON_GPIO_Port, BT_BUTTON_Pin,
  314.                           GPIO_PIN_SET);
  315.       }
  316.  
  317.       uint16_t cc = SerialCharsReceived(&uc1);
  318.       int chr;
  319.       if (cc == 0)
  320.       {
  321.         timeout++;
  322.         if (timeout % 1000 == 0)
  323.         {
  324.           const char msg[] = "Timeout\r\n";
  325.           sendString(&uc3, msg, sizeof(msg));
  326.         }
  327.  
  328.         if (timeout > 60000)
  329.         {
  330.  
  331.           // do turn off screen
  332.         }
  333.       }
  334.       for (chr = 0; chr < cc; chr++)
  335.       {
  336.         char c = GetCharSerial(&uc1);
  337.  
  338.         if (c == PLX_Start) // at any time if the start byte appears, reset the pointers
  339.         {
  340.           PLXPtr = 0; // reset the pointer
  341.           PLXPacket = 1;
  342.           timeout = 0; // Reset the timer
  343.           if (HAL_GetTick() > nextTick)
  344.           {
  345.             nextTick = HAL_GetTick() + LOGGER_INTERVAL;
  346.             log = 1;
  347.           }
  348.           else
  349.             log = 0;
  350.         }
  351.         else if (c == PLX_Stop)
  352.         {
  353.           if (PLXPacket)
  354.           {
  355.             // we can now decode the selected parameter
  356.             PLXItems = PLXPtr / sizeof(PLX_SensorInfo); // total
  357.             // saturate the rotary switch position
  358.  
  359.             // process min/max
  360.             for (i = 0; i < PLXItems; i++)
  361.             {
  362.               Info[i].observation = ConvPLX(Data.Sensor[i].AddrH,
  363.                                             Data.Sensor[i].AddrL);
  364.               Info[i].instance = Data.Sensor[i].Instance;
  365.               Info[i].data = ConvPLX(Data.Sensor[i].ReadingH,
  366.                                      Data.Sensor[i].ReadingL);
  367.               if (Info[i].data > Info[i].Max)
  368.               {
  369.                 Info[i].Max = Info[i].data;
  370.               }
  371.               if (Info[i].data < Info[i].Min)
  372.               {
  373.                 Info[i].Min = Info[i].data;
  374.               }
  375.  
  376.               // Send item to BT
  377.               if (rmc_length)
  378.               {
  379.                 sendString(&uc3, rmc_buff, rmc_length);
  380.                 rmc_length = 0;
  381.               }
  382.  
  383.               if (log)
  384.               {
  385.  
  386.                 char outbuff[100];
  387.  
  388.                 int cnt = small_sprintf(outbuff,
  389.                                         "$PLLOG,%d,%d,%d",
  390.                                         Info[i].observation,
  391.                                         Info[i].instance,
  392.                                         Info[i].data);
  393.  
  394.                 // NMEA style checksum
  395.                 int ck;
  396.                 int sum = 0;
  397.                 for (ck = 1; ck < cnt; ck++)
  398.                   sum += outbuff[ck];
  399.                 cnt += small_sprintf(outbuff + cnt, "*%02X\n",
  400.                                      sum & 0xFF);
  401.                 sendString(&uc3, outbuff, cnt);
  402.               }
  403.             }
  404.  
  405.             // now to display the information
  406.             int suppress = DisplayCurrent(0, -1);
  407.             DisplayCurrent(1, suppress);
  408.           }
  409.           PLXPtr = 0;
  410.           PLXPacket = 0;
  411.         }
  412.         else if (c > PLX_Stop) // illegal char, restart reading
  413.         {
  414.           PLXPacket = 0;
  415.           PLXPtr = 0;
  416.         }
  417.         else if (PLXPacket && PLXPtr < sizeof(Data.Bytes))
  418.         {
  419.           Data.Bytes[PLXPtr++] = c;
  420.         }
  421.       }
  422.  
  423.       HAL_Delay(1);
  424.  
  425.       for (i = 0; i < MAX_DISPLAYS; i++)
  426.       {
  427.         if (dial_pos[i] < 0)
  428.           dial_pos[i] = PLXItems - 1;
  429.         if (dial_pos[i] >= PLXItems)
  430.           dial_pos[i] = 0;
  431.  
  432.         int prevPos = contexts[i].knobPos;
  433.         if (contexts[i].knobPos >= 0)
  434.           contexts[i].knobPos = dial_pos[i];
  435.         // if the dial position was changed then reset timer
  436.         if (prevPos != contexts[i].knobPos)
  437.           contexts[i].dial_timer = DialTimeout;
  438.  
  439.         cc_check_nvram(i);
  440.         if (contexts[i].knobPos >= 0)
  441.           dial_pos[i] = contexts[i].knobPos;
  442.       }
  443.     }
  444.     /* USER CODE END WHILE */
  445.  
  446.     /* USER CODE BEGIN 3 */
  447.   }
  448.   /* USER CODE END 3 */
  449. }
  450.  
  451. /**
  452.  * @brief System Clock Configuration
  453.  * @retval None
  454.  */
  455. void SystemClock_Config(void)
  456. {
  457.   RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  458.   RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
  459.  
  460.   /** Configure the main internal regulator output voltage
  461.    */
  462.   __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  463.   /** Initializes the RCC Oscillators according to the specified parameters
  464.    * in the RCC_OscInitTypeDef structure.
  465.    */
  466.   RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  467.   RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  468.   RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  469.   RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  470.   RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12;
  471.   RCC_OscInitStruct.PLL.PLLDIV = RCC_PLL_DIV3;
  472.   if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  473.   {
  474.     Error_Handler();
  475.   }
  476.   /** Initializes the CPU, AHB and APB buses clocks
  477.    */
  478.   RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
  479.   RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  480.   RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  481.   RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  482.   RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
  483.  
  484.   if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
  485.   {
  486.     Error_Handler();
  487.   }
  488. }
  489.  
  490. /**
  491.  * @brief SPI1 Initialization Function
  492.  * @param None
  493.  * @retval None
  494.  */
  495. static void MX_SPI1_Init(void)
  496. {
  497.  
  498.   /* USER CODE BEGIN SPI1_Init 0 */
  499.  
  500.   /* USER CODE END SPI1_Init 0 */
  501.  
  502.   /* USER CODE BEGIN SPI1_Init 1 */
  503.  
  504.   /* USER CODE END SPI1_Init 1 */
  505.   /* SPI1 parameter configuration*/
  506.   hspi1.Instance = SPI1;
  507.   hspi1.Init.Mode = SPI_MODE_MASTER;
  508.   hspi1.Init.Direction = SPI_DIRECTION_1LINE;
  509.   hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  510.   hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH;
  511.   hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
  512.   hspi1.Init.NSS = SPI_NSS_SOFT;
  513.   hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
  514.   hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  515.   hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  516.   hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  517.   hspi1.Init.CRCPolynomial = 10;
  518.   if (HAL_SPI_Init(&hspi1) != HAL_OK)
  519.   {
  520.     Error_Handler();
  521.   }
  522.   /* USER CODE BEGIN SPI1_Init 2 */
  523.  
  524.   /* USER CODE END SPI1_Init 2 */
  525. }
  526.  
  527. /**
  528.  * @brief TIM2 Initialization Function
  529.  * @param None
  530.  * @retval None
  531.  */
  532. static void MX_TIM2_Init(void)
  533. {
  534.  
  535.   /* USER CODE BEGIN TIM2_Init 0 */
  536.  
  537.   /* USER CODE END TIM2_Init 0 */
  538.  
  539.   TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  540.   TIM_MasterConfigTypeDef sMasterConfig = {0};
  541.  
  542.   /* USER CODE BEGIN TIM2_Init 1 */
  543.  
  544.   /* USER CODE END TIM2_Init 1 */
  545.   htim2.Instance = TIM2;
  546.   htim2.Init.Prescaler = 0;
  547.   htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  548.   htim2.Init.Period = 65535;
  549.   htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  550.   htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  551.   if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  552.   {
  553.     Error_Handler();
  554.   }
  555.   sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  556.   if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
  557.   {
  558.     Error_Handler();
  559.   }
  560.   sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  561.   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  562.   if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  563.   {
  564.     Error_Handler();
  565.   }
  566.   /* USER CODE BEGIN TIM2_Init 2 */
  567.  
  568.   /* USER CODE END TIM2_Init 2 */
  569. }
  570.  
  571. /**
  572.  * @brief TIM3 Initialization Function
  573.  * @param None
  574.  * @retval None
  575.  */
  576. static void MX_TIM3_Init(void)
  577. {
  578.  
  579.   /* USER CODE BEGIN TIM3_Init 0 */
  580.  
  581.   /* USER CODE END TIM3_Init 0 */
  582.  
  583.   TIM_Encoder_InitTypeDef sConfig = {0};
  584.   TIM_MasterConfigTypeDef sMasterConfig = {0};
  585.  
  586.   /* USER CODE BEGIN TIM3_Init 1 */
  587.  
  588.   /* USER CODE END TIM3_Init 1 */
  589.   htim3.Instance = TIM3;
  590.   htim3.Init.Prescaler = 0;
  591.   htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  592.   htim3.Init.Period = 65535;
  593.   htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  594.   htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  595.   sConfig.EncoderMode = TIM_ENCODERMODE_TI1;
  596.   sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
  597.   sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
  598.   sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
  599.   sConfig.IC1Filter = 15;
  600.   sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
  601.   sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
  602.   sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
  603.   sConfig.IC2Filter = 15;
  604.   if (HAL_TIM_Encoder_Init(&htim3, &sConfig) != HAL_OK)
  605.   {
  606.     Error_Handler();
  607.   }
  608.   sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  609.   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  610.   if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  611.   {
  612.     Error_Handler();
  613.   }
  614.   /* USER CODE BEGIN TIM3_Init 2 */
  615.  
  616.   /* USER CODE END TIM3_Init 2 */
  617. }
  618.  
  619. /**
  620.  * @brief TIM9 Initialization Function
  621.  * @param None
  622.  * @retval None
  623.  */
  624. static void MX_TIM9_Init(void)
  625. {
  626.  
  627.   /* USER CODE BEGIN TIM9_Init 0 */
  628.  
  629.   /* USER CODE END TIM9_Init 0 */
  630.  
  631.   TIM_Encoder_InitTypeDef sConfig = {0};
  632.   TIM_MasterConfigTypeDef sMasterConfig = {0};
  633.  
  634.   /* USER CODE BEGIN TIM9_Init 1 */
  635.  
  636.   /* USER CODE END TIM9_Init 1 */
  637.   htim9.Instance = TIM9;
  638.   htim9.Init.Prescaler = 0;
  639.   htim9.Init.CounterMode = TIM_COUNTERMODE_UP;
  640.   htim9.Init.Period = 65535;
  641.   htim9.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  642.   htim9.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  643.   sConfig.EncoderMode = TIM_ENCODERMODE_TI1;
  644.   sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
  645.   sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
  646.   sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
  647.   sConfig.IC1Filter = 15;
  648.   sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
  649.   sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
  650.   sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
  651.   sConfig.IC2Filter = 0;
  652.   if (HAL_TIM_Encoder_Init(&htim9, &sConfig) != HAL_OK)
  653.   {
  654.     Error_Handler();
  655.   }
  656.   sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  657.   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  658.   if (HAL_TIMEx_MasterConfigSynchronization(&htim9, &sMasterConfig) != HAL_OK)
  659.   {
  660.     Error_Handler();
  661.   }
  662.   /* USER CODE BEGIN TIM9_Init 2 */
  663.  
  664.   /* USER CODE END TIM9_Init 2 */
  665. }
  666.  
  667. /**
  668.  * @brief UART4 Initialization Function
  669.  * @param None
  670.  * @retval None
  671.  */
  672. static void MX_UART4_Init(void)
  673. {
  674.  
  675.   /* USER CODE BEGIN UART4_Init 0 */
  676.  
  677.   /* USER CODE END UART4_Init 0 */
  678.  
  679.   /* USER CODE BEGIN UART4_Init 1 */
  680.  
  681.   /* USER CODE END UART4_Init 1 */
  682.   huart4.Instance = UART4;
  683.   huart4.Init.BaudRate = 4800;
  684.   huart4.Init.WordLength = UART_WORDLENGTH_8B;
  685.   huart4.Init.StopBits = UART_STOPBITS_1;
  686.   huart4.Init.Parity = UART_PARITY_NONE;
  687.   huart4.Init.Mode = UART_MODE_TX_RX;
  688.   huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  689.   huart4.Init.OverSampling = UART_OVERSAMPLING_16;
  690.   if (HAL_UART_Init(&huart4) != HAL_OK)
  691.   {
  692.     Error_Handler();
  693.   }
  694.   /* USER CODE BEGIN UART4_Init 2 */
  695.  
  696.   /* USER CODE END UART4_Init 2 */
  697. }
  698.  
  699. /**
  700.  * @brief USART1 Initialization Function
  701.  * @param None
  702.  * @retval None
  703.  */
  704. static void MX_USART1_UART_Init(void)
  705. {
  706.  
  707.   /* USER CODE BEGIN USART1_Init 0 */
  708.  
  709.   /* USER CODE END USART1_Init 0 */
  710.  
  711.   /* USER CODE BEGIN USART1_Init 1 */
  712.  
  713.   /* USER CODE END USART1_Init 1 */
  714.   huart1.Instance = USART1;
  715.   huart1.Init.BaudRate = 19200;
  716.   huart1.Init.WordLength = UART_WORDLENGTH_8B;
  717.   huart1.Init.StopBits = UART_STOPBITS_1;
  718.   huart1.Init.Parity = UART_PARITY_NONE;
  719.   huart1.Init.Mode = UART_MODE_TX_RX;
  720.   huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  721.   huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  722.   if (HAL_UART_Init(&huart1) != HAL_OK)
  723.   {
  724.     Error_Handler();
  725.   }
  726.   /* USER CODE BEGIN USART1_Init 2 */
  727.  
  728.   /* USER CODE END USART1_Init 2 */
  729. }
  730.  
  731. /**
  732.  * @brief USART2 Initialization Function
  733.  * @param None
  734.  * @retval None
  735.  */
  736. static void MX_USART2_UART_Init(void)
  737. {
  738.  
  739.   /* USER CODE BEGIN USART2_Init 0 */
  740.  
  741.   /* USER CODE END USART2_Init 0 */
  742.  
  743.   /* USER CODE BEGIN USART2_Init 1 */
  744.  
  745.   /* USER CODE END USART2_Init 1 */
  746.   huart2.Instance = USART2;
  747.   huart2.Init.BaudRate = 115200;
  748.   huart2.Init.WordLength = UART_WORDLENGTH_8B;
  749.   huart2.Init.StopBits = UART_STOPBITS_1;
  750.   huart2.Init.Parity = UART_PARITY_NONE;
  751.   huart2.Init.Mode = UART_MODE_TX_RX;
  752.   huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  753.   huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  754.   if (HAL_UART_Init(&huart2) != HAL_OK)
  755.   {
  756.     Error_Handler();
  757.   }
  758.   /* USER CODE BEGIN USART2_Init 2 */
  759.  
  760.   /* USER CODE END USART2_Init 2 */
  761. }
  762.  
  763. /**
  764.  * @brief USART3 Initialization Function
  765.  * @param None
  766.  * @retval None
  767.  */
  768. static void MX_USART3_UART_Init(void)
  769. {
  770.  
  771.   /* USER CODE BEGIN USART3_Init 0 */
  772.  
  773.   /* USER CODE END USART3_Init 0 */
  774.  
  775.   /* USER CODE BEGIN USART3_Init 1 */
  776.  
  777.   /* USER CODE END USART3_Init 1 */
  778.   huart3.Instance = USART3;
  779.   huart3.Init.BaudRate = 19200;
  780.   huart3.Init.WordLength = UART_WORDLENGTH_8B;
  781.   huart3.Init.StopBits = UART_STOPBITS_1;
  782.   huart3.Init.Parity = UART_PARITY_NONE;
  783.   huart3.Init.Mode = UART_MODE_TX_RX;
  784.   huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  785.   huart3.Init.OverSampling = UART_OVERSAMPLING_16;
  786.   if (HAL_UART_Init(&huart3) != HAL_OK)
  787.   {
  788.     Error_Handler();
  789.   }
  790.   /* USER CODE BEGIN USART3_Init 2 */
  791.  
  792.   /* USER CODE END USART3_Init 2 */
  793. }
  794.  
  795. /**
  796.  * @brief GPIO Initialization Function
  797.  * @param None
  798.  * @retval None
  799.  */
  800. static void MX_GPIO_Init(void)
  801. {
  802.   GPIO_InitTypeDef GPIO_InitStruct = {0};
  803.  
  804.   /* GPIO Ports Clock Enable */
  805.   __HAL_RCC_GPIOH_CLK_ENABLE();
  806.   __HAL_RCC_GPIOA_CLK_ENABLE();
  807.   __HAL_RCC_GPIOC_CLK_ENABLE();
  808.   __HAL_RCC_GPIOB_CLK_ENABLE();
  809.  
  810.   /*Configure GPIO pin Output Level */
  811.   HAL_GPIO_WritePin(SPI_NSS1_GPIO_Port, SPI_NSS1_Pin, GPIO_PIN_SET);
  812.  
  813.   /*Configure GPIO pin Output Level */
  814.   HAL_GPIO_WritePin(GPIOA, SPI_CD_Pin | BT_BUTTON_Pin, GPIO_PIN_RESET);
  815.  
  816.   /*Configure GPIO pin Output Level */
  817.   HAL_GPIO_WritePin(GPIOC, SPI_RESET_Pin | POWER_LATCH_Pin | USB_PWR_Pin, GPIO_PIN_RESET);
  818.  
  819.   /*Configure GPIO pin Output Level */
  820.   HAL_GPIO_WritePin(SPI_NSS2_GPIO_Port, SPI_NSS2_Pin, GPIO_PIN_SET);
  821.  
  822.   /*Configure GPIO pins : SPI_NSS1_Pin SPI_CD_Pin */
  823.   GPIO_InitStruct.Pin = SPI_NSS1_Pin | SPI_CD_Pin;
  824.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  825.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  826.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  827.   HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  828.  
  829.   /*Configure GPIO pins : SPI_RESET_Pin SPI_NSS2_Pin POWER_LATCH_Pin USB_PWR_Pin */
  830.   GPIO_InitStruct.Pin = SPI_RESET_Pin | SPI_NSS2_Pin | POWER_LATCH_Pin | USB_PWR_Pin;
  831.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  832.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  833.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  834.   HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  835.  
  836.   /*Configure GPIO pins : SW1_PUSH_Pin SW2_PUSH_Pin */
  837.   GPIO_InitStruct.Pin = SW1_PUSH_Pin | SW2_PUSH_Pin;
  838.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  839.   GPIO_InitStruct.Pull = GPIO_PULLUP;
  840.   HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
  841.  
  842.   /*Configure GPIO pin : IGNITION_Pin */
  843.   GPIO_InitStruct.Pin = IGNITION_Pin;
  844.   GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  845.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  846.   HAL_GPIO_Init(IGNITION_GPIO_Port, &GPIO_InitStruct);
  847.  
  848.   /*Configure GPIO pin : BT_BUTTON_Pin */
  849.   GPIO_InitStruct.Pin = BT_BUTTON_Pin;
  850.   GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
  851.   GPIO_InitStruct.Pull = GPIO_NOPULL;
  852.   GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  853.   HAL_GPIO_Init(BT_BUTTON_GPIO_Port, &GPIO_InitStruct);
  854. }
  855.  
  856. /* USER CODE BEGIN 4 */
  857.  
  858. /* USER CODE END 4 */
  859.  
  860. /**
  861.  * @brief  This function is executed in case of error occurrence.
  862.  * @retval None
  863.  */
  864. void Error_Handler(void)
  865. {
  866.   /* USER CODE BEGIN Error_Handler_Debug */
  867.   /* User can add his own implementation to report the HAL error return state */
  868.  
  869.   /* USER CODE END Error_Handler_Debug */
  870. }
  871.  
  872. #ifdef USE_FULL_ASSERT
  873. /**
  874.  * @brief  Reports the name of the source file and the source line number
  875.  *         where the assert_param error has occurred.
  876.  * @param  file: pointer to the source file name
  877.  * @param  line: assert_param error line source number
  878.  * @retval None
  879.  */
  880. void assert_failed(uint8_t *file, uint32_t line)
  881. {
  882.   /* USER CODE BEGIN 6 */
  883.   /* User can add his own implementation to report the file name and line number,
  884.      tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  885.   /* USER CODE END 6 */
  886. }
  887. #endif /* USE_FULL_ASSERT */
  888.  
  889. /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
  890.