1 /* This is a small demo of the high-performance GUIX graphics framework. */
2 
3 #include "demo_guix_car_infotainment.h"
4 
5 #define MEMORY_POOL_BUFFER_SIZE (MAIN_DISPLAY_X_RESOLUTION * MAIN_DISPLAY_Y_RESOLUTION) * 5
6 
7 /* Define total number animatin steps.  */
8 #define TOTAL_NUMBER_ANIMATION_STEPS 10
9 
10 #define CURRENT_NUMBER_VAL_GET(target_val) \
11             (target_val * number_animation_step / TOTAL_NUMBER_ANIMATION_STEPS)
12 
13 #define ARC_RANGE    33
14 #define ARC_INTERVAL 36
15 #define ARC_COUNT    8
16 
17 #define MAX_MPH 150
18 #define MIN_MPH 0
19 
20 typedef struct ARC_INFO_STRUCT {
21     INT start_angle;
22     INT end_angle;
23 }ARC_INFO;
24 
25 ARC_INFO arc_info_list[ARC_COUNT + 1];
26 
27 /* Define prototypes.   */
28 VOID  guix_setup(void);
29 extern UINT win32_graphics_driver_setup_24xrgb(GX_DISPLAY* display);
30 VOID clock_update();
31 VOID time_update();
32 
33 /* Define memory for memory pool. */
34 GX_UBYTE memory_pool_buffer[MEMORY_POOL_BUFFER_SIZE];
35 TX_BYTE_POOL memory_pool;
36 GX_WINDOW_ROOT *root;
37 
38 /* Define variables.  */
39 INT local_time_second = 0;
40 GX_WINDOW *current_screen = (GX_WINDOW *)&main_screen;
41 INT bottom_button_alpha = 255;
42 static INT number_animation_step;
43 static INT target_remain_miles = 382;
44 static INT target_battery_usage = 86;
45 static INT MPH_values[] = { 45, 46, 48, 50, 54, 56, 57, 58, 60, 64, 68 };
46 static INT MPH_value_index = 0;
47 
48 /******************************************************************************************/
49 /* Application entry.                                                                     */
50 /******************************************************************************************/
main(int argc,char ** argv)51 int main(int argc, char ** argv)
52 {
53     tx_kernel_enter();
54     return(0);
55 }
56 
57 /******************************************************************************************/
58 /* Define memory allocator function.                                                      */
59 /******************************************************************************************/
memory_allocate(ULONG size)60 VOID *memory_allocate(ULONG size)
61 {
62     VOID *memptr;
63 
64     if (tx_byte_allocate(&memory_pool, &memptr, size, TX_NO_WAIT) == TX_SUCCESS)
65     {
66         return memptr;
67     }
68     return NULL;
69 }
70 
71 /******************************************************************************************/
72 /* Define memory de-allocator function.                                                   */
73 /******************************************************************************************/
memory_free(VOID * mem)74 void memory_free(VOID *mem)
75 {
76     tx_byte_release(mem);
77 }
78 
79 /******************************************************************************************/
80 /* Define tx_application_define function.                                                 */
81 /******************************************************************************************/
tx_application_define(void * first_unused_memory)82 VOID tx_application_define(void *first_unused_memory)
83 {
84     /* create byte pool. */
85     tx_byte_pool_create(&memory_pool, "memory pool", memory_pool_buffer, MEMORY_POOL_BUFFER_SIZE);
86 
87     guix_setup();
88 }
89 
90 /******************************************************************************************/
91 /* Initialize some information used by main screen.                                       */
92 /******************************************************************************************/
main_screen_init()93 VOID main_screen_init()
94 {
95     INT index;
96     GX_RADIAL_SLIDER_INFO* info = &main_screen.main_screen_radial_slider.gx_radial_slider_info;
97 
98     arc_info_list[0].end_angle = info->gx_radial_slider_info_max_angle;
99     arc_info_list[0].start_angle = arc_info_list[0].end_angle - ARC_RANGE;
100 
101     for (index = 1; index < ARC_COUNT; index++)
102     {
103         arc_info_list[index].start_angle = arc_info_list[index - 1].start_angle - ARC_INTERVAL;
104         arc_info_list[index].end_angle = arc_info_list[index - 1].end_angle - ARC_INTERVAL;
105     }
106 
107     arc_info_list[ARC_COUNT].start_angle = 0;
108     arc_info_list[ARC_COUNT].end_angle = 0;
109 }
110 
111 /******************************************************************************************/
112 /* Initiate and run GUIX.                                                                 */
113 /******************************************************************************************/
guix_setup()114 VOID  guix_setup()
115 {
116 
117     /* Initialize GUIX.  */
118     gx_system_initialize();
119 
120     /* install our memory allocator and de-allocator */
121     gx_system_memory_allocator_set(memory_allocate, memory_free);
122 
123     gx_studio_display_configure(MAIN_DISPLAY, win32_graphics_driver_setup_24xrgb,
124         LANGUAGE_ENGLISH, MAIN_DISPLAY_THEME_1, &root);
125 
126     /* Create the gauge_window */
127     gx_studio_named_widget_create("main_screen", (GX_WIDGET *)root, GX_NULL);
128     main_screen_init();
129 
130     /* Create vehicle scrreen. */
131     gx_studio_named_widget_create("vehicle_screen", GX_NULL, GX_NULL);
132 
133     /* Create climate scrreen. */
134     gx_studio_named_widget_create("climate_screen", GX_NULL, GX_NULL);
135 
136     /* Create phone scrreen. */
137     gx_studio_named_widget_create("phone_screen", GX_NULL, GX_NULL);
138 
139     /* Create audio screen. */
140     gx_studio_named_widget_create("audio_screen", GX_NULL, GX_NULL);
141 
142     /* Create video screen. */
143     gx_studio_named_widget_create("video_screen", GX_NULL, GX_NULL);
144 
145     /* Show the root window to make it and patients screen visible.  */
146     gx_widget_show(root);
147 
148     /* Let GUIX run */
149     gx_system_start();
150 }
151 
152 /******************************************************************************************/
153 /* Start number animation.                                                                */
154 /******************************************************************************************/
number_animation_start()155 static VOID number_animation_start()
156 {
157     number_animation_step = 0;
158     gx_system_timer_start(&main_screen, TIMER_ID_MAIN_SCREEN_NUMBER_ANIMATION, 40 / GX_SYSTEM_TIMER_MS, 40 / GX_SYSTEM_TIMER_MS);
159 }
160 
161 /******************************************************************************************/
162 /* Update number animation.                                                               */
163 /******************************************************************************************/
number_animation_update()164 static VOID number_animation_update()
165 {
166     INT val;
167     number_animation_step++;
168 
169     gx_numeric_prompt_value_set(&main_screen.main_screen_remain_miles, CURRENT_NUMBER_VAL_GET(target_remain_miles));
170     val = CURRENT_NUMBER_VAL_GET(target_battery_usage);
171     gx_numeric_prompt_value_set(&main_screen.main_screen_remain_battery, val);
172     gx_progress_bar_value_set(&main_screen.main_screen_battery_progress_bar, val);
173 
174     if (number_animation_step == TOTAL_NUMBER_ANIMATION_STEPS)
175     {
176         gx_system_timer_stop(&main_screen, TIMER_ID_MAIN_SCREEN_NUMBER_ANIMATION);
177     }
178 }
179 
180 /******************************************************************************************/
181 /* Update speedometer animation.                                                          */
182 /******************************************************************************************/
speedometer_aniomation_update()183 static VOID speedometer_aniomation_update()
184 {
185     GX_RADIAL_SLIDER_INFO *info = &main_screen.main_screen_radial_slider.gx_radial_slider_info;
186     INT angle;
187 
188     if (MPH_value_index + 1 < sizeof(MPH_values) / sizeof(INT))
189     {
190         MPH_value_index++;
191     }
192     else
193     {
194         MPH_value_index = 0;
195     }
196 
197     gx_numeric_prompt_value_set(&main_screen.main_screen_MPH_val, MPH_values[MPH_value_index]);
198 
199     /* Convert MPH value to radial progress bar value. */
200     angle = MPH_values[MPH_value_index] * (info->gx_radial_slider_info_max_angle - info->gx_radial_slider_info_min_angle) / MAX_MPH;
201     angle = info->gx_radial_slider_info_max_angle - angle;
202     gx_radial_slider_angle_set(&main_screen.main_screen_radial_slider, angle);
203 }
204 
205 /******************************************************************************************/
206 /* Override the default event processing of "main_screen" to handle signals from my child */
207 /* widgets.                                                                               */
208 /******************************************************************************************/
main_screen_event_process(GX_WINDOW * window,GX_EVENT * event_ptr)209 UINT main_screen_event_process(GX_WINDOW *window, GX_EVENT *event_ptr)
210 {
211     switch (event_ptr->gx_event_type)
212     {
213     case GX_EVENT_SHOW:
214         clock_update();
215 
216         gx_system_timer_start(window, TIMER_ID_SECOND, GX_TICKS_SECOND, GX_TICKS_SECOND);
217 
218         gx_system_timer_start(&main_screen, TIMER_ID_MAIN_SCREEN_SPEEDOMETER_ANIMATION, GX_TICKS_SECOND / 2, GX_TICKS_SECOND / 2);
219 
220         /* Start number animation. */
221         number_animation_start();
222 
223         /* Call default window event process. */
224         base_event_process(window, event_ptr);
225         break;
226 
227     case GX_EVENT_TIMER:
228         switch (event_ptr->gx_event_payload.gx_event_timer_id)
229         {
230         case TIMER_ID_SECOND:
231             time_update();
232             break;
233 
234         case TIMER_ID_MAIN_SCREEN_NUMBER_ANIMATION:
235             /* Update number animation. */
236             number_animation_update();
237             break;
238 
239         case TIMER_ID_MAIN_SCREEN_SPEEDOMETER_ANIMATION:
240             /* Update speedometer animation. */
241             speedometer_aniomation_update();
242             break;
243         }
244         break;
245 
246     case GX_SIGNAL(ID_VEHICLE_MODE_BUTTON, GX_EVENT_CLICKED):
247         ToggleScreen((GX_WINDOW*)&vehicle_screen);
248         break;
249 
250     default:
251         return base_event_process(window, event_ptr);
252     }
253 
254     return GX_SUCCESS;
255 }
256 
257 /******************************************************************************************/
258 /* Switch screen.                                                                         */
259 /******************************************************************************************/
ToggleScreen(GX_WINDOW * new_win)260 VOID ToggleScreen(GX_WINDOW *new_win)
261 {
262     if (new_win != current_screen)
263     {
264         if (!new_win->gx_widget_parent)
265         {
266             gx_widget_attach(root, (GX_WIDGET*)new_win);
267         }
268         else
269         {
270             gx_widget_show((GX_WIDGET*)new_win);
271         }
272         gx_widget_hide((GX_WIDGET*)current_screen);
273 
274         if (new_win->gx_widget_id != ID_VIDEO_SCREEN)
275         {
276             gx_widget_attach(new_win, &main_screen.main_screen_btn_window);
277             gx_widget_attach(new_win, &main_screen.main_screen_on_off_btn);
278         }
279         current_screen = new_win;
280     }
281 }
282 
283 /******************************************************************************************/
284 /* Update clock of main screen.                                                           */
285 /******************************************************************************************/
clock_update()286 VOID clock_update()
287 {
288 #ifdef WIN32
289     SYSTEMTIME local_time;
290     GetLocalTime(&local_time);
291 
292     gx_numeric_prompt_value_set(&main_screen.main_screen_time_hour, local_time.wHour);
293     gx_numeric_prompt_value_set(&main_screen.main_screen_time_minute, local_time.wMinute);
294     local_time_second = local_time.wSecond;
295 #else
296 #endif
297 }
298 
299 /******************************************************************************************/
300 /* Update time.                                                                           */
301 /******************************************************************************************/
time_update()302 VOID time_update()
303 {
304     GX_RESOURCE_ID color_id;
305 
306     if (local_time_second & 0x1)
307     {
308         if (main_screen.main_screen_weather_win.gx_widget_style & GX_STYLE_ENABLED)
309         {
310             color_id = GX_COLOR_ID_WHITE;
311         }
312         else
313         {
314             color_id = GX_COLOR_ID_DISABLED_FILL;
315         }
316     }
317     else
318     {
319         color_id = GX_COLOR_ID_GRAY;
320     }
321 
322     gx_widget_fill_color_set(&main_screen.main_screen_second_dot_up, color_id, color_id, color_id);
323     gx_widget_fill_color_set(&main_screen.main_screen_second_dot_down, color_id, color_id, color_id);
324     local_time_second++;
325 
326     if (local_time_second >= 60)
327     {
328         clock_update();
329     }
330 }
331 
332 /******************************************************************************************/
333 /* Define time value format callback.                                                     */
334 /******************************************************************************************/
time_value_format(GX_NUMERIC_PROMPT * prompt,INT value)335 VOID time_value_format(GX_NUMERIC_PROMPT *prompt, INT value)
336 {
337     INT index = 0;
338 
339     if (value < 10)
340     {
341         prompt->gx_numeric_prompt_buffer[index++] = '0';
342         prompt->gx_numeric_prompt_buffer[index++] = '0' + value;
343     }
344     else
345     {
346         prompt->gx_numeric_prompt_buffer[index++] = '0' + (value / 10);
347         prompt->gx_numeric_prompt_buffer[index++] = '0' + (value % 10);
348     }
349 
350     prompt->gx_numeric_prompt_buffer[index++] = '\0';
351 }
352 
353 /******************************************************************************************/
354 /* Define custom pixelmap button draw function.                                           */
355 /******************************************************************************************/
custom_pixelmap_button_draw(GX_PIXELMAP_BUTTON * button)356 VOID custom_pixelmap_button_draw(GX_PIXELMAP_BUTTON* button)
357 {
358     GX_WIDGET* child = button->gx_widget_first_child;
359     GX_BRUSH* brush;
360 
361     gx_context_brush_get(&brush);
362 
363     if (button->gx_widget_id != ID_ON_OFF_BTN)
364     {
365         brush->gx_brush_alpha = bottom_button_alpha;
366     }
367 
368     while (child)
369     {
370         if (button->gx_widget_style & GX_STYLE_BUTTON_PUSHED)
371         {
372             gx_widget_style_add(child, GX_STYLE_DRAW_SELECTED);
373         }
374         else
375         {
376             gx_widget_style_remove(child, GX_STYLE_DRAW_SELECTED);
377         }
378 
379         child = child->gx_widget_next;
380     }
381 
382     gx_pixelmap_button_draw(button);
383 }
384 
385 
386 /******************************************************************************************/
387 /* Custom defined draw function for main screen radial slider widget.                     */
388 /******************************************************************************************/
radial_slider_draw(GX_RADIAL_SLIDER * slider)389 VOID radial_slider_draw(GX_RADIAL_SLIDER* slider)
390 {
391     GX_RADIAL_SLIDER_INFO* info = &slider->gx_radial_slider_info;
392     GX_PIXELMAP* map;
393     INT xpos;
394     INT ypos;
395     ARC_INFO* arc = arc_info_list;
396     INT start_angle;
397     INT radius;
398     INT angle = info->gx_radial_slider_info_current_angle;
399     GX_POINT inner_pt;
400     GX_POINT outer_pt;
401 
402     /* Call default widget background draw. */
403     gx_widget_background_draw((GX_WIDGET*)slider);
404 
405     gx_context_pixelmap_get(info->gx_radial_slider_info_background_pixelmap, &map);
406 
407     xpos = slider->gx_widget_size.gx_rectangle_left;
408     ypos = slider->gx_widget_size.gx_rectangle_top;
409 
410     if (map)
411     {
412         gx_context_fill_color_set(GX_COLOR_ID_BLUE);
413 
414         /* Draw background pixelmap. */
415         gx_canvas_pixelmap_draw(xpos, ypos, map);
416     }
417 
418     gx_context_brush_width_set(4);
419     gx_context_brush_define(GX_COLOR_ID_LIGHT_GREEN, GX_COLOR_ID_LIGHT_GREEN, GX_BRUSH_ALIAS | GX_BRUSH_ROUND);
420 
421     xpos += info->gx_radial_slider_info_xcenter;
422     ypos += info->gx_radial_slider_info_ycenter;
423 
424     radius = info->gx_radial_slider_info_radius;
425     radius += (info->gx_radial_slider_info_track_width / 2);
426     radius -= 2;
427 
428     /* Fill outer ring with disconnected arcs. */
429     while (arc->start_angle < arc->end_angle)
430     {
431         if (info->gx_radial_slider_info_current_angle < arc->start_angle)
432         {
433             start_angle = arc->start_angle;
434         }
435         else
436         {
437             start_angle = info->gx_radial_slider_info_current_angle;
438         }
439 
440         if (start_angle < arc->end_angle)
441         {
442             gx_canvas_arc_draw(xpos, ypos, radius, start_angle, arc->end_angle);
443         }
444 
445         if (start_angle == info->gx_radial_slider_info_current_angle)
446         {
447             break;
448         }
449 
450         arc++;
451     }
452 
453     /* Get the point on the inner circle of the track with given center point, radius and angle. */
454     gx_utility_circle_point_get(xpos,
455         ypos,
456         info->gx_radial_slider_info_radius - (info->gx_radial_slider_info_track_width >> 1) + 1,
457         angle,
458         &inner_pt);
459 
460     /* Get the point on the outer circle of the track with given center point, radius and angle. */
461     gx_utility_circle_point_get(xpos,
462         ypos,
463         info->gx_radial_slider_info_radius + (info->gx_radial_slider_info_track_width >> 1) - 1,
464         angle,
465         &outer_pt);
466 
467     /* Draw needle. */
468     gx_canvas_line_draw(inner_pt.gx_point_x, inner_pt.gx_point_y, outer_pt.gx_point_x, outer_pt.gx_point_y);
469 
470     /* Draw children widgets. */
471     gx_widget_children_draw((GX_WIDGET*)slider);
472 }