rt-thread/bsp/efm32/graphics/dmd/ssd2119/dmd_ssd2119_16bit.c
onelife.real ea6d73f140 *** EFM32 branch ***
1. Upgrade Cortex driver library (CMSIS -> CMSIS & Device): version 2.3.2 -> 3.0.1 & 3.0.0
 - Remove "bsp/efm32/Libraries/CMSIS/Lib/ARM", "bsp/efm32/Libraries/CMSIS/Lib/G++" and "bsp/efm32/Libraries/CMSIS/SVD" to save space
2. Upgrade EFM32 driver libraries (efm32lib -> emlib): version 2.3.2 -> 3.0.0
 - Remove "bsp/efm32/Libraries/Device/EnergyMicro/EFM32LG" and "bsp/efm32/Libraries/Device/EnergyMicro/EFM32TG" to save space
3. Upgrade EFM32GG_DK3750 development kit driver library: version 1.2.2 -> 2.0.1
4. Upgrade EFM32_Gxxx_DK development kit driver library: version 1.7.3 -> 2.0.1
5. Add energy management unit driver and test code
6. Modify linker script and related code to compatible with new version of libraries
7. Change EFM32 branch version number to 1.0
8. Add photo frame demo application

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2122 bbd45198-f89e-11dd-88c7-29a3b14d5316
2012-05-18 04:40:40 +00:00

946 lines
30 KiB
C

