Rev 68 | Rev 71 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 68 | Rev 70 | ||
---|---|---|---|
Line 63... | Line 63... | ||
63 | /* USER CODE BEGIN PV */ |
63 | /* USER CODE BEGIN PV */ |
64 | /* Private variables ---------------------------------------------------------*/ |
64 | /* Private variables ---------------------------------------------------------*/ |
65 | 65 | ||
66 | context_t contexts[MAX_DISPLAYS]; |
66 | context_t contexts[MAX_DISPLAYS]; |
67 | 67 | ||
68 | /* timeout when the ignition is switched off */ |
68 | ///@brief timeout when the ignition is switched off |
69 | #define IGNITION_OFF_TIMEOUT 30000UL |
69 | #define IGNITION_OFF_TIMEOUT 30000UL |
70 | 70 | ||
71 | // 500mS per logger period. |
71 | /// @brief 1000mS per logger period, print average per period |
72 | #define LOGGER_INTERVAL 500UL |
72 | #define LOGGER_INTERVAL 1000UL |
73 | 73 | ||
74 | const int DialTimeout = 100; // about 10 seconds after twiddle, save the dial position. |
74 | /// @brief about 10 seconds after twiddle, save the dial position. |
75 | - | ||
76 | nvram_info_t dial_nvram[MAX_DISPLAYS]; |
75 | const int DialTimeout = 100; |
77 | 76 | ||
- | 77 | /// @brief Data storage for readings |
|
78 | info_t Info[MAXRDG]; |
78 | info_t Info[MAXRDG]; |
79 | 79 | ||
- | 80 | /// @brief Define a null item |
|
- | 81 | const info_t nullInfo = {.Max = 0, |
|
- | 82 | .Min = 0xFFF, |
|
- | 83 | .sum = 0, |
|
- | 84 | .count = 0, |
|
- | 85 | .updated = 0, |
|
- | 86 | .lastUpdated = 0, |
|
- | 87 | .observation = PLX_MAX_OBS, |
|
- | 88 | .instance = PLX_MAX_INST}; |
|
- | 89 | ||
80 | /// \brief storage for incoming data |
90 | /// \brief storage for incoming data |
81 | data_t Data; |
91 | data_t Data; |
82 | 92 | ||
83 | int PLXItems; |
- | |
84 | - | ||
85 | uint32_t Latch_Timer = IGNITION_OFF_TIMEOUT; |
93 | uint32_t Latch_Timer = IGNITION_OFF_TIMEOUT; |
86 | 94 | ||
87 | // location for GPS data |
95 | // location for GPS data |
88 | Location loc; |
96 | Location loc; |
89 | 97 | ||
Line 110... | Line 118... | ||
110 | if (contexts[dial].knobPos < 0) |
118 | if (contexts[dial].knobPos < 0) |
111 | return -1; |
119 | return -1; |
112 | return cc_display(dial, suppress); |
120 | return cc_display(dial, suppress); |
113 | } |
121 | } |
114 | 122 | ||
115 | /// \note this code doesnt work so it leaves speed as 9600. |
123 | /// \note HC-05 only accepts : 9600,19200,38400,57600,115200,230400,460800 baud |
116 | /// \brief Setup Bluetooth module |
124 | /// \brief Setup Bluetooth module |
117 | void initModule(usart_ctl *ctl, uint32_t baudRate) |
125 | void initModule(usart_ctl *ctl, uint32_t baudRate) |
118 | { |
126 | { |
119 | char initBuf[30]; |
127 | char initBuf[30]; |
120 | // switch to command mode |
128 | // switch to command mode |
121 | HAL_GPIO_WritePin(BT_BUTTON_GPIO_Port, BT_BUTTON_Pin, GPIO_PIN_RESET); |
129 | HAL_GPIO_WritePin(BT_RESET_GPIO_Port, BT_RESET_Pin, GPIO_PIN_RESET); |
122 | HAL_Delay(500); |
130 | HAL_Delay(500); |
123 | int initLen = small_sprintf(initBuf, "AT+UART=%lu,1,2\n", baudRate); |
- | |
124 | setBaud(ctl, 38400); |
131 | setBaud(ctl, 38400); |
- | 132 | int initLen = small_sprintf(initBuf, "AT+UART=%lu,0,0\n", baudRate); |
|
- | 133 | const char buf[] = "AT+RESET\n"; |
|
125 | sendString(ctl, initBuf, initLen); |
134 | sendString(ctl, initBuf, initLen); |
- | 135 | HAL_Delay(500); |
|
- | 136 | initLen = small_sprintf(initBuf, buf); |
|
- | 137 | sendString(ctl, initBuf, initLen); |
|
- | 138 | ||
126 | TxWaitEmpty(ctl); |
139 | TxWaitEmpty(ctl); |
127 | // switch back to normal comms at new baud rate |
- | |
128 | 140 | ||
- | 141 | // clear the button press |
|
129 | HAL_GPIO_WritePin(BT_BUTTON_GPIO_Port, BT_BUTTON_Pin, GPIO_PIN_SET); |
142 | HAL_GPIO_WritePin(BT_RESET_GPIO_Port, BT_RESET_Pin, GPIO_PIN_SET); |
- | 143 | ||
- | 144 | // switch back to normal comms at new baud rate |
|
130 | setBaud(ctl, baudRate); |
145 | setBaud(ctl, baudRate); |
131 | HAL_Delay(100); |
146 | HAL_Delay(100); |
132 | } |
147 | } |
133 | 148 | ||
134 | // workspace for RMC data read from GPS module. |
149 | // workspace for RMC data read from GPS module. |
Line 146... | Line 161... | ||
146 | uint8_t btConnected() |
161 | uint8_t btConnected() |
147 | { |
162 | { |
148 | return HAL_GPIO_ReadPin(BT_STATE_GPIO_Port, BT_STATE_Pin) == GPIO_PIN_SET; |
163 | return HAL_GPIO_ReadPin(BT_STATE_GPIO_Port, BT_STATE_Pin) == GPIO_PIN_SET; |
149 | } |
164 | } |
150 | 165 | ||
- | 166 | /// @brief return true if this slot is unused |
|
- | 167 | /// @param ptr pointer to the slot to |
|
- | 168 | uint8_t isUnused(int index) |
|
- | 169 | { |
|
- | 170 | if (index < 0 || index > MAXRDG) |
|
- | 171 | return false; |
|
- | 172 | ||
- | 173 | return Info[index].instance == PLX_MAX_INST && Info[index].observation == PLX_MAX_OBS; |
|
- | 174 | } |
|
- | 175 | ||
- | 176 | /// @brief Determine if an entry is currently valid |
|
- | 177 | /// @param index the number of the array entry to display |
|
- | 178 | /// @return true if the entry contains data which is fresh |
|
- | 179 | uint8_t isValid(int index) |
|
- | 180 | { |
|
- | 181 | if (index < 0 || index > MAXRDG) |
|
- | 182 | return false; |
|
- | 183 | if (isUnused(index)) |
|
- | 184 | return false; |
|
- | 185 | ||
- | 186 | uint32_t age = HAL_GetTick() - Info[index].lastUpdated; |
|
- | 187 | ||
- | 188 | if (age > 300) |
|
- | 189 | return false; |
|
- | 190 | ||
- | 191 | return true; |
|
- | 192 | } |
|
- | 193 | ||
151 | /* USER CODE END PFP */ |
194 | /* USER CODE END PFP */ |
152 | 195 | ||
153 | /* Private user code ---------------------------------------------------------*/ |
196 | /* Private user code ---------------------------------------------------------*/ |
154 | /* USER CODE BEGIN 0 */ |
197 | /* USER CODE BEGIN 0 */ |
155 | 198 | ||
Line 234... | Line 277... | ||
234 | 277 | ||
235 | HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL); |
278 | HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL); |
236 | 279 | ||
237 | HAL_TIM_Encoder_Start(&htim9, TIM_CHANNEL_ALL); |
280 | HAL_TIM_Encoder_Start(&htim9, TIM_CHANNEL_ALL); |
238 | 281 | ||
239 | initModule(&uc3, 9600); |
282 | initModule(&uc3, 38400); |
240 | 283 | ||
241 | // Initialise UART for 4800 baud NMEA |
284 | // Initialise UART for 4800 baud NMEA |
242 | setBaud(&uc2, 4800); |
285 | setBaud(&uc2, 4800); |
243 | 286 | ||
244 | // Initialuse UART4 for 4800 baud NMEA. |
287 | // Initialuse UART4 for 4800 baud NMEA. |
Line 267... | Line 310... | ||
267 | 310 | ||
268 | uint32_t nextTick = 0; |
311 | uint32_t nextTick = 0; |
269 | uint8_t log = 0; |
312 | uint8_t log = 0; |
270 | // PLX decoder protocols |
313 | // PLX decoder protocols |
271 | char PLXPacket = 0; |
314 | char PLXPacket = 0; |
- | 315 | ||
- | 316 | ||
272 | for (i = 0; i < MAXRDG; i++) |
317 | for (i = 0; i < MAXRDG; i++) |
273 | { |
318 | { |
274 | Info[i].Max = 0; |
- | |
275 | Info[i].Min = 0xFFF; |
- | |
276 | Info[i].sum = 0; |
- | |
277 | Info[i].count = 0; |
319 | Info[i] = nullInfo; |
278 | Info[i].updated = 0; |
- | |
279 | Info[i].lastUpdated = 0; |
- | |
280 | } |
320 | } |
281 | 321 | ||
282 | int PLXPtr = 0; |
322 | int PLXPtr = 0; |
283 | int logCount = 0; |
323 | int logCount = 0; |
284 | 324 | ||
- | 325 | uint32_t resetCounter; // record time at which both reset buttons were first pressed. |
|
- | 326 | ||
285 | /* USER CODE END 2 */ |
327 | /* USER CODE END 2 */ |
286 | 328 | ||
287 | /* Infinite loop */ |
329 | /* Infinite loop */ |
288 | /* USER CODE BEGIN WHILE */ |
330 | /* USER CODE BEGIN WHILE */ |
289 | while (1) |
331 | while (1) |
Line 307... | Line 349... | ||
307 | // Handle the bluetooth pairing / reset function by pressing both buttons. |
349 | // Handle the bluetooth pairing / reset function by pressing both buttons. |
308 | if ((push_pos[0] == 1) && (push_pos[1] == 1)) |
350 | if ((push_pos[0] == 1) && (push_pos[1] == 1)) |
309 | { |
351 | { |
310 | HAL_GPIO_WritePin(BT_BUTTON_GPIO_Port, BT_BUTTON_Pin, |
352 | HAL_GPIO_WritePin(BT_BUTTON_GPIO_Port, BT_BUTTON_Pin, |
311 | GPIO_PIN_RESET); |
353 | GPIO_PIN_RESET); |
- | 354 | if (resetCounter == 0) |
|
- | 355 | resetCounter = HAL_GetTick(); |
|
312 | } |
356 | } |
313 | else |
357 | else |
314 | { |
358 | { |
315 | HAL_GPIO_WritePin(BT_BUTTON_GPIO_Port, BT_BUTTON_Pin, |
359 | HAL_GPIO_WritePin(BT_BUTTON_GPIO_Port, BT_BUTTON_Pin, |
316 | GPIO_PIN_SET); |
360 | GPIO_PIN_SET); |
- | 361 | ||
- | 362 | if (resetCounter != 0) |
|
- | 363 | { |
|
- | 364 | // Held down reset button for 10 seconds, clear NVRAM. |
|
- | 365 | if ((HAL_GetTick() - resetCounter) > 10000) |
|
- | 366 | { |
|
- | 367 | for (i = 0; i < 2; i++) |
|
- | 368 | { |
|
- | 369 | dial_pos[i] = 0; // default to items 0 and 1 |
|
- | 370 | contexts[i].knobPos = -1; // set the knob position |
|
- | 371 | contexts[i].dial_timer = 1; // timeout immediately when decremented |
|
- | 372 | } |
|
- | 373 | erase_nvram(); |
|
- | 374 | } |
|
- | 375 | resetCounter = 0; |
|
- | 376 | } |
|
317 | } |
377 | } |
318 | 378 | ||
319 | // poll GPS Position/time on UART4 |
379 | // poll GPS Position/time on UART4 |
320 | (void)updateLocation(&loc, &uc4); |
380 | (void)updateLocation(&loc, &uc4); |
321 | if (loc.valid == 'V') |
381 | if (loc.valid == 'V') |
Line 346... | Line 406... | ||
346 | 406 | ||
347 | if (log) |
407 | if (log) |
348 | { |
408 | { |
349 | log = 0; |
409 | log = 0; |
350 | // Send items to BT if it is in connected state |
410 | // Send items to BT if it is in connected state |
351 | for (int i = 0; i < PLXItems; ++i) |
411 | for (int i = 0; i < MAXRDG; ++i) |
352 | { |
412 | { |
- | 413 | if(!isValid(i)) |
|
- | 414 | continue; |
|
353 | char outbuff[100]; |
415 | char outbuff[100]; |
354 | 416 | ||
355 | int cnt = small_sprintf(outbuff, |
417 | int cnt = small_sprintf(outbuff, |
356 | "$PLLOG,%d,%d,%d,%ld", |
418 | "$PLLOG,%d,%d,%d,%ld", |
357 | logCount, |
419 | logCount, |
Line 407... | Line 469... | ||
407 | if (c == PLX_Stop) |
469 | if (c == PLX_Stop) |
408 | { |
470 | { |
409 | if (PLXPacket) |
471 | if (PLXPacket) |
410 | { |
472 | { |
411 | // we can now decode the selected parameter |
473 | // we can now decode the selected parameter |
412 | PLXItems = PLXPtr / sizeof(PLX_SensorInfo); // total |
474 | int PLXNewItems = PLXPtr / sizeof(PLX_SensorInfo); // total items in last reading batch |
413 | // saturate the rotary switch position |
- | |
414 | 475 | ||
415 | // process min/max |
476 | // process items |
416 | for (i = 0; i < PLXItems; i++) |
477 | for (i = 0; i < PLXNewItems; i++) |
417 | { |
478 | { |
- | 479 | // search to see if the item already has a slot in the Info[] array |
|
- | 480 | // match the observation and instance: if found, update entry |
|
418 | Info[i].observation = ConvPLX(Data.Sensor[i].AddrH, |
481 | enum PLX_Observations observation = ConvPLX(Data.Sensor[i].AddrH, |
419 | Data.Sensor[i].AddrL); |
482 | Data.Sensor[i].AddrL); |
- | 483 | ||
- | 484 | char instance = Data.Sensor[i].Instance; |
|
- | 485 | ||
- | 486 | // validate the current item, discard out of range |
|
420 | 487 | ||
421 | Info[i].instance = Data.Sensor[i].Instance; |
488 | if ((instance > PLX_MAX_INST) || (observation > PLX_MAX_OBS)) |
422 | Info[i].data = ConvPLX(Data.Sensor[i].ReadingH, |
489 | continue; |
- | 490 | ||
423 | Data.Sensor[i].ReadingL); |
491 | // search for the item in the list |
- | 492 | int j; |
|
424 | if (Info[i].data > Info[i].Max) |
493 | for (j = 0; j < MAXRDG; ++j) |
425 | { |
494 | { |
- | 495 | if ((Info[j].observation == observation) && (Info[j].instance == instance)) |
|
426 | Info[i].Max = Info[i].data; |
496 | break; |
427 | } |
497 | } |
- | 498 | // fallen off the end of the list of existing items without a match, so j points at next new item |
|
- | 499 | // |
|
428 | if (Info[i].data < Info[i].Min) |
500 | // Find an unused slot |
- | 501 | ||
- | 502 | if (j == MAXRDG) |
|
429 | { |
503 | { |
- | 504 | int k; |
|
- | 505 | { |
|
- | 506 | for (k = 0; k < MAXRDG; ++k) |
|
- | 507 | if (!isValid(k)) |
|
- | 508 | { |
|
- | 509 | j = k; // found a spare slot |
|
- | 510 | break; |
|
- | 511 | } |
|
- | 512 | } |
|
- | 513 | if (k == MAXRDG) |
|
- | 514 | continue; // abandon this iteration |
|
- | 515 | } |
|
- | 516 | ||
- | 517 | // give up if we are going to fall off the end of the array |
|
- | 518 | if (j > MAXRDG) |
|
- | 519 | break; |
|
- | 520 | ||
- | 521 | Info[j].observation = observation; |
|
- | 522 | ||
- | 523 | Info[j].instance = instance; |
|
- | 524 | Info[j].data = ConvPLX(Data.Sensor[j].ReadingH, |
|
- | 525 | Data.Sensor[j].ReadingL); |
|
- | 526 | if (Info[j].data > Info[j].Max) |
|
- | 527 | { |
|
- | 528 | Info[j].Max = Info[j].data; |
|
- | 529 | } |
|
- | 530 | if (Info[j].data < Info[j].Min) |
|
- | 531 | { |
|
430 | Info[i].Min = Info[i].data; |
532 | Info[j].Min = Info[j].data; |
431 | } |
533 | } |
432 | // take an average |
534 | // take an average |
433 | Info[i].sum += Info[i].data; |
535 | Info[j].sum += Info[j].data; |
434 | Info[i].count++; |
536 | Info[j].count++; |
435 | // note the last update time |
537 | // note the last update time |
436 | Info[i].lastUpdated = HAL_GetTick(); |
538 | Info[j].lastUpdated = HAL_GetTick(); |
437 | Info[i].updated = 1; // it has been updated |
539 | Info[j].updated = 1; // it has been updated |
438 | } |
540 | } |
439 | PLXPtr = 0; |
541 | PLXPtr = 0; |
440 | PLXPacket = 0; |
542 | PLXPacket = 0; |
- | 543 | ||
- | 544 | // scan through and invalidate all old items |
|
- | 545 | for (int i = 0; i < MAXRDG; ++i) |
|
- | 546 | { |
|
- | 547 | if (!isValid(i)) |
|
- | 548 | Info[i] = nullInfo; |
|
- | 549 | } |
|
- | 550 | ||
441 | break; // something to process |
551 | break; // something to process |
442 | } |
552 | } |
443 | } |
553 | } |
444 | if (c > PLX_Stop) // illegal char, restart reading |
554 | if (c > PLX_Stop) // illegal char, restart reading |
445 | { |
555 | { |
446 | PLXPacket = 0; |
556 | PLXPacket = 0; |
Line 454... | Line 564... | ||
454 | } |
564 | } |
455 | int suppress = -1; |
565 | int suppress = -1; |
456 | for (i = 0; i < MAX_DISPLAYS; i++) |
566 | for (i = 0; i < MAX_DISPLAYS; i++) |
457 | { // now to display the information |
567 | { // now to display the information |
458 | suppress = DisplayCurrent(i, suppress); |
568 | suppress = DisplayCurrent(i, suppress); |
459 | - | ||
460 | 569 | ||
461 | if (dial_pos[i] < 0) |
570 | if (dial_pos[i] < 0) |
462 | dial_pos[i] = PLXItems - 1; |
571 | dial_pos[i] = MAXRDG - 1; |
463 | if (dial_pos[i] >= PLXItems) |
572 | if (dial_pos[i] >= MAXRDG) |
464 | dial_pos[i] = 0; |
573 | dial_pos[i] = 0; |
465 | 574 | ||
466 | int prevPos = contexts[i].knobPos; |
575 | int prevPos = contexts[i].knobPos; |
467 | if (contexts[i].knobPos >= 0) |
576 | if (contexts[i].knobPos >= 0) |
468 | contexts[i].knobPos = dial_pos[i]; |
577 | contexts[i].knobPos = dial_pos[i]; |
Line 875... | Line 984... | ||
875 | __HAL_RCC_GPIOA_CLK_ENABLE(); |
984 | __HAL_RCC_GPIOA_CLK_ENABLE(); |
876 | __HAL_RCC_GPIOC_CLK_ENABLE(); |
985 | __HAL_RCC_GPIOC_CLK_ENABLE(); |
877 | __HAL_RCC_GPIOB_CLK_ENABLE(); |
986 | __HAL_RCC_GPIOB_CLK_ENABLE(); |
878 | 987 | ||
879 | /*Configure GPIO pin Output Level */ |
988 | /*Configure GPIO pin Output Level */ |
880 | HAL_GPIO_WritePin(SPI_NSS1_GPIO_Port, SPI_NSS1_Pin, GPIO_PIN_SET); |
989 | HAL_GPIO_WritePin(GPIOA, SPI_NSS1_Pin | BT_RESET_Pin, GPIO_PIN_SET); |
881 | 990 | ||
882 | /*Configure GPIO pin Output Level */ |
991 | /*Configure GPIO pin Output Level */ |
883 | HAL_GPIO_WritePin(GPIOA, SPI_CD_Pin | BT_BUTTON_Pin, GPIO_PIN_RESET); |
992 | HAL_GPIO_WritePin(GPIOA, SPI_CD_Pin | BT_BUTTON_Pin, GPIO_PIN_RESET); |
884 | 993 | ||
885 | /*Configure GPIO pin Output Level */ |
994 | /*Configure GPIO pin Output Level */ |
Line 912... | Line 1021... | ||
912 | GPIO_InitStruct.Pin = IGNITION_Pin; |
1021 | GPIO_InitStruct.Pin = IGNITION_Pin; |
913 | GPIO_InitStruct.Mode = GPIO_MODE_INPUT; |
1022 | GPIO_InitStruct.Mode = GPIO_MODE_INPUT; |
914 | GPIO_InitStruct.Pull = GPIO_NOPULL; |
1023 | GPIO_InitStruct.Pull = GPIO_NOPULL; |
915 | HAL_GPIO_Init(IGNITION_GPIO_Port, &GPIO_InitStruct); |
1024 | HAL_GPIO_Init(IGNITION_GPIO_Port, &GPIO_InitStruct); |
916 | 1025 | ||
917 | /*Configure GPIO pin : BT_BUTTON_Pin */ |
1026 | /*Configure GPIO pins : BT_BUTTON_Pin BT_RESET_Pin */ |
918 | GPIO_InitStruct.Pin = BT_BUTTON_Pin; |
1027 | GPIO_InitStruct.Pin = BT_BUTTON_Pin | BT_RESET_Pin; |
919 | GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; |
1028 | GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; |
920 | GPIO_InitStruct.Pull = GPIO_NOPULL; |
1029 | GPIO_InitStruct.Pull = GPIO_NOPULL; |
921 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; |
1030 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; |
922 | HAL_GPIO_Init(BT_BUTTON_GPIO_Port, &GPIO_InitStruct); |
1031 | HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); |
923 | } |
1032 | } |
924 | 1033 | ||
925 | /* USER CODE BEGIN 4 */ |
1034 | /* USER CODE BEGIN 4 */ |
926 | 1035 | ||
927 | /* USER CODE END 4 */ |
1036 | /* USER CODE END 4 */ |