Wakeup Light with touch user interface, anti-aliased Font, SD card access and RTC usage on STM32F746NG-DISCO board

Dependencies:   BSP_DISCO_F746NG_patch_fixed LCD_DISCO_F746NG TS_DISCO_F746NG FATFileSystem TinyJpgDec_interwork mbed-src

Revision:
3:ecf7f1f8d749
Parent:
2:80026d18fcf3
Child:
5:13c70bcde7f6
--- a/UI.cpp	Thu Oct 29 12:59:54 2015 +0000
+++ b/UI.cpp	Thu Oct 29 18:09:31 2015 +0000
@@ -1,6 +1,6 @@
 #include "WakeupLight.h"
 
-#define CLIENT_COLOR_BG         ((uint32_t)0xFF602020)
+#define CLIENT_COLOR_BG         ((uint32_t)0xFF000000)
 #define CLIENT_COLOR_FG         ((uint32_t)0xFFD0D0D0)
 
 #define HEADER_HEIGHT           25
@@ -12,10 +12,25 @@
 
 #define COLOR_BG                ((uint32_t)0xFF000000)
 
+#define MAX_BOXES_PER_LINE      3
+#define BOX_SPACING             10
+#define BOX_TEXT_SPACING        10
+#define BOX_COLOR_BG            ((uint32_t)0xFF808080)
+#define BOX_COLOR_FG            CLIENT_COLOR_FG
+
 LCD_DISCO_F746NG                uiLcd;
 TS_DISCO_F746NG                 uiTs;
-int32_t                         uiCounter=0;
+uint16_t                        uiLastTouchX;
+uint16_t                        uiLastTouchY;
 UI_STRUCT                       *uiCurrent=NULL;
+UI_STRUCT                       uiClock;
+UI_STRUCT                       uiClockInWords;
+UI_STRUCT                       uiWakeup;
+UI_STRUCT                       uiMain;
+UI_BOX_LIST_ITEM_STRUCT         uiMainItems[]=
+{
+    { "Clock" }, { "Clock\nWith Words" }, { "Adjust\nTimers" }, { "Lights On" }, { "Lights Off" }
+};
 
 //
 // helper function
@@ -26,6 +41,33 @@
     uiLcd.FillRect(0,HEADER_HEIGHT,uiLcd.GetXSize()-1,uiLcd.GetYSize()-1);
 }
 
+void UI_ShowDisplayText(int16_t x,int16_t y,char *text)
+{
+    int16_t             xStart;
+    int16_t             charWidth;
+    int16_t             charHeight;
+
+    xStart=x;
+    charHeight=uiLcd.GetFont()->Height+3;
+    charWidth=uiLcd.GetFont()->Width;
+    
+    while ((*text)!='\0')
+    {
+        if ((*text)=='\n')
+        {
+            y+=charHeight;
+            x=xStart;
+        }
+        else
+        {
+            uiLcd.DisplayChar(x,y,*text);
+            x+=charWidth;
+        }
+
+        text++;
+    }
+}
+    
 //
 // box list
 //
@@ -33,14 +75,81 @@
 {
     if (initial==true)
     {
+        int8_t          lines;
+        int8_t          columns;
+        int8_t          box;
+        int16_t         width;
+        int16_t         height;
+        int16_t         startX;
+        int16_t         startY;
+
         // fill background
         UI_ShowClearClientRect();
-    }
+
+        // paint boxes
+        if (uiCurrent->data.boxList.count<=MAX_BOXES_PER_LINE)
+            lines=1;
+        else
+            lines=2;
+
+        columns=((uiCurrent->data.boxList.count + (lines-1)) / lines);
+
+        width=(uiLcd.GetXSize() - BOX_SPACING) / columns;
+        height=(uiLcd.GetYSize() - HEADER_HEIGHT - BOX_SPACING) / lines;
+
+        for (box=0;box<uiCurrent->data.boxList.count;box++)
+        {
+            startX=BOX_SPACING+(width*(box % columns));
+            startY=HEADER_HEIGHT+BOX_SPACING+(height*(box/columns));
+
+            // paint box background
+            uiLcd.SetTextColor(BOX_COLOR_BG);
+            uiLcd.FillRect(startX,startY,width-BOX_SPACING,height-BOX_SPACING);
+            
+            // paint box text
+            uiLcd.SetFont(&display_font_12x22);
+            uiLcd.SetBackColor(BOX_COLOR_BG);
+            uiLcd.SetTextColor(BOX_COLOR_FG);
+            UI_ShowDisplayText(startX+BOX_TEXT_SPACING,startY+BOX_TEXT_SPACING,uiCurrent->data.boxList.items[box].name);
+        }
+      }
 }
 
 void UI_ClickBoxList(uint16_t x,uint16_t y)
 {
-    // detect at which block was clicked
+    int8_t          lines;
+    int8_t          columns;
+    int8_t          box;
+    int16_t         width;
+    int16_t         height;
+    int16_t         startX;
+    int16_t         startY;
+
+    // detect at which box was clicked
+    if (uiCurrent->data.boxList.count<=MAX_BOXES_PER_LINE)
+        lines=1;
+    else
+        lines=2;
+
+    columns=((uiCurrent->data.boxList.count + (lines-1)) / lines);
+
+    width=(uiLcd.GetXSize() - BOX_SPACING) / columns;
+    height=(uiLcd.GetYSize() - HEADER_HEIGHT - BOX_SPACING) / lines;
+
+    for (box=0;box<uiCurrent->data.boxList.count;box++)
+    {
+        startX=BOX_SPACING+(width*(box % columns));
+        startY=HEADER_HEIGHT+BOX_SPACING+(height*(box/columns));
+
+        if (        (x>=startX) && (x<(startX+width-BOX_SPACING))
+                &&
+                    (y>=startY) && (y<(startY+height-BOX_SPACING))
+           )
+        {
+            uiCurrent->handler(UR_CLICK,box,uiCurrent);
+            break;
+        }
+    }
 }
 
 //
