Subversion Repositories DashDisplay

Rev

Rev 55 | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * display.cpp
  3.  *
  4.  *  Created on: 30 Nov 2020
  5.  *      Author: mike
  6.  */
  7.  
  8. #include "main.h"
  9. #include "display.h"
  10. #include "switches.h"
  11. #include "nvram.h"
  12. #include <cstring>
  13. #include "libOLED/stm32_halDisplay.H"
  14. #include "libOLED/fontclass.H"
  15. #include "libOLED/displayDial.H"
  16. #include "libPlx/displayInfo.H"
  17. #include "libOLED/ap_math.h"
  18.  
  19. #include "splash.H"
  20.  
  21. namespace
  22. {
  23.   int const WIDTH = 128;
  24.   int const HEIGHT = 64;
  25.   int const DISPLAY_RAMWIDTH = 132;
  26. }
  27.  
  28. uint8_t displayBuffer[2][dataSize (WIDTH, HEIGHT)];
  29.  
  30. stm32_halDisplay_t displays[MAX_DISPLAYS] =
  31.   { stm32_halDisplay_t (WIDTH, HEIGHT, DISPLAY_RAMWIDTH, displayBuffer[0],
  32.                         &hspi1,
  33.                         SPI_CD_GPIO_Port,
  34.                         SPI_CD_Pin,
  35.                         SPI_RESET_GPIO_Port,
  36.                         SPI_RESET_Pin,
  37.                         SPI_NSS1_GPIO_Port,
  38.                         SPI_NSS1_Pin), stm32_halDisplay_t (WIDTH, HEIGHT,
  39.                                                            DISPLAY_RAMWIDTH,
  40.                                                            displayBuffer[1],
  41.                                                            &hspi1,
  42.                                                            SPI_CD_GPIO_Port,
  43.                                                            SPI_CD_Pin,
  44.                                                            SPI_RESET_GPIO_Port,
  45.                                                            SPI_RESET_Pin,
  46.                                                            SPI_NSS2_GPIO_Port,
  47.                                                            SPI_NSS2_Pin) };
  48.  
  49. displayDial_t dials[MAX_DISPLAYS] =
  50.   { displayDial_t (displays[0], 64, 60, 60, 90), displayDial_t (displays[1], 64,
  51.                                                                 60, 60, 90) };
  52. #if defined __cplusplus
  53. extern "C"
  54. {
  55. #endif
  56.   static void
  57.   showMinMax (display_t &display, uint8_t dp_pos, int16_t int_min,
  58.               uint16_t int_max)
  59.   {
  60.     display.fontSigDigits (small_font, 0, 0, 0, dp_pos, int_min, WHITE);
  61.     display.gotoxy (0, 8);
  62.  
  63.     display.printString (small_font, "Min", 3, WHITE);
  64.  
  65.     display.fontSigDigits (small_font, 120, 0, 1, dp_pos, int_max, WHITE);
  66.     display.gotoxy (110, 8);
  67.     display.printString (small_font, "Max", 3, WHITE);
  68.   }
  69.  
  70.   void
  71.   cc_init ()
  72.   {
  73.     for (auto i = 0; i < MAX_DISPLAYS; i++)
  74.       {
  75.         display_t &display = displays[i];
  76.         if (i == 0)
  77.           display.reset ();
  78.         display.init ();
  79.         display.clearDisplay (BLACK);
  80.         displaySplash (display);
  81.         display.gotoxy (8, 32);
  82.         display.printString (large_font, i == 0 ? "1" : "2", 1, BLACK);
  83.         display.display ();
  84.       }
  85.  
  86.     HAL_Delay (1000);
  87.  
  88.     for (auto i = 0; i < MAX_DISPLAYS; i++)
  89.       {
  90.         display_t &display = displays[i];
  91.         displayDial_t &dial = dials[i];
  92.         display.clearDisplay (BLACK);
  93.         display.setPixelMode (WHITE);
  94.         dial.draw_scale (0, 10, 12, 1, 1);
  95.         dial.draw_limits ();
  96.         display.gotoxy (8, 32);
  97.         display.printString (large_font, "Display ", 8, WHITE);
  98.         display.printString (large_font, i == 0 ? "1" : "2", 1, BLACK);
  99.         showMinMax (display, 2, 123, 456);
  100.  
  101.         display.display ();
  102.         context_t &context = contexts[i];
  103.         context.dial_timer = DialTimeout * 2; // extra long delay before writeback dial setting
  104.         context.dial1 = -1;
  105.       }
  106.  
  107.   }
  108.  
  109.   // Check to see if there is an observation/instance in the dynamic data array
  110.   // that matches the current observation/instance in the NVRAM
  111.   int
  112.   cc_check_nvram (int dialIndex, int itemIndex)
  113.   {
  114.     if (dialIndex < 0 && dialIndex > MAX_DISPLAYS)
  115.       return -1;
  116.     context_t &context = contexts[dialIndex];
  117.     // check for timer timeout on consistent timer
  118.  
  119.     if (context.dial_timer)
  120.       {
  121.         context.dial_timer--;
  122.         if (context.dial_timer == 0)
  123.           {
  124.             context.dial_timer = DialTimeout;
  125.             int i;
  126.             if (itemIndex < 0)
  127.               {
  128.                 for (i = 0; i < PLXItems; i++)
  129.                   if (Info[i].observation
  130.                       == dial_nvram[dialIndex].data.observation
  131.                       && Info[i].instance
  132.                           == dial_nvram[dialIndex].data.instance)
  133.                     {
  134.                       itemIndex = i;
  135.                       return itemIndex;
  136.                     }
  137.               }
  138.             if (itemIndex == -1)
  139.               itemIndex = dialIndex; // timed out , not in NVRAM, use a default
  140.  
  141.             // is this a change since the last timeout ?
  142.             if (Info[itemIndex].observation
  143.                 != dial_nvram[dialIndex].data.observation
  144.                 || Info[itemIndex].instance
  145.                     != dial_nvram[dialIndex].data.instance)
  146.               {
  147.  
  148.                 // store the observation and instance in the NVRAM, not dial position.
  149.                 nvram_info_t curr_val;
  150.                 curr_val.data.observation = Info[itemIndex].observation;
  151.                 curr_val.data.instance = Info[itemIndex].instance;
  152.                 uint32_t addr = (uint32_t) (&dial_nvram[dialIndex]);
  153.                 WriteUint32NVRAM (addr, curr_val.u32);
  154.               }
  155.           }
  156.       }
  157.     return itemIndex;
  158.   }
  159.  
  160.   int
  161.   cc_display (int dialIndex, int itemIndex, int suppressIndex)
  162.  
  163.   {
  164.     if (dialIndex < 0 && dialIndex > MAX_DISPLAYS)
  165.       return -1;
  166.     context_t &context = contexts[dialIndex];
  167.     displayDial_t &dial = dials[dialIndex];
  168.     stm32_halDisplay_t &display = displays[dialIndex];
  169.     char buff[10];
  170.     int i;
  171.  
  172.     // check for item suppression
  173.     if (itemIndex == suppressIndex)
  174.       {
  175.         context.dial1 = -1;
  176.         context.OldObservation = -1;
  177.         context.OldObservationIndex = -1;
  178.  
  179.         display.clearDisplay ();
  180.         display.display ();
  181.         return -1; // we suppressed this display
  182.       }
  183.  
  184.     // clear startup display off the screen
  185.     if (context.OldObservation == -1)
  186.       display.clearDisplay (BLACK);
  187.  
  188.     int DataVal = Info[itemIndex].data; // data reading
  189.     int Observation = Info[itemIndex].observation;
  190.     int ObservationIndex = Info[itemIndex].instance;
  191.     // now to convert the readings and format strings
  192.     // find out limits
  193.     char *msg;
  194.     int len;
  195.  
  196.     // if the user presses the dial then reset min/max to current value
  197.     if (push_pos[dialIndex] == 1)
  198.       {
  199.         Info[itemIndex].Max = DataVal;
  200.         Info[itemIndex].Min = DataVal; // 12 bit max value
  201.       }
  202.  
  203.     if (Observation < PLX_MAX_OBS)
  204.       {
  205.         if (Observation != context.OldObservation
  206.             || ObservationIndex != context.OldObservationIndex)
  207.           {
  208.  
  209.             display.clearDisplay ();
  210.             dial.draw_scale (DisplayInfo[Observation].Low,
  211.                              DisplayInfo[Observation].High, 12, 1,
  212.                              DisplayInfo[Observation].TickScale);
  213.  
  214.             dial.draw_limits ();
  215.  
  216.             msg = DisplayInfo[Observation].name;
  217.             len = 7;
  218.             int len1 = ObservationIndex > 0 ? len - 1 : len;
  219.             for (i = 0; i < len1 && msg[i]; i++)
  220.               {
  221.                 buff[i] = msg[i];
  222.               }
  223.             if (ObservationIndex > 0 && i < len)
  224.               {
  225.                 buff[i++] = ObservationIndex + '1';
  226.               }
  227.  
  228.             display.gotoxy (64 - i * 4, 48);
  229.             display.printString (large_font, buff, i, WHITE);
  230.  
  231.             context.OldObservation = Observation;
  232.             context.OldObservationIndex = ObservationIndex;
  233.  
  234.             display.display ();
  235.  
  236.           }
  237.  
  238.       }
  239.  
  240.     double max_rdg;
  241.     double min_rdg;
  242.     double cur_rdg;
  243.     int int_rdg;
  244.     int int_max;
  245.     int int_min;
  246.  
  247.     max_rdg = ConveriMFDRaw2Data (Observation, DisplayInfo[Observation].Units,
  248.                                   Info[itemIndex].Max);
  249.     min_rdg = ConveriMFDRaw2Data (Observation, DisplayInfo[Observation].Units,
  250.                                   Info[itemIndex].Min);
  251.     cur_rdg = ConveriMFDRaw2Data (Observation, DisplayInfo[Observation].Units,
  252.                                   Info[itemIndex].data);
  253.  
  254.     int dp_pos;  // where to print the decimal place
  255.     float scale = 1.0;
  256.     switch (DisplayInfo[Observation].DP)
  257.       {
  258.       default:
  259.       case 0:
  260.         scale = 1.0;
  261.         dp_pos = display_t::NO_DECIMAL;
  262.         break;
  263.       case 1:
  264.         scale = 10.0;
  265.         dp_pos = 1;
  266.         break;
  267.       case 2:
  268.         scale = 100.0;
  269.         dp_pos = 2;
  270.         break;
  271.  
  272.       }
  273.     int_rdg = (int) (cur_rdg * scale);
  274.     int_max = (int) (max_rdg * scale);
  275.     int_min = (int) (min_rdg * scale);
  276.  
  277.     cur_rdg -= DisplayInfo[Observation].Low;
  278.     cur_rdg = ap_math::SINE_STEPS * cur_rdg
  279.         / (DisplayInfo[Observation].High - DisplayInfo[Observation].Low);
  280.  
  281.     context.dial0 = (int) cur_rdg;
  282.  
  283.     display.gotoxy (32, 28);
  284.     display.fontDigits (large_font, 4, dp_pos, int_rdg, WHITE);
  285.  
  286.     display.printString (small_font, DisplayInfo[Observation].suffix,
  287.                          strlen (DisplayInfo[Observation].suffix));
  288.     display.printString (small_font, "    ",
  289.                          3 - strlen (DisplayInfo[Observation].suffix));
  290.     // print value overlaid by needle
  291.  
  292.     /* old needle un-draw */
  293.     if (context.dial1 >= 0)
  294.       {
  295.         dial.draw_needle (context.dial1);
  296.       }
  297.     dial.draw_needle (context.dial0);
  298.     context.dial1 = context.dial0;
  299.     showMinMax (display, dp_pos, int_min, int_max);
  300.  
  301.     display.display ();
  302.  
  303.     return itemIndex;
  304.   }
  305.  
  306. }
  307.  
  308.