/** * @function GUI_DBG_Task * @brief debug display task * @param none * @return none */ void GUI_DBG_Task(void) { gui_font_t font; #define DEBUG_STR 50 char str[DEBUG_STR]; if(bDispMem) { /*display every 1s*/ if(IsTimerElapsed(tmDisp)) { /*save current user font*/ font = GetCurrentFont(); /*configure P2D*/ P2D_SetDisplayMode(DISPLAY_SOLID); P2D_SetClip(NULL); SetFont(G_FONT_DEFAULT); P2D_SetColors(COLOR_BLACK, COLOR_LIGHT_GREY); snprintf(str, DEBUG_STR, "MEM:%06d/%06dB CY:%04d", sallocGetUsed(), sallocGetTotal(), cycleCnt); /*display info*/ P2D_PutText(0, LCD_GetHeight() - P2D_GetTextHeight(), str); /*restore current user font*/ SetFont(font); tmDisp = GetPeriodicTimeout(1000); cycleCnt = 0; } cycleCnt++; } }
/** * @function main * @brief entry point * @param none * @return dummy */ int32_t main(void) { timer_t tmInit; UcInit(); /*uc init; shall be the first one*/ TicksInit(); /*software clock init*/ LCD_Init(); /*start the ILI932X*/ /* start a timer; backlight will be turned on once this timer will elapse * -> this avoids a white flash*/ tmInit = GetTimeout(120); P2D_Init(); GUI_Init(); TouchScreenCalib(NULL); TouchScreenEnable(); /*mount the file system*/ disk_initialize(0); f_mount(0, &Fatfs); /* wait the 120ms timeout */ while(IsTimerElapsed(tmInit) == false) DelayMs(1); BacklightInit(); /*set the main task*/ pCurrentTask = &SetupTask; /*main loop*/ while(1) { /*execute the main task, if any*/ if(pCurrentTask != NULL) pCurrentTask(); /*GUI task*/ GUI_DrawObjects(); GUI_DBG_Task(); /*software RTC task*/ RtcTask(); /*CPU limiter; reduces the power consumption*/ DelayMs(1); } /*never arrive here*/ return -1; }
void ArCom_Schedule(void) { static uint32 I = 0; // TODO if(IsTimerElapsed(1)) { uint32 elapsed = GetTimerElapsedMicroSeconds(); for (uint32 i=0; i<sArch.PduNbr; i++) { ArComPduType* Pdu = &(sArch.Pdu[i]); if( (Pdu->IsTxEnabled) && (Pdu->Period != 0) && (Pdu->Timer < Pdu->Period)) { Pdu->Timer += elapsed; } } StartTimer(); } for (; I<sArch.PduNbr; I++) { ArComPduType* Pdu = &(sArch.Pdu[I]); if( (Pdu->IsTxEnabled) && (Pdu->Period != 0) && (Pdu->Timer >= Pdu->Period)) // Elapsed Timer { Transmit(Pdu); Pdu->Timer = 0; // Reset it I++; break; // Each time, only transmit 1 item } } if(I >= sArch.PduNbr) { I = 0; } }
/** * @function GraphRefresh * @brief graph task; force refresh if timer has elapsed, read touch coords inside the graph * @param void *_g_obj: generic object * @param void *_obj: graph object * @return none */ static void GraphRefresh(void *_g_obj, void *_obj) { g_obj_st *g_obj; graph_st *graph; coord_t x, y, xt, yt; if(_g_obj != NULL && _obj != NULL) { graph = (graph_st*) _obj; g_obj = (g_obj_st *) _g_obj; /*timer elapsed? refresh graph*/ if(graph->refreshTime != 0 && IsTimerElapsed(graph->timer)) { graph->timer = GetPeriodicTimeout(graph->refreshTime); GUI_ObjSetNeedRefresh(g_obj, true); } /*read xt & yt if pressed*/ if(GUI_ObjIsPressed(g_obj) && GUI_ObjIsDisabled(g_obj) == false) { /*at this point, xt & yt are included in the object clip*/ GUI_ReadTouchScreen(&xt, &yt); x = xt - g_obj->rec.x; if(x < 0) x = 0; /*should not happen... robustness purpose*/ else if(x > g_obj->rec.w) x = g_obj->rec.w; y = (coord_t) g_obj->rec.h - (yt - g_obj->rec.y); if(y < 0) y = 0; /*should not happen... robustness purpose*/ else if(y > g_obj->rec.h) y = g_obj->rec.h; } else { x = y = -1; } graph->xt = x; graph->yt = y; } }
/** * @function GUI_DrawObjects * @brief handle all object (user event, refresh) * @param none * @return none */ void GUI_DrawObjects(void) { g_obj_st *ptr = NULL; coord_t newX, newY; /*reset signal & read touch screen; only once for all object*/ signal = 0; TouchScreenRead(&newX, &newY); /*small hysteresis to compensate touchscreen noise*/ #define TOUCH_THRES_HYS 2 if(newX < 0 || newY < 0) { x = y = -1; } else { if(x < 0 || y < 0) { x = newX; y = newY; } else if(P2D_Abs(newX - x) > TOUCH_THRES_HYS || P2D_Abs(newY - y) > TOUCH_THRES_HYS) { x = newX; y = newY; } } /*get the object list, according to the active layer*/ ptr = GetObjectList(); /*process notification blink*/ if(IsTimerElapsed(tmrBlink)) { bBlink = !bBlink; tmrBlink = GetPeriodicTimeout(500); while(ptr != NULL) { GUI_ObjSetBlink(ptr, bBlink); ptr = ptr->next; } } /*process each generic object of the current layer*/ while(ptr != NULL) { /*handle user interaction*/ HandleTouchEvent(x, y, ptr); /*handle object signals*/ HandleSignal(ptr); if(ptr->obj != NULL) { /*launch the object task, if any*/ if(ptr->task != NULL) ptr->task(ptr, ptr->obj); /*redraw the object, only if needed*/ if(GUI_ObjIsNeedRefresh(ptr) && ptr->draw != NULL) { P2D_SetClip(&(ptr->rec)); ptr->draw(ptr, ptr->obj); GUI_ObjSetNeedRefresh(ptr, false); } } /*next object*/ ptr = ptr->next; } /** * execute, if any, the top layer task * pInternalTask may close the top layer and return a signal; * when closing the top layer, pInternalTask becomes NULL * this signal will be given to the user at end of GUI_DrawObjects() */ if(pInternalTask != NULL) signal = pInternalTask(signal); /** * Save the last non null signal (for slave remote) */ if(signal != 0 && pInternalTask == NULL) { lastSignal = signal; } /** * execute the user task, if no internal task is running * DO NOT concate this condition with the previous one in a if/else statement ! */ if(pInternalTask == NULL) { if(pUserTask != NULL) pUserTask(signal); } }
/** * @function EntryTask * @brief user entry task; handles user interaction, ensures correct display (according to insert line position) * TODO: rewrite it, quite complex ><", even if it seems to work properly * @param void *_g_obj: generic object * @param void *_obj: frame object * @return none */ static void EntryTask(void *_g_obj, void *_obj) { g_obj_st *g_obj; usr_entry_st *entry; uint16_t selectedGlyph, len; coord_t xt, xMin, xMax; /*retrieve the entry object & its absolute coord, then deduce text coordinates*/ g_obj = (g_obj_st *) _g_obj; entry = (usr_entry_st*) _obj; SetFont(entry->font); /*ensure that the correct font is used for text coordinates calulus*/ GetTextCoords(&(g_obj->rec), &xMin, NULL, &xMax, NULL); /*gets text area coords*/ /** * 1) overall protection * may trig if the user modifies the buffer without using dedicated functions * in case, just reset display, & ensure the \0 terminaison */ len = gstrlen(entry->buffer); if(entry->len != len) { if(len > entry->sizeMax - 1) len = entry->sizeMax - 1; entry->len = len; entry->buffer[entry->len] = 0; entry->offsetDisplay = 0; entry->cursStart = 0; entry->cursStop = 0; entry->bPressed = false; GUI_ObjSetNeedRefresh(g_obj, true); } /** * 2) For insert mode only (no text selected, i.e. entry->cursStart == entry->cursStop) * always check if the insert line is not outside the current displayed text area. * may happen after an insertion / deletion (n.b. these functions always set NeedRefresh to true). * If outside, modify the offsetDisplay to make the insert line visible */ if(GUI_ObjIsNeedRefresh(g_obj) == true && entry->cursStart == entry->cursStop) { /** * the insert bar is out (left side); may happen if: * - <delete key> when the insert bar is at the left of the entry * - <replace / delete selection> when the text selection starts before the displayed text */ if(entry->cursStart < entry->offsetDisplay) { if(entry->cursStart > CAR_SHIFT) entry->offsetDisplay = entry->cursStart - CAR_SHIFT; else entry->offsetDisplay = 0; } /** * the insert bar "may" be out (right side); may happen if: * - <insert> when the insert bar is close to the right of the entry * - <insert buffer> inserting a big copy/paste text */ else { if(xMax < xMin + GetPartialStrWidth(entry->buffer, entry->offsetDisplay, entry->cursStart)) { if(entry->cursStart > CAR_SHIFT) entry->offsetDisplay = entry->cursStart - CAR_SHIFT; else entry->offsetDisplay = 0; } } } /** * 3) For text selection (i.e. entry->cursStart != entry->cursStop) * handle scroll & update the user selection */ else { if(GUI_ObjIsPressed(g_obj)) { /*finds the selectedGlyph #id which correspond to the x touchcreen*/ GUI_ReadTouchScreen(&xt, NULL); selectedGlyph = FindSelectedCar(entry->buffer, entry->offsetDisplay, xMin, xt); /*scroll text?*/ if(IsTimerElapsed(entry->tScroll)) { /*scroll to left?*/ if(xt < (xMin + SCROLL_TRIG) && entry->offsetDisplay > 0) { entry->offsetDisplay--; selectedGlyph--; } /*scroll to right*/ else if(xt > (xMax - SCROLL_TRIG) && entry->buffer[selectedGlyph] != 0) { entry->offsetDisplay++; selectedGlyph++; } entry->tScroll = GetPeriodicTimeout(SCROLL_TM); } /*if the entry wasn't previously pressed, start a new selection (i.e. cursStart = cursStop = selectedGlyph)*/ if(entry->bPressed == false) { entry->bPressed = true; entry->cursStart = selectedGlyph; entry->cursStop = selectedGlyph; GUI_ObjSetNeedRefresh(g_obj, true); } /*otherwise, update the current selection (i.e. update only cursStop)*/ else { if(entry->cursStop != selectedGlyph) { entry->cursStop = selectedGlyph; GUI_ObjSetNeedRefresh(g_obj, true); } } } else { entry->bPressed = false; } } /*check timer blink (for blinking the insert line)*/ if(IsTimerElapsed(entry->tBlink) && entry->bEditable == true) { entry->bBlink = !entry->bBlink; entry->tBlink = GetPeriodicTimeout(500); GUI_ObjSetNeedRefresh(g_obj, true); } }