123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529 |
- /***************************************************************************//**
- * @file
- * @brief Dot matrix display Direct Driver for TFT SSD2119 "Generic" mode
- * @author Energy Micro AS
- * @version 2.0.1
- *******************************************************************************
- * @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 "graphics/em_types.h"
- #include "dmdif_ssd2119_ebi.h"
- #include "dmd_ssd2119_registers.h"
- #include "dmd_ssd2119.h"
- #include "efm32.h"
- #include "em_usart.h"
- #include "em_cmu.h"
- #include "em_gpio.h"
- #include "tftspi.h"
- /** Dimensions of the display */
- DMD_DisplayGeometry dimensions =
- {
- .xSize = 320,
- .ySize = 240,
- .xClipStart = 0,
- .yClipStart = 0,
- .clipWidth = 320,
- .clipHeight = 240,
- };
- /** FramePointer base address */
- static volatile uint16_t *frameBuffer;
- /* Local variables */
- static uint32_t initialized = 0;
- static uint16_t rcDriverOutputControl = 0;
- /* Local function prototypes */
- static uint16_t colorTransform24ToRGB565(uint8_t red, uint8_t green, uint8_t blue);
- #if 0
- static void colorTransformRGB565To24bpp(uint16_t color, uint8_t *red, uint8_t *green, uint8_t *blue);
- #endif
- /**************************************************************************//**
- * @brief
- * Transforms a 24bpp pixel data into an RGB565 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
- * 16-bit RGB565 value of pixel
- ******************************************************************************/
- static uint16_t colorTransform24ToRGB565(uint8_t red, uint8_t green, uint8_t blue)
- {
- /* Transform each color into 6 bits by dropping the 2 LSB */
- red = red >> 3;
- green = green >> 2;
- blue = blue >> 3;
- /* Put it together to one 18bpp color number */
- return (red << 11) | (green << 5) | blue;
- }
- /**************************************************************************//**
- * @brief
- * Transforms an 16-bit RGB565 pixel into a 24bpp pixel
- *
- * @param[in] color
- * RGB565 16-bit 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
- ******************************************************************************/
- #if 0
- static void colorTransformRGB565To24bpp(uint16_t color, uint8_t *red,
- uint8_t *green, uint8_t *blue)
- {
- /* Get the individual colors out of the 18bpp number */
- uint8_t redValue = (color & 0x0003F000) >> 12;
- uint8_t greenValue = (color & 0x00000FC0) >> 6;
- uint8_t blueValue = (color & 0x0000003F);
- /* Convert each color to 8-bit */
- redValue <<= 2;
- greenValue <<= 2;
- blueValue <<= 2;
- *red = redValue;
- *green = greenValue;
- *blue = blueValue;
- return;
- }
- #endif
- /**************************************************************************//**
- * @brief
- * Writes a value to a control register in the LCD controller
- *
- * @param reg
- * The register that will be written to
- * @param data
- * The value to write to the register
- *
- * @return
- * DMD_OK on success, otherwise error code
- ******************************************************************************/
- EMSTATUS DMDIF_writeReg(uint8_t reg, uint16_t data)
- {
- SPI_TFT_WriteRegister(reg, data);
- return DMD_OK;
- }
- /**************************************************************************//**
- * @brief
- * Initializes the LCD display
- *
- * @param cmdRegAddr
- * If set to 0, initialize SSD2119 for direct drive, if set to 1 update
- * frame buffer base pointer (offset to EBI bank) only
- * @param dataRegAddr
- * Address in memory for frame buffer base pointer
- *
- * @return
- * DMD_OK on success, otherwise error code
- ******************************************************************************/
- EMSTATUS DMD_init(uint32_t cmdRegAddr, uint32_t dataRegAddr)
- {
- uint16_t data;
- volatile uint32_t i;
- (void) cmdRegAddr;
- (void) dataRegAddr;
- /* Use data reg addr as pointer to frame buffer */
- frameBuffer = (uint16_t *) dataRegAddr;
- if(cmdRegAddr==1) return DMD_OK;
- SPI_TFT_Init();
- DMDIF_writeReg(DMD_SSD2119_VCOM_OTP_1, 0x0006);
- /* Oscillation driven DCLK */
- #if 0
- data = DMD_SSD2119_OSCILLATION_START_OSCEN;
- DMDIF_writeReg(DMD_SSD2119_OSCILLATION_START, data);
- #endif
- /* Display control */
- data = 0;
- // 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, data);
- /* Exit sleep mode */
- data = 0;
- DMDIF_writeReg(DMD_SSD2119_SLEEP_MODE_1, data);
- /* Wait */
- for (i = 0; i < 100000; i++);
- /* Display control */
- DMDIF_writeReg(DMD_SSD2119_DISPLAY_CONTROL, 0x33);
- /* Entry mode */
- data = DMD_SSD2119_ENTRY_MODE_DFM_65K << DMD_SSD2119_ENTRY_MODE_DFM_SHIFT;
- data |= DMD_SSD2119_ENTRY_MODE_WMODE;
- data |= DMD_SSD2119_ENTRY_MODE_NOSYNC;
- data |= DMD_SSD2119_ENTRY_MODE_DMODE;
- data |= DMD_SSD2119_ENTRY_MODE_ID1;
- data |= DMD_SSD2119_ENTRY_MODE_ID0;
- DMDIF_writeReg(DMD_SSD2119_ENTRY_MODE, data);
- // DMDIF_writeReg(DMD_SSD2119_DRIVER_OUTPUT_CONTROL, 0x3aef);
- /* Generic Interface Control */
- // data = DMD_SSD2119_GENERIC_INTERFACE_CONTROL_INVDEN;
- // DMDIF_writeReg(DMD_SSD2119_GENERIC_INTERFACE_CONTROL, data);
- /* Driver output control */
- data = 0;
- data |= DMD_SSD2119_DRIVER_OUTPUT_CONTROL_REV;
- data |= DMD_SSD2119_DRIVER_OUTPUT_CONTROL_GD;
- // data |= DMD_SSD2119_DRIVER_OUTPUT_CONTROL_TB;
- // data |= DMD_SSD2119_DRIVER_OUTPUT_CONTROL_SM;
- // data |= DMD_SSD2119_DRIVER_OUTPUT_CONTROL_RL;
- data |= ((DMD_VERTICAL_SIZE - 1) << DMD_SSD2119_DRIVER_OUTPUT_CONTROL_MUX_SHIFT);
- DMDIF_writeReg(DMD_SSD2119_DRIVER_OUTPUT_CONTROL, data);
- /* LCD AC control */
- data = DMD_SSD2119_LCD_AC_CONTROL_BC;
- data |= DMD_SSD2119_LCD_AC_CONTROL_EOR;
- /* data |= DMD_SSD2119_LCD_AC_CONTROL_FLC; */
- DMDIF_writeReg(DMD_SSD2119_LCD_AC_CONTROL, data);
- /* RAM data write */
- data = 0xff;
- DMDIF_writeReg(DMD_SSD2119_ACCESS_DATA, data);
- /* Mark graphics as initialized */
- initialized = 1;
- 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)
- {
- 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;
- }
- /* Update the dimensions structure */
- dimensions.xClipStart = xStart;
- dimensions.yClipStart = yStart;
- dimensions.clipWidth = width;
- dimensions.clipHeight = height;
- 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)
- {
- uint8_t *dest = (uint8_t *)((uint32_t) frameBuffer +
- (uint32_t) (y*dimensions.xSize*sizeof(uint16_t)) +
- (uint32_t) (x*sizeof(uint16_t)));
- while(numPixels--)
- {
- *dest++ = *data++;
- }
- return DMD_OK;
- }
- /**************************************************************************//**
- * @brief
- * Reads data from display memory
- * DOESN'T WORK yet - TIMING ISSUE?
- *
- * @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)
- {
- uint8_t *source = (uint8_t *)((uint32_t) frameBuffer +
- (uint32_t) (y*dimensions.xSize*sizeof(uint16_t)) +
- (uint32_t) (x*sizeof(uint16_t)));
- if (y > dimensions.ySize) return DMD_ERROR_PIXEL_OUT_OF_BOUNDS;
- while(numPixels--)
- {
- *data++ = *source++;
- }
- 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)
- {
- uint16_t color;
- uint16_t xStart = x;
- uint16_t *pixelPointer = (uint16_t *)
- ((uint32_t) frameBuffer +
- (uint32_t) ((y+dimensions.yClipStart)*dimensions.xSize*sizeof(uint16_t)) +
- (uint32_t) ((x+dimensions.xClipStart)*sizeof(uint16_t)));
- color = colorTransform24ToRGB565(red,green,blue);
- /* Draw the requied number of pixels */
- while(numPixels--)
- {
- x++;
- *pixelPointer++ = color;
- /* Increment line, start at the right x position inside clipping region */
- if (x>=dimensions.clipWidth)
- {
- x = xStart;
- pixelPointer = (uint16_t *)
- ((uint32_t) frameBuffer +
- (uint32_t) (((++y)+dimensions.yClipStart)*dimensions.xSize*sizeof(uint16_t)) +
- (uint32_t) ((xStart+dimensions.xClipStart)*sizeof(uint16_t)));
- }
- }
- 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, data);
- /* Delay 10 frames */
- /*DMDIF_delay((1000 / DMD_FRAME_FREQUENCY) * 10);*/
- return DMD_OK;
- }
- /**************************************************************************//**
- * @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;
- }
|