946 lines
28 KiB
C
946 lines
28 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;
|
|
|
|
}
|