Subversion Repositories DashDisplay

Rev

Rev 79 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 79 Rev 80
Line 16... Line 16...
16
 *
16
 *
17
 ******************************************************************************
17
 ******************************************************************************
18
 */
18
 */
19
/* USER CODE END Header */
19
/* USER CODE END Header */
20
/* Includes ------------------------------------------------------------------*/
20
/* Includes ------------------------------------------------------------------*/
-
 
21
 
21
#include "main.h"
22
#include "main.h"
22
 
23
 
23
/* Private includes ----------------------------------------------------------*/
24
/* Private includes ----------------------------------------------------------*/
24
/* USER CODE BEGIN Includes */
25
/* USER CODE BEGIN Includes */
-
 
26
#include <stdio.h>
25
#include <stdlib.h>
27
#include <stdlib.h>
26
 
28
 
27
#include "libPLX/plx.h"
29
#include "libPLX/plx.h"
28
#include "libPLX/displayinfo.h"
30
#include "libPLX/displayinfo.h"
29
#include "libPLX/commsLib.h"
31
#include "libPLX/commsLib.h"
Line 71... Line 73...
71
uint32_t const IGNITION_OFF_TIMEOUT = 30000UL;
73
uint32_t const IGNITION_OFF_TIMEOUT = 30000UL;
72
 
74
 
73
/// @brief 1000mS per logger period, print average per period
75
/// @brief 1000mS per logger period, print average per period
74
uint32_t const LOGGER_INTERVAL = 250UL;
76
uint32_t const LOGGER_INTERVAL = 250UL;
75
 
77
 
76
/// @brief  about 10 seconds after twiddle, save the dial position.
78
/// @brief  about 2 seconds after twiddle, save the dial position.
77
const int DialTimeout = 100;
79
const int DialTimeout = 2000;
-
 
80
 
-
 
81
/// @brief Observations are stale if not seen for 1 second  
-
 
82
const int MAX_OBS_AGE = 1000;
78
 
83
 
79
/// @brief Unused Observation
84
/// @brief Unused Observation
80
uniqueObs_t const nullObs = {PLX_MAX_OBS,
85
uniqueObs_t const nullObs = {PLX_MAX_OBS,
81
                             PLX_MAX_INST};
86
                             PLX_MAX_INST};
82
 
87
 
Line 99... Line 104...
99
context_t contexts[MAX_DISPLAYS];
104
context_t contexts[MAX_DISPLAYS];
100
 
105
 
101
/// @brief Data storage for readings
106
/// @brief Data storage for readings
102
info_t Info[INFO_SIZE];
107
info_t Info[INFO_SIZE];
103
 
108
 
104
uint32_t Latch_Timer;
109
uint32_t Latch_Timer = 0 ;
105
 
110
 
106
// location for GPS data
111
// location for GPS data
107
Location loc;
112
Location loc = {};
108
 
113
 
109
/// @brief Time when the logged data will be sent
114
/// @brief Time when the logged data will be sent
110
uint32_t nextTickReload;
115
uint32_t nextTickReload = 0;
111
 
116
 
112
// data timeout
117
// data timeout
113
uint32_t dataTimeout = 0; //
118
uint32_t dataTimeout = 0; //
114
 
119
 
115
// USART buffers
120
// USART buffers
Line 214... Line 219...
214
  if (isUnused(index))
219
  if (isUnused(index))
215
    return false;
220
    return false;
216
 
221
 
217
  uint32_t age = HAL_GetTick() - Info[index].lastUpdated;
222
  uint32_t age = HAL_GetTick() - Info[index].lastUpdated;
218
 
223
 
219
  if (age > 300)
224
  if (age > MAX_OBS_AGE )
220
    return false;
225
    return false;
221
 
226
 
222
  return true;
227
  return true;
223
}
228
}
224
 
229
 
Line 227... Line 232...
227
/* Private user code ---------------------------------------------------------*/
232
/* Private user code ---------------------------------------------------------*/
228
/* USER CODE BEGIN 0 */
233
/* USER CODE BEGIN 0 */
229
 
234
 