/*************************************************************************//**
* @file dmd_ssd2119.c
* @brief Dot matrix display driver for LCD controller SSD2119
* @author Energy Micro AS
******************************************************************************
* @section License
* <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
******************************************************************************
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
* 4. The source and compiled code may only be used on Energy Micro "EFM32"
* microcontrollers and "EFR4" radios.
*
* DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
* obligation to support this Software. Energy Micro AS is providing the
* Software "AS IS", with no express or implied warranties of any kind,
* including, but not limited to, any implied warranties of merchantability
* or fitness for any particular purpose or warranties against infringement
* of any proprietary rights of a third party.
*
* Energy Micro AS will not be liable for any consequential, incidental, or
* special damages, or any other relief, or for any claim by any third party,
* arising from your use of this Software.
*
*****************************************************************************/
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include "dmd_ssd2119.h"
#include "dmd_ssd2119_registers.h"
#include "dmdif_ssd2119_ebi.h"
/** Dimensions of the display */
DMD_DisplayGeometry dimensions;
/* Local variables */
static uint32_t initialized = 0;
static uint16_t rcDriverOutputControl;
/* Local function prototypes */
static uint32_t colorTransform24To16bpp( uint8_t red, uint8_t green, uint8_t blue);
static void colorTransform16To24bpp(uint32_t color,
uint8_t *red, uint8_t *green, uint8_t *blue);
/**************************************************************************//**
* @brief
* Initializes the LCD display
*
* @param cmdRegAddr
* The address in memory where data to the command register in the display
* controller are written
* @param dataRegAddr
* The address in memory where data to the data register in the display
* controller are written
*
* @return
* DMD_OK on success, otherwise error code
******************************************************************************/
EMSTATUS DMD_init(uint32_t cmdRegAddr, uint32_t dataRegAddr){
EMSTATUS stat;
uint16_t data;
/* Initialize register cache variables */
rcDriverOutputControl = 0;
/* Initialize DMD interface */
if ((stat = DMDIF_init(cmdRegAddr, dataRegAddr)) != DMD_OK)
{
return stat;
}
/* Initialization sequence, see UMSH-8252MD-T page 13 */
/* printf("R%x: 0x%x\n", DMD_SSD2119_VCOM_OTP_1, 0x0006); */
DMDIF_writeReg(DMD_SSD2119_VCOM_OTP_1, 0x0006);
/* Start oscillation */
data = DMD_SSD2119_OSCILLATION_START_OSCEN;
/* printf("R%x: 0x%x\n", DMD_SSD2119_OSCILLATION_START, data); */
DMDIF_writeReg(DMD_SSD2119_OSCILLATION_START, data);
/* Exit sleep mode */
data = 0;
/* printf("R%x: 0x%x\n", DMD_SSD2119_SLEEP_MODE_1, data); */
DMDIF_writeReg(DMD_SSD2119_SLEEP_MODE_1, data);
/* Display control */
data = DMD_SSD2119_DISPLAY_CONTROL_DTE;
data |= DMD_SSD2119_DISPLAY_CONTROL_GON;
data |= DMD_SSD2119_DISPLAY_CONTROL_D1;
data |= DMD_SSD2119_DISPLAY_CONTROL_D0;
/* printf("R%x: 0x%x\n", DMD_SSD2119_DISPLAY_CONTROL, data); */
DMDIF_writeReg(DMD_SSD2119_DISPLAY_CONTROL, data);
/* Entry mode */
data = DMD_SSD2119_ENTRY_MODE_DFM_65K << DMD_SSD2119_ENTRY_MODE_DFM_SHIFT;
data |= DMD_SSD2119_ENTRY_MODE_DENMODE;
data |= DMD_SSD2119_ENTRY_MODE_WMODE;
data |= DMD_SSD2119_ENTRY_MODE_NOSYNC;
data |= DMD_SSD2119_ENTRY_MODE_TY_TYPE_B << DMD_SSD2119_ENTRY_MODE_TY_SHIFT;
data |= DMD_SSD2119_ENTRY_MODE_ID1;
data |= DMD_SSD2119_ENTRY_MODE_ID0;
/* printf("R%x: 0x%x\n", DMD_SSD2119_ENTRY_MODE, data); */
DMDIF_writeReg(DMD_SSD2119_ENTRY_MODE, data);
/* LCD AC control */
data = DMD_SSD2119_LCD_AC_CONTROL_BC;
data |= DMD_SSD2119_LCD_AC_CONTROL_EOR;
/* printf("R%x: 0x%x\n", DMD_SSD2119_LCD_AC_CONTROL, data); */
DMDIF_writeReg(DMD_SSD2119_LCD_AC_CONTROL, data);
/* Power control */
data = 0x06 << DMD_SSD2119_POWER_CONTROL_1_DCT_SHIFT;
data |= 0x05 << DMD_SSD2119_POWER_CONTROL_1_BT_SHIFT;
data |= 0x03 << DMD_SSD2119_POWER_CONTROL_1_DC_SHIFT;
data |= 0x04 << DMD_SSD2119_POWER_CONTROL_1_AP_SHIFT;
/* printf("R%x: 0x%x\n", DMD_SSD2119_POWER_CONTROL_1, data); */
DMDIF_writeReg(DMD_SSD2119_POWER_CONTROL_1, data);
/* Driver output control */
data = DMD_SSD2119_DRIVER_OUTPUT_CONTROL_RL;
data |= DMD_SSD2119_DRIVER_OUTPUT_CONTROL_REV;
data |= DMD_SSD2119_DRIVER_OUTPUT_CONTROL_GD;
data |= DMD_SSD2119_DRIVER_OUTPUT_CONTROL_TB;
data |= (DMD_VERTICAL_SIZE - 1) << DMD_SSD2119_DRIVER_OUTPUT_CONTROL_MUX_SHIFT;
rcDriverOutputControl = data;
/* printf("R%x: 0x%x\n", DMD_SSD2119_DRIVER_OUTPUT_CONTROL, data); */
DMDIF_writeReg(DMD_SSD2119_DRIVER_OUTPUT_CONTROL, data);
/* Power Control */
data = 0x05 << DMD_SSD2119_POWER_CONTROL_2_VRC_SHIFT;
/* printf("R%x: 0x%x\n", DMD_SSD2119_POWER_CONTROL_2, data); */
DMDIF_writeReg(DMD_SSD2119_POWER_CONTROL_2, data);
data = 0x0D << DMD_SSD2119_POWER_CONTROL_3_VRH_SHIFT;
/* printf("R%x: 0x%x\n", DMD_SSD2119_POWER_CONTROL_3, data); */
DMDIF_writeReg(DMD_SSD2119_POWER_CONTROL_3, data);
data = DMD_SSD2119_POWER_CONTROL_4_VCOMG;
data |= 0x0D << DMD_SSD2119_POWER_CONTROL_4_VDV_SHIFT;
/* printf("R%x: 0x%x\n", DMD_SSD2119_POWER_CONTROL_4, data); */
DMDIF_writeReg(DMD_SSD2119_POWER_CONTROL_4, data);
data = DMD_SSD2119_POWER_CONTROL_5_NOTP;
data |= 0x3E << DMD_SSD2119_POWER_CONTROL_5_VCM_SHIFT;
/* printf("R%x: 0x%x\n", DMD_SSD2119_POWER_CONTROL_5, data); */
DMDIF_writeReg(DMD_SSD2119_POWER_CONTROL_5, data);
data = 0x0058;
/* printf("R%x: 0x%x\n", DMD_SSD2119_GENERIC_INTERFACE_CONTROL, data); */
DMDIF_writeReg(DMD_SSD2119_GENERIC_INTERFACE_CONTROL, data);
/* Gamma settings */
data = 0x00 << DMD_SSD2119_GAMMA_1_PKP1_SHIFT;
data |= 0x00 << DMD_SSD2119_GAMMA_1_PKP0_SHIFT;
/* printf("R%x: 0x%x\n", DMD_SSD2119_GAMMA_1, data); */
DMDIF_writeReg(DMD_SSD2119_GAMMA_1, data);
data = 0x01 << DMD_SSD2119_GAMMA_2_PKP3_SHIFT;
data |= 0x01 << DMD_SSD2119_GAMMA_2_PKP2_SHIFT;
/* printf("R%x: 0x%x\n", DMD_SSD2119_GAMMA_2, data); */
DMDIF_writeReg(DMD_SSD2119_GAMMA_2, data);
data = 0x01 << DMD_SSD2119_GAMMA_3_PKP5_SHIFT;
data |= 0x00 << DMD_SSD2119_GAMMA_3_PKP4_SHIFT;
/* printf("R%x: 0x%x\n", DMD_SSD2119_GAMMA_3, data); */
DMDIF_writeReg(DMD_SSD2119_GAMMA_3, data);
data = 0x03 << DMD_SSD2119_GAMMA_4_PRP1_SHIFT;
data |= 0x05 << DMD_SSD2119_GAMMA_4_PRP0_SHIFT;
/* printf("R%x: 0x%x\n", DMD_SSD2119_GAMMA_4, data); */
DMDIF_writeReg(DMD_SSD2119_GAMMA_4, data);
data = 0x07 << DMD_SSD2119_GAMMA_5_PKN1_SHIFT;
data |= 0x07 << DMD_SSD2119_GAMMA_5_PKN0_SHIFT;
/* printf("R%x: 0x%x\n", DMD_SSD2119_GAMMA_5, data); */
DMDIF_writeReg(DMD_SSD2119_GAMMA_5, data);
data = 0x03 << DMD_SSD2119_GAMMA_6_PKN3_SHIFT;
data |= 0x05 << DMD_SSD2119_GAMMA_6_PKN2_SHIFT;
/* printf("R%x: 0x%x\n", DMD_SSD2119_GAMMA_6, data); */
DMDIF_writeReg(DMD_SSD2119_GAMMA_6, data);
data = 0x07 << DMD_SSD2119_GAMMA_7_PKN5_SHIFT;
data |= 0x07 << DMD_SSD2119_GAMMA_7_PKN4_SHIFT;
/* printf("R%x: 0x%x\n", DMD_SSD2119_GAMMA_7, data); */
DMDIF_writeReg(DMD_SSD2119_GAMMA_7, data);
data = 0x02 << DMD_SSD2119_GAMMA_8_PRN1_SHIFT;
data |= 0x01 << DMD_SSD2119_GAMMA_8_PRN0_SHIFT;
/* printf("R%x: 0x%x\n", DMD_SSD2119_GAMMA_8, data); */
DMDIF_writeReg(DMD_SSD2119_GAMMA_8, data);
data = 0x12 << DMD_SSD2119_GAMMA_9_VRP1_SHIFT;
data |= 0x00 << DMD_SSD2119_GAMMA_9_VRP0_SHIFT;
/* printf("R%x: 0x%x\n", DMD_SSD2119_GAMMA_9, data); */
DMDIF_writeReg(DMD_SSD2119_GAMMA_9, data);
data = 0x09 << DMD_SSD2119_GAMMA_10_VRN1_SHIFT;
data |= 0x00 << DMD_SSD2119_GAMMA_10_VRN0_SHIFT;
/* printf("R%x: 0x%x\n", DMD_SSD2119_GAMMA_10, data); */
DMDIF_writeReg(DMD_SSD2119_GAMMA_10, data);
/* Set up dimensions of the display */
dimensions.xSize = DMD_HORIZONTAL_SIZE;
dimensions.ySize = DMD_VERTICAL_SIZE;
/* At initialization, the clip is the entire display */
dimensions.xClipStart = 0;
dimensions.yClipStart = 0;
dimensions.clipWidth = dimensions.xSize;
dimensions.clipHeight = dimensions.ySize;
initialized = 1;
/* Fill the entire display with black color */
DMD_writeColor(0, 0, 0x00, 0x00, 0x00, dimensions.xSize * dimensions.ySize);
return DMD_OK;
}
/**************************************************************************//**
* \brief
* Get the dimensions of the display and of the current clipping area
*
* \return
* DMD_Dimensions structure containing the size of the display and the
* clipping area
******************************************************************************/
EMSTATUS DMD_getDisplayGeometry(DMD_DisplayGeometry **geometry)
{
if (!initialized)
{
return DMD_ERROR_DRIVER_NOT_INITIALIZED;
}
*geometry = &dimensions;
return DMD_OK;
}
/**************************************************************************//**
* @brief
* Sets the clipping area. All coordinates given to writeData/writeColor/readData
* are relative to this clipping area.
*
* @param xStart
* X coordinate of the upper left corner of the clipping area
* @param yStart
* Y coordinate of the upper left corner of the clipping area
* @param width
* Width of the clipping area
* @param height
* Height of the clipping area
*
* @return
* DMD_OK on success, otherwise error code
******************************************************************************/
EMSTATUS DMD_setClippingArea(uint16_t xStart, uint16_t yStart,
uint16_t width, uint16_t height)
{
uint16_t verticalPos;
uint16_t xEnd;
uint16_t yEnd;
if (!initialized)
{
return DMD_ERROR_DRIVER_NOT_INITIALIZED;
}
/* Check parameters */
if (xStart + width > dimensions.xSize ||
yStart + height > dimensions.ySize)
{
return DMD_ERROR_PIXEL_OUT_OF_BOUNDS;
}
if (width == 0 || height == 0)
{
return DMD_ERROR_EMPTY_CLIPPING_AREA;
}
xEnd = xStart + width - 1;
yEnd = yStart + height - 1;
/* Set the clipping region in the display */
DMDIF_writeReg(DMD_SSD2119_HORIZONTAL_RAM_ADDRESS_START_POS, xStart);
DMDIF_writeReg(DMD_SSD2119_HORIZONTAL_RAM_ADDRESS_END_POS, xEnd);
verticalPos = yEnd << DMD_SSD2119_VERTICAL_RAM_ADDRESS_POS_END_SHIFT;
verticalPos |= yStart << DMD_SSD2119_VERTICAL_RAM_ADDRESS_POS_START_SHIFT;
DMDIF_writeReg(DMD_SSD2119_VERTICAL_RAM_ADDRESS_POS, verticalPos);
/* Update the dimensions structure */
dimensions.xClipStart = xStart;
dimensions.yClipStart = yStart;
dimensions.clipWidth = width;
dimensions.clipHeight = height;
return DMD_OK;
}
/**************************************************************************//**
* @brief
* Set the x and y coordinate of the next pixel to draw
*
* @param x
* X address of the pixel, relative to the current clipping area
* @param y
* Y address of the pixel, relative to the current clipping area
*
* @return
* DMD_OK on success, otherwise error code
******************************************************************************/
EMSTATUS setPixelAddress(uint16_t x, uint16_t y)
{
/* Check parameters */
if (x > dimensions.clipWidth || y > dimensions.clipHeight)
{
return DMD_ERROR_PIXEL_OUT_OF_BOUNDS;
}
/* Set pixel position */
DMDIF_writeReg(DMD_SSD2119_SET_X_ADDRESS_COUNTER,
x + dimensions.xClipStart);
DMDIF_writeReg(DMD_SSD2119_SET_Y_ADDRESS_COUNTER,
y + dimensions.yClipStart);
return DMD_OK;
}
/**************************************************************************//**
* @brief
* Draws pixels to the display
*
* @param x
* X coordinate of the first pixel to be written, relative to the clipping area
* @param y
* Y coordinate of the first pixel to be written, relative to the clipping area
* @param data
* Array containing the pixel data. Each 8-bit element in the array are one color
* component of the pixel, so that 3 bytes represent one pixel. The pixels are
* ordered by increasing x coordinate, after the last pixel of a row, the next
* pixel will be the first pixel on the next row.
* @param numPixels
* Number of pixels to be written
*
* @return
* DMD_OK on success, otherwise error code
******************************************************************************/
EMSTATUS DMD_writeData(uint16_t x, uint16_t y, const uint8_t data[],
uint32_t numPixels)
{
uint32_t statusCode;
uint32_t clipRemaining;
uint32_t color;
uint32_t i;
if (!initialized)
{
return DMD_ERROR_DRIVER_NOT_INITIALIZED;
}
/* Set the address of the first pixel */
statusCode = setPixelAddress(x, y);
if (statusCode != DMD_OK)
{
return statusCode;
}
/* Number of pixels from the first pixel (given by x and y) to the end
* of the clipping area */
clipRemaining = (dimensions.clipHeight - y - 1) * dimensions.clipWidth +
dimensions.clipWidth - x;
/* Check that the length of data isn't longer than the number of pixels
* in the rest of the clipping area */
if (numPixels > clipRemaining)
{
return DMD_ERROR_TOO_MUCH_DATA;
}
/* Write data */
DMDIF_prepareDataAccess( );
for (i = 0; i < numPixels; i++)
{
color = colorTransform24To16bpp(data[3 * i], data[3 * i + 1],
data[3 * i + 2]);
DMDIF_writeData(color);
}
return DMD_OK;
}
/**************************************************************************//**
* @brief
* Draws pixels to the display at location x,y, from a source data array in
* GIMP RLE compressed C-format, mixing with another RGB color to create a
* "blended" look or for fading images in and out
* @param x
* X coordinate of the first pixel to be written, relative to the clipping area
* @param y
* Y coordinate of the first pixel to be written, relative to the clipping area
* @param data
* Array containing the pixel data in GIMP RLE compressed format
* @param numPixels
* Number of pixels to be written
* @param red
* Red component of color to mix with orignal
* @param green
* Red component of color to mix with orignal
* @param blue
* Red component of color to mix with orignal
* @param weight
* Ratio to which red/green/blue component and original color should be combined
* @return
* DMD_OK on success, otherwise error code
******************************************************************************/
EMSTATUS DMD_writeDataRLEFade(uint16_t x, uint16_t y, uint16_t xlen, uint16_t ylen,
const uint8_t *data,
int red, int green, int blue, int weight)
{
uint32_t color = 0;
int xpos, ypos;
const uint8_t *ptr;
int r,g,b;
uint8_t readRGB = 0;
uint8_t copyColor = 0;
ptr = data;
for (ypos = y; ypos < (ylen+y); ypos++){
setPixelAddress(x, ypos);
DMDIF_prepareDataAccess( );
for (xpos = x; xpos < (xlen+x); xpos++){
if ( readRGB ) {
readRGB--;
r = *ptr++;
g = *ptr++;
b = *ptr++;
r = ((r * weight/100) + (red * (100-weight)/100));
g = ((g * weight/100) + (green * (100-weight)/100));
b = ((b * weight/100) + (blue * (100-weight)/100));
color = colorTransform24To16bpp(r,g,b);
DMDIF_writeData(color);
continue;
}
if ( copyColor ) {
copyColor--;
DMDIF_writeData( color );
continue;
}
if ( *ptr & 0x80 ) {
copyColor = (*ptr - 0x80);
ptr++;
r = *ptr++;
g = *ptr++;
b = *ptr++;
r = ((r * weight/100) + (red * (100-weight)/100));
g = ((g * weight/100) + (green * (100-weight)/100));
b = ((b * weight/100) + (blue * (100-weight)/100));
copyColor--;
}
else {
readRGB = *ptr;
ptr++;
r = *ptr++;
g = *ptr++;
b = *ptr++;
r = ((r * weight/100) + (red * (100-weight)/100));
g = ((g * weight/100) + (green * (100-weight)/100));
b = ((b * weight/100) + (blue * (100-weight)/100));
readRGB--;
}
color = colorTransform24To16bpp(r,g,b);
DMDIF_writeData( color );
}
}
return DMD_OK;
}
/**************************************************************************//**
* @brief
* Draws pixels to the display at location x,y, from a source data array in
* GIMP RLE compressed C-format
* @param x
* X coordinate of the first pixel to be written, relative to the clipping area
* @param y
* Y coordinate of the first pixel to be written, relative to the clipping area
* @param data
* Array containing the pixel data in GIMP RLE compressed format
* @param numPixels
* Number of pixels to be written
* @return
* DMD_OK on success, otherwise error code
******************************************************************************/
EMSTATUS DMD_writeDataRLE(uint16_t x, uint16_t y, uint16_t xlen, uint16_t ylen,
const uint8_t *data)
{
uint32_t color = 0;
int xpos, ypos;
const uint8_t *ptr;
uint8_t r,g,b;
uint8_t readRGB = 0;
uint8_t copyColor = 0;
ptr = data;
for (ypos = y; ypos < (ylen+y); ypos++){
setPixelAddress(x, ypos);
DMDIF_prepareDataAccess( );
for (xpos = x; xpos < (xlen+x); xpos++){
if ( readRGB ) {
readRGB--;
r = *ptr++;
g = *ptr++;
b = *ptr++;
color = colorTransform24To16bpp(r,g,b);
DMDIF_writeData(color);
continue;
}
if ( copyColor ) {
copyColor--;
DMDIF_writeData( color );
continue;
}
if ( *ptr & 0x80 ) {
copyColor = (*ptr - 0x80);
ptr++;
r = *ptr++;
g = *ptr++;
b = *ptr++;
copyColor--;
} else {
readRGB = *ptr;
ptr++;
r = *ptr++;
g = *ptr++;
b = *ptr++;
readRGB--;
}
color = colorTransform24To16bpp(r,g,b);
DMDIF_writeData( color );
}
}
return DMD_OK;
}
/**************************************************************************//**
* @brief
* Reads data from display memory
* WORKING NOW, fixed by onelife
*
* @param x
* X coordinate of the first pixel to be read, relative to the clipping area
* @param y
* Y coordinate of the first pixel to be read, relative to the clipping area
* @param data
* Pointer to where the pixel data will be stored
* @param numPixels
* Number of pixels to be read
*
* @return
* DMD_OK on success, otherwise error code
******************************************************************************/
EMSTATUS DMD_readData(uint16_t x, uint16_t y,
uint8_t data[], uint32_t numPixels)
{
uint32_t statusCode;
uint32_t clipRemaining;
uint32_t i;
uint32_t color;
uint8_t red, green, blue;
if (!initialized)
{
return DMD_ERROR_DRIVER_NOT_INITIALIZED;
}
/* Set the address of the first pixel */
statusCode = setPixelAddress(x, y);
if (statusCode != DMD_OK)
{
return statusCode;
}
/* Number of pixels from the first pixel (given by x and y) to the end
* of the clipping area */
clipRemaining = (dimensions.clipHeight - y - 1) * dimensions.clipWidth +
dimensions.clipWidth - x;
/* Check that the length of data isn't longer than the number of pixels
* in the rest of the clipping area */
if (numPixels > clipRemaining)
{
return DMD_ERROR_TOO_MUCH_DATA;
}
/* Read data */
DMDIF_prepareDataAccess();
/* Dummy read */
color = DMDIF_readData();
for (i = 0; i < numPixels; i++)
{
/* Read the color value */
color = DMDIF_readData();
/* Transform into 24bpp */
colorTransform16To24bpp(color, &red, &green, &blue);
data[3 * i] = red;
data[3 * i + 1] = green;
data[3 * i + 2] = blue;
}
return DMD_OK;
}
/**************************************************************************//**
* \brief
* Draws a number of pixels of the same color to the display
*
* @param x
* X coordinate of the first pixel to be written, relative to the clipping area
* @param y
* Y coordinate of the first pixel to be written, relative to the clipping area
* @param red
* Red component of the color
* @param green
* Green component of the color
* @param blue
* Blue component of the color
* @param numPixels
* Number of pixels to be written
*
* @return
* DMD_OK on success, otherwise error code
******************************************************************************/
EMSTATUS DMD_writeColor(uint16_t x, uint16_t y, uint8_t red,
uint8_t green, uint8_t blue, uint32_t numPixels)
{
uint32_t clipRemaining;
uint32_t statusCode;
uint32_t color;
if (!initialized){
return DMD_ERROR_DRIVER_NOT_INITIALIZED;
}
/* Set the address of the first pixel */
statusCode = setPixelAddress(x, y);
if (statusCode != DMD_OK){
return statusCode;
}
/* Number of pixels from the first pixel (given by x and y) to the end
* of the clipping area */
clipRemaining = (dimensions.clipHeight - y - 1) * dimensions.clipWidth +
dimensions.clipWidth - x;
/* Check that the length of data isn't longer than the number of pixels
* in the rest of the clipping area */
if (numPixels > clipRemaining){
return DMD_ERROR_TOO_MUCH_DATA;
}
/* Write data */
DMDIF_prepareDataAccess( );
color = colorTransform24To16bpp(red, green, blue);
DMDIF_writeDataRepeated(color, numPixels);
return DMD_OK;
}
/**************************************************************************//**
* @brief
* Draws a number of pixels of the same color to the display
* This function is added by onelife
*
* @param x
* X coordinate of the pixel to be written, relative to the clipping area
* @param y
* Y coordinate of the pixel to be written, relative to the clipping area
* @param color
* RGB565 format
* @param numPixels
* Number of pixels to be written
*
* @return
* DMD_OK on success, otherwise error code
******************************************************************************/
EMSTATUS DMD_writePixel(uint16_t x, uint16_t y, uint16_t color,
uint32_t numPixels)
{
uint32_t clipRemaining;
uint32_t statusCode;
if (!initialized){
return DMD_ERROR_DRIVER_NOT_INITIALIZED;
}
/* Set the address of the first pixel */
statusCode = setPixelAddress(x, y);
if (statusCode != DMD_OK){
return statusCode;
}
/* Number of pixels from the first pixel (given by x and y) to the end
* of the clipping area */
clipRemaining = (dimensions.clipHeight - y - 1) * dimensions.clipWidth +
dimensions.clipWidth - x;
/* Check that the length of data isn't longer than the number of pixels
* in the rest of the clipping area */
if (numPixels > clipRemaining){
return DMD_ERROR_TOO_MUCH_DATA;
}
/* Write data */
DMDIF_prepareDataAccess( );
DMDIF_writeDataRepeated((uint32_t)color, numPixels);
return DMD_OK;
}
/**************************************************************************//**
* @brief
* Read the color of a specified pixel
* This function is added by onelife
*
* @param x
* X coordinate of the pixel to be written, relative to the clipping area
* @param y
* Y coordinate of the pixel to be written, relative to the clipping area
* @param color
* RGB565 format
*
* @return
* DMD_OK on success, otherwise error code
******************************************************************************/
EMSTATUS DMD_readPixel(uint16_t x, uint16_t y, uint16_t *color)
{
uint32_t statusCode;
if (!initialized){
return DMD_ERROR_DRIVER_NOT_INITIALIZED;
}
/* Set the address of the first pixel */
statusCode = setPixelAddress(x, y);
if (statusCode != DMD_OK){
return statusCode;
}
/* Read color */
DMDIF_prepareDataAccess( );
*color = DMDIF_readData() & 0x0000FFFF;
return DMD_OK;
}
/**************************************************************************//**
* @brief
* Turns off the display and puts it into sleep mode
* Does not turn off backlight
*
* @return
* DMD_OK on success, otherwise error code
******************************************************************************/
EMSTATUS DMD_sleep(void){
uint16_t data;
if (!initialized){
return DMD_ERROR_DRIVER_NOT_INITIALIZED;
}
/* Put into sleep mode */
data = DMD_SSD2119_SLEEP_MODE_1_SLP;
DMDIF_writeReg(DMD_SSD2119_SLEEP_MODE_1, data);
/* Turn off display */
data = 0;
DMDIF_writeReg(DMD_SSD2119_DISPLAY_CONTROL, 0x0000);
/* Delay 1.5 frame */
/*DMDIF_delay((1000 / DMD_FRAME_FREQUENCY) * 3 / 2);*/
return DMD_OK;
}
/**************************************************************************//**
* @brief
* Wakes up the display from sleep mode
*
* @return
* DMD_OK on success, otherwise error code
******************************************************************************/
EMSTATUS DMD_wakeUp(void){
uint16_t data;
if (!initialized){
return DMD_ERROR_DRIVER_NOT_INITIALIZED;
}
/* Get out of sleep mode */
data = 0;
DMDIF_writeReg(DMD_SSD2119_SLEEP_MODE_1, data);
/* Turn on display */
data = DMD_SSD2119_DISPLAY_CONTROL_DTE;
data |= DMD_SSD2119_DISPLAY_CONTROL_GON;
data |= DMD_SSD2119_DISPLAY_CONTROL_D1;
data |= DMD_SSD2119_DISPLAY_CONTROL_D0;
DMDIF_writeReg(DMD_SSD2119_DISPLAY_CONTROL, 0x0033);
/* Delay 10 frames */
/*DMDIF_delay((1000 / DMD_FRAME_FREQUENCY) * 10);*/
return DMD_OK;
}
/**************************************************************************//**
* @brief
* Transforms a 24bpp pixel data into an 16bpp pixel
*
* @param red
* 8-bit red component of the pixel
* @param green
* 8-bit green component of the pixel
* @param blue
* 8-bit blue component of the pixel
* @return
* 16bpp value of pixel
******************************************************************************/
static uint32_t colorTransform24To16bpp(uint8_t red, uint8_t green, uint8_t blue){
/* Transform each color into 6 bits by dropping the 2 LSB */
red = (red >> 3) & 0x1F;
green = (green >> 2) & 0x3F;
blue = (blue >> 3) & 0x1F;
/* Put it together to one 16bpp color number */
return (red << 11) | (green << 5) | blue;
}
/**************************************************************************//**
* @brief
* Transforms an 18 bpp pixel into a 24bpp pixel
*
* @param color
* 16bpp color pixel
* @param red
* return value for red component of 24bpp pixel
* @param green
* return value for green component of 24bpp pixel
* @param blue
* return value for blue component of 24bpp pixel
******************************************************************************/
static void colorTransform16To24bpp(uint32_t color, uint8_t *red,
uint8_t *green, uint8_t *blue){
/* Get the individual colors out of the 16bpp number */
uint8_t redValue = (color & 0x0000F800) >> 11;
uint8_t greenValue = (color & 0x000007E0) >> 5;
uint8_t blueValue = (color & 0x0000001F);
/* Convert each color to 8-bit */
redValue <<= 3;
greenValue <<= 2;
blueValue <<= 3;
*red = redValue;
*green = greenValue;
*blue = blueValue;
return;
}
/**************************************************************************//**
* @brief
* Set horizontal and vertical flip mode of display controller
*
* @param hor
* Set to flip display horizontally
*
* @param ver
* Set to flip display vertically
*
* @return
* Returns DMD_OK is successful, error otherwise.
******************************************************************************/
EMSTATUS DMD_flipDisplay(int horizontal, int vertical){
uint16_t reg;
reg = rcDriverOutputControl;
if (horizontal) reg &= ~DMD_SSD2119_DRIVER_OUTPUT_CONTROL_RL;
else reg |= DMD_SSD2119_DRIVER_OUTPUT_CONTROL_RL;
if (vertical) reg &= ~DMD_SSD2119_DRIVER_OUTPUT_CONTROL_TB;
else reg |= DMD_SSD2119_DRIVER_OUTPUT_CONTROL_TB;
rcDriverOutputControl = reg;
DMDIF_writeReg(DMD_SSD2119_DRIVER_OUTPUT_CONTROL, rcDriverOutputControl);
return DMD_OK;
}