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

UI.cpp

Committer:
the_sz
Date:
2015-10-29
Revision:
3:ecf7f1f8d749
Parent:
2:80026d18fcf3
Child:
5:13c70bcde7f6

File content as of revision 3:ecf7f1f8d749:

#include "WakeupLight.h"

#define CLIENT_COLOR_BG         ((uint32_t)0xFF000000)
#define CLIENT_COLOR_FG         ((uint32_t)0xFFD0D0D0)

#define HEADER_HEIGHT           25
#define HEADER_COLOR_BG         ((uint32_t)0xFF404040)
#define HEADER_COLOR_FG         ((uint32_t)0xFFD3D3D3)

#define CLOCK_COLOR_BG          ((uint32_t)0xFF000000)
#define CLOCK_COLOR_FG          ((uint32_t)0xFF707070)

#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;
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
//
void UI_ShowClearClientRect(void)
{
    uiLcd.SetTextColor(CLIENT_COLOR_BG);
    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
//
void UI_ShowBoxList(bool initial)
{
    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)
{
    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;
        }
    }
}

//
// message box
//
void UI_ShowMessageBox(bool initial)
{
    if (initial==true)
    {
        // fill background
        UI_ShowClearClientRect();
    }
}

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);
}

//
// clock
//
void UI_ShowClock(bool initial)
{
    char                        buffer[100];
    struct tm                   *tmStruct;
    time_t                      timeValue;

    if (initial==true)
    {
        // fill background
        uiLcd.SetTextColor(CLOCK_COLOR_BG);
        uiLcd.FillRect(0,0,uiLcd.GetXSize()-1,uiLcd.GetYSize()-1);
    }

    // show clock
    uiLcd.SetFont(&display_font_12x22);
    uiLcd.SetBackColor(CLOCK_COLOR_BG);
    uiLcd.SetTextColor(CLOCK_COLOR_FG);
    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);
}

//
// clock in words
//
void UI_ShowClockInWords(bool initial)
{
    if (initial==true)
    {
        // fill background
        UI_ShowClearClientRect();
    }

    // show clock in words
    uiLcd.SetFont(&display_font_12x22);
    uiLcd.SetBackColor(CLIENT_COLOR_BG);
    uiLcd.SetTextColor(CLIENT_COLOR_FG);
    uiLcd.DisplayStringAt(5,30,(uint8_t *)"UM F\x9ANF ZEHN VIERTEL HALB",LEFT_MODE);
    uiLcd.DisplayStringAt(5,60,(uint8_t *)"NACH VOR",LEFT_MODE);
    uiLcd.DisplayStringAt(5,90,(uint8_t *)"EINS ZWEI DREI VIER",LEFT_MODE);
    uiLcd.DisplayStringAt(5,120,(uint8_t *)"F\x9ANF SECHS SIEBEN ACHT",LEFT_MODE);
    uiLcd.DisplayStringAt(5,150,(uint8_t *)"NEUN ZEHN ELF ZW\x99LF",LEFT_MODE);

    // draw charset
    /*
    int x;
    for (x=0x80;x<=0xFF;x++)
    {
        uiLcd.DisplayChar(1+(((x-0x80) % 16)*14),30+(((x-0x80)/16)*20),x);
    }
    */
}

void UI_ClickClockInWords(uint16_t x,uint16_t y)
{
    // exit view
    UI_Show(&uiMain);
}

//
// timer adjust
//
void UI_ShowTimerAdjust(bool initial)
{
    if (initial==true)
    {
        // fill background
        UI_ShowClearClientRect();
    }
}

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);
}

//
// common
//
void UI_Init(void)
{
    uiCurrent=NULL;

    uiLastTouchX=0;
    uiLastTouchY=0;

    uiLcd.Init();
    uiLcd.Clear(COLOR_BG);

    if (uiTs.Init(uiLcd.GetXSize(),uiLcd.GetYSize())==TS_OK)
        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)
    {
        // fill background
        uiLcd.SetTextColor(HEADER_COLOR_BG);
        uiLcd.FillRect(0,0,uiLcd.GetXSize()-1,HEADER_HEIGHT);
    }

    // show clock
    uiLcd.SetFont(&display_font_12x22);
    uiLcd.SetBackColor(HEADER_COLOR_BG);
    uiLcd.SetTextColor(HEADER_COLOR_FG);
    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);

    typeFlag=uiCurrent->flags & ~UI_FLAG_NEEDS_CHROME;
    if ((typeFlag & UI_FLAG_TYPE_BOX_LIST)!=0)
        UI_ShowBoxList(initial);
    else if ((typeFlag & UI_FLAG_TYPE_MESSAGE_BOX)!=0)
        UI_ShowMessageBox(initial);
    else if ((typeFlag & UI_FLAG_TYPE_CLOCK)!=0)
        UI_ShowClock(initial);
    else if ((typeFlag & UI_FLAG_TYPE_CLOCK_IN_WORDS)!=0)
        UI_ShowClockInWords(initial);
    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)
{
    uint8_t     typeFlag;

    typeFlag=uiCurrent->flags & ~UI_FLAG_NEEDS_CHROME;
    if ((typeFlag & UI_FLAG_TYPE_BOX_LIST)!=0)
        UI_ClickBoxList(x,y);
    else if ((typeFlag & UI_FLAG_TYPE_MESSAGE_BOX)!=0)
        UI_ClickMessageBox(x,y);
    else if ((typeFlag & UI_FLAG_TYPE_CLOCK)!=0)
        UI_ClickClock(x,y);
    else if ((typeFlag & UI_FLAG_TYPE_CLOCK_IN_WORDS)!=0)
        UI_ClickClockInWords(x,y);
    else if ((typeFlag & UI_FLAG_TYPE_TIMER_ADJUST)!=0)
        UI_ClickTimerAdjust(x,y);
}

void UI_Poll(void)
{
    TS_StateTypeDef             tsState;

    uiTs.GetState(&tsState);
    if (tsState.touchDetected>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);
    }
}