230
unsigned mapToIndex(unsigned instance, unsigned item)
235
unsigned mapToIndex(unsigned instance, unsigned item)
231
{
236
{
232
  return  instance  + item * PLX_MAX_INST_LIMIT;
237
  return instance + item * PLX_MAX_INST_LIMIT;
233
}
238
}
234
 
239
 
235
void libPLXcallbackSendUserData(struct usart_ctl *instance)
240
void libPLXcallbackSendUserData(struct usart_ctl *instance)
236
{
241
{
237
  (void)instance;
242
  (void)instance;
Line 251... Line 256...
251
 
256
 
252
  // validate the current item, discard out of range
257
  // validate the current item, discard out of range
253
  if ((instance > PLX_MAX_INST_LIMIT) || (observation > PLX_MAX_OBS))
258
  if ((instance > PLX_MAX_INST_LIMIT) || (observation > PLX_MAX_OBS))
254
    return;
259
    return;
255
 
260
 
-
 
261
  unsigned currentSlot = mapToIndex(instance, observation);
256
 
262
 
257
  unsigned currentSlot = mapToIndex(instance ,observation);
-
 
258
 
-
 
259
 
-
 
260
  int16_t data = ConvPLX(info->ReadingH,
263
  int16_t data = ConvPLX(info->ReadingH,
261
                         info->ReadingL);
264
                         info->ReadingL);
262
 
265
 
263
  Info[currentSlot].observation.Obs = observation;
266
  Info[currentSlot].observation.Obs = observation;
264
 
267
 
Line 276... Line 279...
276
  Info[currentSlot].sum += data;
279
  Info[currentSlot].sum += data;
277
  Info[currentSlot].count++;
280
  Info[currentSlot].count++;
278
  // note the last update time
281
  // note the last update time
279
  Info[currentSlot].lastUpdated = HAL_GetTick();
282
  Info[currentSlot].lastUpdated = HAL_GetTick();
280
  Info[currentSlot].updated = 1; // it has been updated
283
  Info[currentSlot].updated = 1; // it has been updated
281
 
-
 
282
}
284
}
-
 
285
 
-
 
286
// move to the next valid item if the current is not valid
-
 
287
int nextItem(int pos, int delta)
-
 
288
{
-
 
289
  int start = pos;
-
 
290
  // move in positive direction
-
 
291
  while (delta > 0)
-
 
292
  {
-
 
293
    // skip invalid items, dont count
-
 
294
    if (pos < INFO_SIZE - 1)
-
 
295
      pos++;
-
 
296
    else
-
 
297
      pos = 0;
-
 
298
 
-
 
299
    if (isValid(pos))
-
 
300
      delta--; // count a valid item
-
 
301
 
-
 
302
    // wrap
-
 
303
    if (pos == start)
-
 
304
      break;
-
 
305
  }
-
 
306
 
-
 
307
  // move in negative direction
-
 
308
  while (delta < 0)
-
 
309
  {
-
 
310
    // skip invalid items, dont count
-
 
311
    if (pos > 0)
-
 
312
      pos--;
-
 
313
    else
-
 
314
      pos = INFO_SIZE - 1;
-
 
315
 
-
 
316
    if (isValid(pos))
-
 
317
      delta++; // count a valid item
-
 
318
 
-
 
319
    // wrap
-
 
320
    if (pos == start)
-
 
321
      break;
-
 
322
  }
-
 
323
  return pos;
-
 
324
}
-
 
325
 
-
 
326
/// @brief Log data to bluetooth as a sort of NMEA0183
-
 
327
/// @param offsetTicks fraction of a second offset
-
 
328
/// @return new offsetTicks value 
-
 
329
uint32_t logBt( uint32_t offsetTicks)
-
 
