GRAPH widget performance optimization

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • GRAPH widget performance optimization

      Greetings,

      I am looking for ways to optimize the performance of the GRAPH_DATA_XY widget for the refresh of the screen for new data on embedded hardware. The vertical refresh is progressively slower the more data is displayed (# of chart graphs, primarily).

      I have an STM32F429ZI running with external 32 MB SPANSION SDRAM on an 800x480 LCD. WM_SetCreateFlags(WM_CF_MEMDEV) is set before GUI_Init(). I believe I have triple buffering on now which helped with screen flicker between emWin screens previously.

      Example code:

      C Source Code

      1. #include "DIALOG.h"
      2. #include <stdio.h>
      3. /*********************************************************************
      4. *
      5. * Defines
      6. *
      7. **********************************************************************
      8. */
      9. #define OutputDebugString(x) printf(x)
      10. #define ID_WINDOW_0 (GUI_ID_USER + 0x00)
      11. #define ID_GRAPH_0 (GUI_ID_USER + 0x01)
      12. #define ID_BUTTON_0 (GUI_ID_USER + 0x02)
      13. #define ID_BUTTON_1 (GUI_ID_USER + 0x03)
      14. #define Y_SCALE_MAX 113.0 // So that 100 is the highest Y scale bar number displayed
      15. #define Y_SCALE_MIN 0
      16. #define VSCROLL_OFFY 10
      17. #define GY (340)
      18. #define GRAPH_PIXELS_Y GY // Delta-Y of our chart area
      19. #define Y_SCALE_FACTOR ((float)(Y_SCALE_MAX-(Y_SCALE_MIN))/GRAPH_PIXELS_Y)
      20. #define GX (740)
      21. #define GRAPH_PIXELS_X GX // Widget pixels
      22. #define GXp (GX - 5) // Usable graph pixels
      23. #define GXLO 15 // X left offset pixels
      24. #define GXRO 15 // X rigt offset pixels
      25. #define ID_BUTTON_0 (GUI_ID_USER + 0x03)
      26. #define ID_BUTTON_1 (GUI_ID_USER + 0x04)
      27. #define ID_BUTTON_2 (GUI_ID_USER + 0x05)
      28. #define ID_TEXT_0 (GUI_ID_USER + 0x23)
      29. #define ID_GRAPH_0 (GUI_ID_USER + 0x24)
      30. #define ID_BUTTON_3 (GUI_ID_USER + 0x25)
      31. #define ID_BUTTON_4 (GUI_ID_USER + 0x27)
      32. #define PREPOPULATED_DATA_POINTS (MAXSTRIPINDEX/5)
      33. #define MAX_GRAPHS 10
      34. /*********************************************************************
      35. *
      36. * Static data
      37. *
      38. **********************************************************************
      39. */
      40. static GRAPH_DATA_Handle _ahData[MAX_GRAPHS]; // Array of handles for the GRAPH_DATA objects
      41. static GRAPH_SCALE_Handle _hScaleV; // Handle of vertical scale
      42. static GRAPH_SCALE_Handle _hScaleH; // Handle of horizontal scale
      43. static GUI_POINT _aPoint[MAX_GRAPHS];
      44. static I16 _aValue[MAX_GRAPHS];
      45. static int _Stop = 0;
      46. // Array of colors for the GRAPH_DATA objects
      47. static GUI_COLOR _aColor[] = {
      48. GUI_LIGHTGRAY, GUI_LIGHTGRAY, GUI_LIGHTGRAY, GUI_ORANGE,
      49. GUI_GREEN, GUI_GREEN, GUI_RED, GUI_RED,
      50. GUI_LIGHTBLUE, GUI_LIGHTBLUE };
      51. static U8 _aLineStyles[] = {
      52. GUI_LS_SOLID, GUI_LS_SOLID, GUI_LS_SOLID, GUI_LS_DASH,
      53. GUI_LS_SOLID, GUI_LS_DASH, GUI_LS_SOLID, GUI_LS_DASH,
      54. GUI_LS_SOLID, GUI_LS_DASH };
      55. /*********************************************************************
      56. *
      57. * _aDialogCreate
      58. */
      59. static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = { {
      60. WINDOW_CreateIndirect, "Window", ID_WINDOW_0, 0, 0, 780, 440, 0, 0x0, 0 }, {
      61. GRAPH_CreateIndirect, "Graph", ID_GRAPH_0, 20, 80, GX, GY, 0, 0x0, 0 }, {
      62. BUTTON_CreateIndirect, "Right", ID_BUTTON_0, 760, 80, 20, GY, 0, 0x0, 0 }, {
      63. BUTTON_CreateIndirect, "Left", ID_BUTTON_1, 0, 80, 20, GY, 0, 0x0, 0 }, };
      64. /*********************************************************************
      65. *
      66. * Static code
      67. *
      68. **********************************************************************
      69. */
      70. /*********************************************************************
      71. *
      72. * _AddValues
      73. *
      74. * Function description
      75. * This routine calculates new random values in dependence of the previous added values
      76. * and adds them to the GRAPH_DATA objects
      77. */
      78. static void _AddValues(void) {
      79. static unsigned data_time = 0;
      80. unsigned i = 0;
      81. GUI_POINT pt;
      82. pt.x = data_time;
      83. for (int i = 0; i < MAX_GRAPHS; i++) {
      84. pt.y = i * 20 + rand() % 50 / Y_SCALE_FACTOR;
      85. GRAPH_DATA_XY_AddPoint(_ahData[i], &pt);
      86. }
      87. data_time++;
      88. }
      89. /*********************************************************************
      90. *
      91. * _cbDialog
      92. */
      93. static void _cbDialog(WM_MESSAGE * pMsg) {
      94. WM_HWIN hItem;
      95. WM_HWIN hDlg;
      96. static GRAPH_DATA_Handle hGraphData;
      97. int NCode;
      98. int Id;
      99. static int DataAttached;
      100. unsigned i;
      101. hDlg = pMsg->hWin;
      102. switch (pMsg->MsgId) {
      103. case WM_INIT_DIALOG:
      104. //
      105. // Initialization of 'Window'
      106. //
      107. hItem = pMsg->hWin;
      108. WINDOW_SetBkColor(hItem, GUI_GRAY);
      109. //
      110. // Initialize the GRAPH widget
      111. //
      112. hItem = WM_GetDialogItem(pMsg->hWin, ID_GRAPH_0);
      113. for (i = 0; i < MAX_GRAPHS; i++) {
      114. _ahData[i] = GRAPH_DATA_XY_Create(_aColor[i], 2000, 0, 0);
      115. GRAPH_AttachData(hItem, _ahData[i]);
      116. GRAPH_DATA_XY_SetLineStyle(_ahData[i], _aLineStyles[i]);
      117. GRAPH_DATA_XY_SetOffY(_ahData[i], 10 / Y_SCALE_FACTOR);
      118. }
      119. GRAPH_SetVSizeY(hItem, 120);
      120. GRAPH_SetGridVis(hItem, 1);
      121. WIDGET_SetEffect(hItem, &WIDGET_Effect_3D);
      122. //
      123. // Create and add vertical scale
      124. //
      125. _hScaleV = GRAPH_SCALE_Create(5, GUI_TA_LEFT | GUI_TA_BOTTOM,
      126. GRAPH_SCALE_CF_VERTICAL, 10 / Y_SCALE_FACTOR);
      127. GRAPH_SCALE_SetTextColor(_hScaleV, GUI_YELLOW);
      128. GRAPH_AttachScale(hItem, _hScaleV);
      129. GRAPH_SetGridDistY(hItem, 10 / Y_SCALE_FACTOR);
      130. GRAPH_SCALE_SetFactor(_hScaleV, Y_SCALE_FACTOR);
      131. GRAPH_SCALE_SetOff(_hScaleV,
      132. -(Y_SCALE_MIN / Y_SCALE_FACTOR) + VSCROLL_OFFY + 5);
      133. //
      134. // Create and add horizontal scale
      135. //
      136. _hScaleH = GRAPH_SCALE_Create(320, GUI_TA_RIGHT, GRAPH_SCALE_CF_HORIZONTAL,
      137. 60);
      138. GRAPH_SCALE_SetTextColor(_hScaleH, GUI_DARKGREEN);
      139. GRAPH_AttachScale(hItem, _hScaleH);
      140. GRAPH_SetGridDistX(hItem, 60);
      141. GRAPH_SCALE_SetTickDist(_hScaleH, 60);
      142. break;
      143. case WM_NOTIFY_PARENT:
      144. Id = WM_GetId(pMsg->hWinSrc);
      145. NCode = pMsg->Data.v;
      146. switch (Id) {
      147. case ID_BUTTON_0: // Notifications sent by 'Right'
      148. switch (NCode) {
      149. case WM_NOTIFICATION_CLICKED:
      150. break;
      151. case WM_NOTIFICATION_RELEASED:
      152. break;
      153. }
      154. break;
      155. case ID_BUTTON_1: // Notifications sent by 'Left'
      156. switch (NCode) {
      157. case WM_NOTIFICATION_CLICKED:
      158. break;
      159. case WM_NOTIFICATION_RELEASED:
      160. break;
      161. }
      162. break;
      163. }
      164. break;
      165. default:
      166. WM_DefaultProc(pMsg);
      167. break;
      168. }
      169. }
      170. /*********************************************************************
      171. *
      172. * Public code
      173. *
      174. **********************************************************************
      175. */
      176. /*********************************************************************
      177. *
      178. * CreateWindow
      179. */
      180. void MainTask(void) {
      181. WM_HWIN hGraph;
      182. WM_HWIN hDlg;
      183. hGraph = 0;
      184. WM_SetCreateFlags(WM_CF_MEMDEV);
      185. GUI_Init();
      186. hDlg = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate),
      187. _cbDialog, WM_HBKWIN, 0, 0);
      188. GUI_Delay(50);
      189. for (int i = 0; i < 20; i++) // PREPOPULATED_DATA_POINTS
      190. _AddValues();
      191. while (1) {
      192. GUI_Delay(500);
      193. if (!_Stop) {
      194. if (!hGraph) {
      195. hGraph = WM_GetDialogItem(hDlg, GUI_ID_GRAPH0);
      196. }
      197. _AddValues();
      198. }
      199. }
      200. }
      201. /*************************** End of file ****************************/
      Display All
    • Hi,

      Good that it is working.

      You should get rid of the following line:

      C Source Code

      1. WM_SetCreateFlags(WM_CF_MEMDEV);


      and exchange it with:

      C Source Code

      1. WM_MULTIBUF_Enable(1);


      I guess you are using it to avoid flickering, but automatic memory devices should be used as a last option against flickering.

      It leads to unnecessary drawing operations (first drawing into a memory device and then drawing the memory device) and might have a big impact on the performance if not enough memory available to hold the entire window (worst case). If there is not enough memory available it will split the drawing operation into multiple small memory devices.

      Regards,
      Sven
      Please read the forum rules before posting.

      Keep in mind, this is *not* a support forum.
      Our engineers will try to answer your questions between their projects if possible but this can be delayed by longer periods of time.
      Should you be entitled to support you can contact us via our support system: segger.com/ticket/

      Or you can contact us via e-mail.