Source code for the SX126xDVK1xAS Dev Kit. This example code has only been tested on the Nucleo L476RG

Dependencies:   mbed DmTftLibrary SX126xLib

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers DisplayDriver.cpp Source File

DisplayDriver.cpp

00001 /*
00002   ______                              _
00003  / _____)             _              | |
00004 ( (____  _____ ____ _| |_ _____  ____| |__
00005  \____ \| ___ |    (_   _) ___ |/ ___)  _ \
00006  _____) ) ____| | | || |_| ____( (___| | | |
00007 (______/|_____)_|_|_| \__)_____)\____)_| |_|
00008     (C)2016 Semtech
00009 
00010 Description: Display driver implementation
00011 
00012 Maintainer: Gregory Cristian & Gilbert Menth
00013 */
00014 
00015 #include "mbed.h"
00016 #include "Eeprom.h"
00017 #include "DisplayDriver.h"
00018 #include "DmTftIli9341.h"
00019 #include "DmTouch.h"
00020 #include "DmTouchCalibration.h"
00021 
00022 
00023 //If DISPLAY_INVERT is defined as 1 then the display will be inverted from its native orientation
00024 #define DISPLAY_INVERT      1
00025 
00026 #define MAX_GO_STRING       30
00027 #define SPACE_ASCII         0x20
00028 #define FONT_WIDTH          8
00029 
00030 // DmTftIli9341( PinName cs, PinName dc, PinName mosi, PinName miso, PinName clk )
00031 // DM_TFT28_105
00032 DmTftIli9341 Tft( D10, D9, D11, D12, D13 );
00033 DmTouch Touch( DmTouch::DM_TFT28_105, D9, D11, D12 );
00034 DmTouchCalibration Calibration = DmTouchCalibration( &Tft, &Touch );
00035 
00036 /* 
00037  * Used only to define pull-up on the CS lines
00038  */
00039 DigitalInOut CsTouch( D4, PIN_OUTPUT, PullUp, 1 );
00040 DigitalInOut CsDisplay( D10, PIN_OUTPUT, PullUp, 1 );
00041 DigitalInOut CsSDCard( D8, PIN_OUTPUT, PullUp, 1 );
00042 DigitalInOut CsFlash( D6, PIN_OUTPUT, PullUp, 1 );
00043 DigitalOut DebugPin( A3 );
00044 
00045 MenuSettings_t MenuSettings;
00046 char GoTmpString[MAX_GO_STRING];
00047 
00048 static int BmpWidth;
00049 static int BmpHeight;
00050 static uint8_t BmpImageoffset;
00051 
00052 
00053 static bool BmpReadHeader( uint8_t *thisBmp );
00054 static uint16_t Read16( uint8_t *src );
00055 static uint32_t Read32( uint8_t *src );
00056 static void DrawBmpFromFlash( uint8_t *thisBmp, int x, int y );
00057 
00058 
00059 void DisplayDriverInit( void )
00060 {
00061     Tft.init( );
00062     Touch.init( );
00063 
00064     DisplayDriverCalibrate( );
00065     Tft.clearScreen( );
00066     
00067     for( uint8_t i = 0; i < MAX_GO_STRING; i++) GoTmpString[i] = SPACE_ASCII;
00068 }
00069 
00070 // Calibrates the touch screen
00071 void DisplayDriverCalibrate( void )
00072 {
00073     uint16_t x, y = 0;
00074     bool touched = false;
00075     
00076     if( Eeprom.EepromData.MenuSettings.ScreenCalibrated == false ) 
00077     {
00078         Tft.drawString( 5, 5, "Press and hold on cross" );
00079         Tft.drawString( 5, 25, "until it turns green. " );
00080     
00081         Point displayRefPoint[5];
00082         Point touchRefPoint[5];
00083     
00084         if( Calibration.getTouchReferencePoints( displayRefPoint, touchRefPoint,\
00085             Tft.width( ), Tft.height( ) ) ) 
00086         {
00087             CalibrationMatrix calibrationMatrix = \
00088                 Calibration.calculateCalibrationMatrix( displayRefPoint, \
00089                                                         touchRefPoint );
00090 
00091             Touch.setCalibrationMatrix( calibrationMatrix );
00092             Tft.clearScreen( );
00093             Eeprom.EepromData.MenuSettings.Calibration.a = calibrationMatrix.a;
00094             Eeprom.EepromData.MenuSettings.Calibration.b = calibrationMatrix.b;
00095             Eeprom.EepromData.MenuSettings.Calibration.c = calibrationMatrix.c;
00096             Eeprom.EepromData.MenuSettings.Calibration.d = calibrationMatrix.d;
00097             Eeprom.EepromData.MenuSettings.Calibration.e = calibrationMatrix.e;
00098             Eeprom.EepromData.MenuSettings.Calibration.f = calibrationMatrix.f;
00099             Eeprom.EepromData.MenuSettings.ScreenCalibrated = true;
00100             EepromSaveSettings( SCREEN_DATA );
00101         } 
00102         else 
00103         {
00104             Tft.clearScreen( );
00105             Tft.drawString( 5, 5, "Calibration failed" );
00106             Tft.drawString( 5, 25, "Please try again." );
00107             delay( 2000 );
00108             Tft.clearScreen( );
00109             return;
00110         }
00111     }
00112     else
00113     {
00114         Touch.setCalibrationMatrix( Eeprom.EepromData.MenuSettings.Calibration );
00115         Tft.clearScreen( );
00116     }
00117   
00118     if( Touch.isTouched( ) ) 
00119     {
00120         Touch.readTouchData( x, y, touched );
00121         Calibration.drawCalibPoint( x, y );
00122     }
00123 } 
00124 
00125 GraphObjectStatus_t GraphObjectDraw( GraphObject_t* goObject, uint8_t* source, \
00126                                      bool doFill, bool activeTouch)
00127 {
00128     GraphObjectStatus_t status = GO_STATUS_NOERR;
00129     uint8_t maxChar;
00130 
00131     if( goObject == NULL )
00132     {
00133         return GO_STATUS_BAD_ARG;
00134     }
00135     if( goObject->Xpos + goObject->Width > SCREEN_WIDTH )
00136     {
00137         return GO_STATUS_BAD_COORD;
00138     }
00139     if( goObject->Ypos + goObject->Height > SCREEN_HEIGHT )
00140     {
00141         return GO_STATUS_BAD_COORD;
00142     }
00143     switch( goObject->Type )
00144     {
00145         case GO_TEXT:
00146             if( source == NULL )
00147             {
00148                 status = GO_STATUS_BAD_ARG;
00149             }
00150             else
00151             {
00152                 uint8_t i = 0;
00153                 uint8_t j = 0;
00154                 // max character in the object string
00155                 maxChar = goObject->Width / FONT_WIDTH;
00156                 Tft.setTextColor( goObject->BackColor, goObject->FrontColor );
00157                 for( i = 0; i < maxChar; i++)
00158                 {
00159                     if( *source != 0 )
00160                     {
00161                         Tft.drawChar( goObject->Xpos + j, goObject->Ypos, \
00162                                       ( char )*( source++ ), false );
00163                         j += FONT_WIDTH;
00164                     }
00165                     else
00166                     {
00167                         Tft.drawChar( goObject->Xpos + ( FONT_WIDTH * i ), \
00168                                       goObject->Ypos, SPACE_ASCII, false);
00169                     }
00170                 }
00171                 goObject->TouchActive = activeTouch;
00172             }
00173             break;
00174 
00175         case GO_RECTANGLE:
00176             Tft.drawRectangle( goObject->Xpos, goObject->Ypos, goObject->Xpos + \
00177                                goObject->Width - 1, goObject->Ypos + \
00178                                goObject->Height - 1, goObject->FrontColor );
00179             if( doFill )
00180             {
00181                 Tft.fillRectangle( goObject->Xpos + 1, goObject->Ypos + 1, \
00182                                    goObject->Xpos + goObject->Width - 2, \
00183                                    goObject->Ypos + goObject->Height - 2, \
00184                                    goObject->FillColor );
00185             }
00186             goObject->TouchActive = activeTouch;
00187             break;
00188 
00189         case GO_CIRCLE:
00190             Tft.drawCircle( goObject->Xpos, goObject->Ypos, \
00191                             ( goObject->Height < goObject->Width ) ? \
00192                               ( goObject->Height / 2 ) : ( goObject->Width / 2 ), \
00193                             goObject->FrontColor );
00194             if( doFill )
00195             {
00196                 Tft.fillCircle( goObject->Xpos, goObject->Ypos, \
00197                                 ( goObject->Height < goObject->Width ) ? \
00198                                   ( goObject->Height / 2 ) - 1 : ( goObject->Width / 2 ) - 1, \
00199                                 goObject->FillColor );
00200             }
00201             goObject->TouchActive = activeTouch;
00202             break;
00203 
00204         case GO_TRIANGLE:
00205             status = GO_STATUS_BAD_ARG;
00206             break;
00207 
00208         case GO_IMAGE:
00209             if( source == NULL )
00210             {
00211                 status = GO_STATUS_BAD_ARG;
00212             }
00213             else
00214             {
00215                 if( BmpReadHeader( goObject->Source ) ) 
00216                 {
00217                     DrawBmpFromFlash( goObject->Source, goObject->Xpos, \
00218                                       goObject->Ypos );
00219                 }
00220                 else
00221                 {
00222                     // draw a red rectangle with a line through, to show error
00223                     Tft.drawRectangle( goObject->Xpos, goObject->Ypos, \
00224                                        goObject->Xpos + goObject->Width - 1, \
00225                                        goObject->Ypos + goObject->Height - 1, \
00226                                        OBJECT_ERROR );
00227                     Tft.drawLine( goObject->Xpos, goObject->Ypos, goObject->Xpos + \
00228                                   goObject->Width - 1, goObject->Ypos + \
00229                                   goObject->Height - 1, OBJECT_ERROR );
00230                 }
00231                 goObject->TouchActive = activeTouch;
00232             }
00233             break;
00234 
00235         case GO_LINE:
00236             Tft.drawLine( goObject->Xpos, goObject->Ypos, goObject->Xpos + \
00237                                   goObject->Width - 1, goObject->Ypos + \
00238                                   goObject->Height - 1, goObject->FrontColor );
00239             break;
00240 
00241         default:
00242             status = GO_STATUS_BAD_ARG;
00243     }
00244     return status;
00245 }
00246 
00247 GraphObjectStatus_t GraphObjectClear( GraphObject_t* goObject, bool doFill )
00248 {
00249     GraphObjectStatus_t status = GO_STATUS_NOERR;
00250     uint8_t maxChar;
00251 
00252     if( goObject == NULL )
00253     {
00254         return GO_STATUS_BAD_ARG;
00255     }
00256     if( goObject->Xpos + goObject->Width > SCREEN_WIDTH )
00257     {
00258         return GO_STATUS_BAD_COORD;
00259     }
00260     if( goObject->Ypos + goObject->Height > SCREEN_HEIGHT )
00261     {
00262         return GO_STATUS_BAD_COORD;
00263     }
00264     switch( goObject->Type )
00265     {
00266         case GO_TEXT:
00267             // max character in the object string
00268             maxChar = goObject->Width / FONT_WIDTH;
00269             GoTmpString[maxChar] = NULL;
00270             Tft.setTextColor( goObject->BackColor, goObject->FrontColor );
00271             Tft.drawString( goObject->Xpos, goObject->Ypos, GoTmpString );
00272             GoTmpString[maxChar] = SPACE_ASCII;
00273             goObject->TouchActive = false;
00274             break;
00275 
00276         case GO_RECTANGLE:
00277         case GO_IMAGE:
00278             if( doFill )
00279             {
00280                 Tft.fillRectangle( goObject->Xpos, goObject->Ypos, \
00281                                    goObject->Xpos + goObject->Width - 1, \
00282                                    goObject->Ypos + goObject->Height - 1, \
00283                                    goObject->BackColor );
00284             }
00285             else
00286             {
00287                 Tft.drawRectangle( goObject->Xpos, goObject->Ypos, goObject->Xpos + \
00288                                    goObject->Width - 1, goObject->Ypos + \
00289                                    goObject->Height - 1, goObject->BackColor );
00290             }
00291             goObject->TouchActive = false;
00292             break;
00293 
00294         case GO_CIRCLE:
00295             if( doFill )
00296             {
00297                 Tft.fillCircle( goObject->Xpos, goObject->Ypos, \
00298                                 ( goObject->Height < goObject->Width ) ? \
00299                                   ( goObject->Height / 2 ) : ( goObject->Width / 2 ), \
00300                                 goObject->BackColor );
00301             }
00302             else
00303             {
00304                 Tft.drawCircle( goObject->Xpos, goObject->Ypos, \
00305                                 ( goObject->Height < goObject->Width ) ? \
00306                                   ( goObject->Height / 2 ) : ( goObject->Width / 2 ), \
00307                                 goObject->BackColor );
00308             }
00309             goObject->TouchActive = false;
00310             break;
00311 
00312         case GO_TRIANGLE:
00313             status = GO_STATUS_BAD_ARG;
00314             goObject->TouchActive = false;
00315             break;
00316 
00317         case GO_LINE:
00318             Tft.drawLine( goObject->Xpos, goObject->Ypos, goObject->Xpos + \
00319                                   goObject->Width - 1, goObject->Ypos + \
00320                                   goObject->Height - 1, goObject->BackColor );
00321             goObject->TouchActive = false;
00322             break;
00323 
00324         default:
00325             status = GO_STATUS_BAD_ARG;
00326     }
00327     return status;
00328 }
00329 
00330 void DisplayDriverDrawLogo( uint8_t *thisBmp, uint8_t xPos, uint8_t yPos )
00331 {
00332     if( BmpReadHeader( thisBmp ) ) 
00333     {
00334         DrawBmpFromFlash( thisBmp, xPos, yPos );
00335     }
00336 }
00337 
00338 GraphObjectStatus_t GraphObjectTouched( GraphObject_t* objects, \
00339                                         uint8_t objectsCount, \
00340                                         uint8_t* touchedObject)
00341 {
00342     uint8_t objScan;
00343     uint16_t x, y = 0;
00344     bool touched = false;
00345     GraphObjectStatus_t status = GO_STATUS_BAD_COORD;
00346     
00347     DebugPin = 1;
00348 
00349     if( Touch.isTouched( ) )
00350     {
00351         Touch.readTouchData( x, y, touched );
00352 
00353         if( touched == true )
00354         {
00355             for( objScan = 0; objScan < objectsCount; objScan++)
00356             {
00357                 if( objects[objScan].TouchActive == true )
00358                 {
00359                     if( ( y >= objects[objScan].Ypos ) && ( y <= ( objects[objScan].Ypos + objects[objScan].Height - 1 ) ) ) 
00360                     {
00361                         if( ( x >= objects[objScan].Xpos ) && ( x <= ( objects[objScan].Xpos + objects[objScan].Width - 1 ) ) )
00362                         {
00363                             *touchedObject = objects[objScan].Id;
00364                             status = GO_STATUS_NOERR;
00365                             break;      // return the first object match and no scan of other following objects
00366                         }
00367                     }
00368                 }
00369             }
00370         }
00371     }
00372 
00373     DebugPin = 0;
00374     return status;
00375 }
00376 
00377 static bool BmpReadHeader( uint8_t *thisBmp )
00378 {
00379     uint16_t pos = 0;
00380 
00381     Read16( thisBmp );
00382     if( Read16( thisBmp ) != 0x4D42 )
00383     { // read magic byte
00384         return false;
00385     }
00386     pos += 2;
00387 
00388     // read file size
00389     pos += 4;
00390     pos += 4; // Skip creator bytes
00391     BmpImageoffset = Read32( thisBmp + pos );
00392     pos += 4;
00393     // read DIB header
00394     pos +=4;
00395     BmpWidth = Read32( thisBmp + pos );
00396     pos += 4;
00397     BmpHeight = Read32( thisBmp + pos );
00398     pos += 4;
00399     if( Read16( thisBmp + pos ) != 1 )
00400     {
00401         // number of color planes must be 1
00402         return false;
00403     }
00404     pos += 2;
00405     pos += 2;
00406     if( Read16( thisBmp + pos ) != 0 ) 
00407     {
00408         return false; // compression not supported!
00409     }
00410     pos += 2; // Should really be 2??
00411     return true;
00412 }
00413 
00414 // LITTLE ENDIAN!
00415 static uint16_t Read16( uint8_t *src )
00416 {
00417     uint16_t d;
00418     uint8_t b;
00419     b = *src;
00420     d = *( src + 1 );
00421     d <<= 8;
00422     d |= b;
00423     return d;
00424 }
00425 
00426 // LITTLE ENDIAN!
00427 static uint32_t Read32( uint8_t *src )
00428 {
00429     uint32_t d;
00430     uint16_t b;
00431 
00432     b = Read16( src );
00433     d = Read16( src + 2 );
00434     d <<= 16;
00435     d |= b;
00436     return d;
00437 }
00438 
00439 static void DrawBmpFromFlash( uint8_t *thisBmp, int xPos, int yPos )
00440 {
00441     uint16_t pos = BmpImageoffset;
00442     uint16_t p;  // pixel
00443     uint8_t g;
00444     uint8_t b;
00445     int i, j; // line, column
00446 
00447     for( i = BmpHeight; i > 0; i-- )
00448     {
00449         for( j = 0; j < BmpWidth; j++ )
00450         {
00451             b = *( thisBmp + pos++ );
00452             g = *( thisBmp + pos++ );
00453             p = *( thisBmp + pos++ );
00454 
00455             p >>= 3;
00456             p <<= 6;
00457 
00458             g >>= 2;
00459             p |= g;
00460             p <<= 5;
00461 
00462             b >>= 3;
00463             p |= b;
00464 
00465             // write out the 16 bits of color
00466             Tft.setPixel( j + xPos, i + yPos, p );
00467         }
00468         pos += 1;  
00469     }
00470 }