Subversion Repositories DashDisplay

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
50 mjames 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
 
54 mjames 63
    display.printString (small_font, "Min", 3, WHITE);
50 mjames 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 ();
55 mjames 79
        display.clearDisplay (BLACK);
50 mjames 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];
56 mjames 91
        display.clearDisplay (BLACK);
54 mjames 92
        display.setPixelMode (WHITE);
50 mjames 93
        display.display ();
56 mjames 94
        context_t &context = contexts[i];
57 mjames 95
        context.dial_timer = 200; // enough time to see at least one frame of PLX before NVRAM check
56 mjames 96
        context.dial1 = -1;
57 mjames 97
        context.OldObservation = -1;
98
        context.OldObservationIndex = -1;
50 mjames 99
      }
56 mjames 100
 
50 mjames 101
  }
102
 
56 mjames 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
57 mjames 105
 
106
  void
107
  cc_check_nvram (int dialIndex)
56 mjames 108
  {
109
    if (dialIndex < 0 && dialIndex > MAX_DISPLAYS)
57 mjames 110
      return;
56 mjames 111
    context_t &context = contexts[dialIndex];
57 mjames 112
 
56 mjames 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;
57 mjames 122
            if (context.knobPos < 0)
56 mjames 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
                    {
57 mjames 130
                      context.knobPos = i;
131
                      return;
56 mjames 132
                    }
133
              }
57 mjames 134
            if (context.knobPos == -1)
135
              context.knobPos = dialIndex; // timed out , not in NVRAM, use a default
56 mjames 136
 
137
            // is this a change since the last timeout ?
57 mjames 138
            if (Info[context.knobPos].observation
56 mjames 139
                != dial_nvram[dialIndex].data.observation
57 mjames 140
                || Info[context.knobPos].instance
56 mjames 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;
57 mjames 146
                curr_val.data.observation = Info[context.knobPos].observation;
147
                curr_val.data.instance = Info[context.knobPos].instance;
56 mjames 148
                uint32_t addr = (uint32_t) (&dial_nvram[dialIndex]);
149
                WriteUint32NVRAM (addr, curr_val.u32);
150
              }
151
          }
152
      }
153
  }
154
 
155
  int
57 mjames 156
  cc_display (int dialIndex, int suppressIndex)
50 mjames 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];
57 mjames 164
    int itemIndex = context.knobPos;
50 mjames 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)
56 mjames 182
      display.clearDisplay (BLACK);
50 mjames 183
 
56 mjames 184
    int DataVal = Info[itemIndex].data; // data reading
185
    int Observation = Info[itemIndex].observation;
186
    int ObservationIndex = Info[itemIndex].instance;
50 mjames 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
      {
56 mjames 195
        Info[itemIndex].Max = DataVal;
196
        Info[itemIndex].Min = DataVal; // 12 bit max value
50 mjames 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;
57 mjames 229
            context.dial1 = -1; // do not display old needl, cleared screen
50 mjames 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,
56 mjames 244
                                  Info[itemIndex].Max);
50 mjames 245
    min_rdg = ConveriMFDRaw2Data (Observation, DisplayInfo[Observation].Units,
56 mjames 246
                                  Info[itemIndex].Min);
50 mjames 247
    cur_rdg = ConveriMFDRaw2Data (Observation, DisplayInfo[Observation].Units,
56 mjames 248
                                  Info[itemIndex].data);
50 mjames 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