1st Fork

Dependencies:   mbed QEI DmTftLibrary

Revision:
20:626b92b70bf7
Child:
21:ab8027016a2c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Display/DisplayDriver.cpp	Thu Nov 08 10:14:39 2018 +0000
@@ -0,0 +1,467 @@
+/*
+  ______                              _
+ / _____)             _              | |
+( (____  _____ ____ _| |_ _____  ____| |__
+ \____ \| ___ |    (_   _) ___ |/ ___)  _ \
+ _____) ) ____| | | || |_| ____( (___| | | |
+(______/|_____)_|_|_| \__)_____)\____)_| |_|
+    (C)2016 Semtech
+
+Description: Display driver implementation
+
+Maintainer: Gregory Cristian & Gilbert Menth
+*/
+
+#include "mbed.h"
+#include "Eeprom.h"
+#include "DisplayDriver.h"
+#include "DmTftIli9341.h"
+#include "DmTouch.h"
+#include "DmTouchCalibration.h"
+
+
+//If DISPLAY_INVERT is defined as 1 then the display will be inverted from its native orientation
+#define DISPLAY_INVERT      1
+
+#define MAX_GO_STRING       30
+#define SPACE_ASCII         0x20
+#define FONT_WIDTH          8
+
+// DmTftIli9341( PinName cs, PinName dc, PinName mosi, PinName miso, PinName clk )
+// DM_TFT28_105
+DmTftIli9341 Tft( D10, D9, D11, D12, D13 );
+DmTouch Touch( DmTouch::DM_TFT28_105, D9, D11, D12 );
+DmTouchCalibration Calibration = DmTouchCalibration( &Tft, &Touch );
+
+/* 
+ * Used only to define pull-up on the CS lines
+ */
+DigitalInOut CsTouch( D4, PIN_OUTPUT, PullUp, 1 );
+DigitalInOut CsDisplay( D10, PIN_OUTPUT, PullUp, 1 );
+DigitalInOut CsSDCard( D8, PIN_OUTPUT, PullUp, 1 );
+DigitalInOut CsFlash( D6, PIN_OUTPUT, PullUp, 1 );
+
+MenuSettings_t MenuSettings;
+char GoTmpString[MAX_GO_STRING];
+
+
+static int BmpWidth;
+static int BmpHeight;
+static uint8_t BmpImageoffset;
+
+static bool BmpReadHeader( uint8_t *thisBmp );
+static uint16_t Read16( uint8_t *src );
+static uint32_t Read32( uint8_t *src );
+static void DrawBmpFromFlash( uint8_t *thisBmp, int x, int y );
+
+
+void DisplayDriverInit( void )
+{
+    Tft.init( );
+    Touch.init( );
+
+    DisplayDriverCalibrate( );
+    Tft.clearScreen( );
+
+    for( uint8_t i = 0; i < MAX_GO_STRING; i++) GoTmpString[i] = SPACE_ASCII;
+}
+
+// Calibrates the touch screen
+void DisplayDriverCalibrate( void )
+{
+    uint16_t x, y = 0;
+    bool touched = false;
+
+    if( Eeprom.EepromData.MenuSettings.ScreenCalibrated == false )
+    {
+        Tft.drawString( 5, 5, "Press and hold on cross" );
+        Tft.drawString( 5, 25, "until it turns green. " );
+
+        Point displayRefPoint[5];
+        Point touchRefPoint[5];
+
+        if( Calibration.getTouchReferencePoints( displayRefPoint, touchRefPoint,\
+            Tft.width( ), Tft.height( ) ) )
+        {
+            CalibrationMatrix calibrationMatrix = \
+                Calibration.calculateCalibrationMatrix( displayRefPoint, \
+                                                        touchRefPoint );
+
+            Touch.setCalibrationMatrix( calibrationMatrix );
+            Tft.clearScreen( );
+            Eeprom.EepromData.MenuSettings.Calibration.a = calibrationMatrix.a;
+            Eeprom.EepromData.MenuSettings.Calibration.b = calibrationMatrix.b;
+            Eeprom.EepromData.MenuSettings.Calibration.c = calibrationMatrix.c;
+            Eeprom.EepromData.MenuSettings.Calibration.d = calibrationMatrix.d;
+            Eeprom.EepromData.MenuSettings.Calibration.e = calibrationMatrix.e;
+            Eeprom.EepromData.MenuSettings.Calibration.f = calibrationMatrix.f;
+            Eeprom.EepromData.MenuSettings.ScreenCalibrated = true;
+            EepromSaveSettings( SCREEN_DATA );
+        }
+        else
+        {
+            Tft.clearScreen( );
+            Tft.drawString( 5, 5, "Calibration failed" );
+            Tft.drawString( 5, 25, "Please try again." );
+            delay( 2000 );
+            Tft.clearScreen( );
+            return;
+        }
+    }
+    else
+    {
+        Touch.setCalibrationMatrix( Eeprom.EepromData.MenuSettings.Calibration );
+        Tft.clearScreen( );
+    }
+
+    if( Touch.isTouched( ) )
+    {
+        Touch.readTouchData( x, y, touched );
+        Calibration.drawCalibPoint( x, y );
+    }
+}
+
+GraphObjectStatus_t GraphObjectDraw( GraphObject_t* goObject, uint8_t* source, \
+                                     bool doFill, bool activeTouch)
+{
+    GraphObjectStatus_t status = GO_STATUS_NOERR;
+    uint8_t maxChar;
+
+    if( goObject == NULL )
+    {
+        return GO_STATUS_BAD_ARG;
+    }
+    if( goObject->Xpos + goObject->Width > SCREEN_WIDTH )
+    {
+        return GO_STATUS_BAD_COORD;
+    }
+    if( goObject->Ypos + goObject->Height > SCREEN_HEIGHT )
+    {
+        return GO_STATUS_BAD_COORD;
+    }
+    switch( goObject->Type )
+    {
+        case GO_TEXT:
+            if( source == NULL )
+            {
+                status = GO_STATUS_BAD_ARG;
+            }
+            else
+            {
+                uint8_t i = 0;
+                uint8_t j = 0;
+                // max character in the object string
+                maxChar = goObject->Width / FONT_WIDTH;
+                Tft.setTextColor( goObject->BackColor, goObject->FrontColor );
+                for( i = 0; i < maxChar; i++)
+                {
+                    if( *source != 0 )
+                    {
+                        Tft.drawChar( goObject->Xpos + j, goObject->Ypos, \
+                                      ( char )*( source++ ), false );
+                        j += FONT_WIDTH;
+                    }
+                    else
+                    {
+                        Tft.drawChar( goObject->Xpos + ( FONT_WIDTH * i ), \
+                                      goObject->Ypos, SPACE_ASCII, false);
+                    }
+                }
+                goObject->TouchActive = activeTouch;
+            }
+            break;
+
+        case GO_RECTANGLE:
+            Tft.drawRectangle( goObject->Xpos, goObject->Ypos, goObject->Xpos + \
+                               goObject->Width - 1, goObject->Ypos + \
+                               goObject->Height - 1, goObject->FrontColor );
+            if( doFill )
+            {
+                Tft.fillRectangle( goObject->Xpos + 1, goObject->Ypos + 1, \
+                                   goObject->Xpos + goObject->Width - 2, \
+                                   goObject->Ypos + goObject->Height - 2, \
+                                   goObject->FillColor );
+            }
+            goObject->TouchActive = activeTouch;
+            break;
+
+        case GO_CIRCLE:
+            Tft.drawCircle( goObject->Xpos, goObject->Ypos, \
+                            ( goObject->Height < goObject->Width ) ? \
+                              ( goObject->Height / 2 ) : ( goObject->Width / 2 ), \
+                            goObject->FrontColor );
+            if( doFill )
+            {
+                Tft.fillCircle( goObject->Xpos, goObject->Ypos, \
+                                ( goObject->Height < goObject->Width ) ? \
+                                  ( goObject->Height / 2 ) - 1 : ( goObject->Width / 2 ) - 1, \
+                                goObject->FillColor );
+            }
+            goObject->TouchActive = activeTouch;
+            break;
+
+        case GO_TRIANGLE:
+            status = GO_STATUS_BAD_ARG;
+            break;
+
+        case GO_IMAGE:
+            if( source == NULL )
+            {
+                status = GO_STATUS_BAD_ARG;
+            }
+            else
+            {
+                if( BmpReadHeader( goObject->Source ) )
+                {
+                    DrawBmpFromFlash( goObject->Source, goObject->Xpos, \
+                                      goObject->Ypos );
+                }
+                else
+                {
+                    // draw a red rectangle with a line through, to show error
+                    Tft.drawRectangle( goObject->Xpos, goObject->Ypos, \
+                                       goObject->Xpos + goObject->Width - 1, \
+                                       goObject->Ypos + goObject->Height - 1, \
+                                       OBJECT_ERROR );
+                    Tft.drawLine( goObject->Xpos, goObject->Ypos, goObject->Xpos + \
+                                  goObject->Width - 1, goObject->Ypos + \
+                                  goObject->Height - 1, OBJECT_ERROR );
+                }
+                goObject->TouchActive = activeTouch;
+            }
+            break;
+
+        case GO_LINE:
+            Tft.drawLine( goObject->Xpos, goObject->Ypos, goObject->Xpos + \
+                                  goObject->Width - 1, goObject->Ypos + \
+                                  goObject->Height - 1, goObject->FrontColor );
+            break;
+
+        default:
+            status = GO_STATUS_BAD_ARG;
+    }
+    return status;
+}
+
+GraphObjectStatus_t GraphObjectClear( GraphObject_t* goObject, bool doFill )
+{
+    GraphObjectStatus_t status = GO_STATUS_NOERR;
+    uint8_t maxChar;
+
+    if( goObject == NULL )
+    {
+        return GO_STATUS_BAD_ARG;
+    }
+    if( goObject->Xpos + goObject->Width > SCREEN_WIDTH )
+    {
+        return GO_STATUS_BAD_COORD;
+    }
+    if( goObject->Ypos + goObject->Height > SCREEN_HEIGHT )
+    {
+        return GO_STATUS_BAD_COORD;
+    }
+    switch( goObject->Type )
+    {
+        case GO_TEXT:
+            // max character in the object string
+            maxChar = goObject->Width / FONT_WIDTH;
+            GoTmpString[maxChar] = NULL;
+            Tft.setTextColor( goObject->BackColor, goObject->FrontColor );
+            Tft.drawString( goObject->Xpos, goObject->Ypos, GoTmpString );
+            GoTmpString[maxChar] = SPACE_ASCII;
+            goObject->TouchActive = false;
+            break;
+
+        case GO_RECTANGLE:
+        case GO_IMAGE:
+            if( doFill )
+            {
+                Tft.fillRectangle( goObject->Xpos, goObject->Ypos, \
+                                   goObject->Xpos + goObject->Width - 1, \
+                                   goObject->Ypos + goObject->Height - 1, \
+                                   goObject->BackColor );
+            }
+            else
+            {
+                Tft.drawRectangle( goObject->Xpos, goObject->Ypos, goObject->Xpos + \
+                                   goObject->Width - 1, goObject->Ypos + \
+                                   goObject->Height - 1, goObject->BackColor );
+            }
+            goObject->TouchActive = false;
+            break;
+
+        case GO_CIRCLE:
+            if( doFill )
+            {
+                Tft.fillCircle( goObject->Xpos, goObject->Ypos, \
+                                ( goObject->Height < goObject->Width ) ? \
+                                  ( goObject->Height / 2 ) : ( goObject->Width / 2 ), \
+                                goObject->BackColor );
+            }
+            else
+            {
+                Tft.drawCircle( goObject->Xpos, goObject->Ypos, \
+                                ( goObject->Height < goObject->Width ) ? \
+                                  ( goObject->Height / 2 ) : ( goObject->Width / 2 ), \
+                                goObject->BackColor );
+            }
+            goObject->TouchActive = false;
+            break;
+
+        case GO_TRIANGLE:
+            status = GO_STATUS_BAD_ARG;
+            goObject->TouchActive = false;
+            break;
+
+        case GO_LINE:
+            Tft.drawLine( goObject->Xpos, goObject->Ypos, goObject->Xpos + \
+                                  goObject->Width - 1, goObject->Ypos + \
+                                  goObject->Height - 1, goObject->BackColor );
+            goObject->TouchActive = false;
+            break;
+
+        default:
+            status = GO_STATUS_BAD_ARG;
+    }
+    return status;
+}
+
+void DisplayDriverDrawLogo( uint8_t *thisBmp, uint8_t xPos, uint8_t yPos )
+{
+    if( BmpReadHeader( thisBmp ) )
+    {
+        DrawBmpFromFlash( thisBmp, xPos, yPos );
+    }
+}
+
+GraphObjectStatus_t GraphObjectTouched( GraphObject_t* objects, \
+                                        uint8_t objectsCount, \
+                                        uint8_t* touchedObject)
+{
+    uint8_t objScan;
+    uint16_t x, y = 0;
+    bool touched = false;
+    GraphObjectStatus_t status = GO_STATUS_BAD_COORD;
+
+    if( Touch.isTouched( ) )
+    {
+        Touch.readTouchData( x, y, touched );
+
+        if( touched == true )
+        {
+            for( objScan = 0; objScan < objectsCount; objScan++)
+            {
+                if( objects[objScan].TouchActive == true )
+                {
+                    if( ( y >= objects[objScan].Ypos ) && ( y <= ( objects[objScan].Ypos + objects[objScan].Height - 1 ) ) )
+                    {
+                        if( ( x >= objects[objScan].Xpos ) && ( x <= ( objects[objScan].Xpos + objects[objScan].Width - 1 ) ) )
+                        {
+                            *touchedObject = objects[objScan].Id;
+                            status = GO_STATUS_NOERR;
+                            break;      // return the first object match and no scan of other following objects
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    return status;
+}
+
+static bool BmpReadHeader( uint8_t *thisBmp )
+{
+    uint16_t pos = 0;
+
+    Read16( thisBmp );
+    if( Read16( thisBmp ) != 0x4D42 )
+    { // read magic byte
+        return false;
+    }
+    pos += 2;
+
+    // read file size
+    pos += 4;
+    pos += 4; // Skip creator bytes
+    BmpImageoffset = Read32( thisBmp + pos );
+    pos += 4;
+    // read DIB header
+    pos +=4;
+    BmpWidth = Read32( thisBmp + pos );
+    pos += 4;
+    BmpHeight = Read32( thisBmp + pos );
+    pos += 4;
+    if( Read16( thisBmp + pos ) != 1 )
+    {
+        // number of color planes must be 1
+        return false;
+    }
+    pos += 2;
+    pos += 2;
+    if( Read16( thisBmp + pos ) != 0 )
+    {
+        return false; // compression not supported!
+    }
+    pos += 2; // Should really be 2??
+    return true;
+}
+
+// LITTLE ENDIAN!
+static uint16_t Read16( uint8_t *src )
+{
+    uint16_t d;
+    uint8_t b;
+    b = *src;
+    d = *( src + 1 );
+    d <<= 8;
+    d |= b;
+    return d;
+}
+
+// LITTLE ENDIAN!
+static uint32_t Read32( uint8_t *src )
+{
+    uint32_t d;
+    uint16_t b;
+
+    b = Read16( src );
+    d = Read16( src + 2 );
+    d <<= 16;
+    d |= b;
+    return d;
+}
+
+static void DrawBmpFromFlash( uint8_t *thisBmp, int xPos, int yPos )
+{
+    uint16_t pos = BmpImageoffset;
+    uint16_t p;  // pixel
+    uint8_t g;
+    uint8_t b;
+    int i, j; // line, column
+
+    for( i = BmpHeight; i > 0; i-- )
+    {
+        for( j = 0; j < BmpWidth; j++ )
+        {
+            b = *( thisBmp + pos++ );
+            g = *( thisBmp + pos++ );
+            p = *( thisBmp + pos++ );
+
+            p >>= 3;
+            p <<= 6;
+
+            g >>= 2;
+            p |= g;
+            p <<= 5;
+
+            b >>= 3;
+            p |= b;
+
+            // write out the 16 bits of color
+            Tft.setPixel( j + xPos, i + yPos, p );
+        }
+        pos += 1;
+    }
+}
+