330
{
-
 
331
  // Send items  to BT if it is in connected state
-
 
332
  // print timestamp as a $PLTIM record.
-
 
333
  char linebuff[20];
-
 
334
  strftime(linebuff, sizeof(linebuff), "%H%M%S", &loc.tv);
-
 
335
 
-
 
336
  char outbuff[100];
-
 
337
  int cnt = small_sprintf(outbuff, "$PLTIM,%s.%03lu\n", linebuff, offsetTicks);
-
 
338
  sendString(&uc3, outbuff, cnt);
-
 
339
  offsetTicks += LOGGER_INTERVAL;
-
 
340
 
-
 
341
  // increment timer
-
 
342
  if (offsetTicks >= (1000))
-
 
343
  {
-
 
344
    offsetTicks -= 1000;
-
 
345
    loc.tv.tm_sec++;
-
 
346
    if (loc.tv.tm_sec >= 60)
-
 
347
    {
-
 
348
      loc.tv.tm_sec = 0;
-
 
349
      loc.tv.tm_min++;
-
 
350
      if (loc.tv.tm_min >= 60)
-
 
351
      {
-
 
352
        loc.tv.tm_hour++;
-
 
353
        if (loc.tv.tm_hour >= 24)
-
 
354
          loc.tv.tm_hour = 0;
-
 
355
      }
-
 
356
    }
-
 
357
  }
-
 
358
 
-
 
359
  for (int i = 0; i < INFO_SIZE; ++i)
-
 
360
  {
-
 
361
    if (!isValid(i))
-
 
362
      continue;
-
 
363
    // format output
-
 
364
    // avoid division by zero for items with no sample data this iteration
-
 
365
    if (Info[i].count == 0)
-
 
366
      continue;
-
 
367
    double average = (double)Info[i].sum / Info[i].count;
-
 
368
    enum PLX_Observations Observation = Info[i].observation.Obs;
-
 
369
 
-
 
370
    double cur_rdg = ConveriMFDRaw2Data((enum PLX_Observations)Observation, DisplayInfo[Observation].Units,
-
 
371
                                        average);
-
 
372
    int cnt;
-
 
373
    int intPart;
-
 
374
    // depending on digits after the decimal point,
-
 
375
    // choose how to format data
-
 
376
    switch (DisplayInfo[Observation].DP)
-
 
377
    {
-
 
378
    default:
-
 
379
    case 0:
-
 
380
      cnt = small_sprintf(outbuff,
-
 
381
                          "$PLLOG,%s,%d,%d",
-
 
382
                          DisplayInfo[Info[i].observation.Obs].name,
-
 
383
                          Info[i].observation.Instance,
-
 
384
                          (int)cur_rdg);
-
 
385
 
-
 
386
      break;
-
 
387
    case 1:
-
 
388
      intPart = (int)(cur_rdg * 10);
-
 
389
      cnt = small_sprintf(outbuff,
-
 
390
                          "$PLLOG,%s,%d,%d.%1d",
-
 
391
                          DisplayInfo[Info[i].observation.Obs].name,
-
 
392
                          Info[i].observation.Instance,
-
 
393
                          intPart / 10, abs(intPart) % 10);
-
 
394
 
-
 
395
      break;
-
 
396
    case 2:
-
 
397
      intPart = (int)(cur_rdg * 100);
-
 
398
      cnt = small_sprintf(outbuff,
-
 
399
                          "$PLLOG,%s,%d,%d.%02d",
-
 
400
                          DisplayInfo[Info[i].observation.Obs].name,
-
 
401
                          Info[i].observation.Instance,
-
 
402
                          intPart / 100, abs(intPart) % 100);
-
 
403
 
-
 
404
      break;
-
 
405
    }
-
 
406
 
-
 
407
    Info[i].count = 0;
-
 
408
    Info[i].sum = 0;
-
 
409
 
-
 
410
    // NMEA style checksum
-
 
411
    int ck;
-
 
412
    int sum = 0;
-
 
413
    for (ck = 1; ck < cnt; ck++)
-
 
414
      sum += outbuff[ck];
-
 
415
    cnt += small_sprintf(outbuff + cnt, "*%02X\n",
-
 
416
                         sum & 0xFF);
-
 
417
    sendString(&uc3, outbuff, cnt);
-
 
418
  }
-
 
419
return offsetTicks;
-
 
420
}
-
 
421
 
-
 
422
 
-
 
