displayls013b7dh03.c

Go to the documentation of this file.
00001 /**************************************************************************/
00018 #include <stdint.h>
00019 #include <stdbool.h>
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023 
00024 /* DISPLAY driver inclustions */
00025 #include "displayconfigall.h"
00026 #include "displaypal.h"
00027 #include "displaybackend.h"
00028 #include "displayls013b7dh03.h"
00029 
00032 /*******************************************************************************
00033  ********************************  DEFINES  ************************************
00034  ******************************************************************************/
00035 
00036 /* LS013B7DH03 SPI commands */
00037 #define LS013B7DH03_CMD_UPDATE     (0x01)
00038 #define LS013B7DH03_CMD_ALL_CLEAR  (0x04)
00039 
00040 /* Frequency of LCD polarity inversion. */
00041 #ifndef LS013B7DH03_POLARITY_INVERSION_FREQUENCY
00042 #define LS013B7DH03_POLARITY_INVERSION_FREQUENCY (64)
00043 #endif
00044 
00045 #ifdef USE_CONTROL_BYTES
00046 #define LS013B7DH03_CONTROL_BYTES     (2)
00047 #else
00048 #define LS013B7DH03_CONTROL_BYTES     (0)
00049 #endif
00050 
00051 #ifdef PIXEL_MATRIX_ALLOC_SUPPORT
00052 
00053   #ifdef USE_STATIC_PIXEL_MATRIX_POOL
00054     /* Static pool has been chosen for pixelmatix allocation.
00055        Disable the use of malloc for allocation of pixel matrices. */
00056     #undef USE_MALLOC
00057   #endif
00058 
00059   #ifdef USE_MALLOC
00060     /* malloc has been chosen for pixelmatix allocation.
00061        Disable the use of static pool for allocation of pixel matrices. */
00062     #undef USE_STATIC_PIXEL_MATRIX_POOL
00063   #endif
00064 
00065 #endif /*  PIXEL_MATRIX_ALLOC_SUPPORT  */
00066 
00067 
00068 /*******************************************************************************
00069  *********************************  TYPEDEFS  **********************************
00070  ******************************************************************************/
00071 
00072 #ifdef PIXEL_MATRIX_ALLOC_SUPPORT
00073 #ifndef PIXEL_MATRIX_ALIGNMENT
00074 typedef uint8_t PixelMatrixAlign_t;
00075 #else
00076   #if (1 == PIXEL_MATRIX_ALIGNMENT)
00077     typedef uint8_t PixelMatrixAlign_t;
00078   #elif (2 == PIXEL_MATRIX_ALIGNMENT)
00079     typedef uint16_t PixelMatrixAlign_t;
00080   #elif (4 == PIXEL_MATRIX_ALIGNMENT)
00081     typedef uint32_t PixelMatrixAlign_t;
00082   #else
00083     #error Unsupported PIXEL_MATRIX_ALIGNMENT.
00084   #endif
00085 #endif
00086 #endif
00087 
00088 
00089 /*******************************************************************************
00090  ********************************  STATICS  ************************************
00091  ******************************************************************************/
00092 
00093 /* Static variables: */
00094 static uint8_t        lcdPolarity = 0;
00095 
00096 #ifdef PIXEL_MATRIX_ALLOC_SUPPORT
00097 #ifdef USE_STATIC_PIXEL_MATRIX_POOL
00098 #define PIXEL_MATRIX_POOL_ELEMENTS                                \
00099   (PIXEL_MATRIX_POOL_SIZE/sizeof(PixelMatrixAlign_t) +            \
00100    ((PIXEL_MATRIX_POOL_SIZE%sizeof(PixelMatrixAlign_t))? 1 : 0))
00101 static PixelMatrixAlign_t  pixelMatrixPoolBase[PIXEL_MATRIX_POOL_ELEMENTS];
00102 static PixelMatrixAlign_t* pixelMatrixPool = pixelMatrixPoolBase;
00103 #endif
00104 #endif
00105 
00106 
00107 /*******************************************************************************
00108  ************************   STATIC FUNCTION PROTOTYPES   ***********************
00109  ******************************************************************************/
00110 
00111 static EMSTATUS DisplayEnable(DISPLAY_Device_t*     device,
00112                               bool enable);
00113 static EMSTATUS DisplayClear(void);
00114 #ifndef POLARITY_INVERSION_EXTCOMIN_PAL_AUTO_TOGGLE
00115 static EMSTATUS DisplayPolarityInverse (void);
00116 #endif
00117 
00118 #ifdef PIXEL_MATRIX_ALLOC_SUPPORT
00119 static EMSTATUS PixelMatrixAllocate( DISPLAY_Device_t*     device,
00120                                      unsigned int           width,
00121 #ifdef EMWIN_WORKAROUND
00122                                      unsigned int           userStride,
00123 #endif
00124                                      unsigned int           height,
00125                                      DISPLAY_PixelMatrix_t *pixelMatrix);
00126 static EMSTATUS PixelMatrixFree( DISPLAY_Device_t*     device,
00127                                  DISPLAY_PixelMatrix_t pixelMatrix);
00128 #endif
00129 static EMSTATUS PixelMatrixDraw( DISPLAY_Device_t*     device,
00130                                  DISPLAY_PixelMatrix_t pixelMatrix,
00131                                  unsigned int          startColumn,
00132                                  unsigned int          width,
00133 #ifdef EMWIN_WORKAROUND
00134                                  unsigned int          userStride,
00135 #endif
00136                                  unsigned int          startRow,
00137                                  unsigned int          height );
00138 static EMSTATUS PixelMatrixClear( DISPLAY_Device_t*      device,
00139                                   DISPLAY_PixelMatrix_t  pixelMatrix,
00140                                   unsigned int           width,
00141                                   unsigned int           height);
00142 static EMSTATUS DriverRefresh (DISPLAY_Device_t* device);
00143 
00144 
00145 /*******************************************************************************
00146  **************************     GLOBAL FUNCTIONS      **************************
00147  ******************************************************************************/
00148 
00149 /**************************************************************************/
00154 EMSTATUS DISPLAY_Ls013b7dh03Init(void)
00155 {
00156   DISPLAY_Device_t      display;
00157   EMSTATUS              status;
00158 
00159   /* Initialize the Platform Abstraction Layer (PAL) interface.  */
00160   PAL_TimerInit();
00161   PAL_SpiInit();
00162   PAL_GpioInit();
00163 
00164   /* Setup GPIOs */
00165   PAL_GpioPinModeSet(LCD_PORT_SCLK,    LCD_PIN_SCLK,    palGpioModePushPull,0);
00166   PAL_GpioPinModeSet(LCD_PORT_SI,      LCD_PIN_SI,      palGpioModePushPull,0);
00167   PAL_GpioPinModeSet(LCD_PORT_SCS,     LCD_PIN_SCS,     palGpioModePushPull,0);
00168   PAL_GpioPinModeSet(LCD_PORT_DISP_SEL,LCD_PIN_DISP_SEL,palGpioModePushPull,0);
00169   PAL_GpioPinModeSet(LCD_PORT_DISP_PWR,LCD_PIN_DISP_PWR,palGpioModePushPull,0);
00170   PAL_GpioPinModeSet(LCD_PORT_EXTMODE, LCD_PIN_EXTMODE, palGpioModePushPull,0);
00171   PAL_GpioPinModeSet(LCD_PORT_EXTCOMIN,LCD_PIN_EXTCOMIN,palGpioModePushPull,0);
00172 
00173 #ifdef PAL_TIMER_REPEAT_FUNCTION
00174   /* If the platform specifies to use a timer repeat function we should
00175      register the DisplayPolarityInverse to be called every second in
00176      order to toggle the EXTCOMIN pin at 1Hz.
00177   */
00178   status =
00179     PAL_TimerRepeat((void(*)(void*)) DisplayPolarityInverse, 0,
00180                     LS013B7DH03_POLARITY_INVERSION_FREQUENCY);
00181 #elif defined POLARITY_INVERSION_EXTCOMIN_PAL_AUTO_TOGGLE
00182   /* Setup system (via PAL) to toggle the EXTCOMIN pin every second. */
00183   status = PAL_GpioPinAutoToggle(LCD_PORT_EXTCOMIN, LCD_PIN_EXTCOMIN,
00184                                  LS013B7DH03_POLARITY_INVERSION_FREQUENCY);
00185 #else
00186   /* System does not support toggling the EXTCOMIN pin. Return error. */
00187   return DISPLAY_EMSTATUS_NOT_SUPPORTED;
00188 #endif
00189   if (PAL_EMSTATUS_OK != status)
00190   {
00191     return status;
00192   }
00193   
00194   /* Setup and register the LS013B7DH03 as a DISPLAY device now. */  
00195   display.name                  = SHARP_MEMLCD_DEVICE_NAME;
00196   display.colourMode            = DISPLAY_COLOUR_MODE_MONOCHROME_INVERSE;
00197   display.addressMode           = DISPLAY_ADDRESSING_BY_ROWS_ONLY;
00198   display.geometry.width        = LS013B7DH03_WIDTH;
00199   display.geometry.height       = LS013B7DH03_HEIGHT;
00200   /* stride = pixels + ctrl bytes */
00201   display.geometry.stride       =
00202     display.geometry.width + LS013B7DH03_CONTROL_BYTES*8;
00203 
00204   display.pDisplayPowerOn       = DisplayEnable;
00205 #ifdef PIXEL_MATRIX_ALLOC_SUPPORT
00206   display.pPixelMatrixAllocate  = PixelMatrixAllocate;
00207   display.pPixelMatrixFree      = PixelMatrixFree;
00208 #else
00209   display.pPixelMatrixAllocate  = NULL;
00210   display.pPixelMatrixFree      = NULL;
00211 #endif
00212   display.pPixelMatrixDraw      = PixelMatrixDraw;
00213   display.pPixelMatrixClear     = PixelMatrixClear;
00214   display.pDriverRefresh        = DriverRefresh;
00215 
00216   status = DISPLAY_DeviceRegister (&display);
00217 
00218   if (DISPLAY_EMSTATUS_OK == status)
00219   {
00220     /* Turn on display. */
00221     DisplayEnable(&display, true);
00222 
00223     /* Clear display */
00224     DisplayClear();
00225   }
00226      
00227   return status;
00228 }
00229 
00230 
00231 /*******************************************************************************
00232  *****************************   STATIC FUNCTIONS   ****************************
00233  ******************************************************************************/
00234 
00235 /**************************************************************************/
00242 static EMSTATUS DriverRefresh(DISPLAY_Device_t* device)
00243 {
00244   EMSTATUS      status = DISPLAY_EMSTATUS_OK;
00245 
00246   (void) device; /* Suppress compiler warning: unused parameter. */
00247 
00248   /* Reinitialize the timer and SPI configuration.  */
00249   PAL_TimerInit();
00250   PAL_SpiInit();
00251 
00252   return status;
00253 }
00254 
00255 
00256 /**************************************************************************/
00269 static EMSTATUS DisplayEnable(DISPLAY_Device_t* device,
00270                               bool              enable)
00271 {
00272   (void) device; /* Suppress compiler warning: unused parameter. */
00273 
00274   if (enable)
00275   {
00276     /* Set EFM_DISP_SELECT pin. */
00277     PAL_GpioPinOutSet(LCD_PORT_DISP_SEL, LCD_PIN_DISP_SEL);
00278     /* Drive voltage on EFM_DISP_PWR_EN pin. */
00279     PAL_GpioPinOutSet(LCD_PORT_DISP_PWR, LCD_PIN_DISP_PWR);
00280   }
00281   else
00282   {
00283     /* Stop driving voltage on EFM_DISP_PWR_EN pin. */
00284     PAL_GpioPinOutClear(LCD_PORT_DISP_PWR, LCD_PIN_DISP_PWR);
00285     /* Clear EFM_DISP_SELECT pin. */
00286     PAL_GpioPinOutClear(LCD_PORT_DISP_SEL, LCD_PIN_DISP_SEL);
00287   }
00288 
00289   return DISPLAY_EMSTATUS_OK;
00290 }
00291 
00292 
00293 /**************************************************************************/
00300 static EMSTATUS DisplayClear ( void )
00301 {
00302   uint16_t cmd;
00303   
00304   /* Set SCS */
00305   PAL_GpioPinOutSet( LCD_PORT_SCS, LCD_PIN_SCS );
00306   
00307   /* SCS setup time: min 6us */
00308   PAL_TimerMicroSecondsDelay(6);
00309   
00310   /* Send command */
00311   cmd = LS013B7DH03_CMD_ALL_CLEAR | lcdPolarity;
00312   PAL_SpiTransmit ((uint8_t*) &cmd, 2 );
00313   
00314   /* SCS hold time: min 2us */
00315   PAL_TimerMicroSecondsDelay(2);
00316   
00317   /* Clear SCS */
00318   PAL_GpioPinOutClear( LCD_PORT_SCS, LCD_PIN_SCS );
00319   
00320   return DISPLAY_EMSTATUS_OK;
00321 }
00322 
00323 
00324 #ifdef PAL_TIMER_REPEAT_FUNCTION
00325 
00326 /**************************************************************************/
00334 static EMSTATUS DisplayPolarityInverse (void)
00335 {
00336 #ifdef POLARITY_INVERSION_EXTCOMIN
00337   
00338   /* Toggle extcomin gpio */
00339   PAL_GpioPinOutToggle( LCD_PORT_EXTCOMIN, LCD_PIN_EXTCOMIN );
00340   
00341 #else /* POLARITY_INVERSION_EXTCOMIN */
00342   
00343   /* Send a packet with inverted com */
00344   PAL_GpioPinOutSet( LCD_PORT_SCS, LCD_PIN_SCS );
00345   
00346   /* SCS setup time: min 6us */
00347   PAL_TimerMicroSecondsDelay(6);
00348 
00349   /* Send polarity command including dummy bits */
00350   PAL_SpiTransmit ((uint8_t*) &lcdPolarity, 2 );
00351 
00352   /* SCS hold time: min 2us */
00353   PAL_TimerMicroSecondsDelay(2);
00354       
00355   PAL_GpioPinOutClear( LCD_PORT_SCS, LCD_PIN_SCS );
00356 
00357   /* Invert com polarity */
00358   if (lcdPolarity == 0x00)
00359   {
00360     lcdPolarity = 0x02;
00361   }
00362   else
00363   {
00364     lcdPolarity = 0x00;
00365   }
00366 
00367 #endif /* POLARITY_INVERSION_EXTCOMIN */
00368 
00369   return DISPLAY_EMSTATUS_OK;
00370 }
00371 
00372 #endif /* POLARITY_INVERSION_EXTCOMIN_PAL_AUTO_TOGGLE */
00373 
00374 
00375 #ifdef PIXEL_MATRIX_ALLOC_SUPPORT
00376 /**************************************************************************/
00394 static EMSTATUS PixelMatrixAllocate( DISPLAY_Device_t*      device,
00395                                      unsigned int           width,
00396 #ifdef EMWIN_WORKAROUND
00397                                      unsigned int           userStride,
00398 #endif
00399                                      unsigned int           height,
00400                                      DISPLAY_PixelMatrix_t *pixelMatrix)
00401 {
00402 #ifdef EMWIN_WORKAROUND
00403   unsigned int allocSize = (userStride/8 + LS013B7DH03_CONTROL_BYTES) * height;
00404 #else
00405   unsigned int allocSize = (width/8 + LS013B7DH03_CONTROL_BYTES) * height;
00406 #endif
00407 
00408   (void) device; /* Suppress compiler warning: unused parameter. */
00409 
00410   if (width != LS013B7DH03_WIDTH)
00411     return DISPLAY_EMSTATUS_OUT_OF_RANGE;
00412 #ifdef EMWIN_WORKAROUND
00413   if (userStride < width)
00414     return DISPLAY_EMSTATUS_INVALID_PARAMETER;
00415 #endif
00416 
00417 #ifdef USE_MALLOC
00418 
00419   /* Allocate the pixel matrix buffer including 2 control bytes per line. */
00420   *pixelMatrix = (DISPLAY_PixelMatrix_t) malloc (allocSize);
00421 
00422   if (NULL == *pixelMatrix)
00423     return DISPLAY_EMSTATUS_NOT_ENOUGH_MEMORY;
00424   else
00425     return DISPLAY_EMSTATUS_OK;
00426 
00427 #endif /* USE_MALLOC */
00428 
00429 #ifdef USE_STATIC_PIXEL_MATRIX_POOL
00430 
00431   if (((uint8_t*)pixelMatrixPool)     + allocSize >
00432       ((uint8_t*)pixelMatrixPoolBase) + PIXEL_MATRIX_POOL_SIZE)
00433   {
00434     *pixelMatrix     = NULL;
00435     return DISPLAY_EMSTATUS_NOT_ENOUGH_MEMORY;
00436   }
00437   else
00438   {
00439     *pixelMatrix     = pixelMatrixPool;
00440     pixelMatrixPool += allocSize / sizeof(PixelMatrixAlign_t) +
00441       ((allocSize % sizeof(PixelMatrixAlign_t))? 1 : 0);
00442     return DISPLAY_EMSTATUS_OK;
00443   }
00444 
00445 #endif /* USE_STATIC_PIXEL_MATRIX_POOL */
00446   
00447 }
00448 #endif /* PIXEL_MATRIX_ALLOC_SUPPORT */
00449 
00450 
00451 #ifdef PIXEL_MATRIX_ALLOC_SUPPORT
00452 /**************************************************************************/
00462 static EMSTATUS PixelMatrixFree( DISPLAY_Device_t*     device,
00463                                  DISPLAY_PixelMatrix_t pixelMatrix)
00464 {
00465   (void) device; /* Suppress compiler warning: unused parameter. */
00466 
00467 #ifdef USE_MALLOC
00468   free(pixelMatrix);
00469   return DISPLAY_EMSTATUS_OK;
00470 #endif /* USE_MALLOC */
00471 
00472 #ifdef USE_STATIC_PIXEL_MATRIX_POOL
00473   /* The non-malloc PixelMatrixAllocate function only allocates buffers
00474      consequtively from a pool. It is not possible to free the buffers.
00475      I.e. this allocator can only be used for one-shot allocations of
00476      buffers that will should never be freed and re-alloced.
00477   */
00478   (void) pixelMatrix;   /* Supress compiles warning: unused parameter. */
00479   return DISPLAY_EMSTATUS_NOT_SUPPORTED;
00480 #endif
00481 }
00482 #endif /* PIXEL_MATRIX_ALLOC_SUPPORT */
00483 
00484 
00485 /**************************************************************************/
00502 static EMSTATUS PixelMatrixClear( DISPLAY_Device_t*      device,
00503                                   DISPLAY_PixelMatrix_t  pixelMatrix,
00504                                   unsigned int           width,
00505                                   unsigned int           height)
00506 {
00507   uint8_t*       pByte = (uint8_t*) pixelMatrix;
00508   unsigned int   i;
00509 
00510   (void) device; /* Suppress compiler warning: unused parameter. */
00511   (void) width;  /* Suppress compiler warning: unused parameter. */
00512   
00513   for (i=0; i<height; i++)
00514   {
00515     /* Clear line */
00516     memset(pByte, 0, LS013B7DH03_WIDTH/8);
00517     pByte += LS013B7DH03_WIDTH/8;
00518 
00519 #ifdef USE_CONTROL_BYTES
00520     /* Set dummy byte. */
00521     *pByte++ = 0xff;
00522     /* Set address of next line */
00523     *pByte++ = i+1;
00524 #endif
00525   }
00526 
00527   return DISPLAY_EMSTATUS_OK;
00528 }
00529 
00530 
00531 #ifdef USE_CONTROL_BYTES
00532 /**************************************************************************/
00543 static EMSTATUS pixelMatrixSetup( DISPLAY_PixelMatrix_t  pixelMatrix,
00544                                   unsigned int           startRow,
00545                                   unsigned int           height
00546 #ifdef EMWIN_WORKAROUND
00547                                   ,
00548                                   unsigned int           userStride
00549 #endif
00550                                   )
00551 {
00552   int       i          = 0;
00553   uint8_t*  pByte      = (uint8_t*) pixelMatrix;
00554 #ifdef EMWIN_WORKAROUND
00555   int       strideGap  =
00556     (userStride-LS013B7DH03_WIDTH-(LS013B7DH03_CONTROL_BYTES*8)) /
00557     8 / sizeof(uint8_t);
00558   if ((userStride-LS013B7DH03_WIDTH) % sizeof(uint16_t))
00559     return DISPLAY_EMSTATUS_INVALID_PARAMETER;
00560 #endif
00561   
00562   while (i<height)
00563   {
00564     pByte += LS013B7DH03_WIDTH/8;
00565     /* Set dummy byte. */
00566     *pByte++ = 0xff;
00567 
00568     if (i == height-1)
00569     {
00570       /* Set dummy data at end of last line. */
00571       *pByte++ = 0xff;
00572       break;
00573     }
00574     else
00575       /* Set address of next line */
00576       *pByte++ = startRow + (++i);
00577 
00578 #ifdef EMWIN_WORKAROUND
00579     pByte += strideGap;
00580 #endif
00581   }
00582 
00583   return DISPLAY_EMSTATUS_OK;
00584 }
00585 
00586 #endif /* USE_CONTROL_BYTES */
00587 
00588 
00589 /**************************************************************************/
00606 static EMSTATUS PixelMatrixDraw( DISPLAY_Device_t*      device,
00607                                  DISPLAY_PixelMatrix_t  pixelMatrix,
00608                                  unsigned int           startColumn,
00609                                  unsigned int           width,
00610 #ifdef EMWIN_WORKAROUND
00611                                  unsigned int           userStride,
00612 #endif
00613                                  unsigned int           startRow,
00614                                  unsigned int           height )
00615 {
00616   unsigned int i;
00617   uint16_t*    p = (uint16_t *)pixelMatrix;
00618   uint16_t     cmd;
00619 #ifdef EMWIN_WORKAROUND
00620   int          strideGap =
00621     (userStride-width-(LS013B7DH03_CONTROL_BYTES*8)) / 8 / sizeof(uint16_t);
00622   if ((userStride-width) % sizeof(uint16_t))
00623     return DISPLAY_EMSTATUS_INVALID_PARAMETER;
00624 #else
00625   (void) width;  /* Suppress compiler warning: unused parameter. */
00626 #endif
00627   (void) startColumn;  /* Suppress compiler warning: unused parameter. */
00628   (void) device; /* Suppress compiler warning: unused parameter. */
00629 
00630   /* Need to adjust start row by one because LS013B7DH03 starts counting lines
00631      from 1, while the DISPLAY interface starts from 0. */
00632   startRow++;
00633 
00634 #ifdef USE_CONTROL_BYTES
00635   /* Setup line addressing in control words. */
00636   pixelMatrixSetup(pixelMatrix, startRow, height
00637 #ifdef EMWIN_WORKAROUND
00638                    , userStride
00639 #endif
00640                    );
00641 #endif
00642 
00643   /* Assert SCS */
00644   PAL_GpioPinOutSet( LCD_PORT_SCS, LCD_PIN_SCS );
00645 
00646   /* SCS setup time: min 6us */
00647   PAL_TimerMicroSecondsDelay(6);
00648   
00649   /* Send update command and first line address */
00650   cmd = LS013B7DH03_CMD_UPDATE | (startRow << 8);
00651   PAL_SpiTransmit((uint8_t*) &cmd, 2 );
00652 
00653   /* Get start address to draw from */
00654   for ( i=0; i<height; i++ ) {
00655         
00656     /* Send pixels for this line */
00657     PAL_SpiTransmit((uint8_t*) p,
00658                     LS013B7DH03_WIDTH/8 + LS013B7DH03_CONTROL_BYTES);
00659     p+=(LS013B7DH03_WIDTH/8 + LS013B7DH03_CONTROL_BYTES) / sizeof(uint16_t);
00660 
00661 #ifndef USE_CONTROL_BYTES
00662     if (i==height-1)
00663     {
00664       cmd = 0xffff;
00665     }
00666     else
00667     {
00668       cmd = 0xff | ((startRow+i+1) << 8);
00669     }
00670     PAL_SpiTransmit((uint8_t*) &cmd, 2 );
00671 #endif
00672 
00673 #ifdef EMWIN_WORKAROUND
00674     p += strideGap;
00675 #endif
00676 
00677   }
00678   
00679   /* SCS hold time: min 2us */
00680   PAL_TimerMicroSecondsDelay(2);
00681   
00682   /* De-assert SCS */
00683   PAL_GpioPinOutClear( LCD_PORT_SCS, LCD_PIN_SCS );
00684 
00685   return DISPLAY_EMSTATUS_OK;
00686 }
00687