/* --COPYRIGHT--,BSD * Copyright (c) 2013, Texas Instruments Incorporated * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Texas Instruments Incorporated nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * --/COPYRIGHT--*/ //***************************************************************************** // // Close the Doxygen group. //! @} // //***************************************************************************** //***************************************************************************** // // IMPORTANT NOTE: The following driver file supports using either RAM or // non-volatile memory(Flash or FRAM) to store the LCD DisplayBuffer. // //***************************************************************************** //***************************************************************************** // // Sharp96x96.c // //***************************************************************************** // //! \addtogroup display_api //! @{ // //***************************************************************************** #include "grlib.h" #include "Sharp96x96.h" #include #ifdef __MSP430FR5969 #include "HAL_MSP-EXP430FR5969_Sharp96x96.h" #include "../driverlibHeaders.h" #include "inc/hw_memmap.h" #elif defined(__MSP430G2553) #include "HAL_MSP-EXP430G2_Sharp96x96.h" #endif #include static void Sharp96x96_InitializeDisplayBuffer(void *pvDisplayData, uint8_t ucValue); //***************************************************************************** // // If flash is used as non-volatile memory, the DisplayBuffer will have 32 extra // vertical lines to create a buffer size which is a multiple of 512 Byte // (this is the default size of flash memory segments in MSP430 device). It is // required that the display buffer is a multiple of 512 Bytes to be able to // initialize the buffer using the FLASH segment erase feature of the FLASH // controller. // //***************************************************************************** #ifdef NON_VOLATILE_MEMORY_BUFFER #pragma location=NON_VOLATILE_MEMORY_ADDRESS #endif #ifndef NON_VOLATILE_MEMORY_BUFFER uint8_t DisplayBuffer[LCD_VERTICAL_MAX][LCD_HORIZONTAL_MAX/8]; #else #ifdef __ICC430__ __no_init uint8_t DisplayBuffer[LCD_VERTICAL_MAX +32][LCD_HORIZONTAL_MAX/8]; #else uint8_t DisplayBuffer[LCD_VERTICAL_MAX +32][LCD_HORIZONTAL_MAX/8]; #endif //__ICC430__ #endif //NON_VOLATILE_MEMORY_BUFFER uint8_t VCOMbit= 0x40; uint8_t flagSendToggleVCOMCommand = 0; //******************************************************************************* // //! Reverses the bit order.- Since the bit reversal function is called //! frequently by the several driver function this function is implemented //! to maximize code execution // //******************************************************************************* const uint8_t referse_data[] = {0x0, 0x8, 0x4, 0xC, 0x2, 0xA, 0x6, 0xE, 0x1, 0x9, 0x5, 0xD, 0x3, 0xB, 0x7, 0xF}; uint8_t reverse(uint8_t x) { uint8_t b = 0; b = referse_data[x & 0xF]<<4; b |= referse_data[(x & 0xF0)>>4]; return b; } //***************************************************************************** // //! Draws a pixel on the screen. //! //! \param pvDisplayData is a pointer to the driver-specific data for this //! display driver. //! \param lX is the X coordinate of the pixel. //! \param lY is the Y coordinate of the pixel. //! \param ulValue is the color of the pixel. //! //! This function sets the given pixel to a particular color. The coordinates //! of the pixel are assumed to be within the extents of the display. //! //! \return None. // //***************************************************************************** static void Sharp96x96_PixelDraw(void *pvDisplayData, int16_t lX, int16_t lY, uint16_t ulValue) { #ifdef NON_VOLATILE_MEMORY_BUFFER PrepareMemoryWrite(); #endif if( ClrBlack == ulValue){ DisplayBuffer[lY][lX>>3] &= ~(0x80 >> (lX & 0x7)); }else{ DisplayBuffer[lY][lX>>3] |= (0x80 >> (lX & 0x7)); } #ifdef NON_VOLATILE_MEMORY_BUFFER FinishMemoryWrite(); #endif } //***************************************************************************** // //! Draws a horizontal sequence of pixels on the screen. //! //! \param pvDisplayData is a pointer to the driver-specific data for this //! display driver. //! \param lX is the X coordinate of the first pixel. //! \param lY is the Y coordinate of the first pixel. //! \param lX0 is sub-pixel offset within the pixel data, which is valid for 1 //! or 4 bit per pixel formats. //! \param lCount is the number of pixels to draw. //! \param lBPP is the number of bits per pixel; must be 1, 4, or 8. //! \param pucData is a pointer to the pixel data. For 1 and 4 bit per pixel //! formats, the most significant bit(s) represent the left-most pixel. //! \param pucPalette is a pointer to the palette used to draw the pixels. //! //! This function draws a horizontal sequence of pixels on the screen, using //! the supplied palette. For 1 bit per pixel format, the palette contains //! pre-translated colors; for 4 and 8 bit per pixel formats, the palette //! contains 24-bit RGB values that must be translated before being written to //! the display. //! //! \return None. // //***************************************************************************** static void Sharp96x96_DrawMultiple(void *pvDisplayData, int16_t lX, int16_t lY, int16_t lX0, int16_t lCount, int16_t lBPP, const uint8_t *pucData, const uint16_t *pucPalette) { uint8_t *pData = &DisplayBuffer[lY][lX>>3]; uint16_t xj = 0; #ifdef NON_VOLATILE_MEMORY_BUFFER PrepareMemoryWrite(); #endif //Write bytes of data to the display buffer for(xj=0;xj>3;xj++){ *pData++ = *pucData++; } //Write last data byte to the display buffer *pData = (*pData & (0xFF >> (lCount & 0x7))) | *pucData; #ifdef NON_VOLATILE_MEMORY_BUFFER FinishMemoryWrite(); #endif } //***************************************************************************** // //! Draws a horizontal line. //! //! \param pvDisplayData is a pointer to the driver-specific data for this //! display driver. //! \param lX1 is the X coordinate of the start of the line. //! \param lX2 is the X coordinate of the end of the line. //! \param lY is the Y coordinate of the line. //! \param ulValue is the color of the line. //! //! This function draws a horizontal line on the display. The coordinates of //! the line are assumed to be within the extents of the display. //! //! \return None. // //***************************************************************************** static void Sharp96x96_LineDrawH(void *pvDisplayData, int16_t lX1, int16_t lX2, int16_t lY, uint16_t ulValue) { volatile uint16_t xi = 0; volatile uint16_t x_index_min = lX1>>3; volatile uint16_t x_index_max = lX2>>3; volatile uint8_t *pucData, ucfirst_x_byte, uclast_x_byte; #ifdef NON_VOLATILE_MEMORY_BUFFER PrepareMemoryWrite(); #endif //calculate first byte //mod by 8 and shift this # bits ucfirst_x_byte = (0xFF >> (lX1 & 0x7)); //calculate last byte //mod by 8 and shift this # bits uclast_x_byte = (0xFF << (7-(lX2 & 0x7))); //check if more than one data byte if(x_index_min != x_index_max){ //set buffer to correct location pucData = &DisplayBuffer[lY][x_index_min]; //black pixels (clear bits) if(ClrBlack == ulValue) { //write first byte *pucData++ &= ~ucfirst_x_byte; //write middle bytes for(xi = x_index_min; xi < x_index_max-1; xi++) { *pucData++ = 0x00; } //write last byte *pucData &= ~uclast_x_byte; } //white pixels (set bits) else { //write first byte *pucData++ |= ucfirst_x_byte; //write middle bytes for(xi = x_index_min; xi < x_index_max-1; xi++) { *pucData++ = 0xFF; } //write last byte *pucData |= uclast_x_byte; } } //only one data byte else { //calculate value of single byte ucfirst_x_byte &= uclast_x_byte; //set buffer to correct location pucData = &DisplayBuffer[lY][x_index_min]; //draw black pixels (clear bits) if(ClrBlack == ulValue) { *pucData++ &= ~ucfirst_x_byte; } //white pixels (set bits) else { *pucData++ |= ucfirst_x_byte; } } #ifdef NON_VOLATILE_MEMORY_BUFFER FinishMemoryWrite(); #endif } //***************************************************************************** // //! Draws a vertical line. //! //! \param pvDisplayData is a pointer to the driver-specific data for this //! display driver. //! \param lX is the X coordinate of the line. //! \param lY1 is the Y coordinate of the start of the line. //! \param lY2 is the Y coordinate of the end of the line. //! \param ulValue is the color of the line. //! //! This function draws a vertical line on the display. The coordinates of the //! line are assumed to be within the extents of the display. //! //! \return None. // //***************************************************************************** static void Sharp96x96_LineDrawV(void *pvDisplayData, int16_t lX, int16_t lY1, int16_t lY2, uint16_t ulValue) { volatile uint16_t yi = 0; volatile uint16_t x_index = lX>>3; volatile uint8_t data_byte; #ifdef NON_VOLATILE_MEMORY_BUFFER PrepareMemoryWrite(); #endif //calculate data byte //mod by 8 and shift this # bits data_byte = (0x80 >> (lX & 0x7)); //write data to the display buffer for(yi = lY1; yi <= lY2; yi++){ //black pixels (clear bits) if(ClrBlack == ulValue) { DisplayBuffer[yi][x_index] &= ~data_byte; } //white pixels (set bits) else { DisplayBuffer[yi][x_index] |= data_byte; } } #ifdef NON_VOLATILE_MEMORY_BUFFER FinishMemoryWrite(); #endif } //***************************************************************************** // //! Fills a rectangle. //! //! \param pvDisplayData is a pointer to the driver-specific data for this //! display driver. //! \param pRect is a pointer to the structure describing the rectangle. //! \param ulValue is the color of the rectangle. //! //! This function fills a rectangle on the display. The coordinates of the //! rectangle are assumed to be within the extents of the display, and the //! rectangle specification is fully inclusive (in other words, both sXMin and //! sXMax are drawn, along with sYMin and sYMax). //! //! \return None. // //***************************************************************************** static void Sharp96x96_RectFill(void *pvDisplayData, const tRectangle *pRect, uint16_t ulValue) { volatile uint16_t xi = 0; volatile uint16_t yi = 0; volatile uint16_t x_index_min = pRect->sXMin>>3; volatile uint16_t x_index_max = pRect->sXMax>>3; volatile uint8_t *pucData, ucfirst_x_byte, uclast_x_byte; #ifdef NON_VOLATILE_MEMORY_BUFFER PrepareMemoryWrite(); #endif //calculate first byte //mod by 8 and shift this # bits ucfirst_x_byte = (0xFF >> (pRect->sXMin & 0x7)); //calculate last byte //mod by 8 and shift this # bits uclast_x_byte = (0xFF << (7-(pRect->sXMax & 0x7))); //check if more than one data byte if(x_index_min != x_index_max){ //write bytes for (yi = pRect->sYMin; yi<= pRect->sYMax; yi++) { //set buffer to correct location pucData = &DisplayBuffer[yi][x_index_min]; //black pixels (clear bits) if(ClrBlack == ulValue) { //write first byte *pucData++ &= ~ucfirst_x_byte; //write middle bytes for(xi = x_index_min; xi < x_index_max-1; xi++) { *pucData++ = 0x00; } //write last byte *pucData &= ~uclast_x_byte; } //white pixels (set bits) else { //write first byte *pucData++ |= ucfirst_x_byte; //write middle bytes for(xi = x_index_min; xi < x_index_max-1; xi++) { *pucData++ = 0xFF; } //write last byte *pucData |= uclast_x_byte; } } } //only one data byte else { //calculate value of single byte ucfirst_x_byte &= uclast_x_byte; //set buffer to correct location pucData = &DisplayBuffer[pRect->sYMin][x_index_min]; //black pixels (clear bits) if(ClrBlack == ulValue) { *pucData++ &= ~ucfirst_x_byte; } //white pixels (set bits) else { *pucData++ |= ucfirst_x_byte; } } #ifdef NON_VOLATILE_MEMORY_BUFFER FinishMemoryWrite(); #endif } //***************************************************************************** // //! Translates a 24-bit RGB color to a display driver-specific color. //! //! \param pvDisplayData is a pointer to the driver-specific data for this //! display driver. //! \param ulValue is the 24-bit RGB color. The least-significant byte is the //! blue channel, the next byte is the green channel, and the third byte is the //! red channel. //! //! This function translates a 24-bit RGB color into a value that can be //! written into the display's frame buffer in order to reproduce that color, //! or the closest possible approximation of that color. //! //! \return Returns the display-driver specific color. // //***************************************************************************** static uint16_t Sharp96x96_ColorTranslate(void *pvDisplayData, uint32_t ulValue) { // // Translate from a 24-bit RGB color to mono color. // return(DPYCOLORTRANSLATE(ulValue)); } //***************************************************************************** // //! Flushes any cached drawing operations. //! //! \param pvDisplayData is a pointer to the driver-specific data for this //! display driver. //! //! //! This functions flushes any cached drawing operations to the display. This //! is useful when a local frame buffer is used for drawing operations, and the //! flush would copy the local frame buffer to the display. //! //! \return None. // //***************************************************************************** static void Sharp96x96_Flush (void *pvDisplayData) { uint8_t *pucData = &DisplayBuffer[0][0]; int32_t xi =0; int32_t xj = 0; //image update mode(1X000000b) uint8_t command = SHARP_LCD_CMD_WRITE_LINE; //COM inversion bit command = command^VCOMbit; SetCS(); WriteCmdData(command); flagSendToggleVCOMCommand = SHARP_SKIP_TOGGLE_VCOM_COMMAND; #ifdef LANDSCAPE for(xj=0; xj>3); xi++) { WriteCmdData(*(pucData++)); } WriteCmdData(SHARP_LCD_TRAILER_BYTE); } #endif #ifdef LANDSCAPE_FLIP pucData = &DisplayBuffer[LCD_VERTICAL_MAX-1][(LCD_HORIZONTAL_MAX>>3)-1]; for(xj=1; xj<=LCD_VERTICAL_MAX; xj++) { WriteCmdData(reverse(xj)); for(xi=0; xi < (LCD_HORIZONTAL_MAX>>3); xi++) { WriteCmdData(reverse(*pucData--)); } WriteCmdData(SHARP_LCD_TRAILER_BYTE); } #endif WriteCmdData(SHARP_LCD_TRAILER_BYTE); // Wait for last byte to be sent, then drop SCS WaitUntilLcdWriteFinished(); // Ensure a 2us min delay to meet the LCD's thSCS __delay_cycles(SYSTEM_CLOCK_SPEED * 0.000002); ClearCS(); } //***************************************************************************** // //! Send command to clear screen. //! //! \param pvDisplayData is a pointer to the driver-specific data for this //! display driver. //! \param ucValue is the background color of the buffered data. //! //! This function sets every pixel to the background color. //! //! \return None. // //***************************************************************************** static void Sharp96x96_ClearScreen (void *pvDisplayData, uint16_t ulValue) { //clear screen mode(0X100000b) uint8_t command = SHARP_LCD_CMD_CLEAR_SCREEN; //COM inversion bit command = command^VCOMbit; SetCS(); WriteCmdData(command); flagSendToggleVCOMCommand = SHARP_SKIP_TOGGLE_VCOM_COMMAND; WriteCmdData(SHARP_LCD_TRAILER_BYTE); // Wait for last byte to be sent, then drop SCS WaitUntilLcdWriteFinished(); // Ensure a 2us min delay to meet the LCD's thSCS __delay_cycles(SYSTEM_CLOCK_SPEED * 0.000002); ClearCS(); if(ClrBlack == ulValue) Sharp96x96_InitializeDisplayBuffer(pvDisplayData, SHARP_BLACK); else Sharp96x96_InitializeDisplayBuffer(pvDisplayData, SHARP_WHITE); } //***************************************************************************** // //! Send toggle VCOM command. //! //! This function toggles the state of VCOM which prevents a DC bias from being //! built up within the panel. //! //! \return None. // //***************************************************************************** void Sharp96x96_SendToggleVCOMCommand() { VCOMbit ^= SHARP_VCOM_TOGGLE_BIT; if(SHARP_SEND_TOGGLE_VCOM_COMMAND == flagSendToggleVCOMCommand) { //clear screen mode(0X100000b) uint8_t command = SHARP_LCD_CMD_CHANGE_VCOM; //COM inversion bit command = command^VCOMbit; SetCS(); WriteCmdData(command); WriteCmdData(SHARP_LCD_TRAILER_BYTE); // Wait for last byte to be sent, then drop SCS WaitUntilLcdWriteFinished(); // Ensure a 2us min delay to meet the LCD's thSCS __delay_cycles(SYSTEM_CLOCK_SPEED * 0.000002); ClearCS(); } flagSendToggleVCOMCommand = SHARP_SEND_TOGGLE_VCOM_COMMAND; } //***************************************************************************** // //! Initialize DisplayBuffer. //! //! \param pvDisplayData is a pointer to the driver-specific data for this //! display driver. //! //! \param ucValue is the foreground color of the buffered data. //! //! This function initializes the display buffer and discards any cached data. //! //! \return None. // //***************************************************************************** static void Sharp96x96_InitializeDisplayBuffer(void *pvDisplayData, uint8_t ucValue) { uint16_t i=0,j=0; uint8_t *pucData = pvDisplayData; #ifdef USE_FLASH_BUFFER // This is a callback function to HAL file since it implements device specific // functionality InitializeDisplayBuffer(pvDisplayData, ucValue); #else for(i =0; i< LCD_VERTICAL_MAX; i++) for(j =0; j< (LCD_HORIZONTAL_MAX>>3); j++) *pucData++ = ucValue; #endif //USE_FLASH_BUFFER } //***************************************************************************** // //! The display structure that describes the driver for the //! sharpLCD panel // //***************************************************************************** const tDisplay g_sharp96x96LCD = { sizeof(tDisplay), DisplayBuffer, LCD_HORIZONTAL_MAX, LCD_VERTICAL_MAX, Sharp96x96_PixelDraw, //PixelDraw, Sharp96x96_DrawMultiple, Sharp96x96_LineDrawH, Sharp96x96_LineDrawV, //LineDrawV, Sharp96x96_RectFill, //RectFill, Sharp96x96_ColorTranslate, Sharp96x96_Flush, //Flush Sharp96x96_ClearScreen //Clear screen. Contents of display buffer unmodified }; //***************************************************************************** // // Close the Doxygen group. //! @} // //*****************************************************************************