423
void resetDialTimer(int index)
-
 
424
{
-
 
425
  contexts[index].dial_timer =  HAL_GetTick() + DialTimeout;
-
 
426
}
-
 
427
 
283
/* USER CODE END 0 */
428
/* USER CODE END 0 */
284
 
429
 
285
/**
430
/**
286
 * @brief  The application entry point.
431
 * @brief  The application entry point.
287
 * @retval int
432
 * @retval int
288
 */
433
 */
289
int main(void)
434
int main(void)
290
{
435
{
291
 
436
 
292
  /* USER CODE BEGIN 1 */
437
  /* USER CODE BEGIN 1 */
-
 
438
#if defined SEMIHOSTING
-
 
439
  initialise_monitor_handles();
-
 
440
  #endif
293
  __HAL_RCC_SPI1_CLK_ENABLE();
441
  __HAL_RCC_SPI1_CLK_ENABLE();
294
  __HAL_RCC_USART1_CLK_ENABLE(); // PLX main port
442
  __HAL_RCC_USART1_CLK_ENABLE(); // PLX main port
295
  __HAL_RCC_USART2_CLK_ENABLE(); // debug port
443
  __HAL_RCC_USART2_CLK_ENABLE(); // debug port
296
  __HAL_RCC_USART3_CLK_ENABLE(); // Bluetooth port
444
  __HAL_RCC_USART3_CLK_ENABLE(); // Bluetooth port
297
  __HAL_RCC_UART4_CLK_ENABLE();  // NMEA0183 port
445
  __HAL_RCC_UART4_CLK_ENABLE();  // NMEA0183 port
Line 387... Line 535...
387
  cc_init();
535
  cc_init();
388
 
536
 
389
  for (int i = 0; i < MAX_DISPLAYS; ++i)
537
  for (int i = 0; i < MAX_DISPLAYS; ++i)
390
  {
538
  {
391
    contexts[i] = nullContext; // set the knob position
539
    contexts[i] = nullContext; // set the knob position
-
 
540
    resetDialTimer(i);
392
  }
541
  }
393
 
542
 
394
  /* reset the display timeout, latch on power from accessories */
543
  /* reset the display timeout, latch on power from accessories */
395
  Latch_Timer = IGNITION_OFF_TIMEOUT;
544
  Latch_Timer = IGNITION_OFF_TIMEOUT;
396
  HAL_GPIO_WritePin(POWER_LATCH_GPIO_Port, POWER_LATCH_Pin, GPIO_PIN_RESET);
545
  HAL_GPIO_WritePin(POWER_LATCH_GPIO_Port, POWER_LATCH_Pin, GPIO_PIN_RESET);
Line 410... Line 559...
410
  }
559
  }
411
 
560
 
412
  uint32_t resetCounter = 0; // record time at which both reset buttons were first pressed.
561
  uint32_t resetCounter = 0; // record time at which both reset buttons were first pressed.
413
 
562
 
414
  resetPLX();
563
  resetPLX();
-
 
564
 
415
  /* USER CODE END 2 */
565
  /* USER CODE END 2 */
416
 
566
 
417
  /* Infinite loop */
567
  /* Infinite loop */
418
  /* USER CODE BEGIN WHILE */
568
  /* USER CODE BEGIN WHILE */
419
  while (1)
569
  while (1)
Line 453... Line 603...
453
        if ((HAL_GetTick() - resetCounter) > 10000)
603
        if ((HAL_GetTick() - resetCounter) > 10000)
454
        {
604
        {
455
          for (int i = 0; i < MAX_DISPLAYS; i++)
605
          for (int i = 0; i < MAX_DISPLAYS; i++)
456
          {
606
          {
457
            contexts[i] = nullContext;
607
            contexts[i] = nullContext;
458
            contexts[i].dial_timer = 1; // timeout immediately when decremented
608
            contexts[i].dial_timer = HAL_GetTick(); // timeout immediately when decremented
459
          }
609
          }
460
          erase_nvram();
610
          erase_nvram();
461
        }
611
        }
462
        resetCounter = 0;
