LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { netPriv * priv; // Initialise the receiver thread (if it hasn't been done already) if (!hThread) { MUTEX_INIT; hThread = gfxThreadCreate(waNetThread, sizeof(waNetThread), HIGH_PRIORITY, NetThread, 0); gfxThreadClose(hThread); } // Only turn on mouse on the first window for now #if GINPUT_NEED_MOUSE if (!g->controllerdisplay) { mouseDisplay = g; g->flags |= GDISP_FLG_HASMOUSE; } #endif // Create a private area for this window if (!(priv = gfxAlloc(sizeof(netPriv)))) gfxHalt("GDISP: uGFXnet - Memory allocation failed"); memset(priv, 0, sizeof(netPriv)); g->priv = priv; g->board = 0; // no board interface for this controller // Initialise the GDISP structure g->g.Orientation = GDISP_ROTATE_0; g->g.Powermode = powerOn; g->g.Backlight = 100; g->g.Contrast = 50; g->g.Width = GDISP_SCREEN_WIDTH; g->g.Height = GDISP_SCREEN_HEIGHT; return TRUE; }
int main(void) { char* msg = "uGFX"; gfxInit(); /* Create a static thread from the default heap with normal priority. No parameter passed */ thd1 = gfxThreadCreate(NULL, 128, NORMAL_PRIORITY, Thread1_function, 0); /* Create a static thread from the default heap with normal priority. String parameter passed */ thd2 = gfxThreadCreate(NULL, 128, NORMAL_PRIORITY, Thread2_function, (void*)msg); while(TRUE) { gfxSleepMilliseconds(500); } }
void gtimerStart(GTimer *pt, GTimerFunction fn, void *param, bool_t periodic, delaytime_t millisec) { gfxMutexEnter(&mutex); // Start our thread if not already going if (!hThread) { hThread = gfxThreadCreate(waTimerThread, GTIMER_THREAD_WORKAREA_SIZE, GTIMER_THREAD_PRIORITY, GTimerThreadHandler, 0); if (hThread) {gfxThreadClose(hThread);} // We never really need the handle again } // Is this already scheduled? if (pt->flags & GTIMER_FLG_SCHEDULED) { // Cancel it! if (pt->next == pt) pTimerHead = 0; else { pt->next->prev = pt->prev; pt->prev->next = pt->next; if (pTimerHead == pt) pTimerHead = pt->next; } } // Set up the timer structure pt->fn = fn; pt->param = param; pt->flags = GTIMER_FLG_SCHEDULED; if (periodic) pt->flags |= GTIMER_FLG_PERIODIC; if (millisec == TIME_INFINITE) { pt->flags |= GTIMER_FLG_INFINITE; pt->period = TIME_INFINITE; } else { pt->period = gfxMillisecondsToTicks(millisec); pt->when = gfxSystemTicks() + pt->period; } // Just pop it on the end of the queue if (pTimerHead) { pt->next = pTimerHead; pt->prev = pTimerHead->prev; pt->prev->next = pt; pt->next->prev = pt; } else pt->next = pt->prev = pTimerHead = pt; // Bump the thread if (!(pt->flags & GTIMER_FLG_INFINITE)) gfxSemSignal(&waitsem); gfxMutexExit(&mutex); }
/** * Our main function. * There are two prototypes - one for systems with a command line and one for embedded systems without one. */ int main(proto_args) { uint16_t cmd[5]; unsigned cnt; // Initialize and clear the display gfxInit(); font = gdispOpenFont("UI2"); // Open the connection gdispDrawStringBox(0, 0, gdispGetWidth(), gdispGetHeight(), "Connecting to host...", font, White, justifyCenter); StartSockets(); netfd = doConnect(cmd_args); if (netfd == (SOCKET_TYPE)-1) gfxHalt("Could not connect to the specified server"); gdispClear(Black); // Get the initial packet from the host if (!getpkt(cmd, 2)) goto alldone; if (cmd[0] != GNETCODE_INIT || cmd[1] != GNETCODE_VERSION) gfxHalt("Oops - The protocol doesn't look like one we understand"); // Get the rest of the initial arguments if (!getpkt(cmd, 4)) goto alldone; // cmd[] = width, height, pixelformat, hasmouse // We will ignore size mismatches but the pixel format must match if (cmd[2] != GDISP_PIXELFORMAT) gfxHalt("Oops - The remote display is using a different pixel format to us.\nTry defining GDISP_PIXELFORMAT in your gfxconf.h file."); #if GFX_USE_GINPUT && GINPUT_NEED_MOUSE // Start the mouse thread if needed if (cmd[3]) gfxThreadClose(gfxThreadCreate(waNetThread, sizeof(waNetThread), HIGH_PRIORITY, NetThread, 0)); #endif // Process incoming instructions while(getpkt(cmd, 1)) { switch(cmd[0]) { case GNETCODE_FLUSH: gdispFlush(); break; case GNETCODE_PIXEL: if (!getpkt(cmd, 3)) goto alldone; // cmd[] = x, y, color gdispDrawPixel(cmd[0], cmd[1], cmd[2]); break; case GNETCODE_FILL: if (!getpkt(cmd, 5)) goto alldone; // cmd[] = x, y, cx, cy, color gdispFillArea(cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]); break; case GNETCODE_BLIT: if (!getpkt(cmd, 4)) goto alldone; // cmd[] = x, y, cx, cy - Followed by cx * cy pixels gdispStreamStart(cmd[0],cmd[1],cmd[2],cmd[3]); for(cnt = (unsigned)cmd[2] * cmd[3]; cnt; cnt--) { if (!getpkt(cmd, 1)) goto alldone; gdispStreamColor(cmd[0]); } gdispStreamStop(); break; #if GDISP_NEED_PIXELREAD case GNETCODE_READ: if (!getpkt(cmd, 2)) goto alldone; // cmd[] = x, y - Response is GNETCODE_READ,color cmd[1] = gdispGetPixelColor(cmd[0], cmd[1]); cmd[0] = GNETCODE_READ; if (!sendpkt(cmd, 2)) goto alldone; break; #endif #if GDISP_NEED_SCROLL case GNETCODE_SCROLL: if (!getpkt(cmd, 5)) goto alldone; // cmd[] = x, y, cx, cy, lines gdispVerticalScroll(cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], Black); break; #endif case GNETCODE_CONTROL: if (!getpkt(cmd, 2)) goto alldone; // cmd[] = what,data - Response is GNETCODE_CONTROL, 0x0000 (fail) or GNETCODE_CONTROL, 0x0001 (success) gdispControl(cmd[0], (void *)(unsigned)cmd[1]); switch(cmd[0]) { case GDISP_CONTROL_ORIENTATION: cmd[1] = (uint16_t)gdispGetOrientation() == cmd[1] ? 1 : 0; break; case GDISP_CONTROL_POWER: cmd[1] = (uint16_t)gdispGetPowerMode() == cmd[1] ? 1 : 0; break; case GDISP_CONTROL_BACKLIGHT: cmd[1] = (uint16_t)gdispGetBacklight() == cmd[1] ? 1 : 0; break; default: cmd[1] = 0; break; } cmd[0] = GNETCODE_CONTROL; if (!sendpkt(cmd, 2)) goto alldone; break; default: gfxHalt("Oops - The host has sent invalid commands"); break; } } alldone: closesocket(netfd); gfxHalt("Connection closed"); return 0; }
static DECLARE_THREAD_FUNCTION(visualizerThread, arg) { (void)arg; GListener event_listener; geventListenerInit(&event_listener); geventAttachSource(&event_listener, (GSourceHandle)¤t_status, 0); visualizer_keyboard_status_t initial_status = { .default_layer = 0xFFFFFFFF, .layer = 0xFFFFFFFF, .mods = 0xFF, .leds = 0xFFFFFFFF, .suspended = false, }; visualizer_state_t state = { .status = initial_status, .current_lcd_color = 0, #ifdef LCD_ENABLE .font_fixed5x8 = gdispOpenFont("fixed_5x8"), .font_dejavusansbold12 = gdispOpenFont("DejaVuSansBold12") #endif }; initialize_user_visualizer(&state); state.prev_lcd_color = state.current_lcd_color; #ifdef LCD_BACKLIGHT_ENABLE lcd_backlight_color( LCD_HUE(state.current_lcd_color), LCD_SAT(state.current_lcd_color), LCD_INT(state.current_lcd_color)); #endif systemticks_t sleep_time = TIME_INFINITE; systemticks_t current_time = gfxSystemTicks(); while(true) { systemticks_t new_time = gfxSystemTicks(); systemticks_t delta = new_time - current_time; current_time = new_time; bool enabled = visualizer_enabled; if (!same_status(&state.status, ¤t_status)) { if (visualizer_enabled) { if (current_status.suspended) { stop_all_keyframe_animations(); visualizer_enabled = false; state.status = current_status; user_visualizer_suspend(&state); } else { state.status = current_status; update_user_visualizer_state(&state); } state.prev_lcd_color = state.current_lcd_color; } } if (!enabled && state.status.suspended && current_status.suspended == false) { // Setting the status to the initial status will force an update // when the visualizer is enabled again state.status = initial_status; state.status.suspended = false; stop_all_keyframe_animations(); user_visualizer_resume(&state); state.prev_lcd_color = state.current_lcd_color; } sleep_time = TIME_INFINITE; for (int i=0;i<MAX_SIMULTANEOUS_ANIMATIONS;i++) { if (animations[i]) { update_keyframe_animation(animations[i], &state, delta, &sleep_time); } } #ifdef LED_ENABLE gdispGFlush(LED_DISPLAY); #endif #ifdef EMULATOR draw_emulator(); #endif // The animation can enable the visualizer // And we might need to update the state when that happens // so don't sleep if (enabled != visualizer_enabled) { sleep_time = 0; } systemticks_t after_update = gfxSystemTicks(); unsigned update_delta = after_update - current_time; if (sleep_time != TIME_INFINITE) { if (sleep_time > update_delta) { sleep_time -= update_delta; } else { sleep_time = 0; } } dprintf("Update took %d, last delta %d, sleep_time %d\n", update_delta, delta, sleep_time); #ifdef PROTOCOL_CHIBIOS // The gEventWait function really takes milliseconds, even if the documentation says ticks. // Unfortunately there's no generic ugfx conversion from system time to milliseconds, // so let's do it in a platform dependent way. // On windows the system ticks is the same as milliseconds anyway if (sleep_time != TIME_INFINITE) { sleep_time = ST2MS(sleep_time); } #endif geventEventWait(&event_listener, sleep_time); } #ifdef LCD_ENABLE gdispCloseFont(state.font_fixed5x8); gdispCloseFont(state.font_dejavusansbold12); #endif return 0; } void visualizer_init(void) { gfxInit(); #ifdef LCD_BACKLIGHT_ENABLE lcd_backlight_init(); #endif #ifdef SERIAL_LINK_ENABLE add_remote_objects(remote_objects, sizeof(remote_objects) / sizeof(remote_object_t*) ); #endif #ifdef LCD_ENABLE LCD_DISPLAY = get_lcd_display(); #endif #ifdef LED_ENABLE LED_DISPLAY = get_led_display(); #endif // We are using a low priority thread, the idea is to have it run only // when the main thread is sleeping during the matrix scanning gfxThreadCreate(visualizerThreadStack, sizeof(visualizerThreadStack), VISUALIZER_THREAD_PRIORITY, visualizerThread, NULL); } void update_status(bool changed) { if (changed) { GSourceListener* listener = geventGetSourceListener((GSourceHandle)¤t_status, NULL); if (listener) { geventSendEvent(listener); } } #ifdef SERIAL_LINK_ENABLE static systime_t last_update = 0; systime_t current_update = chVTGetSystemTimeX(); systime_t delta = current_update - last_update; if (changed || delta > MS2ST(10)) { last_update = current_update; visualizer_keyboard_status_t* r = begin_write_current_status(); *r = current_status; end_write_current_status(); } #endif } uint8_t visualizer_get_mods() { uint8_t mods = get_mods(); #ifndef NO_ACTION_ONESHOT if (!has_oneshot_mods_timed_out()) { mods |= get_oneshot_mods(); } #endif return mods; } void visualizer_update(uint32_t default_state, uint32_t state, uint8_t mods, uint32_t leds) { // Note that there's a small race condition here, the thread could read // a state where one of these are set but not the other. But this should // not really matter as it will be fixed during the next loop step. // Alternatively a mutex could be used instead of the volatile variables bool changed = false; #ifdef SERIAL_LINK_ENABLE if (is_serial_link_connected ()) { visualizer_keyboard_status_t* new_status = read_current_status(); if (new_status) { if (!same_status(¤t_status, new_status)) { changed = true; current_status = *new_status; } } } else { #else { #endif visualizer_keyboard_status_t new_status = { .layer = state, .default_layer = default_state, .mods = mods, .leds = leds, .suspended = current_status.suspended, }; if (!same_status(¤t_status, &new_status)) { changed = true; current_status = new_status; } } update_status(changed); } void visualizer_suspend(void) { current_status.suspended = true; update_status(true); } void visualizer_resume(void) { current_status.suspended = false; update_status(true); }
LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { XSizeHints *pSH; XSetWindowAttributes xa; XTextProperty WindowTitle; char * WindowTitleText; xPriv *priv; if (!initdone) { gfxThreadHandle hth; initdone = TRUE; #if GFX_USE_OS_LINUX || GFX_USE_OS_OSX XInitThreads(); #endif dis = XOpenDisplay(0); scr = DefaultScreen(dis); cxt = XUniqueContext(); wmDelete = XInternAtom(dis, "WM_DELETE_WINDOW", False); XSetIOErrorHandler(FatalXIOError); #if GDISP_FORCE_24BIT if (!XMatchVisualInfo(dis, scr, 24, TrueColor, &vis)) { fprintf(stderr, "Your display has no TrueColor mode\n"); XCloseDisplay(dis); return FALSE; } cmap = XCreateColormap(dis, RootWindow(dis, scr), vis.visual, AllocNone); #else vis.visual = CopyFromParent; vis.depth = DefaultDepth(dis, scr); cmap = DefaultColormap(dis, scr); #endif fprintf(stderr, "Running GFX Window in %d bit color\n", vis.depth); if (!(hth = gfxThreadCreate(waXThread, sizeof(waXThread), HIGH_PRIORITY, ThreadX, 0))) { fprintf(stderr, "Cannot start X Thread\n"); XCloseDisplay(dis); exit(0); } #if GFX_USE_OS_LINUX || GFX_USE_OS_OSX pthread_detach(hth); #endif gfxThreadClose(hth); } g->priv = gfxAlloc(sizeof(xPriv)); priv = (xPriv *)g->priv; g->board = 0; // No board interface for this driver xa.colormap = cmap; xa.border_pixel = 0xFFFFFF; xa.background_pixel = 0x000000; priv->win = XCreateWindow(dis, RootWindow(dis, scr), 16, 16, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT, 0, vis.depth, InputOutput, vis.visual, CWBackPixel|CWColormap|CWBorderPixel, &xa); XSync(dis, TRUE); XSaveContext(dis, priv->win, cxt, (XPointer)g); XSetWMProtocols(dis, priv->win, &wmDelete, 1); { char buf[132]; sprintf(buf, "uGFX - %u", g->systemdisplay+1); WindowTitleText = buf; XStringListToTextProperty(&WindowTitleText, 1, &WindowTitle); XSetWMName(dis, priv->win, &WindowTitle); XSetWMIconName(dis, priv->win, &WindowTitle); XSync(dis, TRUE); } pSH = XAllocSizeHints(); pSH->flags = PSize | PMinSize | PMaxSize; pSH->min_width = pSH->max_width = pSH->base_width = GDISP_SCREEN_WIDTH; pSH->min_height = pSH->max_height = pSH->base_height = GDISP_SCREEN_HEIGHT; XSetWMNormalHints(dis, priv->win, pSH); XFree(pSH); XSync(dis, TRUE); priv->pix = XCreatePixmap(dis, priv->win, GDISP_SCREEN_WIDTH, GDISP_SCREEN_HEIGHT, vis.depth); XSync(dis, TRUE); priv->gc = XCreateGC(dis, priv->win, 0, 0); XSetBackground(dis, priv->gc, BlackPixel(dis, scr)); XSync(dis, TRUE); // Create the associated mouse before the map #if GINPUT_NEED_MOUSE priv->mouse = (GMouse *)gdriverRegister((const GDriverVMT const *)GMOUSE_DRIVER_VMT, g); #endif XSelectInput(dis, priv->win, StructureNotifyMask); XMapWindow(dis, priv->win); // Wait for the window creation to complete (for safety) while(!(((volatile GDisplay *)g)->flags & GDISP_FLG_READY)) gfxSleepMilliseconds(100); /* Initialise the GDISP structure to match */ g->g.Orientation = GDISP_ROTATE_0; g->g.Powermode = powerOn; g->g.Backlight = 100; g->g.Contrast = 50; g->g.Width = GDISP_SCREEN_WIDTH; g->g.Height = GDISP_SCREEN_HEIGHT; return TRUE; }