Subversion Repositories DashDisplay

Rev

Rev 74 | Rev 76 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 74 Rev 75
Line 18... Line 18...
18
 */
18
 */
19
/* USER CODE END Header */
19
/* USER CODE END Header */
20
/* Includes ------------------------------------------------------------------*/
20
/* Includes ------------------------------------------------------------------*/
21
#include "main.h"
21
#include "main.h"
22
 
22
 
-
 
23
#include <stdlib.h>
-
 
24
 
23
/* Private includes ----------------------------------------------------------*/
25
/* Private includes ----------------------------------------------------------*/
24
/* USER CODE BEGIN Includes */
26
/* USER CODE BEGIN Includes */
25
 
27
 
26
#include "libPLX/plx.h"
28
#include "libPLX/plx.h"
-
 
29
#include "libPLX/displayinfo.h"
27
#include "libSerial/serial.H"
30
#include "libSerial/serialUtils.H"
-
 
31
 
28
#include "libSmallPrintf/small_printf.h"
32
#include "libSmallPrintf/small_printf.h"
29
#include "libNMEA/nmea.h"
33
#include "libNMEA/nmea.h"
30
#include "switches.h"
34
#include "switches.h"
31
#include <string.h>
35
#include <string.h>
32
 
36
 
Line 61... Line 65...
61
UART_HandleTypeDef huart3;
65
UART_HandleTypeDef huart3;
62
 
66
 
63
/* USER CODE BEGIN PV */
67
/* USER CODE BEGIN PV */
64
/* Private variables ---------------------------------------------------------*/
68
/* Private variables ---------------------------------------------------------*/
65
 
69
 
66
context_t contexts[MAX_DISPLAYS];
-
 
67
 
-
 
68
///@brief  timeout when the ignition is switched off
70
///@brief  timeout when the ignition is switched off
69
#define IGNITION_OFF_TIMEOUT 30000UL
71
uint32_t const IGNITION_OFF_TIMEOUT = 30000UL;
70
 
72
 
71
/// @brief 1000mS per logger period, print average per period
73
/// @brief 1000mS per logger period, print average per period
72
#define LOGGER_INTERVAL 500UL
74
uint32_t const LOGGER_INTERVAL = 250UL;
73
 
75
 
74
/// @brief  about 10 seconds after twiddle, save the dial position.
76
/// @brief  about 10 seconds after twiddle, save the dial position.
75
const int DialTimeout = 100;
77
const int DialTimeout = 100;
76
 
78
 
77
/// @brief Data storage for readings
79
/// @brief Unused Observation
-
 
80
uniqueObs_t const nullObs = {PLX_MAX_OBS,
-
 
81
                             PLX_MAX_INST};
-
 
82
 
78
info_t Info[MAXRDG];
83
/// @brief Null context
-
 
84
context_t const nullContext = {.knobPos = -1,
-
 
85
                               .dial_timer = 0,
-
 
86
                               .dial0 = -1,
-
 
87
                               .dial1 = -1,
-
 
88
                               .OldObservation = nullObs};
79
 
89
 
80
/// @brief Define a null item
90
/// @brief Define a null item
81
const info_t nullInfo = {.Max = 0,
91
info_t const nullInfo = {.Max = 0,
82
                         .Min = 0xFFF,
92
                         .Min = 0xFFF,
83
                         .sum = 0,
93
                         .sum = 0,
84
                         .count = 0,
94
                         .count = 0,
85
                         .updated = 0,
95
                         .updated = 0,
86
                         .lastUpdated = 0,
96
                         .lastUpdated = 0,
87
                         .observation.Obs = PLX_MAX_OBS,
97
                         .observation = nullObs};
-
 
98
 
-
 
99
context_t contexts[MAX_DISPLAYS];
-
 
100
 
88
                         .observation.Instance = PLX_MAX_INST};
101
/// @brief Data storage for readings
-
 
102
info_t Info[MAXRDG];
89
 
103
 
90
/// \brief storage for incoming data
104
/// \brief storage for incoming data
91
data_t Data;
105
data_t Data;
92
 
106
 
93
uint32_t Latch_Timer = IGNITION_OFF_TIMEOUT;
107
uint32_t Latch_Timer;
94
 
108
 
95
// location for GPS data
109
// location for GPS data
96
Location loc;
110
Location loc;
97
 
111
 
