/*********************************************************************
* Portions COPYRIGHT 2016 STMicroelectronics *
* Portions SEGGER Microcontroller GmbH & Co. KG *
* Solutions for real time microcontroller applications *
**********************************************************************
* *
* (c) 1996 - 2015 SEGGER Microcontroller GmbH & Co. KG *
* *
* Internet: www.segger.com Support: support@segger.com *
* *
**********************************************************************
** emWin V5.28 - Graphical user interface for embedded applications **
All Intellectual Property rights in the Software belongs to SEGGER.
emWin is protected by international copyright laws. Knowledge of the
source code may not be used to write a similar product. This file may
only be used in accordance with the following terms:
The software has been licensed to STMicroelectronics International
N.V. a Dutch company with a Swiss branch and its headquarters in Plan-
les-Ouates, Geneva, 39 Chemin du Champ des Filles, Switzerland for the
purposes of creating libraries for ARM Cortex-M-based 32-bit microcon_
troller products commercialized by Licensee only, sublicensed and dis_
tributed under the terms and conditions of the End User License Agree_
ment supplied by STMicroelectronics International N.V.
Full source code is available at: www.segger.com
We appreciate your understanding and fairness.
----------------------------------------------------------------------
File : GUIDEMO_Graph.c
Purpose : Several GUIDEMO routines
----------------------------------------------------------------------
*/
/**
******************************************************************************
* @file GUIDEMO_Graph.c
* @author MCD Application Team
* @brief Several GUIDEMO routines
******************************************************************************
* @attention
*
*
© Copyright (c) 2017 STMicroelectronics International N.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted, provided that the following conditions are met:
*
* 1. Redistribution of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of STMicroelectronics nor the names of other
* contributors to this software may be used to endorse or promote products
* derived from this software without specific written permission.
* 4. This software, including modifications and/or derivative works of this
* software, must execute solely and exclusively on microcontroller or
* microprocessor devices manufactured by or for STMicroelectronics.
* 5. Redistribution and use of this software other than as permitted under
* this license is void and will automatically terminate your rights under
* this license.
*
* THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
* PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY
* RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT
* SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
#include "GUIDEMO.h"
#if (SHOW_GUIDEMO_GRAPH && GUI_SUPPORT_MEMDEV)
/*********************************************************************
*
* Configuration defines
*
**********************************************************************
*/
#define MAX_GRAPH_SIZE_X 440
#define MAX_GRAPH_SIZE_Y (MAX_GRAPH_SIZE_X * 11) / 20
#define DIST_TO_BORDER 10
#define DIST_TO_WIN 5
#define BORDER_TOP 0
#define BORDER_BOTTOM 9
#define BORDER_LEFT 19
#define BORDER_RIGHT 0
#define COLOR_BK GUI_DARKGRAY
#define COLOR_BORDER BK_COLOR_1
#define COLOR_FRAME GUI_BLACK
#define COLOR_GRID GUI_GRAY
#define SCALE_H_HEIGHT 4
#define TICK_DIST_H 25
#define TICK_DIST_V 20
#define TIME_RUN 5000
#define TIME_STEP 15
#define HEARTBEAT_TIME 1000
#define MAX_NUM_DATA_OBJ 5
#define GRAPH_DIV 9 // (2^9 = 512) If this value is changed _aWaves[] need to be changed too!
#define GRID_DIST_X 25
#define GRID_DIST_Y 10
#define GRID_OFF_Y 25
/*********************************************************************
*
* Typedef / Data
*
**********************************************************************
*/
typedef struct {
char * Name;
int ScaleVOff;
int DataVOff;
int GridVOff;
void (* pfAddData)(GRAPH_DATA_Handle hData, int DataID);
int NumWaves;
} GRAPH_WAVE;
static int _HeartBeat[] = {
2, 4, 6, 8, 10, 6, 2, 0, 0, 0,
-8, 16, 40, 64, 88, 58, 28, -2, -32, -30,
-20, -10, 0, 2, 2, 4, 4, 6, 6, 8,
8, 10, 12, 14, 16, 18, 20, 16, 12, 8,
4, 2, 2, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static GUI_COLOR _aColorData[MAX_NUM_DATA_OBJ] = {
0x50C0FF,
0xFFC050,
0x50FFC0,
0x800000,
0x000080
};
GRAPH_SCALE_Handle _hScaleH, _hScaleV;
static int _DataAdjust;
/*********************************************************************
*
* Static functions
*
**********************************************************************
*/
/*********************************************************************
*
* _AddData_Sine
*/
static void _AddData_Sine(GRAPH_DATA_Handle hData, int DataID) {
static int x1000[MAX_NUM_DATA_OBJ];
I32 SinHQ;
int Multi, Step;
switch (DataID) {
case 0:
Multi = 70;
Step = 3;
break;
case 1:
Multi = 50;
Step = 1;
break;
case 2:
Multi = 30;
Step = 7;
break;
default:
return;
}
SinHQ = GUI__SinHQ(x1000[DataID]);
x1000[DataID] += 1000 * Step;
GRAPH_DATA_YT_AddValue(hData, ((SinHQ * Multi) >> 16) + _DataAdjust);
}
/*********************************************************************
*
* _AddData_Heartbeat
*/
static void _AddData_Heartbeat(GRAPH_DATA_Handle hData, int DataID) {
static int Index;
GUI_USE_PARA(DataID);
GRAPH_DATA_YT_AddValue(hData, (_HeartBeat[Index]) + _DataAdjust);
if (++Index == GUI_COUNTOF(_HeartBeat)) {
Index = 0;
}
}
/*********************************************************************
*
* DATA _aWave - Keep below _AddData-functions
*/
GRAPH_WAVE _aWave[] = {
{ "Heartbeat", // Name
157, // Vertical scale offset in relation to GRAPH_DIV
152, // Vertical data offset in relation to GRAPH_DIV
21, // Vertical grid offset in relation to GRAPH_DIV
_AddData_Heartbeat, // Pointer to specific AddData function
1 // Number of waves
},
{ "Sine Waves",
265,
253,
23,
_AddData_Sine,
3
},
0
};
/*********************************************************************
*
* _ShowGraph
*/
static void _ShowGraph(GRAPH_Handle hGraph, GRAPH_DATA_Handle hData[], int DataCount, void (* pfAddData)(GRAPH_DATA_Handle hData, int DataID)) {
int Count, Data_xSize, xSize;
int TimeStart, TimeDiff, TimeStep;
int NextState, i, Flag;
xSize = LCD_GetXSize();
Data_xSize = xSize - (DIST_TO_BORDER << 1) - (BORDER_LEFT + BORDER_RIGHT);
Count = 0;
//
// Attach data objects
//
for (i = 0; i < DataCount; i++) {
GRAPH_AttachData(hGraph, hData[i]);
}
//
// Add values before GRAPH is displayed
//
while (Count < Data_xSize) {
for (i = 0; i < DataCount; i++) {
pfAddData(hData[i], i);
}
Count++;
}
//
// Add values depending on time
//
TimeStart = GUIDEMO_GetTime();
Flag = 1;
do {
TimeDiff = GUIDEMO_GetTime() - TimeStart;
for (i = 0; i < DataCount; i++) {
pfAddData(hData[i], i);
}
if (Flag) {
Flag = 0;
GUI_Exec();
GRAPH_DetachScale(hGraph, _hScaleH);
GRAPH_DetachScale(hGraph, _hScaleV);
WM_ValidateWindow(hGraph);
}
NextState = GUIDEMO_CheckCancel();
TimeStep = GUIDEMO_GetTime() - TimeStart;
if ((TimeStep - TimeDiff) < TIME_STEP) {
GUI_Delay(TIME_STEP - (TimeStep - TimeDiff));
}
} while ((TimeDiff < TIME_RUN) && (NextState == 0));
for (i = 0; i < DataCount; i++) {
GRAPH_DetachData(hGraph, hData[i]);
}
GUIDEMO_NotifyStartNext();
}
/*********************************************************************
*
* _cbBk
*/
static void _cbBk(WM_MESSAGE * pMsg) {
switch (pMsg->MsgId) {
case WM_PAINT:
GUIDEMO_DrawBk(1);
break;
default:
WM_DefaultProc(pMsg);
}
}
/*********************************************************************
*
* _GraphDemo
*/
static void _GraphDemo(void) {
const WIDGET_EFFECT * pEffectOld;
GRAPH_Handle hGraph;
GRAPH_DATA_Handle hData[MAX_NUM_DATA_OBJ];
int xSize, ySize, i;
int Graph_xSize, Graph_ySize, Data_ySize;
int Graph_xPos, Graph_yPos;
xSize = LCD_GetXSize();
ySize = LCD_GetYSize();
pEffectOld = WIDGET_SetDefaultEffect(&WIDGET_Effect_Simple);
//
// Set Callback function for background window
//
WM_SetCallback(WM_HBKWIN, _cbBk);
//
// Determine size of GRAPH
//
Graph_xSize = xSize - (DIST_TO_BORDER << 1); // xsize = Screen size subtracting twice the distance to the border of the screen
Graph_ySize = ySize - INFO_SIZE_Y - (DIST_TO_WIN << 1); // ysize = Screen size subtracting the window sizes and twice the distance to the windows
if (Graph_ySize > MAX_GRAPH_SIZE_Y) {
Graph_ySize = MAX_GRAPH_SIZE_Y;
if (Graph_xSize > (Graph_ySize * 20) / 11) {
Graph_xSize = (Graph_ySize * 20) / 11;
}
}
//
// Create and configure GRAPH_WIDGET
//
Graph_xPos = (xSize - Graph_xSize) >> 1;
Graph_yPos = (ySize - Graph_ySize) >> 1;
if (Graph_yPos < INFO_SIZE_Y + DIST_TO_WIN) {
Graph_yPos = INFO_SIZE_Y + DIST_TO_WIN;
}
hGraph = GRAPH_CreateEx(Graph_xPos, Graph_yPos, Graph_xSize, Graph_ySize, WM_HBKWIN, WM_CF_SHOW | WM_CF_CONST_OUTLINE, 0, 0);
GRAPH_SetBorder(hGraph, BORDER_LEFT, BORDER_TOP, BORDER_RIGHT, BORDER_BOTTOM);
WM_SetHasTrans (hGraph);
GRAPH_SetColor (hGraph, COLOR_BK, GRAPH_CI_BK);
GRAPH_SetColor (hGraph, COLOR_BORDER, GRAPH_CI_BORDER);
GRAPH_SetColor (hGraph, COLOR_FRAME, GRAPH_CI_FRAME);
GRAPH_SetColor (hGraph, COLOR_GRID, GRAPH_CI_GRID);
//
// Adjust grid
//
GRAPH_SetGridVis (hGraph, 1);
GRAPH_SetGridDistX(hGraph, GRID_DIST_X);
GRAPH_SetGridDistY(hGraph, GRID_DIST_Y);
WM_BringToBottom (hGraph);
//
// Create and configure GRAPH_DATA_YT object
//
for (i = 0; i < MAX_NUM_DATA_OBJ; i++) {
hData[i] = GRAPH_DATA_YT_Create(_aColorData[i], xSize - (DIST_TO_BORDER << 1) - BORDER_LEFT, 0, 0);
}
Data_ySize = Graph_ySize - BORDER_BOTTOM;
//
// Create and configure GRAPH_SCALE objects
//
_hScaleH = GRAPH_SCALE_Create(BORDER_BOTTOM >> 1, GUI_TA_VCENTER, GRAPH_SCALE_CF_HORIZONTAL, TICK_DIST_H);
_hScaleV = GRAPH_SCALE_Create(BORDER_LEFT >> 1, GUI_TA_HCENTER, GRAPH_SCALE_CF_VERTICAL, TICK_DIST_V);
GRAPH_SCALE_SetPos(_hScaleH, Graph_ySize - SCALE_H_HEIGHT);
GRAPH_SCALE_SetOff(_hScaleH, -5);
//
// Show some graphs
//
i = 0;
while (_aWave[i].pfAddData != 0) {
GUIDEMO_ShowInfo(_aWave[i].Name);
GRAPH_AttachScale(hGraph, _hScaleH);
GRAPH_AttachScale(hGraph, _hScaleV);
_DataAdjust = (Data_ySize * _aWave[i].DataVOff) >> GRAPH_DIV;
GRAPH_SetGridOffY (hGraph, (Data_ySize * _aWave[i].GridVOff) >> GRAPH_DIV);
GRAPH_SCALE_SetOff(_hScaleV, (((Data_ySize - BORDER_BOTTOM) * _aWave[i].ScaleVOff) >> GRAPH_DIV));
_ShowGraph(hGraph, hData, _aWave[i].NumWaves, _aWave[i].pfAddData);
i++;
}
//
// Clean up
//
GRAPH_DetachScale(hGraph, _hScaleH);
GRAPH_DetachScale(hGraph, _hScaleV);
GRAPH_SCALE_Delete(_hScaleH);
GRAPH_SCALE_Delete(_hScaleV);
for (i = 0; i < MAX_NUM_DATA_OBJ; i++) {
GRAPH_DATA_YT_Delete(hData[i]);
}
WM_DeleteWindow(hGraph);
WIDGET_SetDefaultEffect(pEffectOld);
}
/*********************************************************************
*
* Public functions
*
**********************************************************************
*/
void GUIDEMO_Graph(void) {
GUIDEMO_ShowIntro("Drawing a graph",
"Optimized drawing routine\n"
"for drawing graph data");
GUIDEMO_ShowInfoWin();
_GraphDemo();
GUIDEMO_NotifyStartNext();
}
#else
void GUIDEMO_Graph(void) {}
#endif
/*************************** End of file ****************************/