1 #include "demo_guix_smart_watch.h"
2 
3 #define CHART_SCROLL     4
4 #define CHART_Y_CENTER   30
5 #define EKG_COUNT        15
6 #define EKG_MAP_HEIGHT   50
7 #define EKG_MAP_WIDTH    255
8 
9 #define ANIMATION_TOTAL_STEPS 20
10 #define CAL_ANIMATION_VAL(val) ((val) * animation_step / ANIMATION_TOTAL_STEPS)
11 
12 extern GX_WINDOW_ROOT* root;
13 
14 /* Define local variables.  */
15 static GX_PIXELMAP ekg_map;
16 static GX_CANVAS   ekg_canvas;
17 static GX_COLOR    ekg_map_data_buffer[EKG_MAP_WIDTH * EKG_MAP_HEIGHT];
18 
19 static INT ekg_line_start_y;
20 static INT ekg_line_end_y;
21 static INT ekg_index;
22 static INT ekg_values[EKG_COUNT] = { 0, 0, 0, 0, 0, 5, 7, 4, 1, 0, -16, 25, 18, -6, -1 };
23 
24 static INT animation_step = 0;
25 
26 /******************************************************************************************/
27 /* Initialize fitness screen.                                                             */
28 /******************************************************************************************/
fitness_screen_initialize()29 VOID fitness_screen_initialize()
30 {
31     memset(&ekg_map, 0, sizeof(GX_PIXELMAP));
32 
33     ekg_map.gx_pixelmap_data = (GX_UBYTE*)ekg_map_data_buffer;
34     ekg_map.gx_pixelmap_data_size = sizeof(ekg_map_data_buffer);
35     ekg_map.gx_pixelmap_height = EKG_MAP_HEIGHT;
36     ekg_map.gx_pixelmap_width = EKG_MAP_WIDTH;
37     ekg_map.gx_pixelmap_format = GX_COLOR_FORMAT_24XRGB;
38 
39     memset(&ekg_canvas, 0, sizeof(GX_CANVAS));
40 
41     /* Create a canvas for drawing ekg. */
42     gx_canvas_create(&ekg_canvas, "ekg",
43         root->gx_window_root_canvas->gx_canvas_display, GX_CANVAS_SIMPLE,
44         EKG_MAP_WIDTH, EKG_MAP_HEIGHT, (GX_COLOR*)ekg_map.gx_pixelmap_data, ekg_map.gx_pixelmap_data_size);
45 
46     ekg_line_start_y = CHART_Y_CENTER;
47     ekg_line_end_y = CHART_Y_CENTER;
48     ekg_index = 0;
49 }
50 
51 /******************************************************************************************/
52 /* Reset screen data.                                                                     */
53 /******************************************************************************************/
screen_data_reset()54 static void screen_data_reset()
55 {
56     gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_running_steps, 0);
57     gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_running_distance, 0);
58     gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_calorie_burned_progress_val, 0);
59     gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_running_progress_val, 0);
60     gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_standing_progress_val, 0);
61     gx_radial_progress_bar_value_set(&fitness_screen.fitness_screen_calorie_burned_progress, 0);
62     gx_radial_progress_bar_value_set(&fitness_screen.fitness_screen_running_progress, 0);
63     gx_radial_progress_bar_value_set(&fitness_screen.fitness_screen_standing_progress, 0);
64 }
65 
66 /******************************************************************************************/
67 /* Start a timer for animation.                                                           */
68 /******************************************************************************************/
animation_start(GX_WINDOW * window)69 static void animation_start(GX_WINDOW* window)
70 {
71     animation_step = 0;
72 
73     gx_system_timer_start(window, SCREEN_ANIMATION_TIMER_ID, 40 / GX_SYSTEM_TIMER_MS, 40 / GX_SYSTEM_TIMER_MS);
74 }
75 
76 /******************************************************************************************/
77 /* Update animation.                                                                      */
78 /******************************************************************************************/
animation_update()79 static void animation_update()
80 {
81     INT val;
82 
83     animation_step++;
84 
85     val = get_running_steps();
86     gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_running_steps, CAL_ANIMATION_VAL(val));
87 
88     val = get_running_distance();
89     gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_running_distance, CAL_ANIMATION_VAL(val));
90 
91     val = get_calorie_burned_progress_val();
92     gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_calorie_burned_progress_val, CAL_ANIMATION_VAL(val));
93 
94     val = val * (-360) / 100;
95     gx_radial_progress_bar_value_set(&fitness_screen.fitness_screen_calorie_burned_progress, CAL_ANIMATION_VAL(val));
96 
97     val = get_running_progress_val();
98     gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_running_progress_val, CAL_ANIMATION_VAL(val));
99 
100     val = val * (-360) / 100;
101     gx_radial_progress_bar_value_set(&fitness_screen.fitness_screen_running_progress, CAL_ANIMATION_VAL(val));
102 
103     val = get_standing_progress_val();
104     gx_numeric_prompt_value_set(&fitness_screen.fitness_screen_standing_progress_val, CAL_ANIMATION_VAL(val));
105 
106     val = val * (-360) / 100;
107     gx_radial_progress_bar_value_set(&fitness_screen.fitness_screen_standing_progress, CAL_ANIMATION_VAL(val));
108 
109     if (animation_step == ANIMATION_TOTAL_STEPS)
110     {
111         gx_system_timer_stop(&fitness_screen, SCREEN_ANIMATION_TIMER_ID);
112     }
113 }
114 
115 
116 /******************************************************************************************/
117 /* Update ekg map.                                                                        */
118 /******************************************************************************************/
ekg_map_update()119 static VOID ekg_map_update()
120 {
121     GX_RECTANGLE line_draw_rect;
122     GX_RECTANGLE canvas_size;
123 
124     gx_utility_rectangle_define(&canvas_size, 0, 0, EKG_MAP_WIDTH - 1, EKG_MAP_HEIGHT - 1);
125     gx_utility_rectangle_define(&line_draw_rect, 0, 0, CHART_SCROLL - 1, EKG_MAP_HEIGHT - 1);
126 
127     /* Initiate drawing on this canvas.  */
128     gx_canvas_drawing_initiate(&ekg_canvas, GX_NULL, &canvas_size);
129     gx_canvas_block_move(&canvas_size, CHART_SCROLL, 0, GX_NULL);
130 
131     /* Erase the rectangle ahead of the line */
132     gx_context_brush_define(GX_COLOR_ID_RED, GX_COLOR_ID_CANVAS, GX_BRUSH_SOLID_FILL | GX_BRUSH_ROUND | GX_BRUSH_ALIAS);
133     gx_context_brush_width_set(0);
134     gx_canvas_rectangle_draw(&line_draw_rect);
135 
136     gx_context_brush_width_set(2);
137 
138     ekg_line_end_y = ekg_line_start_y;
139     ekg_line_start_y = CHART_Y_CENTER - ekg_values[ekg_index];
140 
141     gx_canvas_line_draw(0, ekg_line_start_y, CHART_SCROLL - 1, ekg_line_end_y);
142     gx_widget_shift(&fitness_screen.fitness_screen_ekg_dot_icon, 0, ekg_line_start_y - ekg_line_end_y, GX_TRUE);
143 
144     /* Indicate that drawing on this canvas is complete.  */
145     gx_canvas_drawing_complete(&ekg_canvas, GX_FALSE);
146 
147     /* Mark waveform window as dirty.   */
148     gx_system_dirty_mark((GX_WIDGET*)&fitness_screen.fitness_screen_ekg_waveform_win);
149 
150     ekg_index++;
151 
152     if (ekg_index >= EKG_COUNT)
153     {
154         ekg_index = 0;
155     }
156 }
157 
158 /******************************************************************************************/
159 /* Override the default event processing of "fitness_screen" to handle signals from my    */
160 /* child widgets.                                                                         */
161 /******************************************************************************************/
fitness_screen_event_process(GX_WINDOW * window,GX_EVENT * event_ptr)162 UINT fitness_screen_event_process(GX_WINDOW *window, GX_EVENT *event_ptr)
163 {
164     switch (event_ptr->gx_event_type)
165     {
166     case GX_EVENT_SHOW:
167         screen_data_reset();
168         break;
169 
170     case USER_EVENT_ANIMATION_START:
171         gx_system_timer_start(window, FITNESS_SCREEN_CHART_TIMER_ID, 100 / GX_SYSTEM_TIMER_MS, 100 / GX_SYSTEM_TIMER_MS);
172         animation_start(window);
173         break;
174 
175     case USER_EVENT_ANIMATION_STOP:
176         gx_system_timer_stop(window, FITNESS_SCREEN_CHART_TIMER_ID);
177         gx_system_timer_stop(window, SCREEN_ANIMATION_TIMER_ID);
178         break;
179 
180     case GX_EVENT_TIMER:
181         switch (event_ptr->gx_event_payload.gx_event_timer_id)
182         {
183         case FITNESS_SCREEN_CHART_TIMER_ID:
184             ekg_map_update();
185             break;
186 
187         case SCREEN_ANIMATION_TIMER_ID:
188             animation_update();
189             break;
190         }
191         break;
192 
193     case GX_SIGNAL(ID_CALORIE_BUTTON, GX_EVENT_CLICKED):
194         page_screen_slide((GX_WIDGET *)window, (GX_WIDGET *)&calories_screen);
195         break;
196 
197     case GX_SIGNAL(ID_RUNNING_BUTTON, GX_EVENT_CLICKED):
198         page_screen_slide((GX_WIDGET *)window, (GX_WIDGET *)&run_screen);
199         break;
200 
201     case GX_SIGNAL(ID_STANDING_BUTTON, GX_EVENT_CLICKED):
202         page_screen_slide((GX_WIDGET *)window, (GX_WIDGET *)&stand_screen);
203         break;
204 
205     default:
206         break;
207     }
208 
209     return screen_template_event_process(window, event_ptr);
210 }
211 
212 /******************************************************************************************/
213 /* Override the default drawing of ekg waveform window.                                   */
214 /******************************************************************************************/
ekg_waveform_win_draw(GX_WINDOW * window)215 VOID ekg_waveform_win_draw(GX_WINDOW* window)
216 {
217     GX_PIXELMAP *line_cover_gradient;
218     GX_RECTANGLE *size = &window->gx_widget_size;
219 
220     /* Draw ekg waveform.  */
221     gx_canvas_pixelmap_draw(size->gx_rectangle_left, size->gx_rectangle_top, &ekg_map);
222 
223     /* Pick line cover gradient map.  */
224     gx_context_pixelmap_get(GX_PIXELMAP_ID_LANDING_EKG_LINE_COVER_GRADIENT, &line_cover_gradient);
225 
226     /* Draw line cover gradient map.  */
227     gx_canvas_pixelmap_draw(size->gx_rectangle_right - line_cover_gradient->gx_pixelmap_width + 1, size->gx_rectangle_top, line_cover_gradient);
228 }