@@ -57,7 +166,12 @@
 
 void UI_ClickMessageBox(uint16_t x,uint16_t y)
 {
+    uint32_t                    index;
+
     // detect at which button was clicked
+    index=0;
+
+    uiCurrent->handler(UR_CLICK,index,uiCurrent);
 }
 
 //
@@ -66,6 +180,8 @@
 void UI_ShowClock(bool initial)
 {
     char                        buffer[100];
+    struct tm                   *tmStruct;
+    time_t                      timeValue;
 
     if (initial==true)
     {
@@ -78,14 +194,16 @@
     uiLcd.SetFont(&display_font_12x22);
     uiLcd.SetBackColor(CLOCK_COLOR_BG);
     uiLcd.SetTextColor(CLOCK_COLOR_FG);
-    snprintf(buffer,sizeof(buffer),"ABC %u",uiCounter);
-    uiCounter++;
+    timeValue=time(NULL);
+    tmStruct=localtime(&timeValue);
+    snprintf(buffer,sizeof(buffer),"%u:%02u:%02u",tmStruct->tm_hour,tmStruct->tm_min,tmStruct->tm_sec);
     uiLcd.DisplayStringAt(0,100,(uint8_t *)buffer,CENTER_MODE);
 }
 
 void UI_ClickClock(uint16_t x,uint16_t y)
 {
     // exit view
+    UI_Show(&uiMain);
 }
 
 //
@@ -122,6 +240,7 @@
 void UI_ClickClockInWords(uint16_t x,uint16_t y)
 {
     // exit view
+    UI_Show(&uiMain);
 }
 
 //
@@ -138,7 +257,12 @@
 
 void UI_ClickTimerAdjust(uint16_t x,uint16_t y)
 {
+    uint32_t                    index;
+
     // detect at which button was clicked
+    index=0;
+
+    uiCurrent->handler(UR_CLICK,index,uiCurrent);
 }
 
 //
@@ -148,6 +272,9 @@
 {
     uiCurrent=NULL;
 
+    uiLastTouchX=0;
+    uiLastTouchY=0;
+
     uiLcd.Init();
     uiLcd.Clear(COLOR_BG);
 
@@ -155,11 +282,27 @@
         DPrintf("UI_Init: Size: %ux%u.\r\n",uiLcd.GetXSize(),uiLcd.GetYSize());
     else
         DPrintf("UI_Init: Can't init touch screen.\r\n");
+
+    // setup ui structs
+    uiClock.flags=UI_FLAG_TYPE_CLOCK;
+    uiClock.handler=NULL;
+    uiClockInWords.flags=UI_FLAG_TYPE_CLOCK_IN_WORDS;
+    uiClockInWords.handler=NULL;
+    uiWakeup.flags=UI_FLAG_TYPE_BOX_LIST;
+    uiWakeup.handler=UI_WakeupHandler;
+    uiMain.flags=UI_FLAG_TYPE_BOX_LIST;
+    uiMain.handler=UI_MainHandler;
+    uiMain.data.boxList.items=uiMainItems;
+    uiMain.data.boxList.count=COUNT_OF(uiMainItems);
+
+    UI_Show(&uiMain);
 }
 
 void UI_ShowChrome(bool initial)
 {
     char                        buffer[100];
+    struct tm                   *tmStruct;
+    time_t                      timeValue;
 
     if (initial==true)
     {
@@ -172,48 +315,61 @@
     uiLcd.SetFont(&display_font_12x22);
     uiLcd.SetBackColor(HEADER_COLOR_BG);
     uiLcd.SetTextColor(HEADER_COLOR_FG);
-    snprintf(buffer,sizeof(buffer),"ABC %u",uiCounter);
-    uiCounter++;
+    timeValue=time(NULL);
+    tmStruct=localtime(&timeValue);
+    snprintf(buffer,sizeof(buffer),"%u:%02u",tmStruct->tm_hour,tmStruct->tm_min);
     uiLcd.DisplayStringAt(0,3,(uint8_t *)buffer,CENTER_MODE);
 
     // show next alarm
+    //XXX
 }
 
 void UI_Update(bool initial)
 {
+    uint8_t     typeFlag;
+
     if ((uiCurrent->flags & UI_FLAG_NEEDS_CHROME)!=0)
         UI_ShowChrome(initial);
 
-    if ((uiCurrent->flags & UI_FLAG_TYPE_BOX_LIST)!=0)
+    typeFlag=uiCurrent->flags & ~UI_FLAG_NEEDS_CHROME;
+    if ((typeFlag & UI_FLAG_TYPE_BOX_LIST)!=0)
         UI_ShowBoxList(initial);
-    else if ((uiCurrent->flags & UI_FLAG_TYPE_MESSAGE_BOX)!=0)
+    else if ((typeFlag & UI_FLAG_TYPE_MESSAGE_BOX)!=0)
         UI_ShowMessageBox(initial);
-    else if ((uiCurrent->flags & UI_FLAG_TYPE_CLOCK)!=0)
+    else if ((typeFlag & UI_FLAG_TYPE_CLOCK)!=0)
         UI_ShowClock(initial);
-    else if ((uiCurrent->flags & UI_FLAG_TYPE_CLOCK_IN_WORDS)!=0)
+    else if ((typeFlag & UI_FLAG_TYPE_CLOCK_IN_WORDS)!=0)
         UI_ShowClockInWords(initial);
-    else if ((uiCurrent->flags & UI_FLAG_TYPE_TIMER_ADJUST)!=0)
+    else if ((typeFlag & UI_FLAG_TYPE_TIMER_ADJUST)!=0)
         UI_ShowTimerAdjust(initial);
 }
 
 void UI_Show(UI_STRUCT *ui)
 {
+    DPrintf("UI_Show: 0x%X.\r\n",ui->flags);
+
     uiCurrent=ui;
 
+    if (uiCurrent->handler!=NULL)
+        uiCurrent->handler(UR_SHOW,0,uiCurrent);
+
     UI_Update(true);
 }
 
 void UI_Click(uint16_t x,uint16_t y)
 {
-    if ((uiCurrent->flags & UI_FLAG_TYPE_BOX_LIST)!=0)
+    uint8_t     typeFlag;
+
+    typeFlag=uiCurrent->flags & ~UI_FLAG_NEEDS_CHROME;
+    if ((typeFlag & UI_FLAG_TYPE_BOX_LIST)!=0)
         UI_ClickBoxList(x,y);
-    else if ((uiCurrent->flags & UI_FLAG_TYPE_MESSAGE_BOX)!=0)
+    else if ((typeFlag & UI_FLAG_TYPE_MESSAGE_BOX)!=0)
         UI_ClickMessageBox(x,y);
-    else if ((uiCurrent->flags & UI_FLAG_TYPE_CLOCK)!=0)
+    else if ((typeFlag & UI_FLAG_TYPE_CLOCK)!=0)
         UI_ClickClock(x,y);
-    else if ((uiCurrent->flags & UI_FLAG_TYPE_CLOCK_IN_WORDS)!=0)
+    else if ((typeFlag & UI_FLAG_TYPE_CLOCK_IN_WORDS)!=0)
         UI_ClickClockInWords(x,y);
-    else if ((uiCurrent->flags & UI_FLAG_TYPE_TIMER_ADJUST)!=0)
+    else if ((typeFlag & UI_FLAG_TYPE_TIMER_ADJUST)!=0)
         UI_ClickTimerAdjust(x,y);
 }
 
@@ -224,10 +380,26 @@
     uiTs.GetState(&tsState);
     if (tsState.touchDetected>0)
     {
-        DPrintf("UI_Poll: #%u - %ux%u.\r\n",tsState.touchDetected,tsState.touchX[0],tsState.touchY[0]);
-        UI_Click(tsState.touchX[0],tsState.touchY[0]);
+        if (        (ABS(uiLastTouchX-tsState.touchX[0])>4)
+                ||
+                    (ABS(uiLastTouchY-tsState.touchY[0])>4)
+           )
+        {
+            DPrintf("UI_Poll: #%u - %ux%u.\r\n",tsState.touchDetected,tsState.touchX[0],tsState.touchY[0]);
+
+            uiLastTouchX=tsState.touchX[0];
+            uiLastTouchY=tsState.touchY[0];
+    
+            if (uiCurrent!=NULL)
+                UI_Click(tsState.touchX[0],tsState.touchY[0]);
+        }
     }
   
     if (uiCurrent!=NULL)
+    {
+        if (uiCurrent->handler!=NULL)
+            uiCurrent->handler(UR_TIMER,0,uiCurrent);
+
         UI_Update(false);
+    }
 }