98
/// @brief Time when the logged data will be sent
112
/// @brief Time when the logged data will be sent
99
uint32_t nextTickReload = 0;
113
uint32_t nextTickReload;
100
 
114
 
101
/* USER CODE END PV */
115
/* USER CODE END PV */
102
 
116
 
103
/* Private function prototypes -----------------------------------------------*/
117
/* Private function prototypes -----------------------------------------------*/
104
void SystemClock_Config(void);
118
void SystemClock_Config(void);
Line 292... Line 306...
292
  // Initialuse UART4 for 4800 baud NMEA.
306
  // Initialuse UART4 for 4800 baud NMEA.
293
  setBaud(&uc4, 4800);
307
  setBaud(&uc4, 4800);
294
 
308
 
295
  cc_init();
309
  cc_init();
296
 
310
 
297
  int i;
-
 
298
  for (i = 0; i < 2; i++)
311
  for (int i = 0; i < MAX_DISPLAYS; ++i)
299
  {
312
  {
300
    contexts[i].knobPos = -1; // set the knob position
313
    contexts[i] = nullContext; // set the knob position
301
  }
314
  }
302
 
315
 
303
  /* reset the display timeout, latch on power from accessories */
316
  /* reset the display timeout, latch on power from accessories */
304
  Latch_Timer = IGNITION_OFF_TIMEOUT;
317
  Latch_Timer = IGNITION_OFF_TIMEOUT;
305
  HAL_GPIO_WritePin(POWER_LATCH_GPIO_Port, POWER_LATCH_Pin, GPIO_PIN_RESET);
318
  HAL_GPIO_WritePin(POWER_LATCH_GPIO_Port, POWER_LATCH_Pin, GPIO_PIN_RESET);
306
 
319
 
-
 
320
  /// @brief Time when the logged data will be sent
-
 
321
 
307
  setRmcCallback(&rmc_callback);
322
  setRmcCallback(&rmc_callback);
308
 
323
 
309
  // data timeout
324
  // data timeout
310
  uint32_t timeout = 0; //
325
  uint32_t timeout = 0; //
311
 
326
 
312
  // used in NMEA style logging
327
  // used in NMEA style logging
313
  uint32_t nextTick = 0;    ///< time to send next
328
  uint32_t nextTick = 0; ///< time to send next
-
 
329
  nextTickReload = 0;
314
  uint32_t offsetTicks = 0; ///< time to print as offset in mS for each loop
330
  uint32_t offsetTicks = 0; ///< time to print as offset in mS for each loop
315
 
331
 
316
  // PLX decoder protocols
332
  // PLX decoder protocols
317
  char PLXPacket = 0;
333
  char PLXPacket = 0;
-
 
334
  int PLXPtr = 0;
318
 
335
 
319
  for (i = 0; i < MAXRDG; i++)
336
  for (int i = 0; i < MAXRDG; ++i)
320
  {
337
  {
321
    Info[i] = nullInfo;
338
    Info[i] = nullInfo;
322
  }
339
  }
323
 
340
 
324
  int PLXPtr = 0;
-
 
325
 
-
 
326
  uint32_t resetCounter = 0; // record time at which both reset buttons were first pressed.
341
  uint32_t resetCounter = 0; // record time at which both reset buttons were first pressed.
327
 
342
 
328
  /* USER CODE END 2 */
343
  /* USER CODE END 2 */
329
 
344
 
330
  /* Infinite loop */
345
  /* Infinite loop */
Line 363... Line 378...
363
      if (resetCounter != 0)
378
      if (resetCounter != 0)