612
        resetCounter = 0;
463
      }
613
      }
Line 469... Line 619...
469
      memset(loc.time, '-', 6);
619
      memset(loc.time, '-', 6);
470
 
620
 
471
    // if permitted, log data from RMC packet
621
    // if permitted, log data from RMC packet
472
    if (btConnected())
622
    if (btConnected())
473
    {
623
    {
-
 
624
 
474
      // Timeout for data logging regularly
625
      // Timeout for data logging regularly
475
      if (HAL_GetTick() > nextTick)
626
      if (HAL_GetTick() > nextTick)
476
      {
627
      {
477
        nextTick = nextTickReload;
628
        nextTick = nextTickReload;
478
        nextTickReload += LOGGER_INTERVAL;
629
        nextTickReload += LOGGER_INTERVAL;
479
 
-
 
480
        // Send items  to BT if it is in connected state
-
 
481
        // print timestamp as a $PLTIM record.
-
 
482
        char linebuff[20];
-
 
483
        strftime(linebuff, sizeof(linebuff), "%H%M%S", &loc.tv);
-
 
484
 
-
 
485
        char outbuff[100];
-
 
486
        int cnt = small_sprintf(outbuff, "$PLTIM,%s.%03lu\n", linebuff, offsetTicks);
-
 
487
        sendString(&uc3, outbuff, cnt);
-
 
488
        offsetTicks += LOGGER_INTERVAL;
630
        offsetTicks = logBt(offsetTicks);
489
 
-
 
490
        // increment timer
-
 
491
        if (offsetTicks >= (1000))
-
 
492
        {
-
 
493
          offsetTicks -= 1000;
-
 
494
          loc.tv.tm_sec++;
-
 
495
          if (loc.tv.tm_sec >= 60)
-
 
496
          {
-
 
497
            loc.tv.tm_sec = 0;
-
 
498
            loc.tv.tm_min++;
-
 
499
            if (loc.tv.tm_min >= 60)
-
 
500
            {
-
 
501
              loc.tv.tm_hour++;
-
 
502
              if (loc.tv.tm_hour >= 24)
-
 
503
                loc.tv.tm_hour = 0;
-
 
504
            }
-
 
505
          }
-
 
506
        }
-
 
507
 
-
 
508
        for (int i = 0; i < INFO_SIZE; ++i)
-
 
509
        {
-
 
510
          if (!isValid(i))
-
 
511
            continue;
-
 
512
          // format output
-
 
513
          // avoid division by zero for items with no sample data this iteration
-
 
514
          if (Info[i].count == 0)
-
 
515
            continue;
-
 
516
          double average = (double)Info[i].sum / Info[i].count;
-
 
517
          enum PLX_Observations Observation = Info[i].observation.Obs;
-
 
518
 
-
 
519
          double cur_rdg = ConveriMFDRaw2Data((enum PLX_Observations)Observation, DisplayInfo[Observation].Units,
-
 
520
                                              average);
-
 
521
          int cnt;
-
 
522
          int intPart;
-
 
523
          // depending on digits after the decimal point,
-
 
524
          // choose how to format data
-
 
525
          switch (DisplayInfo[Observation].DP)
-
 
526
          {
-
 
527
          default:
-
 
528
          case 0:
-
 
529
            cnt = small_sprintf(outbuff,
-
 
530
                                "$PLLOG,%s,%d,%d",
-
 
531
                                DisplayInfo[Info[i].observation.Obs].name,
-
 
532
                                Info[i].observation.Instance,
-
 
533
                                (int)cur_rdg);
-
 
534
 
-
 
535
            break;
-
 
536
          case 1:
-
 
537
            intPart = (int)(cur_rdg * 10);
-
 
538
            cnt = small_sprintf(outbuff,
-
 
539
                                "$PLLOG,%s,%d,%d.%1d",
-
 
540
                                DisplayInfo[Info[i].observation.Obs].name,
-
 
541
                                Info[i].observation.Instance,
-
 
542
                                intPart / 10, abs(intPart) % 10);
-
 
543
 
-
 
544
            break;
-
 
545
          case 2:
-
 
546
            intPart = (int)(cur_rdg * 100);
-
 
547
            cnt = small_sprintf(outbuff,
-
 
548
                                "$PLLOG,%s,%d,%d.%02d",
-
 
549
                                DisplayInfo[Info[i].observation.Obs].name,
-
 
550
                                Info[i].observation.Instance,
-
 
551
                                intPart / 100, abs(intPart) % 100);
-
 
552
 
-
 
553
            break;
-
 
554
          }
-
 
555
 
-
 
556
          Info[i].count = 0;
-
 
557
          Info[i].sum = 0;
-
 
558
 
-
 
559
          // NMEA style checksum
-
 
560
          int ck;
-
 
561
          int sum = 0;
-
 
562
          for (ck = 1; ck < cnt; ck++)
-
 
563
            sum += outbuff[ck];
-
 
564
          cnt += small_sprintf(outbuff + cnt, "*%02X\n",
-
 
565
                               sum & 0xFF);
-
 
566
          sendString(&uc3, outbuff, cnt);
-
 
567
        }
-
 
568
      }
631
      }
569
    }
632
    }
