diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gos/chibios.c | 114 | ||||
-rw-r--r-- | src/gos/win32.c | 81 | ||||
-rw-r--r-- | src/gqueue/gqueue.c | 255 | ||||
-rw-r--r-- | src/gqueue/gqueue.mk | 1 | ||||
-rw-r--r-- | src/gwin/button.c | 4 | ||||
-rw-r--r-- | src/gwin/console.c | 201 |
6 files changed, 540 insertions, 116 deletions
diff --git a/src/gos/chibios.c b/src/gos/chibios.c index 6e63a2a4..7e369824 100644 --- a/src/gos/chibios.c +++ b/src/gos/chibios.c @@ -57,13 +57,14 @@ void gfxSleepMicroseconds(delaytime_t ms) { default: chThdSleepMicroseconds(ms); return; } } - void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit) { if (val > limit) val = limit; psem->limit = limit; chSemInit(&psem->sem, val); } - +void gfxSemDestroy(gfxSem *psem) { + chSemReset(&psem->sem, 1); +} bool_t gfxSemWait(gfxSem *psem, delaytime_t ms) { if (ms == TIME_INFINITE) { chSemWait(&psem->sem); @@ -85,115 +86,6 @@ void gfxSemSignalI(gfxSem *psem) { chSemSignalI(&psem->sem); } -void gfxQueueInit(gfxQueue *pqueue) { - pqueue->head = pqueue->tail = 0; - chSemInit(&pqueue->sem, 0); -} - -gfxQueueItem * gfxQueueGet(gfxQueue *pqueue, delaytime_t ms) { - gfxQueueItem *pi; - - chSysLock(); - /* If someone else is waiting or if the queue is empty - wait ourselves */ - if (pqueue->sem.s_cnt < 0 || !pqueue->head) { - if (chSemWaitTimeoutS(&pqueue->sem, ms == TIME_INFINITE ? TIME_INFINITE : MS2ST(ms)) == RDY_TIMEOUT) { - chSysUnlock(); - return NULL; - } - } - /* We can now get the head element */ - pi = pqueue->head; - pqueue->head = pi; - chSemSignalI(&pi->sem); - chSysUnlock(); - return pi; -} - -bool_t gfxQueuePut(gfxQueue *pqueue, gfxQueueItem *pitem, delaytime_t ms) { - chSemInit(&pitem->sem, 0); - chSysLock(); - pitem->next = 0; - if (!pqueue->head) { - pqueue->head = pqueue->tail = pitem; - } else { - pqueue->tail->next = pitem; - pqueue->tail = pitem; - } - /* Wake up someone who is waiting */ - if (chSemGetCounterI(&pqueue->sem) < 0) - chSemSignalI(&pqueue->sem); - chSysUnlock(); - return chSemWaitTimeout(&pitem->sem, ms == TIME_INFINITE ? TIME_INFINITE : MS2ST(ms)) != RDY_TIMEOUT; -} - -bool_t gfxQueuePush(gfxQueue *pqueue, gfxQueueItem *pitem, delaytime_t ms) { - chSemInit(&pitem->sem, 0); - chSysLock(); - pitem->next = pqueue->head; - pqueue->head = pitem; - if (!pitem->next) - pqueue->tail = pitem; - /* Wake up someone who is waiting */ - if (chSemGetCounterI(&pqueue->sem) < 0) - chSemSignalI(&pqueue->sem); - chSysUnlock(); - return chSemWaitTimeout(&pitem->sem, ms == TIME_INFINITE ? TIME_INFINITE : MS2ST(ms)) != RDY_TIMEOUT; -} - -void gfxQueueRemove(gfxQueue *pqueue, gfxQueueItem *pitem) { - gfxQueueItem *pi; - - chSysLock(); - if (pqueue->head) { - if (pqueue->head == pitem) { - pqueue->head = pitem->next; - chSemSignalI(&pitem->sem); - } else { - for(pi = pqueue->head; pi->next; pi = pi->next) { - if (pi->next == pitem) { - pi->next = pitem->next; - if (pqueue->tail == pitem) - pqueue->tail = pi; - chSemSignalI(&pitem->sem); - break; - } - } - } - } - chSysUnlock(); -} - -bool_t gfxQueueIsEmpty(gfxQueue *pqueue) { - return pqueue->head == NULL; -} - -bool_t gfxQueueIsIn(gfxQueue *pqueue, gfxQueueItem *pitem) { - gfxQueueItem *pi; - - chSysLock(); - for(pi = pqueue->head; pi; pi = pi->next) { - if (pi == pitem) { - chSysUnlock(); - return TRUE; - } - } - chSysUnlock(); - return FALSE; -} - -/** - * @brief Start a new thread. - * @return Return TRUE if the thread was started, FALSE on an error - * - * @param[in] stackarea A pointer to the area for the new threads stack or NULL to dynamically allocate it - * @param[in] stacksz The size of the thread stack. 0 means the default operating system size although this - * is only valid when stackarea is dynamically allocated. - * @param[in] prio The priority of the new thread - * @param[in] fn The function the new thread will run - * @param[in] param A parameter to pass the thread function. - * - * @api - */ bool_t gfxCreateThread(void *stackarea, size_t stacksz, threadpriority_t prio, gfxThreadFunction fn, void *param) { if (!stackarea) { if (!stacksz) stacksz = 256; diff --git a/src/gos/win32.c b/src/gos/win32.c index 6cf803a2..bda57f6f 100644 --- a/src/gos/win32.c +++ b/src/gos/win32.c @@ -26,7 +26,86 @@ #if GFX_USE_OS_WIN32 -#error "GOS: WIN32 not supported yet" +#include <stdio.h> + +static HANDLE SystemMutex; + +void _gosInit(void) { +} + +void gfxHalt(const char *msg) { + fprintf(stderr, "%s\n", msg); + ExitProcess(1); +} + +void gfxSleepMicroseconds(delaytime_t ms) { + static LARGE_INTEGER pcfreq; + static int initflag; + LARGE_INTEGER t1, t2, tdiff; + + switch(ms) { + case TIME_IMMEDIATE: return; + case TIME_INFINITE: while(1) Sleep(1000); return; + } + + if (!initflag) { + QueryPerformanceFrequency(&pcfreq); + initflag++; + } + tdiff.QuadPart = pcfreq.QuadPart * ms / 1000000; + + QueryPerformanceCounter(&t1); + do { + QueryPerformanceCounter(&t2); + } while (t2.QuadPart - t1.QuadPart < tdiff.QuadPart); +} + +void gfxSystemLock(void) { + if (!SystemMutex) + SystemMutex = CreateMutex(NULL, FALSE, NULL); + WaitForSingleObject(SystemMutex, INFINITE); +} + +void gfxSystemUnlock(void) { + ReleaseMutex(SystemMutex); +} + +bool_t gfxSemWait(gfxSem *psem, delaytime_t ms) { + return WaitForSingleObject(*psem, ms) == WAIT_OBJECT_0; +} + +typedef LONG __stdcall (*_NtQuerySemaphore)( + HANDLE SemaphoreHandle, + DWORD SemaphoreInformationClass, /* Would be SEMAPHORE_INFORMATION_CLASS */ + PVOID SemaphoreInformation, /* but this is to much to dump here */ + ULONG SemaphoreInformationLength, + PULONG ReturnLength OPTIONAL +); + +semcount_t gfxSemCounter(gfxSem *pSem) { + static _NtQuerySemaphore NtQuerySemaphore; + struct _SEMAPHORE_BASIC_INFORMATION { + ULONG CurrentCount; + ULONG MaximumCount; + } BasicInfo; + + if (!NtQuerySemaphore) + NtQuerySemaphore = (_NtQuerySemaphore)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySemaphore"); + + NtQuerySemaphore(*pSem, 0, &BasicInfo, sizeof(BasicInfo), NULL); + return BasicInfo.CurrentCount; +} + +bool_t gfxCreateThread(void *stackarea, size_t stacksz, threadpriority_t prio, gfxThreadFunction fn, void *param) { + (void) stackarea; + HANDLE thd; + + if (!(thd = CreateThread(NULL, stacksz, fn, param, CREATE_SUSPENDED, NULL))) + return FALSE; + SetThreadPriority(thd, prio); + ResumeThread(thd); + return TRUE; +} #endif /* GFX_USE_OS_WIN32 */ /** @} */ diff --git a/src/gqueue/gqueue.c b/src/gqueue/gqueue.c new file mode 100644 index 00000000..d515a425 --- /dev/null +++ b/src/gqueue/gqueue.c @@ -0,0 +1,255 @@ +/* + ChibiOS/GFX - Copyright (C) 2012, 2013 + Joel Bodenmann aka Tectu <joel@unormal.org> + + This file is part of ChibiOS/GFX. + + ChibiOS/GFX is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/GFX is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ +/** + * @file src/gqueue/gqueue.c + * @brief GQUEUE source file. + */ +#if GFX_USE_GQUEUE + +#if GQUEUE_NEED_ASYNC + void gfxQueueASyncInit(gfxQueueASync *pqueue) { + pqueue->head = pqueue->tail = 0; + } + gfxQueueASyncItem *gfxQueueASyncGet(gfxQueueASync *pqueue) { + gfxQueueASyncItem *pi; + + if (!pqueue->head) return 0; + gfxSystemLock(); + if ((pi = pqueue->head)) + pqueue->head = pi->next; + gfxSytemUnlock(); + return pi; + } + void gfxQueueASyncPut(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { + pitem->next = 0; + + gfxSystemLock(); + if (!pqueue->head) { + pqueue->head = pqueue->tail = pitem; + } else { + pqueue->tail->next = pitem; + pqueue->tail = pitem; + } + gfxSystemUnlock(); + } + void gfxQueueASyncPush(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { + gfxSystemLock(); + pitem->next = pqueue->head; + pqueue->head = pitem; + if (!pitem->next) + pqueue->tail = pitem; + gfxSystemUnlock(); + } + void gfxQueueASyncRemove(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { + if (!pitem) return; + gfxSystemLock(); + if (pqueue->head) { + if (pqueue->head == pitem) { + pqueue->head = pitem->next; + } else { + for(gfxQueueASyncItem *pi = pqueue->head; pi->next; pi = pi->next) { + if (pi->next == pitem) { + pi->next = pitem->next; + if (pqueue->tail == pitem) + pqueue->tail = pi; + break; + } + } + } + } + gfxSystemUnlock(); + } + bool_t gfxQueueASyncIsEmpty(gfxQueueASync *pqueue) { + return pqueue->head == NULL; + } + bool_t gfxQueueASyncIsIn(gfxQueueASync *pqueue, gfxQueueASyncItem *pitem) { + gfxSystemLock(); + for(gfxQueueASyncItem *pi = pqueue->head; pi; pi = pi->next) { + if (pi == pitem) { + gfxSystemUnlock(); + return TRUE; + } + } + gfxSystemUnlock(); + return FALSE; + } +#endif + +#if GQUEUE_NEED_GSYNC + void gfxQueueGSyncInit(gfxQueueGSync *pqueue) { + pqueue->head = pqueue->tail = 0; + gfxSemInit(&pqueue->sem, 0, MAX_SEMAPHORE_COUNT); + } + gfxQueueGSyncItem *gfxQueueGSyncGet(gfxQueueGSync *pqueue, delaytime_t ms) { + gfxQueueGSyncItem *pi; + + if (!gfxSemWait(&pqueue->sem, ms)) return 0; + gfxSystemLock(); + pi = pqueue->head; + pqueue->head = pi->next; + gfxSytemUnlock(); + return pi; + } + void gfxQueueGSyncPut(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { + pitem->next = 0; + + gfxSystemLock(); + if (!pqueue->head) { + pqueue->head = pqueue->tail = pitem; + } else { + pqueue->tail->next = pitem; + pqueue->tail = pitem; + } + gfxSystemUnlock(); + + gfxSemSignal(&pqueue->sem); + } + void gfxQueueGSyncPush(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { + gfxSystemLock(); + pitem->next = pqueue->head; + pqueue->head = pitem; + if (!pitem->next) + pqueue->tail = pitem; + gfxSystemUnlock(); + + gfxSemSignal(&pqueue->sem); + } + void gfxQueueGSyncRemove(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { + if (!pitem) return; + gfxSystemLock(); + if (pqueue->head) { + if (pqueue->head == pitem) { + pqueue->head = pitem->next; + } else { + for(gfxQueueGSyncItem *pi = pqueue->head; pi->next; pi = pi->next) { + if (pi->next == pitem) { + pi->next = pitem->next; + if (pqueue->tail == pitem) + pqueue->tail = pi; + break; + } + } + } + } + gfxSystemUnlock(); + } + bool_t gfxQueueGSyncIsEmpty(gfxQueueGSync *pqueue) { + return pqueue->head == NULL; + } + bool_t gfxQueueGSyncIsIn(gfxQueueGSync *pqueue, gfxQueueGSyncItem *pitem) { + gfxSystemLock(); + for(gfxQueueGSyncItem *pi = pqueue->head; pi; pi = pi->next) { + if (pi == pitem) { + gfxSystemUnlock(); + return TRUE; + } + } + gfxSystemUnlock(); + return FALSE; + } +#endif + +#if GQUEUE_NEED_FSYNC + void gfxQueueFSyncInit(gfxQueueFSync *pqueue) { + pqueue->head = pqueue->tail = 0; + gfxSemInit(&pqueue->sem, 0, MAX_SEMAPHORE_COUNT); + } + gfxQueueFSyncItem *gfxQueueFSyncGet(gfxQueueFSync *pqueue, delaytime_t ms) { + gfxQueueFSyncItem *pi; + + if (!gfxSemWait(&pqueue->sem, ms)) return 0; + gfxSystemLock(); + pi = pqueue->head; + pqueue->head = pi->next; + gfxSytemUnlock(); + + gfxSemSignalI(&pi->sem); + gfxSemDestroy(&pi->sem); + return pi; + } + bool_t gfxQueueFSyncPut(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms) { + gfxSemInit(&pitem->sem, 0, 1); + pitem->next = 0; + + gfxSystemLock(); + if (!pqueue->head) { + pqueue->head = pqueue->tail = pitem; + } else { + pqueue->tail->next = pitem; + pqueue->tail = pitem; + } + gfxSystemUnlock(); + + gfxSemSignal(&pqueue->sem); + return gfxSemWait(&pitem->sem, ms); + } + bool_t gfxQueueFSyncPush(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem, delaytime_t ms) { + gfxSemInit(&pitem->sem, 0, 1); + + gfxSystemLock(); + pitem->next = pqueue->head; + pqueue->head = pitem; + if (!pitem->next) + pqueue->tail = pitem; + gfxSystemUnlock(); + + gfxSemSignal(&pqueue->sem); + return gfxSemWait(&pitem->sem, ms); + } + void gfxQueueFSyncRemove(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem) { + if (!pitem) return; + gfxSystemLock(); + if (pqueue->head) { + if (pqueue->head == pitem) { + pqueue->head = pitem->next; + found: + gfxSystemUnlock(); + gfxSemSignal(&pitem->sem); + gfxSemDestroy(&pitem->sem); + return; + } + for(gfxQueueFSyncItem *pi = pqueue->head; pi->next; pi = pi->next) { + if (pi->next == pitem) { + pi->next = pitem->next; + if (pqueue->tail == pitem) + pqueue->tail = pi; + goto found; + } + } + } + gfxSystemUnlock(); + } + bool_t gfxQueueFSyncIsEmpty(gfxQueueFSync *pqueue) { + return pqueue->head == NULL; + } + bool_t gfxQueueFSyncIsIn(gfxQueueFSync *pqueue, gfxQueueFSyncItem *pitem) { + gfxSystemLock(); + for(gfxQueueFSyncItem *pi = pqueue->head; pi; pi = pi->next) { + if (pi == pitem) { + gfxSystemUnlock(); + return TRUE; + } + } + gfxSystemUnlock(); + return FALSE; + } +#endif + +#endif /* GFX_USE_GQUEUE */ diff --git a/src/gqueue/gqueue.mk b/src/gqueue/gqueue.mk new file mode 100644 index 00000000..ab8a0423 --- /dev/null +++ b/src/gqueue/gqueue.mk @@ -0,0 +1 @@ +GFXSRC += $(GFXLIB)/src/gqueue/gqueue.c diff --git a/src/gwin/button.c b/src/gwin/button.c index 19301698..cf5babc5 100644 --- a/src/gwin/button.c +++ b/src/gwin/button.c @@ -54,7 +54,7 @@ static void gwinButtonCallback(void *param, GEvent *pe) { #define pbe ((GEventGWinButton *)pe) // check if button is disabled - if (gh->enabled == false) + if (!gh->enabled) return; switch (pe->type) { @@ -150,7 +150,7 @@ GHandle gwinCreateButton(GButtonObject *gb, coord_t x, coord_t y, coord_t width, geventRegisterCallback(&gb->listener, gwinButtonCallback, gb); // buttons are enabled by default - gb->gwin.enabled = true; + gb->gwin.enabled = TRUE; return (GHandle)gb; } diff --git a/src/gwin/console.c b/src/gwin/console.c index a01ed79d..32e4f35a 100644 --- a/src/gwin/console.c +++ b/src/gwin/console.c @@ -30,7 +30,7 @@ * Stream interface implementation. The interface is write only */ -#if GFX_USE_OS_CHIBIOS +#if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM #define Stream2GWindow(ip) ((GHandle)(((char *)(ip)) - (size_t)(&(((GConsoleObject *)0)->stream)))) static size_t GWinStreamWrite(void *ip, const uint8_t *bp, size_t n) { gwinPutCharArray(Stream2GWindow(ip), (const char *)bp, n); return RDY_OK; } @@ -71,7 +71,7 @@ GHandle gwinCreateConsole(GConsoleObject *gc, coord_t x, coord_t y, coord_t widt return (GHandle)gc; } -#if GFX_USE_OS_CHIBIOS +#if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM BaseSequentialStream *gwinGetConsoleStream(GHandle gh) { if (gh->type != GW_CONSOLE) return 0; @@ -145,6 +145,203 @@ void gwinPutCharArray(GHandle gh, const char *str, size_t n) { gwinPutChar(gh, *str++); } +#include <stdarg.h> + +#define MAX_FILLER 11 +#define FLOAT_PRECISION 100000 + +static char *ltoa_wd(char *p, long num, unsigned radix, long divisor) { + int i; + char *q; + + if (!divisor) divisor = num; + + q = p + MAX_FILLER; + do { + i = (int)(num % radix); + i += '0'; + if (i > '9') + i += 'A' - '0' - 10; + *--q = i; + num /= radix; + } while ((divisor /= radix) != 0); + + i = (int)(p + MAX_FILLER - q); + do { + *p++ = *q++; + } while (--i); + + return p; +} + +#if GWIN_CONSOLE_USE_FLOAT + static char *ftoa(char *p, double num) { + long l; + unsigned long precision = FLOAT_PRECISION; + + l = num; + p = ltoa_wd(p, l, 10, 0); + *p++ = '.'; + l = (num - l) * precision; + return ltoa_wd(p, l, 10, precision / 10); + } +#endif + +void gwinPrintf(GHandle gh, const char *fmt, ...) { + va_list ap; + char *p, *s, c, filler; + int i, precision, width; + bool_t is_long, left_align; + long l; + #if CHPRINTF_USE_FLOAT + float f; + char tmpbuf[2*MAX_FILLER + 1]; + #else + char tmpbuf[MAX_FILLER + 1]; + #endif + + if (gh->type != GW_CONSOLE || !gh->font) return; + + va_start(ap, fmt); + while (TRUE) { + c = *fmt++; + if (c == 0) { + va_end(ap); + return; + } + if (c != '%') { + gwinPutChar(gh, c); + continue; + } + + p = tmpbuf; + s = tmpbuf; + left_align = FALSE; + if (*fmt == '-') { + fmt++; + left_align = TRUE; + } + filler = ' '; + if (*fmt == '.') { + fmt++; + filler = '0'; + } + width = 0; + + while (TRUE) { + c = *fmt++; + if (c >= '0' && c <= '9') + c -= '0'; + else if (c == '*') + c = va_arg(ap, int); + else + break; + width = width * 10 + c; + } + precision = 0; + if (c == '.') { + while (TRUE) { + c = *fmt++; + if (c >= '0' && c <= '9') + c -= '0'; + else if (c == '*') + c = va_arg(ap, int); + else + break; + precision = precision * 10 + c; + } + } + /* Long modifier.*/ + if (c == 'l' || c == 'L') { + is_long = TRUE; + if (*fmt) + c = *fmt++; + } + else + is_long = (c >= 'A') && (c <= 'Z'); + + /* Command decoding.*/ + switch (c) { + case 'c': + filler = ' '; + *p++ = va_arg(ap, int); + break; + case 's': + filler = ' '; + if ((s = va_arg(ap, char *)) == 0) + s = "(null)"; + if (precision == 0) + precision = 32767; + for (p = s; *p && (--precision >= 0); p++); + break; + case 'D': + case 'd': + if (is_long) + l = va_arg(ap, long); + else + l = va_arg(ap, int); + if (l < 0) { + *p++ = '-'; + l = -l; + } + p = ltoa_wd(p, l, 10, 0); + break; + #if CHPRINTF_USE_FLOAT + case 'f': + f = (float) va_arg(ap, double); + if (f < 0) { + *p++ = '-'; + f = -f; + } + p = ftoa(p, f); + break; + #endif + case 'X': + case 'x': + c = 16; + goto unsigned_common; + case 'U': + case 'u': + c = 10; + goto unsigned_common; + case 'O': + case 'o': + c = 8; + unsigned_common: + if (is_long) + l = va_arg(ap, long); + else + l = va_arg(ap, int); + p = ltoa_wd(p, l, c, 0); + break; + default: + *p++ = c; + break; + } + + i = (int)(p - s); + if ((width -= i) < 0) + width = 0; + if (left_align == FALSE) + width = -width; + if (width < 0) { + if (*s == '-' && filler == '0') { + gwinPutChar(gh, *s++); + i--; + } + do { + gwinPutChar(gh, filler); + } while (++width != 0); + } + while (--i >= 0) + gwinPutChar(gh, *s++); + while (width) { + gwinPutChar(gh, filler); + width--; + } + } +} + #endif /* GFX_USE_GWIN && GWIN_NEED_CONSOLE */ /** @} */ |