1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
|
//*****************************************************************************
//
// stripchartmanager.c - Manages a strip chart widget for the data logger.
//
// Copyright (c) 2011-2014 Texas Instruments Incorporated. All rights reserved.
// Software License Agreement
//
// Texas Instruments (TI) is supplying this software for use solely and
// exclusively on TI's microcontroller products. The software is owned by
// TI and/or its suppliers, and is protected under applicable copyright
// laws. You may not combine this software with "viral" open-source
// software in order to form a larger program.
//
// THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
// NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
// NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
// CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
// DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 2.1.0.12573 of the DK-TM4C123G Firmware Package.
//
//*****************************************************************************
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "inc/hw_types.h"
#include "grlib/grlib.h"
#include "grlib/widget.h"
#include "grlib/canvas.h"
#include "drivers/cfal96x64x16.h"
#include "drivers/slidemenuwidget.h"
#include "drivers/stripchartwidget.h"
#include "stripchartmanager.h"
#include "clocksetwidget.h"
#include "qs-logger.h"
#include "menus.h"
#include "utils/ustdlib.h"
//*****************************************************************************
//
// This module manages a strip chart widget for the data logger application.
// It provides functions to make it easy to configure a strip chart for the
// user-selected data series, and to add new data to the strip chart. The
// functions in this module maintain buffers that hold the data for each data
// series that is selected for display on the strip chart.
//
//*****************************************************************************
//*****************************************************************************
//
// Define a scaling range for each data series. Since multiple kinds of data
// will be shown on the strip chart, no one particular set of units can be
// selected. Instead the strip chart Y axis will just be maintained in units
// of pixels, and the table below maps the Y axis range to min and max values
// for each data series.
//
//*****************************************************************************
typedef struct
{
int16_t i16Min;
int16_t i16Max;
} tDisplayScaling;
tDisplayScaling g_psScaling[] =
{
{ 0, 20000 }, // analog channel inputs,
{ 0, 20000 }, // 0-20V (20000 mV)
{ 0, 20000 },
{ 0, 20000 },
{ -200, 200 }, // accelerometer axes, -10 - 10g
{ -200, 200 }, // (units of 1/100g)
{ -200, 200 },
{ 0, 500 }, // temperature, 0 - 50C (units of
{ 0, 500 }, // 1/10C)
{ 0, 400 }, // current, 0 - 40mA (units of 100uA)
{ -1200, 1200 }, // Gyrometer -250 to 250 rad/sec
{ -1200, 1200 }, // (units of 1/100)
{ -1200, 1200 },
{ -60, 60 }, // Magnometer in microTesla -.1mT to .1mT
{ -60, 60 }, // to be human friendly
{ -60, 60 }, // (unit of 1/100 uT)
};
//*****************************************************************************
//
// Defines the maximum number of items that are stored in a data series. This
// matches the width of the strip chart in pixels.
//
//*****************************************************************************
#define SERIES_LENGTH 96
//*****************************************************************************
//
// Create an array of strip chart data series, one for each channel of data
// that the data logger can acquire. Fields that are unchanging, such as
// the name of each series, are pre-populated here, while other fields that
// may change are updated by functions. These are the data series that get
// added to the strip chart for each item that is selected for logging.
//
//*****************************************************************************
static tStripChartSeries g_psSeries[] =
{
{ 0, "CH0", 0x000040, 1, 1, 0, 0 },
{ 0, "CH1", ClrLime, 1, 1, 0, 0 },
{ 0, "CH2", ClrAqua, 1, 1, 0, 0 },
{ 0, "CH3", ClrRed, 1, 1, 0, 0 },
{ 0, "ACCELX", ClrBlue, 1, 1, 0, 0 },
{ 0, "ACCELY", 0x00A000, 1, 1, 0, 0 },
{ 0, "ACCELZ", ClrFuchsia, 1, 1, 0, 0 },
{ 0, "CURRENT", ClrYellow, 1, 1, 0, 0 },
{ 0, "EXT TEMP", 0xC00040, 1, 1, 0, 0 },
{ 0, "INT TEMP", 0x60E080, 1, 1, 0, 0 },
{ 0, "GYROX", ClrBlue, 1, 1, 0, 0 },
{ 0, "GYROY", 0x00A000, 1, 1, 0, 0 },
{ 0, "GYROZ", ClrFuchsia, 1, 1, 0, 0 },
{ 0, "MAGX", ClrBlue, 1, 1, 0, 0 },
{ 0, "MAGY", 0x00A000, 1, 1, 0, 0 },
{ 0, "MAGZ", ClrFuchsia, 1, 1, 0, 0 },
};
#define MAX_NUM_SERIES (sizeof(g_psSeries) / \
sizeof(tStripChartSeries))
//*****************************************************************************
//
// Defines the X-axis for the strip chart.
//
//*****************************************************************************
static tStripChartAxis g_sAxisX =
{
"X-AXIS", // title of axis
0, // label for minimum of axis
0, // label for maximum of axis
0, // minimum value for the axis
95, // maximum value for the axis
10 // grid interval for the axis
};
//*****************************************************************************
//
// Defines the Y-axis for the strip chart.
//
//*****************************************************************************
static tStripChartAxis g_sAxisY =
{
0, // title of the axis
0, // label for minimum of axis
0, // label for maximum of axis
0, // minimum value for the axis
63, // maximum value for the axis
16 // grid interval for the axis
};
//*****************************************************************************
//
// Defines the strip chart widget. This structure must be fully initialized
// by calling the function StripChartMgrInit().
//
//*****************************************************************************
StripChart(g_sStripChart, 0, 0, 0, 0, 0, 0, 96, 64, 0, g_psFontFixed6x8,
ClrBlack, ClrWhite, ClrWhite, ClrDarkGreen, &g_sAxisX,
&g_sAxisY, 0);
//*****************************************************************************
//
// Creates a buffer space for the values in the data series. The buffer
// must be large enough to hold all of the data for the maximum possible
// number of data items that are selected. If less than the maximum number
// are selected then some of the buffer space will be unused.
//
//*****************************************************************************
static uint8_t g_pui8SeriesData[MAX_NUM_SERIES * SERIES_LENGTH];
//*****************************************************************************
//
// The count of data series that are selected for showing on the strip chart.
// This value is set when the client calls the function StripChartConfigure().
//
//*****************************************************************************
static uint32_t g_ui32SelectedCount;
//*****************************************************************************
//
// The number of items (per series) that have been added to the strip chart.
//
//*****************************************************************************
static uint32_t g_ui32ItemCount;
//*****************************************************************************
//
// A bit mask of the specific data items that have been selected for logging.
//
//*****************************************************************************
static uint32_t g_ui32SelectedMask;
//*****************************************************************************
//
// Configure the strip chart for a selected set of data series. The selected
// series is passed in as a bit mask. Each bit that is set in the bit mask
// represents a selected series. This function will go through the possible
// set of data series and for each that is selected it will be initialized
// and added to the strip chart.
//
//*****************************************************************************
void
StripChartMgrConfigure(uint32_t ui32SelectedMask)
{
uint32_t ui32Idx, ui32ItemIdx;
tStripChartSeries *psSeries;
//
// Save the channel mask for later use
//
g_ui32SelectedMask = ui32SelectedMask;
//
// Determine how many series are to appear in the strip chart.
//
g_ui32SelectedCount = 0;
ui32Idx = ui32SelectedMask;
while(ui32Idx)
{
if(ui32Idx & 1)
{
g_ui32SelectedCount++;
}
ui32Idx >>= 1;
}
//
// Reset the number of items that have been stored in the series buffers.
//
g_ui32ItemCount = 0;
//
// Remove any series that were already added to the strip chart.
//
g_sStripChart.psSeries = 0;
//
// Loop through all series, and configure the selected series and add
// them to the strip chart.
//
ui32ItemIdx = 0;
for(ui32Idx = 0; ui32Idx < MAX_NUM_SERIES; ui32Idx++)
{
//
// Check to see if this series is selected
//
if((1 << ui32Idx) & ui32SelectedMask)
{
//
// Get a pointer to this series.
//
psSeries = &g_psSeries[ui32Idx];
//
// Set the stride for this series. It will be the same as the
// number of enabled data items.
//
psSeries->ui8Stride = g_ui32SelectedCount;
//
// Set the series data pointer to start at the first location
// in the series buffer where this data item will appear.
//
psSeries->pvData = &g_pui8SeriesData[ui32ItemIdx];
//
// Add the series to the strip chart.
//
StripChartSeriesAdd(&g_sStripChart, psSeries);
//
// Increment the index of selected series.
//
ui32ItemIdx++;
}
}
}
//*****************************************************************************
//
// Scales the input data value to a Y pixel range according to the scaling
// table at the top of this file.
//
//*****************************************************************************
static uint8_t
ScaleDataToPixelY(int16_t i16Data, int16_t i16Min, int16_t i16Max)
{
int32_t i32Y;
int16_t i16Range;
//
// Adjust the input value so that the min will be the bottom of display.
//
i16Data -= i16Min;
//
// Compute the range of the input that will appear on the display
//
i16Range = i16Max - i16Min;
//
// Scale the input to the Y pixel range of the display
//
i32Y = (int32_t)i16Data * 63L;
//
// Add in half of divisor to get proper rounding
//
i32Y += (int32_t)i16Range / 2L;
//
// Apply final divisor to get Y pixel value on display
//
i32Y /= (int32_t)i16Range;
//
// If the Y coordinate is out of the range of the display, force the
// value to be just off the display, in order to avoid aliasing to a
// bogus Y pixel value when the return value is converted to a smaller
// data type.
//
if((i32Y < 0) || (i32Y > 63))
{
i32Y = 64;
}
//
// Return the Y pixel value
//
return((uint8_t)i32Y);
}
//*****************************************************************************
//
// Add data items to the strip chart and advance the strip chart position.
// This function will add the items pointed to by the parameter to the data
// series buffer and the strip chart will be updated to reflect the newly
// added data items.
// This function will assume that the number of items passed by the pointer
// is the same as was selected by the function StripChartMgrConfigure().
// up to the caller to ensure that the amount of data passed matches the
// number of items that were selected when the strip chart was configured.
//
//*****************************************************************************
void
StripChartMgrAddItems(int16_t *pi16DataItems)
{
uint32_t ui32Idx, ui32SelectedMask = g_ui32SelectedMask;
uint8_t *pui8NewData;
//
// Check for valid input data pointer
//
if(!pi16DataItems)
{
return;
}
//
// If the number count of items in the strip chart is at the maximum, then
// the items need to "slide down" and new data added to the end of the
// buffer.
//
if(g_ui32ItemCount == SERIES_LENGTH)
{
memmove(&g_pui8SeriesData[0], &g_pui8SeriesData[g_ui32SelectedCount],
SERIES_LENGTH * g_ui32SelectedCount);
//
// Set the pointer for newly added data to be the end of the series
// buffer.
//
pui8NewData = &g_pui8SeriesData[(SERIES_LENGTH - 1) *
g_ui32SelectedCount];
}
else
{
//
// Otherwise, the series data buffer is less than full so compute the
// correct location in the buffer for the new data to be added.
//
pui8NewData = &g_pui8SeriesData[g_ui32ItemCount *
g_ui32SelectedCount];
//
// Increment the number of items that have been added to the strip
// chart series data buffer.
//
g_ui32ItemCount++;
//
// Since the count of data items has changed, it must be updated for
// each series.
//
for(ui32Idx = 0; ui32Idx < MAX_NUM_SERIES; ui32Idx++)
{
g_psSeries[ui32Idx].ui16NumItems = g_ui32ItemCount;
}
}
//
// Convert each of the input data items being added to the strip chart
// to a scaled Y pixel value.
//
ui32Idx = 0;
while(ui32SelectedMask)
{
//
// Is this data item being added to the chart?
//
if(ui32SelectedMask & 1)
{
//
// Scale the data item and add it to the series buffer
//
*pui8NewData = ScaleDataToPixelY(*pi16DataItems,
g_psScaling[ui32Idx].i16Min,
g_psScaling[ui32Idx].i16Max);
//
// Increment the from/to pointers
//
pui8NewData++;
pi16DataItems++;
}
ui32Idx++;
ui32SelectedMask >>= 1;
}
//
// Now that data has been added to the strip chart series buffers, either
// at the end or in the middle, advance the strip chart position by 1.
// Add a request for painting the strip chart widget.
//
StripChartAdvance(&g_sStripChart, 1);
WidgetPaint(WIDGET_ROOT);
}
//*****************************************************************************
//
// Initializes the strip chart manager. The strip chart needs an on-screen
// and off-screen display for drawing. These are passed using the init
// function.
//
//*****************************************************************************
void
StripChartMgrInit(void)
{
g_sStripChart.sBase.psDisplay = &g_sCFAL96x64x16;
g_sStripChart.psOffscreenDisplay = &g_sOffscreenDisplayA;
}
|