570
 
633
 
571
    // poll data into libPLX
634
    // poll data into libPLX
572
    libPLXpollData(&uc1);
635
    libPLXpollData(&uc1);
Line 580... Line 643...
580
      sendString(&uc3, msg, sizeof(msg));
643
      sendString(&uc3, msg, sizeof(msg));
581
    }
644
    }
582
 
645
 
583
    if (dataTimeout > 60000)
646
    if (dataTimeout > 60000)
584
    {
647
    {
585
 
-
 
586
      // do turn off screen
648
      // do turn off screen
587
    }
649
    }
588
 
650
 
589
    // handle switch rotation
651
    // handle switch rotation
590
    for (int i = 0; i < MAX_DIALS; ++i)
652
    for (int i = 0; i < MAX_DIALS; ++i)
591
    {
653
    {
592
      int pos = contexts[i].knobPos;
654
      int pos = contexts[i].knobPos;
593
      if (pos < 0)
655
      if (pos < 0)
594
        break; // dont process until we have read NVRAM for the first time .
656
        break; // dont process until we have read NVRAM for the first time .
595
      int start = pos;
657
      int start = pos;
596
      int delta = get_dial_diff(i);
658
      pos = nextItem(pos, get_dial_diff(i));
597
      // move in positive direction
-
 
598
      while (delta > 0)
-
 
599
      {
-
 
600
        // skip invalid items, dont count
-
 
601
        if (pos < INFO_SIZE - 1)
-
 
602
          pos++;
-
 
603
        else
-
 
604
          pos = 0;
-
 
605
 
-
 
606
        if (isValid(pos))
-
 
607
          delta--; // count a valid item
-
 
608
 
-
 
609
        // wrap
-
 
610
        if (pos == start)
-
 
611
          break;
-
 
612
      }
-
 
613
 
-
 
614
      // move in negative direction
-
 
615
      while (delta < 0)
-
 
616
      {
-
 
617
        // skip invalid items, dont count
-
 
618
        if (pos > 0)
-
 
619
          pos--;
-
 
620
        else
-
 
621
          pos = INFO_SIZE - 1;
-
 
622
 
-
 
623
        if (isValid(pos))
-
 
624
          delta++; // count a valid item
-
 
625
 
-
 
626
        // wrap
-
 
627
        if (pos == start)
-
 
628
          break;
-
 
629
      }
-
 
630
 
659
 
631
      contexts[i].knobPos = pos;
660
      contexts[i].knobPos = pos;
632
      if (pos != start)
661
      if (pos != start)
633
        contexts[i].dial_timer = DialTimeout;
662
       resetDialTimer(i);
634
    }
663
    }
635
 
664
 
636
    int suppress = -1;
665
    int suppress = -1;
637
    for (int i = 0; i < MAX_DISPLAYS; ++i)
666
    for (int i = 0; i < MAX_DISPLAYS; ++i)
638
    { // now to display the information
667
    { // now to display the information