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