1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** GUIX Component */
16 /** */
17 /** System Management (System) */
18 /** */
19 /**************************************************************************/
20
21 //#define GX_SOURCE_CODE
22
23 /* Include necessary system files. */
24
25 #include "gx_api.h"
26 #include "gx_system.h"
27 #include "gx_system_rtos_bind.h"
28
29
30 /**************************************************************************/
31 /* */
32 /* FUNCTION RELEASE */
33 /* */
34 /* _gx_system_rtos_bind PORTABLE C */
35 /* 6.1 */
36 /* AUTHOR */
37 /* */
38 /* Kenneth Maxwell, Microsoft Corporation */
39 /* */
40 /* DESCRIPTION */
41 /* */
42 /* This file contains a small set of shell functions used to bind GUIX */
43 /* to a generic RTOS. GUIX is by default configured to run with the */
44 /* ThreadX RTOS, but you can port to another RTOS by defining the */
45 /* pre-processor directive GX_DISABLE_THREADX_BINDING and completing */
46 /* the implementation of the functions found in this file. */
47 /* Refer to the GUIX User Guide for more information. */
48 /* */
49 /* INPUT */
50 /* */
51 /* Refer to GUIX User Guide */
52 /* */
53 /* OUTPUT */
54 /* */
55 /* Refer to GUIX User Guide */
56 /* */
57 /* CALLS */
58 /* */
59 /* Refer to GUIX User Guide */
60 /* */
61 /* CALLED BY */
62 /* */
63 /* GUIX system serives */
64 /* */
65 /* RELEASE HISTORY */
66 /* */
67 /* DATE NAME DESCRIPTION */
68 /* */
69 /* 05-19-2020 Kenneth Maxwell Initial Version 6.0 */
70 /* 09-30-2020 Kenneth Maxwell Modified comment(s), */
71 /* resulting in version 6.1 */
72 /* */
73 /**************************************************************************/
74
75 #ifndef GX_THREADX_BINDING
76
77 /* This is an example of a generic RTOS binding. We have #ifdefed this code out
78 of the GUIX library build, so that the user attempting to port to a new RTOS
79 will intentionally observe a series of linker errors. These functions need to
80 be implemented in a way that works correctly with the target RTOS.
81 */
82
83 #if defined(GUIX_BINDING_UCOS_III)
84
85 #include "os.h"
86
87 #ifndef OS_CFG_TICK_RATE_HZ
88 #define OS_CFG_TICK_RATE_HZ 100
89 #endif
90
91 #define GX_TIMER_TASK_PRIORITY (GX_SYSTEM_THREAD_PRIORITY + 1)
92 #define GX_TIMER_TASK_STACK_SIZE 512
93 void guix_timer_task_entry(void *);
94
95 /* a few global status variables */
96 GX_BOOL guix_timer_event_pending;
97
98 /* define stack space for GUIX task */
99 CPU_STK guix_task_stack[GX_THREAD_STACK_SIZE];
100
101 /* define stack space for timer task */
102 CPU_STK guix_timer_task_stack[GX_TIMER_TASK_STACK_SIZE];
103
104 /* define semaphore for lock/unlock macros */
105 OS_MUTEX guix_system_lock_mutex;
106
107 OS_ERR uc_error;
108 OS_TCB guix_tcb;
109 OS_TCB guix_timer_tcb;
110
111 /* a custom event structure, to hold event and linked list */
112
113 typedef struct guix_linked_event_struct
114 {
115 GX_EVENT event_data; /* the GUIX event structure */
116 struct guix_linked_event_struct *next; /* add link member */
117 } GUIX_LINKED_EVENT;
118
119
120 /* a custom fifo event queue structure */
121
122 typedef struct guix_event_queue_struct
123 {
124 GUIX_LINKED_EVENT *first; /* first (oldest) event in fifo */
125 GUIX_LINKED_EVENT *last; /* last (newest) event in fifo */
126 GUIX_LINKED_EVENT *free; /* linked list of free events */
127 GUIX_LINKED_EVENT *free_end; /* end of the free list */
128 OS_SEM count_sem; /* number of queued events */
129 OS_MUTEX lock; /* lock to protect queue update */
130 } GUIX_EVENT_QUEUE;
131
132 /* an array of GX_EVENTs used to implement fifo queue */
133
134 GUIX_LINKED_EVENT guix_event_array[GX_MAX_QUEUE_EVENTS];
135 GUIX_EVENT_QUEUE guix_event_queue;
136
137 /* rtos initialize: perform any setup that needs to be done before the GUIX task runs here */
gx_generic_rtos_initialize(VOID)138 VOID gx_generic_rtos_initialize(VOID)
139 {
140 int Loop;
141 GUIX_LINKED_EVENT *current;
142
143 guix_timer_event_pending = GX_FALSE;
144 OSMutexCreate(&guix_system_lock_mutex, "gx_system_lock", &uc_error);
145
146 /* initialize a custom fifo queue structure */
147
148 guix_event_queue.first = GX_NULL;
149 guix_event_queue.last = GX_NULL;
150 guix_event_queue.free = guix_event_array;
151
152 current = guix_event_queue.free;
153
154 /* link all the structures together */
155 for (Loop = 0; Loop < GX_MAX_QUEUE_EVENTS - 1; Loop++)
156 {
157 current -> next = (current + 1);
158 current = current -> next;
159 }
160 current -> next = GX_NULL; /* terminate the list */
161 guix_event_queue.free_end = current;
162
163 /* create mutex for lock access to this queue */
164 OSMutexCreate(&guix_event_queue.lock, "gx_queue_lock", &uc_error);
165
166 /* create counting semaphore to track queue entries */
167 OSSemCreate(&guix_event_queue.count_sem, "gx_queue_count", 0, &uc_error);
168 }
169
170 VOID (*gx_system_thread_entry)(ULONG);
171
172 // A small shell function to convert the void * arg expected by uC/OS to
173 // a ULONG parameter expected by GUIX thread entry
gx_system_thread_entry_shell(void * parg)174 void gx_system_thread_entry_shell(void *parg)
175 {
176 gx_system_thread_entry((ULONG) parg);
177 }
178
179 /* thread_start: start the GUIX thread running. */
gx_generic_thread_start(VOID (* guix_thread_entry)(ULONG))180 UINT gx_generic_thread_start(VOID(*guix_thread_entry)(ULONG))
181 {
182
183 /* save the GUIX system thread entry function pointer */
184 gx_system_thread_entry = guix_thread_entry;
185
186 /* create the main GUIX task */
187
188 OSTaskCreate(&guix_tcb, "guix_task",
189 gx_system_thread_entry_shell,
190 GX_NULL,
191 GX_SYSTEM_THREAD_PRIORITY,
192 &guix_task_stack[0],
193 GX_THREAD_STACK_SIZE - 1,
194 GX_THREAD_STACK_SIZE,
195 0, 0, GX_NULL, OS_OPT_TASK_NONE, &uc_error);
196
197 /* create a simple task to generate timer events into GUIX */
198 OSTaskCreate(&guix_timer_tcb, "guix_timer_task",
199 guix_timer_task_entry,
200 GX_NULL,
201 GX_TIMER_TASK_PRIORITY,
202 &guix_timer_task_stack[0],
203 GX_TIMER_TASK_STACK_SIZE -1,
204 GX_TIMER_TASK_STACK_SIZE,
205 0, 0, GX_NULL, OS_OPT_TASK_NONE, &uc_error);
206
207 /* suspend the timer task until needed */
208 OSTaskSuspend(&guix_timer_tcb, &uc_error);
209 return GX_SUCCESS;
210 }
211
212 /* event_post: push an event into the fifo event queue */
gx_generic_event_post(GX_EVENT * event_ptr)213 UINT gx_generic_event_post(GX_EVENT *event_ptr)
214 {
215 GUIX_LINKED_EVENT *linked_event;
216
217 /* lock down the guix event queue */
218 OSMutexPend(&guix_event_queue.lock, 0, OS_OPT_PEND_BLOCKING, NULL, &uc_error);
219
220 /* grab a free event slot */
221 if (!guix_event_queue.free)
222 {
223 /* there are no free events, return failure */
224 OSMutexPost(&guix_event_queue.lock, OS_OPT_POST_NONE, &uc_error);
225 return GX_FAILURE;
226 }
227
228 linked_event = guix_event_queue.free;
229 guix_event_queue.free = guix_event_queue.free->next;
230
231 if (!guix_event_queue.free)
232 {
233 guix_event_queue.free_end = GX_NULL;
234 }
235
236 /* copy the event data into this slot */
237 linked_event -> event_data = *event_ptr;
238 linked_event -> next = GX_NULL;
239
240 /* insert this event into fifo queue */
241 if (guix_event_queue.last)
242 {
243 guix_event_queue.last -> next = linked_event;
244 }
245 else
246 {
247 guix_event_queue.first = linked_event;
248 }
249 guix_event_queue.last = linked_event;
250
251 /* Unlock the guix queue */
252 OSMutexPost(&guix_event_queue.lock, OS_OPT_POST_NONE, &uc_error);
253
254 /* increment event count */
255 OSSemPost(&guix_event_queue.count_sem, OS_OPT_POST_ALL, &uc_error);
256 return GX_SUCCESS;
257 }
258
259 /* event_fold: update existing matching event, otherwise post new event */
gx_generic_event_fold(GX_EVENT * event_ptr)260 UINT gx_generic_event_fold(GX_EVENT *event_ptr)
261 {
262 GUIX_LINKED_EVENT *pTest;
263
264 /* Lock down the guix queue */
265
266 OSMutexPend(&guix_event_queue.lock, 0, OS_OPT_PEND_BLOCKING, NULL, &uc_error);
267
268 // see if the same event is already in the queue:
269 pTest = guix_event_queue.first;
270
271 while (pTest)
272 {
273 if (pTest -> event_data.gx_event_type == event_ptr -> gx_event_type)
274 {
275 /* found matching event, update it and return */
276 pTest -> event_data.gx_event_payload.gx_event_ulongdata = event_ptr -> gx_event_payload.gx_event_ulongdata;
277 OSMutexPost(&guix_event_queue.lock, OS_OPT_POST_NONE, &uc_error);
278 return GX_SUCCESS;
279 }
280 pTest = pTest -> next;
281 }
282
283 /* did not find a match, push new event */
284
285 OSMutexPost(&guix_event_queue.lock, OS_OPT_POST_NONE, &uc_error);
286 gx_generic_event_post(event_ptr);
287 return GX_SUCCESS;
288 }
289
290
291 /* event_pop: pop oldest event from fifo queue, block if wait and no events exist */
gx_generic_event_pop(GX_EVENT * put_event,GX_BOOL wait)292 UINT gx_generic_event_pop(GX_EVENT *put_event, GX_BOOL wait)
293 {
294 if (!wait)
295 {
296 if (guix_event_queue.first == GX_NULL)
297 {
298 /* the queue is empty, just return */
299 return GX_FAILURE;
300 }
301 }
302
303 /* wait for an event to arrive in queue */
304 OSSemPend(&guix_event_queue.count_sem, 0, OS_OPT_PEND_BLOCKING, NULL, &uc_error);
305
306 /* lock down the queue */
307 OSMutexPend(&guix_event_queue.lock, 0, OS_OPT_PEND_BLOCKING, NULL, &uc_error);
308
309 /* copy the event into destination */
310 *put_event = guix_event_queue.first -> event_data;
311
312 /* link this event holder back into free list */
313 if (guix_event_queue.free_end)
314 {
315 guix_event_queue.free_end -> next = guix_event_queue.first;
316 }
317 else
318 {
319 guix_event_queue.free = guix_event_queue.first;
320 }
321
322 guix_event_queue.free_end = guix_event_queue.first;
323 guix_event_queue.first = guix_event_queue.first -> next;
324 guix_event_queue.free_end -> next = GX_NULL;
325
326 if (!guix_event_queue.first)
327 {
328 guix_event_queue.last = GX_NULL;
329 }
330
331 /* check for popping out a timer event */
332 if (put_event -> gx_event_type == GX_EVENT_TIMER)
333 {
334 guix_timer_event_pending = GX_FALSE;
335 }
336
337 /* unlock the queue */
338 OSMutexPost(&guix_event_queue.lock, OS_OPT_POST_NONE, &uc_error);
339 return GX_SUCCESS;
340 }
341
342 /* event_purge: delete events targetted to particular widget */
gx_generic_event_purge(GX_WIDGET * target)343 VOID gx_generic_event_purge(GX_WIDGET *target)
344 {
345 GX_BOOL Purge;
346 GUIX_LINKED_EVENT *pTest;
347
348 /* Lock down the guix queue */
349
350 OSMutexPend(&guix_event_queue.lock, 0, OS_OPT_PEND_BLOCKING, NULL, &uc_error);
351
352 // look for events targetted to widget or widget children:
353 pTest = guix_event_queue.first;
354
355 while (pTest)
356 {
357 Purge = GX_FALSE;
358
359 if (pTest ->event_data.gx_event_target)
360 {
361 if (pTest -> event_data.gx_event_target == target)
362 {
363 Purge = GX_TRUE;
364 }
365 else
366 {
367 gx_widget_child_detect(target, pTest->event_data.gx_event_target, &Purge);
368 }
369 if (Purge)
370 {
371 pTest ->event_data.gx_event_target = GX_NULL;
372 pTest->event_data.gx_event_type = 0;
373 }
374 }
375 pTest = pTest -> next;
376 }
377
378 OSMutexPost(&guix_event_queue.lock, OS_OPT_POST_NONE, &uc_error);
379 }
380
381 /* start the RTOS timer */
gx_generic_timer_start(VOID)382 VOID gx_generic_timer_start(VOID)
383 {
384 OSTaskResume(&guix_timer_tcb, &uc_error);
385 }
386
387 /* stop the RTOS timer */
gx_generic_timer_stop(VOID)388 VOID gx_generic_timer_stop(VOID)
389 {
390 OSTaskSuspend(&guix_timer_tcb, &uc_error);
391 }
392
393 /* lock the system protection mutex */
gx_generic_system_mutex_lock(VOID)394 VOID gx_generic_system_mutex_lock(VOID)
395 {
396 OSMutexPend(&guix_system_lock_mutex, 0, OS_OPT_PEND_BLOCKING, NULL, &uc_error);
397
398 }
399
400 /* unlock system protection mutex */
gx_generic_system_mutex_unlock(VOID)401 VOID gx_generic_system_mutex_unlock(VOID)
402 {
403 OSMutexPost(&guix_system_lock_mutex, OS_OPT_POST_NONE, &uc_error);
404 }
405
406 /* return number of low-level system timer ticks. Used for pen speed caculations */
gx_generic_system_time_get(VOID)407 ULONG gx_generic_system_time_get(VOID)
408 {
409 return((ULONG)OSTimeGet(&uc_error));
410 }
411
412 /* thread_identify: return current thread identifier, cast as VOID * */
gx_generic_thread_identify(VOID)413 VOID *gx_generic_thread_identify(VOID)
414 {
415 return((VOID *)OSTCBCurPtr);
416 }
417
418 /* a simple task to drive the GUIX timer mechanism */
guix_timer_task_entry(void * unused)419 void guix_timer_task_entry(void *unused)
420 {
421 int TickCount = OS_CFG_TICK_RATE_HZ / GX_TICKS_SECOND;
422
423 if (TickCount <= 0)
424 {
425 TickCount = 1;
426 }
427
428 while (1)
429 {
430 OSTimeDly(TickCount, OS_OPT_TIME_DLY, &uc_error);
431
432 /* prevent sending timer events faster than they can be processed */
433 if (!guix_timer_event_pending)
434 {
435 guix_timer_event_pending = GX_TRUE;
436 _gx_system_timer_expiration(0);
437 }
438 }
439 }
440
gx_generic_time_delay(int ticks)441 VOID gx_generic_time_delay(int ticks)
442 {
443 OSTimeDly(ticks, OS_OPT_TIME_DLY, &uc_error);
444 }
445
446
447 #endif /* Binding for UCOS-III enabled */
448
449 #if defined(GUIX_BINDING_UCOS_II)
450
451 #include "ucos_ii.h"
452
453 #define TIMER_TASK_PRIORITY (GX_SYSTEM_THREAD_PRIORITY + 1)
454 #define TIMER_TASK_STACK_SIZE 512
455 void guix_timer_task_entry(void *);
456
457 /* a few global status variables */
458 GX_BOOL guix_timer_event_pending;
459 INT8U guix_uc_err = 0;
460
461 /* define stack space for GUIX task */
462 OS_STK guix_task_stack[GX_THREAD_STACK_SIZE];
463 OS_STK guix_task_stack[GX_THREAD_STACK_SIZE];
464
465 /* define stack space for timer task */
466 OS_STK guix_timer_task_stack[TIMER_TASK_STACK_SIZE];
467
468 /* define semaphore for lock/unlock macros */
469 OS_EVENT *guix_system_lock_semaphore;
470
471 /* a custom event structure, to hold event and linked list */
472
473 typedef struct guix_linked_event_struct
474 {
475 GX_EVENT event_data; /* the GUIX event structure */
476 struct guix_linked_event_struct *next; /* add link member */
477 } GUIX_LINKED_EVENT;
478
479
480 /* a custom fifo event queue structure */
481
482 typedef struct guix_event_queue_struct
483 {
484 GUIX_LINKED_EVENT *first; /* first (oldest) event in fifo */
485 GUIX_LINKED_EVENT *last; /* last (newest) event in fifo */
486 GUIX_LINKED_EVENT *free; /* linked list of free events */
487 GUIX_LINKED_EVENT *free_end; /* end of the free list */
488 OS_EVENT *count_sem; /* number of queued events */
489 OS_EVENT *lock_sem; /* lock to protect queue update */
490 } GUIX_EVENT_QUEUE;
491
492 /* an array of GX_EVENTs used to implement fifo queue */
493
494 GUIX_LINKED_EVENT guix_event_array[GX_MAX_QUEUE_EVENTS];
495 GUIX_EVENT_QUEUE guix_event_queue;
496
497 /* rtos initialize: perform any setup that needs to be done before the GUIX task runs here */
gx_generic_rtos_initialize(VOID)498 VOID gx_generic_rtos_initialize(VOID)
499 {
500 int Loop;
501 GUIX_LINKED_EVENT *current;
502
503 guix_timer_event_pending = GX_FALSE;
504 guix_system_lock_semaphore = OSSemCreate(1);
505
506 /* initialize a custom fifo queue structure */
507
508 guix_event_queue.first = GX_NULL;
509 guix_event_queue.last = GX_NULL;
510 guix_event_queue.free = guix_event_array;
511
512 current = guix_event_queue.free;
513
514 /* link all the structures together */
515 for (Loop = 0; Loop < GX_MAX_QUEUE_EVENTS - 1; Loop++)
516 {
517 current -> next = (current + 1);
518 current = current -> next;
519 }
520 current -> next = GX_NULL; /* terminate the list */
521 guix_event_queue.free_end = current;
522
523 /* create mutex for lock access to this queue */
524 guix_event_queue.lock_sem = OSSemCreate(1);
525
526 /* create counting semaphore to track queue entries */
527 guix_event_queue.count_sem = OSSemCreate(0);
528 }
529
530 /* A variable to store GUIX thread entry function pointer */
531 VOID (*gx_thread_entry)(ULONG);
532
533 /* a simple shell function to convert the UCOS (void *)
534 parameter to the GUIX ULONG param type. */
guix_thread_entry_shell(void * ptr)535 void guix_thread_entry_shell(void *ptr)
536 {
537 gx_thread_entry((ULONG) ptr);
538 }
539
540 /* thread_start: start the GUIX thread running. */
gx_generic_thread_start(VOID (* guix_thread_entry)(ULONG))541 UINT gx_generic_thread_start(VOID(*guix_thread_entry)(ULONG))
542 {
543 /* save pointer to GUIX thread entry function */
544 gx_thread_entry = guix_thread_entry;
545
546 /* create the main GUIX task */
547 OSTaskCreate(guix_thread_entry_shell, (void *)0,
548 &guix_task_stack[GX_THREAD_STACK_SIZE - 1], GX_SYSTEM_THREAD_PRIORITY);
549
550 /* create a simple task to generate timer events into GUIX */
551 OSTaskCreate(guix_timer_task_entry, (void *)0,
552 &guix_timer_task_stack[TIMER_TASK_STACK_SIZE - 1], TIMER_TASK_PRIORITY);
553
554 /* suspend the timer task until needed */
555 OSTaskSuspend(TIMER_TASK_PRIORITY);
556 return GX_SUCCESS;
557 }
558
559 /* event_post: push an event into the fifo event queue */
gx_generic_event_post(GX_EVENT * event_ptr)560 UINT gx_generic_event_post(GX_EVENT *event_ptr)
561 {
562 GUIX_LINKED_EVENT *linked_event;
563
564 /* lock down the guix event queue */
565 OSSemPend(guix_event_queue.lock_sem, 0, &guix_uc_err);
566
567 /* grab a free event slot */
568 if (!guix_event_queue.free)
569 {
570 /* there are no free events, return failure */
571 OSSemPost(guix_event_queue.lock_sem);
572 return GX_FAILURE;
573 }
574
575 linked_event = guix_event_queue.free;
576 guix_event_queue.free = guix_event_queue.free->next;
577
578 if (!guix_event_queue.free)
579 {
580 guix_event_queue.free_end = GX_NULL;
581 }
582
583 /* copy the event data into this slot */
584 linked_event -> event_data = *event_ptr;
585 linked_event -> next = GX_NULL;
586
587 /* insert this event into fifo queue */
588 if (guix_event_queue.last)
589 {
590 guix_event_queue.last -> next = linked_event;
591 }
592 else
593 {
594 guix_event_queue.first = linked_event;
595 }
596 guix_event_queue.last = linked_event;
597
598 /* Unlock the guix queue */
599 OSSemPost(guix_event_queue.lock_sem);
600
601 /* increment event count */
602 OSSemPost(guix_event_queue.count_sem);
603 return GX_SUCCESS;
604 }
605
606 /* event_fold: update existing matching event, otherwise post new event */
gx_generic_event_fold(GX_EVENT * event_ptr)607 UINT gx_generic_event_fold(GX_EVENT *event_ptr)
608 {
609 GUIX_LINKED_EVENT *pTest;
610
611 /* Lock down the guix queue */
612
613 OSSemPend(guix_event_queue.lock_sem, 0, &guix_uc_err);
614
615 // see if the same event is already in the queue:
616 pTest = guix_event_queue.first;
617
618 while (pTest)
619 {
620 if (pTest -> event_data.gx_event_type == event_ptr -> gx_event_type)
621 {
622 /* found matching event, update it and return */
623 pTest -> event_data.gx_event_payload.gx_event_ulongdata = event_ptr -> gx_event_payload.gx_event_ulongdata;
624 OSSemPost(guix_event_queue.lock_sem);
625 return GX_SUCCESS;
626 }
627 pTest = pTest -> next;
628 }
629
630 /* did not find a match, push new event */
631
632 OSSemPost(guix_event_queue.lock_sem);
633 gx_generic_event_post(event_ptr);
634 return GX_SUCCESS;
635 }
636
637
638 /* event_pop: pop oldest event from fifo queue, block if wait and no events exist */
gx_generic_event_pop(GX_EVENT * put_event,GX_BOOL wait)639 UINT gx_generic_event_pop(GX_EVENT *put_event, GX_BOOL wait)
640 {
641 if (!wait)
642 {
643 if (guix_event_queue.first == GX_NULL)
644 {
645 /* the queue is empty, just return */
646 OSSemPost(guix_event_queue.lock_sem);
647 return GX_FAILURE;
648 }
649 }
650
651 /* wait for an event to arrive in queue */
652 OSSemPend(guix_event_queue.count_sem, 0, &guix_uc_err);
653
654 /* lock down the queue */
655 OSSemPend(guix_event_queue.lock_sem, 0, &guix_uc_err);
656
657 /* copy the event into destination */
658 *put_event = guix_event_queue.first -> event_data;
659
660 /* link this event holder back into free list */
661 if (guix_event_queue.free_end)
662 {
663 guix_event_queue.free_end -> next = guix_event_queue.first;
664 }
665 else
666 {
667 guix_event_queue.free = guix_event_queue.first;
668 }
669
670 guix_event_queue.free_end = guix_event_queue.first;
671 guix_event_queue.first = guix_event_queue.first -> next;
672 guix_event_queue.free_end -> next = GX_NULL;
673
674 if (!guix_event_queue.first)
675 {
676 guix_event_queue.last = GX_NULL;
677 }
678
679 /* check for popping out a timer event */
680 if (put_event -> gx_event_type == GX_EVENT_TIMER)
681 {
682 guix_timer_event_pending = GX_FALSE;
683 }
684
685 /* unlock the queue */
686 OSSemPost(guix_event_queue.lock_sem);
687 return GX_SUCCESS;
688 }
689
690 /* event_purge: delete events targetted to particular widget */
gx_generic_event_purge(GX_WIDGET * target)691 VOID gx_generic_event_purge(GX_WIDGET *target)
692 {
693 GX_BOOL Purge;
694 GUIX_LINKED_EVENT *pTest;
695
696 /* Lock down the guix queue */
697
698 OSSemPend(guix_event_queue.lock_sem, 0, &guix_uc_err);
699
700 // look for events targetted to widget or widget children:
701 pTest = guix_event_queue.first;
702
703 while (pTest)
704 {
705 Purge = GX_FALSE;
706
707 if (pTest ->event_data.gx_event_target)
708 {
709 if (pTest -> event_data.gx_event_target == target)
710 {
711 Purge = GX_TRUE;
712 }
713 else
714 {
715 gx_widget_child_detect(target, pTest->event_data.gx_event_target, &Purge);
716 }
717 if (Purge)
718 {
719 pTest ->event_data.gx_event_target = GX_NULL;
720 pTest->event_data.gx_event_type = 0;
721 }
722 }
723 pTest = pTest -> next;
724 }
725
726 OSSemPost(guix_event_queue.lock_sem);
727 }
728
729 /* start the RTOS timer */
gx_generic_timer_start(VOID)730 VOID gx_generic_timer_start(VOID)
731 {
732 OSTaskResume(TIMER_TASK_PRIORITY);
733 }
734
735 /* stop the RTOS timer */
gx_generic_timer_stop(VOID)736 VOID gx_generic_timer_stop(VOID)
737 {
738 OSTaskSuspend(TIMER_TASK_PRIORITY);
739 }
740
741 /* lock the system protection mutex */
gx_generic_system_mutex_lock(VOID)742 VOID gx_generic_system_mutex_lock(VOID)
743 {
744 OSSemPend(guix_system_lock_semaphore, 0, &guix_uc_err);
745 }
746
747 /* unlock system protection mutex */
gx_generic_system_mutex_unlock(VOID)748 VOID gx_generic_system_mutex_unlock(VOID)
749 {
750 OSSemPost(guix_system_lock_semaphore);
751 }
752
753 /* return number of low-level system timer ticks. Used for pen speed caculations */
gx_generic_system_time_get(VOID)754 ULONG gx_generic_system_time_get(VOID)
755 {
756 return((ULONG)OSTimeGet());
757 }
758
759 /* thread_identify: return current thread identifier, cast as VOID * */
gx_generic_thread_identify(VOID)760 VOID *gx_generic_thread_identify(VOID)
761 {
762 return((VOID *)OSTCBCur);
763 }
764
765 /* a simple task to drive the GUIX timer mechanism */
guix_timer_task_entry(VOID * unused)766 VOID guix_timer_task_entry(VOID *unused)
767 {
768 int TickCount = OS_TICKS_PER_SEC / GX_TICKS_SECOND;
769
770 if (TickCount <= 0)
771 {
772 TickCount = 1;
773 }
774
775 while (1)
776 {
777 OSTimeDly(TickCount);
778
779 /* prevent sending timer events faster than they can be processed */
780 if (!guix_timer_event_pending)
781 {
782 guix_timer_event_pending = GX_TRUE;
783 _gx_system_timer_expiration(0);
784 }
785 }
786 }
787
gx_generic_time_delay(int ticks)788 VOID gx_generic_time_delay(int ticks)
789 {
790 OSTimeDly(ticks);
791 }
792
793
794 #endif /* Binding for UCOS-II enabled */
795
796 #endif /* if !ThreadX */
797
798
799