Andrew Reed / Mbed OS CITY1082-i2c_master_wifi_mqtt
Revision:
5:f62a9e4a499a
diff -r 7ebc3d28bcb2 -r f62a9e4a499a middleware-emwin/Sample/Application/Bounce.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/middleware-emwin/Sample/Application/Bounce.c	Sat Nov 13 12:02:49 2021 +0000
@@ -0,0 +1,1850 @@
+/*********************************************************************
+*                SEGGER Microcontroller GmbH                         *
+*        Solutions for real time microcontroller applications        *
+**********************************************************************
+*                                                                    *
+*        (c) 1996 - 2018  SEGGER Microcontroller GmbH                *
+*                                                                    *
+*        Internet: www.segger.com    Support:  support@segger.com    *
+*                                                                    *
+**********************************************************************
+
+** emWin V5.48 - 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  Cypress Semiconductor Corporation,
+whose registered  office is situated  at 198 Champion Ct. San Jose, CA 
+95134 USA  solely for the  purposes of creating  libraries for Cypress
+PSoC3 and  PSoC5 processor-based devices,  sublicensed and distributed
+under  the  terms  and  conditions  of  the  Cypress  End User License
+Agreement.
+Full source code is available at: www.segger.com
+
+We appreciate your understanding and fairness.
+----------------------------------------------------------------------
+Licensing information
+Licensor:                 SEGGER Microcontroller Systems LLC
+Licensed to:              Cypress Semiconductor Corp, 198 Champion Ct., San Jose, CA 95134, USA
+Licensed SEGGER software: emWin
+License number:           GUI-00319
+License model:            Services and License Agreement, signed June 10th, 2009
+Licensed platform:        Any Cypress platform (Initial targets are: PSoC3, PSoC5)
+----------------------------------------------------------------------
+Support and Update Agreement (SUA)
+SUA period:               2009-06-12 - 2022-07-27
+Contact to extend SUA:    sales@segger.com
+----------------------------------------------------------------------
+File        : Bounce.c
+Purpose     : Bouncing balls demo
+---------------------------END-OF-HEADER------------------------------
+*/
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <math.h>
+
+#include "DIALOG.h"
+
+/*********************************************************************
+*
+*       Define
+*
+**********************************************************************
+*/
+#define ID_WINDOW_0   (GUI_ID_USER + 0x00)
+#define ID_BUTTON_0   (GUI_ID_USER + 0x01)
+#define ID_BUTTON_1   (GUI_ID_USER + 0x02)
+#define ID_BUTTON_2   (GUI_ID_USER + 0x03)
+#define ID_CHECKBOX_0 (GUI_ID_USER + 0x04)
+#define ID_CHECKBOX_1 (GUI_ID_USER + 0x05)
+#define ID_TEXT_0     (GUI_ID_USER + 0x06)
+#define ID_SLIDER_0   (GUI_ID_USER + 0x07)
+
+#define MIN_RANDOM_V  0           // Minimum velocity (x or y) to be used in generating random balls
+#define MAX_RANDOM_V  80          // Maximum velocity (x or y) to be used in generating random balls
+#define MIN_RANDOM_R  5           // Minimum radius to be used in generating random balls
+#define MAX_RANDOM_R  40          // Maximum radius to be used in generating random balls
+#define M_PI          3.1415926f
+#define M_TO_A_RATIO  0.1f        // Ratio of mass to area used in generating random balls
+
+#define TIME_SLICE    20
+#define NUM_BALLS     10
+#define GRAVITY       100
+
+#define XSIZE_SPLASH  220
+#define YSIZE_SPLASH  120
+#define PERIOD_SPLASH 3000
+
+#if GUI_VERSION < 54400
+  #define WM_USER_DATA (WM_USER + 0)
+#endif
+
+/*********************************************************************
+*
+*       Types
+*
+**********************************************************************
+*/
+enum Wall { WALL_NONE, WALL_X1, WALL_Y1, WALL_X2, WALL_Y2 };
+enum Type { TYPE_NONE, TYPE_WALL, TYPE_BALL };
+
+typedef struct {
+  float x, y;
+} VECTOR;
+
+typedef struct {
+  float x1, y1, x2, y2;
+} WALLS;
+
+typedef struct BALL BALL;
+
+struct BALL {
+  VECTOR p;      // Position
+  VECTOR v;      // Velocity
+  float  m;      // Mass
+  float  r;      // Radius
+  U32    Index;  // Normally used as color
+  int    Id;     // ID
+  BALL * pNext;
+};
+
+typedef struct {
+  int   CollisionType;
+  int   WhichWall;
+  float TimeToCollision;
+} COLLISION;
+
+typedef struct {
+  int        xPos, yPos;
+  int        xSize, ySize;
+  void    (* pfDrawBk)  (WM_HWIN hWin, void * pConfig);
+  void    (* pfDrawBall)(WM_HWIN hWin, void * pConfig, U32 Index, float x, float y, float r);
+  unsigned   Range;
+  unsigned * pRadius;
+  unsigned   NumBalls;
+  float      vMin, vMax;
+  float      rMin, rMax;
+  unsigned   TimeSlice;
+  float      Gravity;
+  int        HasBallGravity;
+  int        HasGroundGravity;
+  int        HasInitialVelocity;
+  GUI_COLOR  ColorBk;  // Used if pfDrawBk() not set
+} BALLSIM_CONFIG;
+
+typedef struct {
+  BALL           * pFirstBall;            // Stores all the balls
+  int              HasWalls;              // Have wall boundaries been set?
+  WALLS            Walls;
+  int              NextId;                // Next ID to assign to an added ball
+  unsigned         MaxCollisions;         // Max number of collisions per frame in advanceSim
+  unsigned         MaxCollisionsPerBall;  // Max number of collisions per frame based on the number of balls
+  float            MinArea;               // Minimum area within walls
+  float            MaxDiameter;           // Maximum diameter out of all the balls
+  unsigned         NumBalls;
+  BALLSIM_CONFIG * pConfig;
+} BALLSIM;
+
+/*********************************************************************
+*
+*       Static (const) data
+*
+**********************************************************************
+*/
+static GUI_CONST_STORAGE GUI_COLOR _ColorsSeggerLogo_80x40[] = {
+#if (GUI_USE_ARGB == 0)
+  0x000000, 0xFFFFFF, 0x292929, 0x5F5F5F,
+  0x96433D, 0xB0726E, 0xCACACA, 0xF8F3F3,
+  0xD7D7D7, 0xEBDCDB, 0x363636, 0x9D4F49,
+  0xAA6661, 0x949494, 0xA1A1A1, 0xB77E7A,
+  0x444444, 0xBD8A86, 0xD1ADAA, 0xE4E4E4,
+  0xF2F2F2, 0x6C6C6C, 0x797979, 0xA35B55,
+  0xD8B9B6, 0xAFAFAF, 0xBCBCBC, 0xF2E8E7,
+  0x515151, 0xCBA19E, 0xE5D0CF, 0x878787,
+  0xC49592, 0xDEC4C2
+#else
+  0xFF000000, 0xFFFFFFFF, 0xFF292929, 0xFF5F5F5F,
+  0xFF3D4396, 0xFF6E72B0, 0xFFCACACA, 0xFFF3F3F8,
+  0xFFD7D7D7, 0xFFDBDCEB, 0xFF363636, 0xFF494F9D,
+  0xFF6166AA, 0xFF949494, 0xFFA1A1A1, 0xFF7A7EB7,
+  0xFF444444, 0xFF868ABD, 0xFFAAADD1, 0xFFE4E4E4,
+  0xFFF2F2F2, 0xFF6C6C6C, 0xFF797979, 0xFF555BA3,
+  0xFFB6B9D8, 0xFFAFAFAF, 0xFFBCBCBC, 0xFFE7E8F2,
+  0xFF515151, 0xFF9EA1CB, 0xFFCFD0E5, 0xFF878787,
+  0xFF9295C4, 0xFFC2C4DE
+#endif
+
+};
+
+static GUI_CONST_STORAGE GUI_LOGPALETTE _PalSeggerLogo_80x40 = {
+  34,  // Number of entries
+  1,   // Has transparency
+  &_ColorsSeggerLogo_80x40[0]
+};
+
+static GUI_CONST_STORAGE unsigned char _acSeggerLogo_80x40[] = {
+  0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
+        0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
+  0x02, 0x02, 0x0A, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x0A, 0x02, 0x02,
+  0x02, 0x02, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x02, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x21, 0x0F, 0x09, 0x01, 0x01, 0x01, 0x01, 0x09, 0x11, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x04, 0x04, 0x0C, 0x07, 0x01, 0x01, 0x01, 0x05, 0x04, 0x0B, 0x1B, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x0F, 0x04, 0x04, 0x11, 0x01, 0x01, 0x01, 0x20, 0x04, 0x04, 0x0C, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x07, 0x17, 0x04, 0x04, 0x18, 0x01, 0x01, 0x01, 0x0C, 0x04, 0x04, 0x11, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x01, 0x09, 0x04, 0x04, 0x0B, 0x09, 0x01, 0x01, 0x07, 0x0B, 0x04, 0x04, 0x18, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x01, 0x01, 0x12, 0x04, 0x04, 0x0C, 0x07, 0x01, 0x01, 0x1E, 0x04, 0x04, 0x0B, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x04, 0x04, 0x11, 0x01, 0x01, 0x01, 0x12, 0x04, 0x04, 0x0C, 0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, 0x17, 0x04, 0x04, 0x18, 0x01, 0x01, 0x01, 0x0F, 0x04, 0x04, 0x0F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x12, 0x01, 0x01, 0x01, 0x09, 0x04, 0x04, 0x0B, 0x09, 0x01, 0x01, 0x07, 0x17, 0x04, 0x04, 0x12, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x04, 0x1E, 0x01, 0x01, 0x01, 0x12, 0x04, 0x04, 0x0C, 0x07, 0x01, 0x01, 0x09, 0x0B, 0x04, 0x04, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x04, 0x0B, 0x07, 0x01, 0x01, 0x01, 0x0F, 0x04, 0x04, 0x11, 0x01, 0x01, 0x01, 0x18, 0x04, 0x04, 0x0B, 0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x04, 0x04, 0x05, 0x01, 0x01, 0x01, 0x07, 0x17, 0x04, 0x04, 0x18, 0x01, 0x01, 0x01, 0x11, 0x04, 0x04, 0x17, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 
+        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x1B, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x04, 0x04, 0x04, 0x1D, 0x01, 0x01, 0x01, 0x09, 0x04, 0x04, 0x0B, 0x09, 0x01, 0x01, 0x07, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1D, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x04, 0x04, 0x04, 0x04, 0x1E, 0x01, 0x01, 0x01, 0x12, 0x04, 0x04, 0x0C, 0x07, 0x01, 0x01, 0x1B, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 
+        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x1B, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x04, 0x04, 0x04, 0x04, 0x0B, 0x07, 0x01, 0x01, 0x01, 0x0F, 0x04, 0x04, 0x1D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x04, 0x04, 0x04, 0x04, 0x0B, 0x07, 0x01, 0x01, 0x01, 0x0F, 0x04, 0x04, 0x1D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x04, 0x04, 0x04, 0x04, 0x1E, 0x01, 0x01, 0x01, 0x12, 0x04, 0x04, 0x0C, 0x07, 0x01, 0x01, 0x1B, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 
+        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x1B, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x04, 0x04, 0x04, 0x1D, 0x01, 0x01, 0x01, 0x09, 0x04, 0x04, 0x0B, 0x09, 0x01, 0x01, 0x07, 0x0C, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+        0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1D, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x04, 0x04, 0x05, 0x01, 0x01, 0x01, 0x07, 0x17, 0x04, 0x04, 0x18, 0x01, 0x01, 0x01, 0x11, 0x04, 0x04, 0x17, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 
+        0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x1B, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x04, 0x0B, 0x07, 0x01, 0x01, 0x01, 0x0F, 0x04, 0x04, 0x11, 0x01, 0x01, 0x01, 0x18, 0x04, 0x04, 0x0B, 0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x04, 0x1E, 0x01, 0x01, 0x01, 0x12, 0x04, 0x04, 0x0C, 0x07, 0x01, 0x01, 0x09, 0x0B, 0x04, 0x04, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x12, 0x01, 0x01, 0x01, 0x09, 0x04, 0x04, 0x0B, 0x09, 0x01, 0x01, 0x07, 0x17, 0x04, 0x04, 0x12, 0x01, 0x01, 0x14, 0x1A, 0x0D, 0x0D, 0x1A, 0x01, 0x01, 0x01, 0x13, 0x06, 0x06, 0x06, 0x06, 0x06, 0x08, 0x01, 0x01, 0x01, 0x13, 0x19, 
+        0x0D, 0x0E, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x13, 0x0E, 0x0D, 0x0E, 0x08, 0x01, 0x01, 0x01, 0x14, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x01, 0x01, 0x06, 0x06, 0x06, 0x06, 0x06, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07, 0x17, 0x04, 0x04, 0x18, 0x01, 0x01, 0x01, 0x0F, 0x04, 0x04, 0x0F, 0x01, 0x01, 0x08, 0x0A, 0x02, 0x02, 0x02, 0x02, 0x10, 0x13, 0x01, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x08, 0x01, 0x1F, 0x02, 0x02, 
+        0x02, 0x02, 0x02, 0x03, 0x14, 0x01, 0x01, 0x1F, 0x02, 0x02, 0x02, 0x02, 0x02, 0x15, 0x01, 0x01, 0x16, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x06, 0x06, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x04, 0x04, 0x11, 0x01, 0x01, 0x01, 0x12, 0x04, 0x04, 0x0C, 0x07, 0x01, 0x01, 0x1F, 0x02, 0x15, 0x13, 0x08, 0x1C, 0x02, 0x0D, 0x01, 0x03, 0x02, 0x0E, 0x06, 0x06, 0x06, 0x06, 0x01, 0x19, 0x02, 0x02, 0x0D, 
+        0x06, 0x19, 0x0A, 0x02, 0x19, 0x01, 0x0D, 0x02, 0x02, 0x0E, 0x06, 0x0E, 0x0A, 0x02, 0x06, 0x01, 0x03, 0x02, 0x16, 0x06, 0x06, 0x06, 0x06, 0x14, 0x06, 0x02, 0x1C, 0x06, 0x06, 0x0D, 0x02, 0x02, 0x06, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x01, 0x01, 0x12, 0x04, 0x04, 0x0C, 0x07, 0x01, 0x01, 0x1E, 0x04, 0x04, 0x0B, 0x09, 0x01, 0x01, 0x01, 0x1F, 0x02, 0x10, 0x0E, 0x08, 0x14, 0x06, 0x14, 0x01, 0x03, 0x02, 0x0E, 0x06, 0x06, 0x06, 0x13, 0x01, 0x03, 0x02, 0x16, 0x01, 
+        0x01, 0x01, 0x08, 0x0D, 0x14, 0x01, 0x10, 0x02, 0x0D, 0x01, 0x01, 0x01, 0x08, 0x0E, 0x14, 0x01, 0x03, 0x02, 0x16, 0x06, 0x06, 0x06, 0x13, 0x01, 0x06, 0x02, 0x03, 0x01, 0x01, 0x14, 0x10, 0x02, 0x06, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x01, 0x09, 0x04, 0x04, 0x0B, 0x09, 0x01, 0x01, 0x07, 0x0B, 0x04, 0x04, 0x18, 0x01, 0x01, 0x01, 0x01, 0x08, 0x10, 0x02, 0x02, 0x02, 0x02, 0x15, 0x08, 0x01, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x1A, 0x01, 
+        0x13, 0x03, 0x03, 0x03, 0x0E, 0x01, 0x02, 0x02, 0x06, 0x01, 0x08, 0x03, 0x03, 0x03, 0x0E, 0x01, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0A, 0x01, 0x06, 0x02, 0x0A, 0x03, 0x03, 0x0A, 0x02, 0x03, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x07, 0x17, 0x04, 0x04, 0x18, 0x01, 0x01, 0x01, 0x0C, 0x04, 0x04, 0x11, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x06, 0x0D, 0x03, 0x02, 0x02, 0x1C, 0x01, 0x03, 0x02, 0x0E, 0x06, 0x06, 0x06, 0x13, 0x01, 0x10, 0x02, 0x0E, 0x01, 
+        0x08, 0x0A, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x1A, 0x01, 0x1A, 0x0A, 0x02, 0x02, 0x03, 0x01, 0x03, 0x02, 0x16, 0x06, 0x06, 0x06, 0x08, 0x01, 0x06, 0x02, 0x0A, 0x03, 0x03, 0x0A, 0x02, 0x1C, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x0F, 0x04, 0x04, 0x11, 0x01, 0x01, 0x01, 0x20, 0x04, 0x04, 0x0C, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0E, 0x02, 0x19, 0x01, 0x01, 0x1A, 0x02, 0x02, 0x01, 0x03, 0x02, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x16, 0x02, 0x10, 0x14, 
+        0x01, 0x01, 0x0D, 0x02, 0x03, 0x01, 0x15, 0x02, 0x1C, 0x14, 0x01, 0x01, 0x16, 0x02, 0x03, 0x01, 0x03, 0x02, 0x0D, 0x01, 0x01, 0x01, 0x01, 0x01, 0x06, 0x02, 0x03, 0x01, 0x01, 0x06, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x04, 0x04, 0x0C, 0x07, 0x01, 0x01, 0x01, 0x05, 0x04, 0x0B, 0x1B, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x0E, 0x02, 0x02, 0x03, 0x16, 0x10, 0x02, 0x15, 0x01, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0A, 0x1A, 0x13, 0x0A, 0x02, 0x0A, 
+        0x03, 0x1C, 0x02, 0x02, 0x03, 0x01, 0x08, 0x0A, 0x02, 0x0A, 0x03, 0x10, 0x02, 0x02, 0x03, 0x01, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x19, 0x06, 0x02, 0x03, 0x01, 0x01, 0x01, 0x02, 0x02, 0x08, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x21, 0x0F, 0x09, 0x01, 0x01, 0x01, 0x01, 0x09, 0x11, 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x19, 0x1C, 0x02, 0x02, 0x10, 0x16, 0x14, 0x01, 0x0D, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x08, 0x01, 0x13, 0x16, 0x0A, 
+        0x02, 0x0A, 0x1F, 0x15, 0x15, 0x01, 0x01, 0x08, 0x15, 0x0A, 0x02, 0x10, 0x0D, 0x03, 0x15, 0x01, 0x19, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x1A, 0x08, 0x03, 0x0D, 0x01, 0x01, 0x01, 0x15, 0x10, 0x13, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02,
+  0x02, 0x02, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x02, 0x02,
+  0x02, 0x02, 0x0A, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x0A, 0x02, 0x02,
+  0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
+        0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02
+};
+
+static GUI_CONST_STORAGE GUI_BITMAP _bmSeggerLogo_80x40 = {
+  80, // xSize
+  40, // ySize
+  80, // BytesPerLine
+  8, // BitsPerPixel
+  _acSeggerLogo_80x40,  // Pointer to picture data (indices)
+  &_PalSeggerLogo_80x40   // Pointer to palette
+};
+
+static GUI_CONST_STORAGE unsigned char acGUI_Font32_AA4_Bounce_0042[152] = { /* code 0042, LATIN CAPITAL LETTER B */
+  0x5E, 0xFF, 0xFF, 0xFF, 0xFE, 0xC7, 0x00, 0x00,
+  0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x00,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0x00,
+  0xFF, 0xFF, 0x00, 0x00, 0x19, 0xFF, 0xFE, 0x00,
+  0xFF, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0x00,
+  0xFF, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0xFE, 0x00,
+  0xFF, 0xFF, 0x00, 0x00, 0x19, 0xFF, 0xFA, 0x00,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0x00,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x00,
+  0xFF, 0xFF, 0x00, 0x00, 0x04, 0xDF, 0xFF, 0x70,
+  0xFF, 0xFF, 0x00, 0x00, 0x00, 0x4F, 0xFF, 0xC0,
+  0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF0,
+  0xFF, 0xFF, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF0,
+  0xFF, 0xFF, 0x00, 0x00, 0x00, 0x4F, 0xFF, 0xC0,
+  0xFF, 0xFF, 0x00, 0x00, 0x04, 0xDF, 0xFF, 0x80,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x10,
+  0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD3, 0x00,
+  0x6E, 0xFF, 0xFF, 0xFF, 0xFE, 0xB6, 0x00, 0x00
+};
+
+static GUI_CONST_STORAGE unsigned char acGUI_Font32_AA4_Bounce_0063[ 84] = { /* code 0063, LATIN SMALL LETTER C */
+  0x00, 0x06, 0xBE, 0xFE, 0xB6, 0x00,
+  0x01, 0xCF, 0xFF, 0xFF, 0xFF, 0xC1,
+  0x0B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB,
+  0x5F, 0xFF, 0xE4, 0x02, 0xBF, 0xFF,
+  0xAF, 0xFF, 0x60, 0x00, 0x1B, 0xF8,
+  0xEF, 0xFF, 0x20, 0x00, 0x00, 0x00,
+  0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+  0xEF, 0xFF, 0x20, 0x00, 0x00, 0x00,
+  0xBF, 0xFF, 0x70, 0x00, 0x1A, 0xF8,
+  0x5F, 0xFF, 0xE4, 0x02, 0xBF, 0xFF,
+  0x0C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA,
+  0x01, 0xCF, 0xFF, 0xFF, 0xFF, 0xB1,
+  0x00, 0x07, 0xCF, 0xFE, 0xB5, 0x00
+};
+
+static GUI_CONST_STORAGE unsigned char acGUI_Font32_AA4_Bounce_0065[ 98] = { /* code 0065, LATIN SMALL LETTER E */
+  0x00, 0x06, 0xCE, 0xFE, 0xB6, 0x00, 0x00,
+  0x01, 0xCF, 0xFF, 0xFF, 0xFF, 0xC1, 0x00,
+  0x0C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00,
+  0x5F, 0xFF, 0xD3, 0x03, 0xDF, 0xFF, 0x60,
+  0xBF, 0xFF, 0x50, 0x00, 0x4F, 0xFF, 0xB0,
+  0xEF, 0xFF, 0x10, 0x00, 0x1F, 0xFF, 0xE0,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0,
+  0xDF, 0xFF, 0x10, 0x00, 0x00, 0x00, 0x00,
+  0xAF, 0xFF, 0x50, 0x00, 0x00, 0x00, 0x00,
+  0x5F, 0xFF, 0xE4, 0x00, 0x4B, 0xFB, 0x00,
+  0x0B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00,
+  0x01, 0xCF, 0xFF, 0xFF, 0xFF, 0xE3, 0x00,
+  0x00, 0x06, 0xCE, 0xFE, 0xB7, 0x10, 0x00
+};
+
+static GUI_CONST_STORAGE unsigned char acGUI_Font32_AA4_Bounce_006E[ 84] = { /* code 006E, LATIN SMALL LETTER N */
+  0x6E, 0xE5, 0x06, 0xCF, 0xEB, 0x30,
+  0xEF, 0xFC, 0x9F, 0xFF, 0xFF, 0xF3,
+  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA,
+  0xFF, 0xFF, 0xC2, 0x08, 0xFF, 0xFE,
+  0xFF, 0xFF, 0x30, 0x02, 0xFF, 0xFF,
+  0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
+  0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
+  0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
+  0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
+  0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
+  0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
+  0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
+  0xEF, 0xFE, 0x00, 0x00, 0xEF, 0xFE,
+  0x6E, 0xE6, 0x00, 0x00, 0x6E, 0xE6
+};
+
+static GUI_CONST_STORAGE unsigned char acGUI_Font32_AA4_Bounce_006F[ 98] = { /* code 006F, LATIN SMALL LETTER O */
+  0x00, 0x04, 0xAD, 0xFF, 0xDA, 0x40, 0x00,
+  0x01, 0xAF, 0xFF, 0xFF, 0xFF, 0xFA, 0x10,
+  0x0A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0,
+  0x4F, 0xFF, 0xF6, 0x11, 0x6F, 0xFF, 0xF4,
+  0xAF, 0xFF, 0x70, 0x00, 0x07, 0xFF, 0xFA,
+  0xDF, 0xFF, 0x30, 0x00, 0x03, 0xFF, 0xFD,
+  0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF,
+  0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF,
+  0xDF, 0xFF, 0x30, 0x00, 0x03, 0xFF, 0xFD,
+  0xAF, 0xFF, 0x70, 0x00, 0x07, 0xFF, 0xFA,
+  0x4F, 0xFF, 0xF6, 0x11, 0x6F, 0xFF, 0xF4,
+  0x0A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA0,
+  0x01, 0xAF, 0xFF, 0xFF, 0xFF, 0xFA, 0x10,
+  0x00, 0x04, 0xAD, 0xFF, 0xDA, 0x40, 0x00
+};
+
+static GUI_CONST_STORAGE unsigned char acGUI_Font32_AA4_Bounce_0075[ 84] = { /* code 0075, LATIN SMALL LETTER U */
+  0x6E, 0xE6, 0x00, 0x00, 0x6E, 0xE6,
+  0xEF, 0xFE, 0x00, 0x00, 0xEF, 0xFE,
+  0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
+  0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
+  0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
+  0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
+  0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
+  0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
+  0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF,
+  0xFF, 0xFF, 0x10, 0x03, 0xFF, 0xFF,
+  0xEF, 0xFF, 0x80, 0x2C, 0xFF, 0xFF,
+  0xAF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+  0x3F, 0xFF, 0xFF, 0xF9, 0xCF, 0xFE,
+  0x04, 0xBF, 0xFC, 0x60, 0x5E, 0xE6
+};
+
+static GUI_CONST_STORAGE GUI_CHARINFO_EXT GUI_Font32_AA4_Bounce_CharInfo[6] = {
+   {  15,  19,   2,   7,  18, acGUI_Font32_AA4_Bounce_0042 } /* code 0042, LATIN CAPITAL LETTER B */
+  ,{  12,  14,   1,  12,  14, acGUI_Font32_AA4_Bounce_0063 } /* code 0063, LATIN SMALL LETTER C */
+  ,{  13,  14,   1,  12,  15, acGUI_Font32_AA4_Bounce_0065 } /* code 0065, LATIN SMALL LETTER E */
+  ,{  12,  14,   2,  12,  16, acGUI_Font32_AA4_Bounce_006E } /* code 006E, LATIN SMALL LETTER N */
+  ,{  14,  14,   1,  12,  16, acGUI_Font32_AA4_Bounce_006F } /* code 006F, LATIN SMALL LETTER O */
+  ,{  12,  14,   2,  12,  16, acGUI_Font32_AA4_Bounce_0075 } /* code 0075, LATIN SMALL LETTER U */
+};
+
+static GUI_CONST_STORAGE GUI_FONT_PROP_EXT GUI_Font32_AA4_Bounce_Prop5 = {
+   0x0075 /* first character */
+  ,0x0075 /* last character  */
+  ,&GUI_Font32_AA4_Bounce_CharInfo[  5] /* address of first character */
+  ,(GUI_CONST_STORAGE GUI_FONT_PROP_EXT *)0 /* pointer to next GUI_FONT_PROP_EXT */
+};
+
+static GUI_CONST_STORAGE GUI_FONT_PROP_EXT GUI_Font32_AA4_Bounce_Prop4 = {
+   0x006E /* first character */
+  ,0x006F /* last character  */
+  ,&GUI_Font32_AA4_Bounce_CharInfo[  3] /* address of first character */
+  ,&GUI_Font32_AA4_Bounce_Prop5 /* pointer to next GUI_FONT_PROP_EXT */
+};
+
+static GUI_CONST_STORAGE GUI_FONT_PROP_EXT GUI_Font32_AA4_Bounce_Prop3 = {
+   0x0065 /* first character */
+  ,0x0065 /* last character  */
+  ,&GUI_Font32_AA4_Bounce_CharInfo[  2] /* address of first character */
+  ,&GUI_Font32_AA4_Bounce_Prop4 /* pointer to next GUI_FONT_PROP_EXT */
+};
+
+static GUI_CONST_STORAGE GUI_FONT_PROP_EXT GUI_Font32_AA4_Bounce_Prop2 = {
+   0x0063 /* first character */
+  ,0x0063 /* last character  */
+  ,&GUI_Font32_AA4_Bounce_CharInfo[  1] /* address of first character */
+  ,&GUI_Font32_AA4_Bounce_Prop3 /* pointer to next GUI_FONT_PROP_EXT */
+};
+
+static GUI_CONST_STORAGE GUI_FONT_PROP_EXT GUI_Font32_AA4_Bounce_Prop1 = {
+   0x0042 /* first character */
+  ,0x0042 /* last character  */
+  ,&GUI_Font32_AA4_Bounce_CharInfo[  0] /* address of first character */
+  ,&GUI_Font32_AA4_Bounce_Prop2 /* pointer to next GUI_FONT_PROP_EXT */
+};
+
+static GUI_CONST_STORAGE GUI_FONT GUI_Font32_AA4_Bounce = {
+   GUI_FONTTYPE_PROP_AA4_EXT /* type of font    */
+  ,32 /* height of font  */
+  ,32 /* space of font y */
+  ,1 /* magnification x */
+  ,1 /* magnification y */
+  ,{&GUI_Font32_AA4_Bounce_Prop1}
+  ,26 /* Baseline */
+  ,14 /* Height of lowercase characters */
+  ,19 /* Height of capital characters */
+};
+
+static const GUI_WIDGET_CREATE_INFO _aDialogCreate[] = {
+  { WINDOW_CreateIndirect,   "Window",   ID_WINDOW_0,     0,   0, 280, 130, 0, 0x0,  0 },
+  { BUTTON_CreateIndirect,   "Button",   ID_BUTTON_0,    10,  10, 120,  20, 0, 0x0,  0 },
+  { BUTTON_CreateIndirect,   "Button",   ID_BUTTON_1,    10,  40, 120,  20, 0, 0x0,  0 },
+  { BUTTON_CreateIndirect,   "Button",   ID_BUTTON_2,    10, 100, 260,  20, 0, 0x0,  0 },
+  { CHECKBOX_CreateIndirect, "Checkbox", ID_CHECKBOX_0, 150,  40, 120,  20, 0, 0x0,  0 },
+  { CHECKBOX_CreateIndirect, "Checkbox", ID_CHECKBOX_1, 150,  10, 120,  20, 0, 0x0,  0 },
+  { TEXT_CreateIndirect,     "Text",     ID_TEXT_0,      10,  73, 120,  20, 0, 0x64, 0 },
+  { SLIDER_CreateIndirect,   "Slider",   ID_SLIDER_0,   150,  70, 120,  20, 0, 0x0,  0 },
+};
+
+/*********************************************************************
+*
+*       Static code: Helper(s)
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+*       _Square
+*/
+static float _Square(float x) { 
+  return x * x;
+}
+
+/*********************************************************************
+*
+*       _GetRandomNumber
+*/
+static float _GetRandomNumber(float min, float max) {
+  return (max - min) * rand() / RAND_MAX + min;
+}
+
+#ifdef WIN32
+static size_t _AllocatedBytes;
+#endif
+
+/*********************************************************************
+*
+*       _Free
+*/
+static void _Free(void * p) {
+#ifdef WIN32
+  _AllocatedBytes -= _msize(p);
+#endif
+  free(p);
+}
+
+/*********************************************************************
+*
+*       _Calloc
+*/
+static void * _Calloc(size_t Num, size_t Size) {
+  void * p;
+  p = calloc(Num, Size);
+#ifdef WIN32
+  _AllocatedBytes += _msize(p);
+#endif
+  return calloc(Num, Size);
+}
+
+/*********************************************************************
+*
+*       Static code: VECTOR
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+*       _VECTOR_Create
+*/
+static VECTOR * _VECTOR_Create(float x, float y) {
+  VECTOR * pVectorNew;
+  
+  pVectorNew = (VECTOR *)_Calloc(sizeof(VECTOR), 1);
+  pVectorNew->x = x;
+  pVectorNew->y = y;
+  return pVectorNew;
+}
+
+/*********************************************************************
+*
+*       _VECTOR_CreateCopy
+*/
+static VECTOR * _VECTOR_CreateCopy(VECTOR * pVector) {
+  return _VECTOR_Create(pVector->x, pVector->y);
+}
+
+/*********************************************************************
+*
+*       _VECTOR_CreateCopyPlus
+*/
+static VECTOR * _VECTOR_CreateCopyPlus(VECTOR * pVector, VECTOR * pVector1) {
+  return _VECTOR_Create(pVector->x + pVector1->x, pVector->y + pVector1->y);
+}
+
+/*********************************************************************
+*
+*       _VECTOR_CreateCopyMinus
+*/
+static VECTOR * _VECTOR_CreateCopyMinus(VECTOR * pVector, VECTOR * pVector1) {
+  return _VECTOR_Create(pVector->x - pVector1->x, pVector->y - pVector1->y);
+}
+
+/*********************************************************************
+*
+*       _VECTOR_CreateCopyMult
+*/
+static VECTOR * _VECTOR_CreateCopyMult(VECTOR * pVector, float c) {
+  return _VECTOR_Create(pVector->x * c, pVector->y * c);
+}
+
+/*********************************************************************
+*
+*       _VECTOR_Delete
+*/
+static void _VECTOR_Delete(VECTOR * pVector) {
+  _Free(pVector);
+}
+
+/*********************************************************************
+*
+*       _VECTOR_SetX
+*/
+static void _VECTOR_SetX(VECTOR * pVector, float x) {
+  pVector->x = x;
+}
+
+/*********************************************************************
+*
+*       _VECTOR_SetY
+*/
+static void _VECTOR_SetY(VECTOR * pVector, float y) {
+  pVector->y = y;
+}
+
+/*********************************************************************
+*
+*       _VECTOR_SetXY
+*/
+static void _VECTOR_SetXY(VECTOR * pVector, float x, float y) {
+  pVector->x = x;
+  pVector->y = y;
+}
+
+/*********************************************************************
+*
+*       _VECTOR_Magnitude
+*/
+static float _VECTOR_Magnitude(VECTOR * pVector) { 
+  return sqrt(pVector->x * pVector->x + pVector->y * pVector->y);
+}
+
+/*********************************************************************
+*
+*       _VECTOR_CreateUnitVector
+*/
+static VECTOR * _VECTOR_CreateUnitVector(VECTOR * pVector) {
+  VECTOR * pVectorNew;
+  float    Mag;
+
+  Mag = _VECTOR_Magnitude(pVector);
+  if (Mag != 0.f) {
+    pVectorNew = _VECTOR_Create(pVector->x / Mag, pVector->y / Mag);
+  } else {
+    pVectorNew = _VECTOR_Create(0.f, 0.f);
+  }
+  return pVectorNew;
+}
+
+/*********************************************************************
+*
+*       _VECTOR_DotProduct
+*/
+static float _VECTOR_DotProduct(VECTOR * pVector, VECTOR * pVector1) {
+  float DotProduct;
+
+  DotProduct = pVector->x * pVector1->x + pVector->y * pVector1->y;
+  return DotProduct;
+}
+
+/*********************************************************************
+*
+*       Static code: WALLS
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+*       _WALLS_Create
+*/
+static WALLS * _WALLS_Create(float x1, float y1, float x2, float y2) {
+  WALLS * pWall;
+  
+  pWall = (WALLS *)_Calloc(sizeof(WALLS), 1);
+  pWall->x1 = x1;
+  pWall->y1 = y1;
+  pWall->x2 = x2;
+  pWall->y2 = y2;
+  return pWall;
+}
+
+/*********************************************************************
+*
+*       _WALLS_CreateEmpty
+*/
+static WALLS * _WALLS_CreateEmpty(void) {
+  return _WALLS_Create(0.f, 0.f, 0.f, 0.f);
+}
+
+/*********************************************************************
+*
+*       Static code: BALL
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+*       _BALL_Create
+*/
+static BALL * _BALL_Create(void) {
+  BALL * pBall;
+  
+  pBall = (BALL *)_Calloc(sizeof(BALL), 1);
+  pBall->m = 0.f;
+  pBall->r = 0.f;
+  return pBall;
+}
+
+/*********************************************************************
+*
+*       _BALL_AdvanceBallPosition
+*/
+static void _BALL_AdvanceBallPosition(BALL * pBall, const float dt) {
+  _VECTOR_SetXY(&pBall->p, pBall->p.x + pBall->v.x * dt, pBall->p.y + pBall->v.y * dt);
+}
+
+/*********************************************************************
+*
+*        _BALL_DoBallGravity
+*/
+static void _BALL_DoBallGravity(BALL * pb0, BALL * pb1, const float dt, float g) {
+  VECTOR * v_n;
+  VECTOR * v_un;
+  float    r, f, a0, a1, v0, v1;
+
+  v_n  = _VECTOR_CreateCopyMinus(&pb0->p, &pb1->p);  // v_n = normal vec. - a vector normal to the collision surface
+  v_un = _VECTOR_CreateUnitVector(v_n);              // unit normal vector
+  r = _VECTOR_Magnitude(v_n);
+  f = g * (pb0->m * pb1->m) / (r * r);
+  a0 = f / pb0->m;
+  a1 = f / pb1->m;
+  v0 = a0 * dt;
+  v1 = a1 * dt;
+  _VECTOR_SetXY(&pb0->v, pb0->v.x - v_un->x * v0, pb0->v.y - v_un->y * v0);
+  _VECTOR_SetXY(&pb1->v, pb1->v.x + v_un->x * v1, pb1->v.y + v_un->y * v1);
+  _VECTOR_Delete(v_n);
+  _VECTOR_Delete(v_un);
+}
+
+/*********************************************************************
+*
+*        _BALL_DoGroundGravity
+*/
+static void _BALL_DoGroundGravity(BALL * pb, const float dt, float g) {
+  _VECTOR_SetY(&pb->v, pb->v.y + g * dt * 0.95);
+}
+
+/*********************************************************************
+*
+*       Static code: COLLISION
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+*       _COLLISION_Reset
+*/
+static void _COLLISION_Reset(COLLISION * pCollision) {
+  pCollision->CollisionType   = TYPE_NONE;
+  pCollision->WhichWall       = WALL_NONE;
+  pCollision->TimeToCollision = 0.f;
+}
+
+/*********************************************************************
+*
+*       _COLLISION_Create
+*/
+static COLLISION * _COLLISION_Create(void) {
+  COLLISION * pCollision;
+  
+  pCollision = (COLLISION *)_Calloc(sizeof(COLLISION), 1);
+  _COLLISION_Reset(pCollision);
+  return pCollision;
+}
+
+/*********************************************************************
+*
+*       _COLLISION_SetCollisionWithWall
+*/
+static void _COLLISION_SetCollisionWithWall(COLLISION * pCollision, const float t, int WhichWall) {
+  pCollision->CollisionType   = TYPE_WALL;
+  pCollision->WhichWall       = WhichWall;
+  pCollision->TimeToCollision = t;
+}
+
+/*********************************************************************
+*
+*       _COLLISION_SetCollisionWithBall
+*/
+static void _COLLISION_SetCollisionWithBall(COLLISION * pCollision, const float t) {
+  pCollision->CollisionType   = TYPE_BALL;
+  pCollision->WhichWall       = WALL_NONE;
+  pCollision->TimeToCollision = t;
+}
+
+/*********************************************************************
+*
+*       _COLLISION_Ball1HasCollision
+*/
+static int _COLLISION_Ball1HasCollision(COLLISION * pCollision) {
+  return pCollision->CollisionType != TYPE_NONE;
+}
+
+/*********************************************************************
+*
+*       _COLLISION_Ball2HasCollision
+*/
+static int _COLLISION_Ball2HasCollision(COLLISION * pCollision) {
+  return pCollision->CollisionType == TYPE_BALL;
+}
+
+/*********************************************************************
+*
+*       _COLLISION_Ball1HasCollisionWithWall
+*/
+static int _COLLISION_Ball1HasCollisionWithWall(COLLISION * pCollision) {
+  return pCollision->CollisionType == TYPE_WALL;
+}
+
+/*********************************************************************
+*
+*       _COLLISION_Ball1HasCollisionWithBall
+*/
+static int _COLLISION_Ball1HasCollisionWithBall(COLLISION * pCollision) {
+  return pCollision->CollisionType == TYPE_BALL;
+}
+
+/*********************************************************************
+*
+*       _COLLISION_GetCollisionWall
+*/
+static int _COLLISION_GetCollisionWall(COLLISION * pCollision) {
+  return (int)pCollision->WhichWall;
+}
+
+/*********************************************************************
+*
+*        _COLLISION_FindTimeUntilTwoBallsCollide
+*
+* Function description:
+*   Finds the time until two specified balls collide. If they don't collide,
+*   the returned Collision will indicate that. If the balls are overlapping
+*   a collision is NOT detected.
+*/
+static COLLISION _COLLISION_FindTimeUntilTwoBallsCollide(const BALL * pb1, const BALL * pb2) {
+  COLLISION clsn = {0};
+  float     a, b, c, det, t;
+  
+  // Compute parts of quadratic formula
+  //
+  // a = (v2x - v1x) ^ 2 + (v2y - v1y) ^ 2
+  //
+  a = _Square(pb2->v.x - pb1->v.x) + _Square(pb2->v.y - pb1->v.y);
+  //
+  // b = 2 * ((x20 - x10) * (v2x - v1x) + (y20 - y10) * (v2y - v1y))
+  //
+  b = 2.f * ((pb2->p.x - pb1->p.x) * (pb2->v.x - pb1->v.x) + (pb2->p.y - pb1->p.y) * (pb2->v.y - pb1->v.y));
+  //
+  // c = (x20 - x10) ^ 2 + (y20 - y10) ^ 2 - (r1 + r2) ^ 2
+  //
+  c = _Square(pb2->p.x - pb1->p.x) + _Square(pb2->p.y - pb1->p.y) - _Square(pb1->r + pb2->r);
+  //
+  // Determinant = b^2 - 4ac
+  //
+  det = _Square(b) - 4 * a * c;
+  if (a != 0.f) {                     // If a == 0 then v2x==v1x and v2y==v1y and there will be no collision
+    t = (-b - sqrt(det)) / (2. * a);  // Quadratic formula. t = time to collision
+    if (t >= 0.) {                    // If collision occurs...
+      _COLLISION_SetCollisionWithBall(&clsn, t);
+    }
+  }
+  return clsn;
+}
+
+/*********************************************************************
+*
+*        _COLLISION_FindTimeUntilBallCollidesWithWall
+*
+* Function description:
+*   Finds time until specified ball collides with any wall. If they
+*   don't collide, the returned Collision indicates that. If there
+*   will be collisions with more than one wall, this function returns
+*   the earliest collision.
+*
+* IMPORTANT: This function assumes that the ball is bounded within 
+*   the specified walls.
+*/
+static COLLISION _COLLISION_FindTimeUntilBallCollidesWithWall(const BALL * pb, const WALLS * pw) {
+  COLLISION clsn = {0};
+  float     timeToCollision;
+  float     t;
+  int       whichWall;
+  
+  timeToCollision = 0.f;
+  whichWall       = WALL_NONE;
+  //
+  // Check for collision with wall X1
+  //
+  if (pb->v.x < 0.f) {
+    t = (pb->r - pb->p.x + pw->x1) / pb->v.x;
+    if (t >= 0.f) {  // If t < 0 then ball is headed away from wall
+      timeToCollision = t;
+      whichWall = WALL_X1;
+    }
+  }
+  //
+  // Check for collision with wall Y1
+  //
+  if (pb->v.y < 0.f) {
+    t = (pb->r - pb->p.y + pw->y1) / pb->v.y;
+    if (t >= 0.f) {
+      if (whichWall == WALL_NONE || t < timeToCollision) {
+        timeToCollision = t;
+        whichWall = WALL_Y1;
+      }
+    }
+  }
+  //
+  // Check for collision with wall X2
+  //
+  if (pb->v.x > 0.f) {
+    t = (pw->x2 - pb->r - pb->p.x) / pb->v.x;
+    if (t >= 0.f) {
+      if (whichWall == WALL_NONE || t < timeToCollision) {
+        timeToCollision = t;
+        whichWall = WALL_X2;
+      }
+    }
+  }
+  //
+  // Check for collision with wall Y2
+  //
+  if (pb->v.y > 0.f) {
+    t = (pw->y2 - pb->r - pb->p.y) / pb->v.y;
+    if (t >= 0.f) {
+      if (whichWall == WALL_NONE || t < timeToCollision) {
+        timeToCollision = t;
+        whichWall = WALL_Y2;
+      }
+    }
+  }
+  //
+  // Setup Collision return value
+  //
+  if (whichWall != WALL_NONE) {  // If there is a collision...
+    _COLLISION_SetCollisionWithWall(&clsn, timeToCollision, whichWall);
+  }
+  return clsn;
+}
+
+/*********************************************************************
+*
+*        _COLLISION_DoElasticCollisionTwoBalls
+*
+* Function description:
+*   Updates the velocities of b1 and b2 to reflect the effect of an elastic
+*   collision between the two. IMPORTANT: This function does NOT check the
+*   positions of the balls to see if they're actually colliding. It just
+*   assumes that they are. Use findTimeUntilTwoBallsCollide() to see
+*   if the balls are colliding.
+*/
+static void _COLLISION_DoElasticCollisionTwoBalls(BALL * pb1, BALL * pb2) {
+  VECTOR * v_n;
+  VECTOR * v_un;
+  VECTOR * v_ut;
+  VECTOR * v_v1nPrime;
+  VECTOR * v_v1tPrime;
+  VECTOR * v_v2nPrime;
+  VECTOR * v_v2tPrime;
+  float    v1n, v1t, v2n, v2t;
+  float    v1tPrime, v2tPrime;
+  float    v1nPrime, v2nPrime;
+
+  //
+  // Avoid division by zero below in computing new normal velocities
+  // Doing a collision where both balls have no mass makes no sense anyway
+  //
+  if ((pb1->m == 0.f) && (pb2->m == 0.f)) {
+    return;
+  }
+  //
+  // Compute unit normal and unit tangent vectors
+  //
+  v_n  = _VECTOR_CreateCopyMinus(&pb2->p, &pb1->p);  // v_n = normal vec. - a vector normal to the collision surface
+  v_un = _VECTOR_CreateUnitVector(v_n);              // unit normal vector
+  v_ut = _VECTOR_Create(-v_un->y, v_un->x);          // unit tangent vector
+  //
+  // Compute scalar projections of velocities onto v_un and v_ut
+  //
+  v1n = _VECTOR_DotProduct(v_un, &pb1->v);  // Dot product
+  v1t = _VECTOR_DotProduct(v_ut, &pb1->v);
+  v2n = _VECTOR_DotProduct(v_un, &pb2->v);
+  v2t = _VECTOR_DotProduct(v_ut, &pb2->v);
+  //
+  // Compute new tangential velocities
+  //
+  v1tPrime = v1t;  // Note: in reality, the tangential velocities do not change after the collision
+  v2tPrime = v2t;
+  //
+  // Compute new normal velocities using one-dimensional elastic collision equations in the normal direction
+  // Division by zero avoided. See early return above.
+  //
+  v1nPrime = (v1n * (pb1->m - pb2->m) + 2.f * pb2->m * v2n) / (pb1->m + pb2->m);
+  v2nPrime = (v2n * (pb2->m - pb1->m) + 2.f * pb1->m * v1n) / (pb1->m + pb2->m);
+  //
+  // Compute new normal and tangential velocity vectors
+  //
+  v_v1nPrime = _VECTOR_CreateCopyMult(v_un, v1nPrime);  // Multiplication by a scalar
+  v_v1tPrime = _VECTOR_CreateCopyMult(v_ut, v1tPrime);
+  v_v2nPrime = _VECTOR_CreateCopyMult(v_un, v2nPrime);
+  v_v2tPrime = _VECTOR_CreateCopyMult(v_ut, v2tPrime);
+  //
+  // Set new velocities in x and y coordinates
+  //
+  _VECTOR_SetXY(&pb1->v, v_v1nPrime->x + v_v1tPrime->x, v_v1nPrime->y + v_v1tPrime->y);
+  _VECTOR_SetXY(&pb2->v, v_v2nPrime->x + v_v2tPrime->x, v_v2nPrime->y + v_v2tPrime->y);
+  //
+  // CleanUp
+  //
+  _VECTOR_Delete(v_n);
+  _VECTOR_Delete(v_un);
+  _VECTOR_Delete(v_ut);
+  _VECTOR_Delete(v_v1nPrime);
+  _VECTOR_Delete(v_v1tPrime);
+  _VECTOR_Delete(v_v2nPrime);
+  _VECTOR_Delete(v_v2tPrime);
+}
+
+/*********************************************************************
+*
+*        _COLLISION_DoElasticCollisionWithWall
+*/
+static void _COLLISION_DoElasticCollisionWithWall(BALL * pb, int w) {
+  switch (w) {
+  case WALL_X1:
+    _VECTOR_SetX(&pb->v, fabs(pb->v.x));
+    break;
+  case WALL_Y1:
+    _VECTOR_SetY(&pb->v, fabs(pb->v.y));
+    break;
+  case WALL_X2:
+    _VECTOR_SetX(&pb->v, -fabs(pb->v.x));
+    break;
+  case WALL_Y2:
+    _VECTOR_SetY(&pb->v, -fabs(pb->v.y));
+    break;
+  }
+}
+
+/*********************************************************************
+*
+*       Static code: BALLSIM
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+*        _BALLSIM_ResetBalls
+*/
+static void _BALLSIM_ResetBalls(BALLSIM * pBallsim) {
+  BALL * pBalli;
+  BALL * pBalld;
+  
+  pBallsim->NextId        = 0;   // Reset ID counter
+  pBallsim->MinArea       = 0.;
+  pBallsim->MaxDiameter   = 0.;
+  pBallsim->MaxCollisions = 10;  // This will be overwritten on the first call to addBall()
+  //
+  // Delete all balls
+  //
+  pBalli = pBallsim->pFirstBall;
+  while (pBalli) {
+    pBalld = pBalli;
+    pBalli = pBalli->pNext;
+    _Free(pBalld);
+  }
+}
+
+/*********************************************************************
+*
+*        _BALLSIM_Create
+*/
+static BALLSIM * _BALLSIM_Create(void) {
+  BALLSIM * pBallsim;
+
+  pBallsim = (BALLSIM *)_Calloc(sizeof(BALLSIM), 1);
+  pBallsim->HasWalls = 0;
+  pBallsim->MaxCollisionsPerBall = 10;
+  _BALLSIM_ResetBalls(pBallsim);
+  return pBallsim;
+}
+
+/*********************************************************************
+*
+*        _BALLSIM_AdvanceBallPositions
+*/
+static void _BALLSIM_AdvanceBallPositions(BALLSIM * pBallsim, const float dt) {
+  BALL * pBalli;
+
+  pBalli = pBallsim->pFirstBall;
+  while (pBalli) {
+    _BALL_AdvanceBallPosition(pBalli, dt);
+    pBalli = pBalli->pNext;
+  }
+}
+
+/*********************************************************************
+*
+*        BALLSSIM_FindEarliestCollisionOfTwoBalls
+*/
+static COLLISION BALLSSIM_FindEarliestCollisionOfTwoBalls(BALLSIM * pBallsim, BALL ** ppb1, BALL ** ppb2) {
+  COLLISION earliestCollision;
+  COLLISION c;
+  BALL    * pBalli;
+  BALL    * pBallj;
+  
+  _COLLISION_Reset(&earliestCollision);
+  //
+  // Compare each pair of balls. Index i runs from the first
+  // ball up through the second-to-last ball. For each value of
+  // i, index j runs from the ball after i up through the last ball.
+  //
+  pBalli = pBallsim->pFirstBall;
+  while (pBalli) {
+    pBallj = pBallsim->pFirstBall;
+    while (pBallj) {
+      c = _COLLISION_FindTimeUntilTwoBallsCollide(pBalli, pBallj);
+      if (_COLLISION_Ball1HasCollisionWithBall(&c)) {
+        if (!_COLLISION_Ball1HasCollision(&earliestCollision) || c.TimeToCollision < earliestCollision.TimeToCollision) {
+          earliestCollision = c;
+          *ppb1 = pBalli;
+          *ppb2 = pBallj;
+        }
+      }
+      pBallj = pBallj->pNext;
+    }
+    pBalli = pBalli->pNext;
+  }
+  return earliestCollision;
+}
+
+/*********************************************************************
+*
+*        BALLSSIM_FindEarliestCollisionWithWall
+*/
+static COLLISION BALLSSIM_FindEarliestCollisionWithWall(BALLSIM * pBallsim, BALL ** ppb) {
+  COLLISION earliestCollision;
+  COLLISION c;
+  BALL    * pBalli;
+  
+  _COLLISION_Reset(&earliestCollision);
+  //
+  // If there are no walls, return no collision
+  //
+  if (!pBallsim->HasWalls) {
+    return earliestCollision;
+  }
+  //
+  // Check each ball to see if any collide. Store the earliest colliding ball.
+  //
+  pBalli = pBallsim->pFirstBall;
+  while (pBalli) {
+    c = _COLLISION_FindTimeUntilBallCollidesWithWall(pBalli, &pBallsim->Walls);
+    if (_COLLISION_Ball1HasCollisionWithWall(&c)) {
+      if (!_COLLISION_Ball1HasCollision(&earliestCollision) || c.TimeToCollision < earliestCollision.TimeToCollision) {
+        earliestCollision = c;
+        *ppb = pBalli;
+      }
+    }
+    pBalli = pBalli->pNext;
+  }
+  return earliestCollision;
+}
+
+/*********************************************************************
+*
+*        BALLSSIM_FindEarliestCollision
+*/
+static COLLISION BALLSSIM_FindEarliestCollision(BALLSIM * pBallsim, BALL ** ppb1, BALL ** ppb2) {
+  COLLISION earliestCollision;
+  COLLISION cWalls;
+  BALL    * pbCollideWithWall;
+  
+  earliestCollision = BALLSSIM_FindEarliestCollisionOfTwoBalls(pBallsim, ppb1, ppb2);
+  if (pBallsim->HasWalls) {
+    cWalls = BALLSSIM_FindEarliestCollisionWithWall(pBallsim, &pbCollideWithWall);
+    if (_COLLISION_Ball1HasCollisionWithWall(&cWalls)) {
+      if (!_COLLISION_Ball1HasCollisionWithBall(&earliestCollision) || cWalls.TimeToCollision < earliestCollision.TimeToCollision) {
+        earliestCollision = cWalls;
+        *ppb1 = pbCollideWithWall;
+      }
+    }
+  }
+  return earliestCollision;
+}
+
+/*********************************************************************
+*
+*        _BALLSIM_AdvanceBallGravity
+*/
+static void _BALLSIM_AdvanceBallGravity(BALLSIM * pBallsim, const float dt) {
+  BALL    * pBalli;
+  BALL    * pBallj;
+  
+  pBalli = pBallsim->pFirstBall;
+  while (pBalli) {
+    pBallj = pBalli->pNext;
+    while (pBallj) {
+      _BALL_DoBallGravity(pBalli, pBallj, dt, pBallsim->pConfig->Gravity);
+      pBallj = pBallj->pNext;
+    }
+    pBalli = pBalli->pNext;
+  }
+}
+
+/*********************************************************************
+*
+*       _BALLSIM_AdvanceGroundGravity
+*/
+static void _BALLSIM_AdvanceGroundGravity(BALLSIM * pBallsim, const float dt) {
+  BALL * pBalli;
+
+  pBalli = pBallsim->pFirstBall;
+  while (pBalli) {
+    _BALL_DoGroundGravity(pBalli, dt, pBallsim->pConfig->Gravity);
+    pBalli = pBalli->pNext;
+  }
+}
+
+/*********************************************************************
+*
+*        BALLSSIM_AdvanceSim
+*/
+static void BALLSSIM_AdvanceSim(BALLSIM * pBallsim, const float dt) {
+  float     tElapsed;
+  COLLISION c;
+  BALL    * pb1;
+  BALL    * pb2;
+  unsigned  i;
+
+  tElapsed = 0.f;
+  for (i = 0; i < pBallsim->MaxCollisions; i++) {
+    //
+    // Find earliest collision
+    //
+    c = BALLSSIM_FindEarliestCollision(pBallsim, &pb1, &pb2);
+    //
+    // If no collisions, break
+    //
+    if (!_COLLISION_Ball1HasCollision(&c)) {
+      break;
+    }
+    //
+    // Is collision within the time frame?
+    // Note: condition is tElapsed + timeToCollision strictly < dt, not <=, because if the two were exactly
+    // equal, we would perform the velocity adjustment for collision but not move the balls any more, so the
+    // collision could be detected again on the next call to advanceSim().
+    //
+    if (tElapsed + c.TimeToCollision < dt) {
+      //
+      // Collision is within time frame
+      // Advance balls to point of collision
+      //
+      _BALLSIM_AdvanceBallPositions(pBallsim, c.TimeToCollision);
+      //
+      // Collision is now occuring. Do collision calculation
+      //
+      if (_COLLISION_Ball1HasCollisionWithWall(&c)) {
+        _COLLISION_DoElasticCollisionWithWall(pb1, c.WhichWall);
+      } else if (_COLLISION_Ball1HasCollisionWithBall(&c)) {
+        _COLLISION_DoElasticCollisionTwoBalls(pb1, pb2);
+      }
+      tElapsed += c.TimeToCollision;  // Move time counter forward
+    } else {
+      break;  // Break if collision is not within this frame
+    }
+  }
+  //
+  // Advance ball positions further if necessary after any collisions to complete the time frame
+  //
+  _BALLSIM_AdvanceBallPositions(pBallsim, dt - tElapsed);
+  //
+  // Manage ball gravity
+  //
+  if (pBallsim->pConfig->HasBallGravity) {
+    _BALLSIM_AdvanceBallGravity(pBallsim, dt);
+  }
+  //
+  // Manage ground gravity
+  //
+  if (pBallsim->pConfig->HasGroundGravity) {
+    _BALLSIM_AdvanceGroundGravity(pBallsim, dt);
+  }
+}
+
+/*********************************************************************
+*
+*        BALLSSIM_MoveBallToWithinBounds
+*/
+static void BALLSSIM_MoveBallToWithinBounds(BALLSIM * pBallsim, BALL * pb) {
+  //
+  // Check wall X1
+  //
+  if (pb->p.x - pb->r < pBallsim->Walls.x1) {
+    _VECTOR_SetX(&pb->p, pBallsim->Walls.x1 + pb->r);
+  }
+  //
+  // Check wall Y1
+  //
+  if (pb->p.y - pb->r < pBallsim->Walls.y1) {
+    _VECTOR_SetY(&pb->p, pBallsim->Walls.y1 + pb->r);
+  }
+  //
+  // Check wall X2
+  //
+  if (pb->p.x + pb->r > pBallsim->Walls.x2) {
+    _VECTOR_SetX(&pb->p, pBallsim->Walls.x2 - pb->r);
+  }
+  //
+  // Check wall Y2
+  //
+  if (pb->p.y + pb->r > pBallsim->Walls.y2) {
+    _VECTOR_SetY(&pb->p, pBallsim->Walls.y2 - pb->r);
+  }
+}
+
+/*********************************************************************
+*
+*        BALLSSIM_MoveWalls
+*/
+static void BALLSSIM_MoveWalls(BALLSIM * pBallsim, const WALLS * pNewWalls) {
+  BALL * pBalli;
+
+  pBallsim->Walls = *pNewWalls;
+  pBallsim->HasWalls = 1;
+  pBalli = pBallsim->pFirstBall;
+  while (pBalli) {
+    BALLSSIM_MoveBallToWithinBounds(pBallsim, pBalli);
+    pBalli = pBalli->pNext;
+  }
+}
+
+/*********************************************************************
+*
+*        BALLSSIM_GetMinWallDimension
+*/
+static float BALLSSIM_GetMinWallDimension(BALLSIM * pBallsim, float fixedWallDimension) {
+  float minDimension;
+  
+  minDimension = 0.f;
+  if (fixedWallDimension > 0.f) {
+    minDimension = 4.f * pBallsim->MinArea / fixedWallDimension;
+  }
+  if (minDimension <= pBallsim->MaxDiameter) {
+    minDimension = pBallsim->MaxDiameter + 1;
+  }
+  return minDimension;
+}
+
+/*********************************************************************
+*
+*        BALLSSIM_AddBall
+*/
+static void BALLSSIM_AddBall(BALLSIM * pBallsim, BALL * pNewBall) {
+  BALL * pBalli;
+
+  pBallsim->NumBalls = 0;
+  pBalli = pBallsim->pFirstBall;
+  if (pBalli) {
+    pBallsim->NumBalls++;
+    while (pBalli->pNext) {
+      pBallsim->NumBalls++;
+      pBalli = pBalli->pNext;
+    }
+    pBallsim->NumBalls++;
+    pBalli->pNext = pNewBall;
+  } else {
+    pBallsim->NumBalls++;
+    pBallsim->pFirstBall = pNewBall;
+    pNewBall->pNext = NULL;
+  }
+  pBallsim->MaxCollisions = pBallsim->MaxCollisionsPerBall * pBallsim->NumBalls;
+  BALLSSIM_MoveBallToWithinBounds(pBallsim, pNewBall);
+  if (pNewBall->r * 2.f > pBallsim->MaxDiameter) {
+    pBallsim->MaxDiameter = pNewBall->r * 2.f;
+    pBallsim->MinArea += 4.f * pNewBall->r * pNewBall->r;
+  }
+}
+
+/*********************************************************************
+*
+*       _BALLSIM_GetBallFromPos
+*/
+static BALL * _BALLSIM_GetBallFromPos(BALLSIM * pBallsim, float xPos, float yPos) {
+  float d, dx, dy;
+  BALL * pBalli;
+  
+  pBalli = pBallsim->pFirstBall;
+  while (pBalli) {
+    dx = xPos - pBalli->p.x;
+    dy = yPos - pBalli->p.y;
+    d = sqrt(dx * dx + dy * dy);
+    if (d < pBalli->r) {
+      return pBalli;
+    }
+    pBalli = pBalli->pNext;
+  }
+  return NULL;
+}
+
+/*********************************************************************
+*
+*       _BALLSIM_DeleteBall
+*/
+static void _BALLSIM_DeleteBall(BALLSIM * pBallsim, BALL * pBall) {
+  BALL * pBalli;
+  BALL * pBallPrev = NULL;
+
+  pBalli = pBallsim->pFirstBall;
+  while (pBalli) {
+    if (pBalli == pBall) {
+      if (pBallPrev) {
+        pBallPrev->pNext = pBalli->pNext;
+      } else {
+        pBallsim->pFirstBall = pBallsim->pFirstBall->pNext;
+      }
+      pBallsim->NumBalls--;
+      _Free(pBall);
+      break;
+    }
+    pBallPrev = pBalli;
+    pBalli = pBalli->pNext;
+  }
+}
+
+/*********************************************************************
+*
+*       _BALLSIM_StopMoving
+*/
+static void _BALLSIM_StopMoving(BALLSIM * pBallsim) {
+  BALL * pBalli;
+
+  pBalli = pBallsim->pFirstBall;
+  while (pBalli) {
+    _VECTOR_SetXY(&pBalli->v, 0.f, 0.f);
+    pBalli = pBalli->pNext;
+  }
+}
+
+/*********************************************************************
+*
+*       _BALLSIM_Delete
+*/
+static void _BALLSIM_Delete(BALLSIM * pBallsim) {
+  _BALLSIM_ResetBalls(pBallsim);
+  _Free(pBallsim);
+}
+
+/*********************************************************************
+*
+*       Static code: Ballsim Window
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+*       _UpdateDisplay
+*/
+static void _UpdateDisplay(WM_HWIN hWin, BALLSIM * pBallsim) {
+  BALL * pBalli;
+  U32    Color;
+
+  //
+  // Draw background
+  //
+  if (pBallsim->pConfig->pfDrawBk) {
+    pBallsim->pConfig->pfDrawBk(hWin, pBallsim->pConfig);
+  } else {
+    GUI_SetBkColor(pBallsim->pConfig->ColorBk);
+    GUI_Clear();
+  }
+  //
+  // Draw all balls
+  //
+  pBalli = pBallsim->pFirstBall;
+  while (pBalli) {
+    if (pBallsim->pConfig->pfDrawBall) {
+      pBallsim->pConfig->pfDrawBall(hWin, pBallsim->pConfig, pBalli->Index, pBalli->p.x, pBalli->p.y, pBalli->r);
+    } else {
+      Color = GUI_MAKE_COLOR(pBalli->Index);
+      GUI_SetColor(Color);
+      GUI_FillCircle(pBalli->p.x, pBalli->p.y, pBalli->r);
+    }
+    pBalli = pBalli->pNext;
+  }
+}
+
+/*********************************************************************
+*
+*       _AddRandomBalls
+*/
+static void _AddRandomBalls(BALLSIM * pBallsim) {
+  unsigned i, PosOccupied, Cnt;
+  float d, dx, dy;
+  BALL * pBall;
+  BALL * pBalli;
+  BALLSIM_CONFIG * pConfig;
+
+  pConfig = pBallsim->pConfig;
+  for (i = 0; i < pConfig->NumBalls; i++) {
+    pBall = _BALL_Create();
+    if (pBallsim->pConfig->HasInitialVelocity) {
+      pBall->v.x = _GetRandomNumber(pConfig->vMin, pConfig->vMax);
+      pBall->v.y = _GetRandomNumber(pConfig->vMin, pConfig->vMax);
+    }
+    pBall->Index = (U32)_GetRandomNumber(0, pConfig->Range);
+    if (pConfig->pRadius) {
+      pBall->r = *(pConfig->pRadius + pBall->Index);
+    } else {
+      pBall->r = _GetRandomNumber(pConfig->rMin, pConfig->rMax);
+    }
+    pBall->m = M_TO_A_RATIO * M_PI * pBall->r * pBall->r;
+    //
+    // Generate legal position
+    //
+    Cnt = 0;
+    do {
+      pBall->p.x = _GetRandomNumber((float)pBall->r, (float)(pConfig->xSize) - pBall->r);
+      pBall->p.y = _GetRandomNumber((float)pBall->r, (float)(pConfig->ySize) - pBall->r);
+      PosOccupied = 0;
+      pBalli = pBallsim->pFirstBall;
+      while (pBalli) {
+        dx = pBalli->p.x - pBall->p.x;
+        dy = pBalli->p.y - pBall->p.y;
+        d = sqrt(dx * dx + dy * dy);
+        if (d < pBalli->r + pBall->r) {
+          PosOccupied = 1;
+          break;
+        }
+        pBalli = pBalli->pNext;
+      }
+    } while (PosOccupied && (Cnt++ < 10));
+    //
+    // Add ball to array
+    //
+    if (PosOccupied == 0) {
+      BALLSSIM_AddBall(pBallsim, pBall);
+    }
+  }
+}
+
+/*********************************************************************
+*
+*       _cbConfig
+*/
+static void _cbConfig(WM_MESSAGE * pMsg) {
+  WM_HWIN                     hItem;
+  static BALLSIM            * pBallsim;
+  int                         Id, NCode;
+  int                         xSize, ySize;
+  WM_PID_STATE_CHANGED_INFO * pInfo;
+  GUI_PID_STATE             * pState;
+  static int                  IsDown;
+  static GUI_POINT            pDown;
+
+  switch (pMsg->MsgId) {
+  case WM_PAINT:
+    xSize = WM_GetWindowSizeX(pMsg->hWin);
+    ySize = WM_GetWindowSizeY(pMsg->hWin);
+    GUI_SetColor(GUI_BLACK);
+    GUI_DrawRect(0, 0, xSize - 1, ySize - 1);
+    break;
+  case WM_PID_STATE_CHANGED:
+    pInfo = (WM_PID_STATE_CHANGED_INFO *)pMsg->Data.p;
+    if (pInfo->StatePrev == 0) {
+      IsDown = 1;
+      pDown.x = pInfo->x;
+      pDown.y = pInfo->y;
+      WM_SetCapture(pMsg->hWin, 1);
+    } else {
+      IsDown = 0;
+    }
+    break;
+  case WM_TOUCH:
+    if (IsDown) {
+      pState = (GUI_PID_STATE *)pMsg->Data.p;
+      if (pState) {
+        WM_MoveWindow(pMsg->hWin, pState->x - pDown.x, pState->y - pDown.y);
+      }
+    }
+    break;
+  case WM_USER_DATA:
+    WM_GetUserData(pMsg->hWin, &pBallsim, sizeof(void *));
+    WINDOW_SetBkColor(pMsg->hWin, GUI_WHITE);
+    WM_MakeModal(pMsg->hWin);
+    hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_0);
+    BUTTON_SetText(hItem, "Stop moving");
+    hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_1);
+    BUTTON_SetText(hItem, "Create random balls");
+    hItem = WM_GetDialogItem(pMsg->hWin, ID_BUTTON_2);
+    BUTTON_SetText(hItem, "Back");
+    hItem = WM_GetDialogItem(pMsg->hWin, ID_CHECKBOX_0);
+    CHECKBOX_SetText(hItem, "Ball Gravity");
+    if (pBallsim->pConfig->HasBallGravity) {
+      CHECKBOX_Check(hItem);
+    } else {
+      CHECKBOX_Uncheck(hItem);
+    }
+    hItem = WM_GetDialogItem(pMsg->hWin, ID_CHECKBOX_1);
+    CHECKBOX_SetText(hItem, "Ground Gravity");
+    if (pBallsim->pConfig->HasGroundGravity) {
+      CHECKBOX_Check(hItem);
+    } else {
+      CHECKBOX_Uncheck(hItem);
+    }
+    hItem = WM_GetDialogItem(pMsg->hWin, ID_TEXT_0);
+    TEXT_SetText(hItem, "Gravity:");
+    TEXT_SetTextAlign(hItem, GUI_TA_RIGHT | GUI_TA_VCENTER);
+    hItem = WM_GetDialogItem(pMsg->hWin, ID_SLIDER_0);
+    SLIDER_SetRange(hItem, 0, 400);
+    SLIDER_SetValue(hItem, (int)pBallsim->pConfig->Gravity);
+    break;
+  case WM_NOTIFY_PARENT:
+    Id    = WM_GetId(pMsg->hWinSrc);
+    NCode = pMsg->Data.v;
+    switch(Id) {
+    case ID_BUTTON_0:
+      switch(NCode) {
+      case WM_NOTIFICATION_RELEASED:
+        _BALLSIM_StopMoving(pBallsim);
+        break;
+      }
+      break;
+    case ID_BUTTON_1:
+      switch(NCode) {
+      case WM_NOTIFICATION_RELEASED:
+        _AddRandomBalls(pBallsim);
+        break;
+      }
+      break;
+    case ID_BUTTON_2:
+      switch(NCode) {
+      case WM_NOTIFICATION_RELEASED:
+        WM_DeleteWindow(pMsg->hWin);
+        break;
+      }
+      break;
+    case ID_CHECKBOX_0:
+      switch(NCode) {
+      case WM_NOTIFICATION_VALUE_CHANGED:
+        pBallsim->pConfig->HasBallGravity = CHECKBOX_IsChecked(pMsg->hWinSrc) ? 1 : 0;
+        break;
+      }
+      break;
+    case ID_CHECKBOX_1:
+      switch(NCode) {
+      case WM_NOTIFICATION_VALUE_CHANGED:
+        pBallsim->pConfig->HasGroundGravity = CHECKBOX_IsChecked(pMsg->hWinSrc) ? 1 : 0;
+        break;
+      }
+      break;
+    case ID_SLIDER_0:
+      switch(NCode) {
+      case WM_NOTIFICATION_VALUE_CHANGED:
+        pBallsim->pConfig->Gravity = (float)SLIDER_GetValue(pMsg->hWinSrc);
+        break;
+      }
+      break;
+    }
+    break;
+  default:
+    WM_DefaultProc(pMsg);
+  }
+}
+
+/*********************************************************************
+*
+*       _CreateConfigWindow
+*/
+static void _CreateConfigWindow(BALLSIM * pBallsim, WM_HWIN hParent) {
+  WM_HWIN hWin;
+  int xPos, yPos;
+
+  xPos = (pBallsim->pConfig->xSize - _aDialogCreate[0].xSize) / 2;
+  yPos = (pBallsim->pConfig->ySize - _aDialogCreate[0].ySize) / 3;
+  hWin = GUI_CreateDialogBox(_aDialogCreate, GUI_COUNTOF(_aDialogCreate), _cbConfig, WM_HBKWIN, xPos, yPos);
+  WM_SetUserData(hWin, &pBallsim, sizeof(void *));
+}
+
+/*********************************************************************
+*
+*       _CreateBallsim
+*/
+static BALLSIM * _CreateBallsim(WM_HWIN hWin) {
+  BALLSIM_CONFIG * pConfig;
+  BALLSIM        * pBallsim;
+  WALLS          * pWalls;
+
+  WM_GetUserData(hWin, &pConfig, sizeof(void *));
+  pBallsim = _BALLSIM_Create();
+  pBallsim->pConfig = pConfig;
+  pWalls = _WALLS_Create(0.f, 0.f, (float)pConfig->xSize, (float)pConfig->ySize);
+  BALLSSIM_MoveWalls(pBallsim, pWalls);
+  _AddRandomBalls(pBallsim);
+  _Free(pWalls);
+  return pBallsim;
+}
+
+/*********************************************************************
+*
+*       _cbBallsim
+*/
+static void _cbBallsim(WM_MESSAGE * pMsg) {
+  static BALLSIM            * pBallsim;
+  static GUI_TIMER_TIME       Time;
+  GUI_TIMER_TIME              tNow;
+  WM_HTIMER                   hTimer;
+  WM_PID_STATE_CHANGED_INFO * pInfo;
+  BALL                      * pBall;
+  
+  switch (pMsg->MsgId) {
+  case WM_PID_STATE_CHANGED:
+    pInfo = (WM_PID_STATE_CHANGED_INFO *)pMsg->Data.p;
+    if (pInfo->StatePrev == 0) {
+      pBall = _BALLSIM_GetBallFromPos(pBallsim, (float)pInfo->x, (float)pInfo->y);
+      if (pBall) {
+        _BALLSIM_DeleteBall(pBallsim, pBall);
+      } else {
+        _CreateConfigWindow(pBallsim, pMsg->hWin);
+      }
+    }
+    break;
+  case WM_DELETE:
+    _BALLSIM_Delete(pBallsim);
+    break;
+  case WM_USER_DATA:
+    pBallsim = _CreateBallsim(pMsg->hWin);
+    hTimer   = WM_CreateTimer(pMsg->hWin, 0, TIME_SLICE, 0);
+    Time     = GUI_GetTime();
+    break;
+  case WM_PAINT:
+    _UpdateDisplay(pMsg->hWin, pBallsim);
+    break;
+  case WM_TIMER:
+    WM_RestartTimer(pMsg->Data.v, pBallsim->pConfig->TimeSlice);
+    tNow = GUI_GetTime();
+    BALLSSIM_AdvanceSim(pBallsim, (float)(tNow - Time) / 1000);
+    Time = tNow;
+    WM_InvalidateWindow(pMsg->hWin);
+    break;
+  default:
+    WM_DefaultProc(pMsg);
+  }
+}
+
+/*********************************************************************
+*
+*       _CreateBallsimWindow
+*/
+static WM_HWIN _CreateBallsimWindow(BALLSIM_CONFIG * pConfig, WM_HWIN hParent) {
+  WM_HWIN hWin;
+  
+  hWin = WM_CreateWindowAsChild(pConfig->xPos, pConfig->yPos, pConfig->xSize, pConfig->ySize, hParent, WM_CF_SHOW, _cbBallsim, sizeof(void *));
+  WM_SetUserData(hWin, &pConfig, sizeof(void *));
+#if GUI_VERSION < 54400
+  WM_SendMessageNoPara(hWin, WM_USER_DATA);
+#endif
+  return hWin;
+}
+/*********************************************************************
+*
+*       Static code: Application
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+*       _DrawBk
+*/
+static void _DrawBk(WM_HWIN hWin, void * pVoid) {
+  GUI_SetBkColor(GUI_MAKE_COLOR(0x202020));
+  GUI_Clear();
+}
+
+/*********************************************************************
+*
+*       _DrawBall
+*/
+static void _DrawBall(WM_HWIN hWin, void * pVoid, U32 Index, float x, float y, float r) {
+  GUI_SetColor(GUI_MAKE_COLOR(Index));
+  GUI_AA_FillCircle((int)x, (int)y, (int)r); 
+}
+
+/*********************************************************************
+*
+*       _cbSplash
+*/
+static void _cbSplash(WM_MESSAGE * pMsg) {
+  int xSize, ySize;
+  const GUI_BITMAP * pBm;
+
+  switch (pMsg->MsgId) {
+  case WM_PAINT:
+    xSize = WM_GetWindowSizeX(pMsg->hWin);
+    ySize = WM_GetWindowSizeY(pMsg->hWin);
+    GUI_SetBkColor(GUI_WHITE);
+    GUI_Clear();
+    pBm = &_bmSeggerLogo_80x40;
+    GUI_DrawBitmap(pBm, xSize - pBm->XSize - 10, 5);
+    GUI_SetColor(GUI_BLACK);
+    GUI_SetFont(&GUI_Font32_AA4_Bounce);
+    GUI_DispStringAt("Bounce", 10, 10);
+    GUI_SetFont(GUI_FONT_13_ASCII);
+    GUI_DispStringHCenterAt("Press screen for config dialog,\n"
+                            "Tap balls to remove them.\n\n"
+                            "Have fun...", xSize / 2, pBm->YSize + 20);
+    break;
+  case WM_CREATE:
+    WM_CreateTimer(pMsg->hWin, 0, PERIOD_SPLASH, 0);
+    WM_MakeModal(pMsg->hWin);
+    break;
+  case WM_TIMER:
+    WM_DeleteWindow(pMsg->hWin);
+    break;
+  default:
+    WM_DefaultProc(pMsg);
+  }
+}
+
+/*********************************************************************
+*
+*       _Test
+*/
+static void _Test(void) {
+  int xSize, ySize;
+  int xPos, yPos;
+  WM_HWIN hWin;
+  static BALLSIM_CONFIG Config;
+
+  xSize             = LCD_GetXSize();
+  ySize             = LCD_GetYSize();
+  //
+  // Configuration of ball simulation
+  //
+  Config.xSize      = xSize;
+  Config.ySize      = ySize;
+  Config.Range      = 0xE0E0E0;
+  Config.NumBalls   = NUM_BALLS;
+  Config.TimeSlice  = TIME_SLICE;
+  Config.vMin       = MIN_RANDOM_V;
+  Config.vMax       = MAX_RANDOM_V;
+  Config.rMin       = MIN_RANDOM_R;
+  Config.rMax       = MAX_RANDOM_R;
+  Config.Gravity    = GRAVITY;
+  Config.pfDrawBk   = _DrawBk;
+  Config.pfDrawBall = _DrawBall;
+  hWin = _CreateBallsimWindow(&Config, WM_HBKWIN);
+  //
+  // Create splash screen
+  //
+  xPos = (xSize - XSIZE_SPLASH) / 2;
+  yPos = (ySize - YSIZE_SPLASH) / 3;
+  WM_CreateWindowAsChild(xPos, yPos, XSIZE_SPLASH, YSIZE_SPLASH, hWin, WM_CF_SHOW, _cbSplash, 0);
+}
+
+/*********************************************************************
+*
+*       Public code
+*
+**********************************************************************
+*/
+/*********************************************************************
+*
+*       MainTask
+*/
+void MainTask(void) {
+  GUI_Init();
+  WM_MULTIBUF_Enable(1);
+  BUTTON_SetReactOnLevel();
+  _Test();
+  while (1) {
+    GUI_Delay(100);
+  }
+}
+
+/*************************** End of file ****************************/