364
      {
379
      {
365
        // Held down reset button for 10 seconds, clear NVRAM.
380
        // Held down reset button for 10 seconds, clear NVRAM.
366
        if ((HAL_GetTick() - resetCounter) > 10000)
381
        if ((HAL_GetTick() - resetCounter) > 10000)
367
        {
382
        {
368
          for (i = 0; i < 2; i++)
383
          for (int i = 0; i < MAX_DISPLAYS; i++)
369
          {
384
          {
370
            contexts[i].knobPos = -1;   // set the knob position
385
            contexts[i] = nullContext;
371
            contexts[i].dial_timer = 1; // timeout immediately when decremented
386
            contexts[i].dial_timer = 1; // timeout immediately when decremented
372
          }
387
          }
373
          erase_nvram();
388
          erase_nvram();
374
        }
389
        }
375
        resetCounter = 0;
390
        resetCounter = 0;
Line 382... Line 397...
382
      memset(loc.time, '-', 6);
397
      memset(loc.time, '-', 6);
383
 
398
 
384
    // if permitted, log data from RMC packet
399
    // if permitted, log data from RMC packet
385
    if (btConnected())
400
    if (btConnected())
386
    {
401
    {
387
      // Any RMC data, send it, reset the logger timeout
-
 
388
 
-
 
389
      // Timeout for data logging regularly
402
      // Timeout for data logging regularly
390
      if (HAL_GetTick() > nextTick)
403
      if (HAL_GetTick() > nextTick)
391
      {
404
      {
392
        nextTick = nextTickReload;
405
        nextTick = nextTickReload;
393
        nextTickReload += LOGGER_INTERVAL;
406
        nextTickReload += LOGGER_INTERVAL;
394
   
407
 
395
        // Send items  to BT if it is in connected state
408
        // Send items  to BT if it is in connected state
396
        // print timestamp as a $PLTIM record.
409
        // print timestamp as a $PLTIM record.
397
        char linebuff[20];
410
        char linebuff[20];
398
        strftime(linebuff, sizeof(linebuff), "%H%M%S", &loc.tv);
411
        strftime(linebuff, sizeof(linebuff), "%H%M%S", &loc.tv);
399
 
412
 
400
        char outbuff[100];
413
        char outbuff[100];
401
        int cnt = small_sprintf(outbuff, "$PLTIM,%s.%03lu\n", linebuff, offsetTicks);
414
        int cnt = small_sprintf(outbuff, "$PLTIM,%s.%03lu\n", linebuff, offsetTicks);
402
        sendString(&uc3, outbuff, cnt);
415
        sendString(&uc3, outbuff, cnt);
403
        offsetTicks += LOGGER_INTERVAL;
416
        offsetTicks += LOGGER_INTERVAL;
-
 
417
 
404
       
418
        // increment timer
405
               if (offsetTicks >= (1000))
419
        if (offsetTicks >= (1000))
406
        {
420
        {
407
          offsetTicks = 0;
421
          offsetTicks -= 1000;
408
          loc.tv.tm_sec++;
422
          loc.tv.tm_sec++;
409
          if (loc.tv.tm_sec >= 60)
423
          if (loc.tv.tm_sec >= 60)
410
          {
424
          {
411
            loc.tv.tm_sec = 0;
425
            loc.tv.tm_sec = 0;
412
            loc.tv.tm_min++;
426
            loc.tv.tm_min++;
Line 416... Line 430...
416
              if (loc.tv.tm_hour >= 24)
430
              if (loc.tv.tm_hour >= 24)
417
                loc.tv.tm_hour = 0;
431
                loc.tv.tm_hour = 0;
418
            }
432
            }
419
          }
433
          }
420
        }
434
        }
421
 
435
 
422
       
-
 
423
       
-
 
424
       
-
 
425
       
-
 
426
       
-
 
427
        for (int i = 0; i < MAXRDG; ++i)
436
        for (int i = 0; i < MAXRDG; ++i)
428
        {
437
        {
429
          if (!isValid(i))
438
          if (!isValid(i))
430
            continue;
439
            continue;
-
 
440
          // format output
-
 
441
          // avoid division by zero for items with no sample data this iteration
-
 
442
          if (Info[i].count == 0)
-
 
443
            continue;
-
 
444
          double average = (double)Info[i].sum / Info[i].count;
-
 
445
          enum PLX_Observations Observation = Info[i].observation.Obs;
-
 
446
 
-
 
447
          double cur_rdg = ConveriMFDRaw2Data((enum PLX_Observations)Observation, DisplayInfo[Observation].Units,
-
 
448
                                              average);
-
 
449
          int cnt;
-
 
450
          int intPart;
-
 
451
          switch (DisplayInfo[Observation].DP)
-
 
452
          {
-
 
453
          default:
-
 
454
          case 0:
-
 
455
            cnt = small_sprintf(outbuff,
431
          // print logger items as $PLLOG record
456
                                "$PLLOG,%s,%d,%d",
-
 
457
                                DisplayInfo[Info[i].observation.Obs].name,
-
 
458
                                Info[i].observation.Instance,
-
 
459
                                (int)cur_rdg);
-
 
460
 
-
 
461
            break;
-
 
462
          case 1:
-
 
463
            intPart = (int)(cur_rdg * 10);
432
          int cnt = small_sprintf(outbuff,
464
            cnt = small_sprintf(outbuff,
433
                                  "$PLLOG,%d,%d,%ld",
465
                                "$PLLOG,%s,%d,%d.%1d",
-
 
466
                                DisplayInfo[Info[i].observation.Obs].name,
434
                                  Info[i].observation.Obs,
467
                                Info[i].observation.Instance,
-
 
468
                                intPart / 10, abs(intPart) % 10);
-
 
469
 
-
 
470
            break;
-
 
471
          case 2:
-
 
472
            intPart = (int)(cur_rdg * 100);
-
 
473
            cnt = small_sprintf(outbuff,
-
 
474
                                "$PLLOG,%s,%d,%d.%02d",
-
 
475
                                DisplayInfo[Info[i].observation.Obs].name,
435
                                  Info[i].observation.Instance,
476
                                Info[i].observation.Instance,
436
                                  Info[i].count == 0 ? 0 : Info[i].sum / Info[i].count);
477
                                intPart / 100, abs(intPart) % 100);
-
 
478
 
-
 
479
            break;
-
 
480
          }
-
 
481
 
437
          Info[i].count = 0;
482
          Info[i].count = 0;
438
          Info[i].sum = 0;
483
          Info[i].sum = 0;
439
 
484
 
440
          // NMEA style checksum
485
          // NMEA style checksum
441
          int ck;
486
          int ck;
Line 488... Line 533...
488
        {
533
        {
489
          // we can now decode the selected parameter
534
          // we can now decode the selected parameter
490
          int PLXNewItems = PLXPtr / sizeof(PLX_SensorInfo); // total items in last reading batch
535
          int PLXNewItems = PLXPtr / sizeof(PLX_SensorInfo); // total items in last reading batch
491
 
536
 
492
          // process items
537
          // process items
493
          for (i = 0; i < PLXNewItems; i++)
538
          for (int dataItem = 0; dataItem < PLXNewItems; ++dataItem)
494
          {
539
          {
495
            // search to see if the item already has a slot in the Info[] array
540
            // search to see if the item already has a slot in the Info[] array
496
            // match the observation and instance: if found, update entry
541
            // match the observation and instance: if found, update entry
497
            enum PLX_Observations observation = ConvPLX(Data.Sensor[i].AddrH,
542
            enum PLX_Observations observation = ConvPLX(Data.Sensor[dataItem].AddrH,
498
                                                        Data.Sensor[i].AddrL);
543
                                                        Data.Sensor[dataItem].AddrL);
499
 
544
 
500
            char instance = Data.Sensor[i].Instance;
545
            char instance = Data.Sensor[dataItem].Instance;
501
 
546
 
-
 
547
            int16_t data = ConvPLX(Data.Sensor[dataItem].ReadingH,
-
 
548
                                   Data.Sensor[dataItem].ReadingL);
502
            // validate the current item, discard out of range
549
            // validate the current item, discard out of range
503
 
550
 
504
            if ((instance > PLX_MAX_INST) || (observation > PLX_MAX_OBS))
551
            if ((instance > PLX_MAX_INST) || (observation > PLX_MAX_OBS))
505
              continue;
552
              continue;
506
 
553
 
507
            // search for the item in the list
554
            // search for the item in the list
508
            int j;
555
            int currentSlot;
509
            for (j = 0; j < MAXRDG; ++j)
556
            for (currentSlot = 0; currentSlot < MAXRDG; ++currentSlot)
510
            {
557
            {
511
              if ((Info[j].observation.Obs == observation) && (Info[j].observation.Instance == instance))
558
              if ((Info[currentSlot].observation.Obs == observation) && (Info[currentSlot].observation.Instance == instance))
512
                break;
559
                break;
513
            }
560
            }
514
            // fallen off the end of the list of existing items without a match, so j points at next new item
561
            // fallen off the end of the list of existing items without a match, so j points at next new item
515
            //
562
            //
516
            // Find an unused slot
563
            // Find an unused slot
517
 
564
 
518
            if (j == MAXRDG)
565
            if (currentSlot == MAXRDG)
519
            {
566
            {
520
              int k;
567
              int k;
521
              {
568
              {
522
                for (k = 0; k < MAXRDG; ++k)
569
                for (k = 0; k < MAXRDG; ++k)
523
                  if (!isValid(k))
570
                  if (!isValid(k))
524
                  {
571
                  {
525
                    j = k; // found a spare slot
572
                    currentSlot = k; // found a spare slot
526
                    break;
573
                    break;
527
                  }
574
                  }
528
              }
575
              }
529
              if (k == MAXRDG)
576
              if (k == MAXRDG)
530
                continue; // abandon this iteration
577
                continue; // abandon this iteration
531
            }
578
            }
532
 
579
 
533
            // give up if we are going to fall off the end of the array
580
            // give up if we are going to fall off the end of the array
534
            if (j > MAXRDG)
581
            if (currentSlot >= MAXRDG)
535
              break;
582
              break;
536
 
583
 
537
            Info[j].observation.Obs = observation;
584
            Info[currentSlot].observation.Obs = observation;
538
 
585
 
539
            Info[j].observation.Instance = instance;
586
            Info[currentSlot].observation.Instance = instance;
540
            Info[j].data = ConvPLX(Data.Sensor[j].ReadingH,
587
            Info[currentSlot].data = data;
541
                                   Data.Sensor[j].ReadingL);
-
 
542
            if (Info[j].data > Info[j].Max)
588
            if (data > Info[currentSlot].Max)
543
            {
589
            {
544
              Info[j].Max = Info[j].data;
590
              Info[currentSlot].Max = data;
545
            }
591
            }
546
            if (Info[j].data < Info[j].Min)
592
            if (data < Info[currentSlot].Min)
547
            {
593
            {
548
              Info[j].Min = Info[j].data;
594
              Info[currentSlot].Min = data;
549
            }
595
            }
550
            // take an average
596
            // take an average
551
            Info[j].sum += Info[j].data;
597
            Info[currentSlot].sum += data;
552
            Info[j].count++;
598
            Info[currentSlot].count++;
553
            // note the last update time
599
            // note the last update time
554
            Info[j].lastUpdated = HAL_GetTick();
600
            Info[currentSlot].lastUpdated = HAL_GetTick();
555
            Info[j].updated = 1; // it has been updated
601
            Info[currentSlot].updated = 1; // it has been updated
556
          }
602
          }
557
          PLXPtr = 0;
603
          PLXPtr = 0;
558
          PLXPacket = 0;
604
          PLXPacket = 0;
559
 
605
 
560
          // scan through and invalidate all old items
606
          // scan through and invalidate all old items
Line 578... Line 624...
578
        Data.Bytes[PLXPtr++] = c;
624
        Data.Bytes[PLXPtr++] = c;
579
      }
625
      }
580
    }
626
    }
581
 
627
 
582
    // handle switch rotation
628
    // handle switch rotation
583
    for (i = 0; i < MAX_DIALS; ++i)
629
    for (int i = 0; i < MAX_DIALS; ++i)
584
    {
630
    {
585
      int delta = get_dial_diff(i);
631
      int delta = get_dial_diff(i);
586
      int pos = contexts[i].knobPos;
632
      int pos = contexts[i].knobPos;
587
      if (pos < 0)
633
      if (pos < 0)
588
        break; // dont process until we have read NVRAM for the first time .
634
        break; // dont process until we have read NVRAM for the first time .
Line 604... Line 650...
604
          break;
650
          break;
605
      }
651
      }
606
 
652
 
607
      // move in negative direction
653
      // move in negative direction
608
      while (delta < 0)
654
      while (delta < 0)
609
 
-
 
610
      {
655
      {
611
        // skip invalid items, dont count
656
        // skip invalid items, dont count
612
        if (pos > 0)
657
        if (pos > 0)
613
          pos--;
658
          pos--;
614
        else
659
        else
Line 626... Line 671...
626
      if (pos != start)
671
      if (pos != start)
627
        contexts[i].dial_timer = DialTimeout;
672
        contexts[i].dial_timer = DialTimeout;
628
    }
673
    }
629
 
674
 
630
    int suppress = -1;
675
    int suppress = -1;
631
    for (i = 0; i < MAX_DISPLAYS; i++)
676
    for (int i = 0; i < MAX_DISPLAYS; ++i)
632
    { // now to display the information
677
    { // now to display the information
633
      suppress = DisplayCurrent(i, suppress);
678
      suppress = DisplayCurrent(i, suppress);
634
 
679
 
635
      cc_check_nvram(i);
680
      cc_check_nvram(i);
636
    }
681
    }