You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

698 lines
21 KiB

/* --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 <msp430.h>
#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 <stdint.h>
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<lCount>>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<LCD_VERTICAL_MAX; xj++)
{
WriteCmdData(reverse(xj + 1));
for(xi=0; xi<(LCD_HORIZONTAL_MAX>>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.
//! @}
//
//*****************************************************************************