Subversion Repositories DashDisplay

Rev

Rev 56 | 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.         display.clearDisplay (BLACK);
  92.         display.setPixelMode (WHITE);
  93.         display.display ();
  94.         context_t &context = contexts[i];
  95.         context.dial_timer = 200; // enough time to see at least one frame of PLX before NVRAM check
  96.         context.dial1 = -1;
  97.         context.OldObservation = -1;
  98.         context.OldObservationIndex = -1;
  99.       }
  100.  
  101.   }
  102.  
  103.   // Check to see if there is an observation/instance in the dynamic data array
  104.   // that matches the current observation/instance in the NVRAM
  105.  
  106.   void
  107.   cc_check_nvram (int dialIndex)
  108.   {
  109.     if (dialIndex < 0 && dialIndex > MAX_DISPLAYS)
  110.       return;
  111.     context_t &context = contexts[dialIndex];
  112.  
  113.     // check for timer timeout on consistent timer
  114.  
  115.     if (context.dial_timer)
  116.       {
  117.         context.dial_timer--;
  118.         if (context.dial_timer == 0)
  119.           {
  120.             context.dial_timer = DialTimeout;
  121.             int i;
  122.             if (context.knobPos < 0)
  123.               {
  124.                 for (i = 0; i < PLXItems; i++)
  125.                   if (Info[i].observation
  126.                       == dial_nvram[dialIndex].data.observation
  127.                       && Info[i].instance
  128.                           == dial_nvram[dialIndex].data.instance)
  129.                     {
  130.                       context.knobPos = i;
  131.                       return;
  132.                     }
  133.               }
  134.             if (context.knobPos == -1)
  135.               context.knobPos = dialIndex; // timed out , not in NVRAM, use a default
  136.  
  137.             // is this a change since the last timeout ?
  138.             if (Info[context.knobPos].observation
  139.                 != dial_nvram[dialIndex].data.observation
  140.                 || Info[context.knobPos].instance
  141.                     != dial_nvram[dialIndex].data.instance)
  142.               {
  143.  
  144.                 // store the observation and instance in the NVRAM, not dial position.
  145.                 nvram_info_t curr_val;
  146.                 curr_val.data.observation = Info[context.knobPos].observation;
  147.                 curr_val.data.instance = Info[context.knobPos].instance;
  148.                 uint32_t addr = (uint32_t) (&dial_nvram[dialIndex]);
  149.                 WriteUint32NVRAM (addr, curr_val.u32);
  150.               }
  151.           }
  152.       }
  153.   }
  154.  
  155.   int
  156.   cc_display (int dialIndex, int suppressIndex)
  157.  
  158.   {
  159.     if (dialIndex < 0 && dialIndex > MAX_DISPLAYS)
  160.       return -1;
  161.     context_t &context = contexts[dialIndex];
  162.     displayDial_t &dial = dials[dialIndex];
  163.     stm32_halDisplay_t &display = displays[dialIndex];
  164.     int itemIndex = context.knobPos;
  165.     char buff[10];
  166.     int i;
  167.  
  168.     // check for item suppression
  169.     if (itemIndex == suppressIndex)
  170.       {
  171.         context.dial1 = -1;
  172.         context.OldObservation = -1;
  173.         context.OldObservationIndex = -1;
  174.  
  175.         display.clearDisplay ();
  176.         display.display ();
  177.         return -1; // we suppressed this display
  178.       }
  179.  
  180.     // clear startup display off the screen
  181.     if (context.OldObservation == -1)
  182.       display.clearDisplay (BLACK);
  183.  
  184.     int DataVal = Info[itemIndex].data; // data reading
  185.     int Observation = Info[itemIndex].observation;
  186.     int ObservationIndex = Info[itemIndex].instance;
  187.     // now to convert the readings and format strings
  188.     // find out limits
  189.     char *msg;
  190.     int len;
  191.  
  192.     // if the user presses the dial then reset min/max to current value
  193.     if (push_pos[dialIndex] == 1)
  194.       {
  195.         Info[itemIndex].Max = DataVal;
  196.         Info[itemIndex].Min = DataVal; // 12 bit max value
  197.       }
  198.  
  199.     if (Observation < PLX_MAX_OBS)
  200.       {
  201.         if (Observation != context.OldObservation
  202.             || ObservationIndex != context.OldObservationIndex)
  203.           {
  204.  
  205.             display.clearDisplay ();
  206.             dial.draw_scale (DisplayInfo[Observation].Low,
  207.                              DisplayInfo[Observation].High, 12, 1,
  208.                              DisplayInfo[Observation].TickScale);
  209.  
  210.             dial.draw_limits ();
  211.  
  212.             msg = DisplayInfo[Observation].name;
  213.             len = 7;
  214.             int len1 = ObservationIndex > 0 ? len - 1 : len;
  215.             for (i = 0; i < len1 && msg[i]; i++)
  216.               {
  217.                 buff[i] = msg[i];
  218.               }
  219.             if (ObservationIndex > 0 && i < len)
  220.               {
  221.                 buff[i++] = ObservationIndex + '1';
  222.               }
  223.  
  224.             display.gotoxy (64 - i * 4, 48);
  225.             display.printString (large_font, buff, i, WHITE);
  226.  
  227.             context.OldObservation = Observation;
  228.             context.OldObservationIndex = ObservationIndex;
  229.             context.dial1 = -1; // do not display old needl, cleared screen
  230.             display.display ();
  231.  
  232.           }
  233.  
  234.       }
  235.  
  236.     double max_rdg;
  237.     double min_rdg;
  238.     double cur_rdg;
  239.     int int_rdg;
  240.     int int_max;
  241.     int int_min;
  242.  
  243.     max_rdg = ConveriMFDRaw2Data (Observation, DisplayInfo[Observation].Units,
  244.                                   Info[itemIndex].Max);
  245.     min_rdg = ConveriMFDRaw2Data (Observation, DisplayInfo[Observation].Units,
  246.                                   Info[itemIndex].Min);
  247.     cur_rdg = ConveriMFDRaw2Data (Observation, DisplayInfo[Observation].Units,
  248.                                   Info[itemIndex].data);
  249.  
  250.     int dp_pos;  // where to print the decimal place
  251.     float scale = 1.0;
  252.     switch (DisplayInfo[Observation].DP)
  253.       {
  254.       default:
  255.       case 0:
  256.         scale = 1.0;
  257.         dp_pos = display_t::NO_DECIMAL;
  258.         break;
  259.       case 1:
  260.         scale = 10.0;
  261.         dp_pos = 1;
  262.         break;
  263.       case 2:
  264.         scale = 100.0;
  265.         dp_pos = 2;
  266.         break;
  267.  
  268.       }
  269.     int_rdg = (int) (cur_rdg * scale);
  270.     int_max = (int) (max_rdg * scale);
  271.     int_min = (int) (min_rdg * scale);
  272.  
  273.     cur_rdg -= DisplayInfo[Observation].Low;
  274.     cur_rdg = ap_math::SINE_STEPS * cur_rdg
  275.         / (DisplayInfo[Observation].High - DisplayInfo[Observation].Low);
  276.  
  277.     context.dial0 = (int) cur_rdg;
  278.  
  279.     display.gotoxy (32, 28);
  280.     display.fontDigits (large_font, 4, dp_pos, int_rdg, WHITE);
  281.  
  282.     display.printString (small_font, DisplayInfo[Observation].suffix,
  283.                          strlen (DisplayInfo[Observation].suffix));
  284.     display.printString (small_font, "    ",
  285.                          3 - strlen (DisplayInfo[Observation].suffix));
  286.     // print value overlaid by needle
  287.  
  288.     /* old needle un-draw */
  289.     if (context.dial1 >= 0)
  290.       {
  291.         dial.draw_needle (context.dial1);
  292.       }
  293.     dial.draw_needle (context.dial0);
  294.     context.dial1 = context.dial0;
  295.     showMinMax (display, dp_pos, int_min, int_max);
  296.  
  297.     display.display ();
  298.  
  299.     return itemIndex;
  300.   }
  301.  
  302. }
  303.  
  304.