dmd_ssd2119_direct.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  1. /***************************************************************************//**
  2. * @file
  3. * @brief Dot matrix display Direct Driver for TFT SSD2119 "Generic" mode
  4. * @author Energy Micro AS
  5. * @version 2.0.1
  6. *******************************************************************************
  7. * @section License
  8. * <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
  9. *******************************************************************************
  10. *
  11. * Permission is granted to anyone to use this software for any purpose,
  12. * including commercial applications, and to alter it and redistribute it
  13. * freely, subject to the following restrictions:
  14. *
  15. * 1. The origin of this software must not be misrepresented; you must not
  16. * claim that you wrote the original software.
  17. * 2. Altered source versions must be plainly marked as such, and must not be
  18. * misrepresented as being the original software.
  19. * 3. This notice may not be removed or altered from any source distribution.
  20. * 4. The source and compiled code may only be used on Energy Micro "EFM32"
  21. * microcontrollers and "EFR4" radios.
  22. *
  23. * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
  24. * obligation to support this Software. Energy Micro AS is providing the
  25. * Software "AS IS", with no express or implied warranties of any kind,
  26. * including, but not limited to, any implied warranties of merchantability
  27. * or fitness for any particular purpose or warranties against infringement
  28. * of any proprietary rights of a third party.
  29. *
  30. * Energy Micro AS will not be liable for any consequential, incidental, or
  31. * special damages, or any other relief, or for any claim by any third party,
  32. * arising from your use of this Software.
  33. *
  34. *****************************************************************************/
  35. #include <stdint.h>
  36. #include "graphics/em_types.h"
  37. #include "dmdif_ssd2119_ebi.h"
  38. #include "dmd_ssd2119_registers.h"
  39. #include "dmd_ssd2119.h"
  40. #include "efm32.h"
  41. #include "em_usart.h"
  42. #include "em_cmu.h"
  43. #include "em_gpio.h"
  44. #include "tftspi.h"
  45. /** Dimensions of the display */
  46. DMD_DisplayGeometry dimensions =
  47. {
  48. .xSize = 320,
  49. .ySize = 240,
  50. .xClipStart = 0,
  51. .yClipStart = 0,
  52. .clipWidth = 320,
  53. .clipHeight = 240,
  54. };
  55. /** FramePointer base address */
  56. static volatile uint16_t *frameBuffer;
  57. /* Local variables */
  58. static uint32_t initialized = 0;
  59. static uint16_t rcDriverOutputControl = 0;
  60. /* Local function prototypes */
  61. static uint16_t colorTransform24ToRGB565(uint8_t red, uint8_t green, uint8_t blue);
  62. #if 0
  63. static void colorTransformRGB565To24bpp(uint16_t color, uint8_t *red, uint8_t *green, uint8_t *blue);
  64. #endif
  65. /**************************************************************************//**
  66. * @brief
  67. * Transforms a 24bpp pixel data into an RGB565 pixel
  68. *
  69. * @param red
  70. * 8-bit red component of the pixel
  71. * @param green
  72. * 8-bit green component of the pixel
  73. * @param blue
  74. * 8-bit blue component of the pixel
  75. * @return
  76. * 16-bit RGB565 value of pixel
  77. ******************************************************************************/
  78. static uint16_t colorTransform24ToRGB565(uint8_t red, uint8_t green, uint8_t blue)
  79. {
  80. /* Transform each color into 6 bits by dropping the 2 LSB */
  81. red = red >> 3;
  82. green = green >> 2;
  83. blue = blue >> 3;
  84. /* Put it together to one 18bpp color number */
  85. return (red << 11) | (green << 5) | blue;
  86. }
  87. /**************************************************************************//**
  88. * @brief
  89. * Transforms an 16-bit RGB565 pixel into a 24bpp pixel
  90. *
  91. * @param[in] color
  92. * RGB565 16-bit color pixel
  93. * @param red
  94. * return value for red component of 24bpp pixel
  95. * @param green
  96. * return value for green component of 24bpp pixel
  97. * @param blue
  98. * return value for blue component of 24bpp pixel
  99. ******************************************************************************/
  100. #if 0
  101. static void colorTransformRGB565To24bpp(uint16_t color, uint8_t *red,
  102. uint8_t *green, uint8_t *blue)
  103. {
  104. /* Get the individual colors out of the 18bpp number */
  105. uint8_t redValue = (color & 0x0003F000) >> 12;
  106. uint8_t greenValue = (color & 0x00000FC0) >> 6;
  107. uint8_t blueValue = (color & 0x0000003F);
  108. /* Convert each color to 8-bit */
  109. redValue <<= 2;
  110. greenValue <<= 2;
  111. blueValue <<= 2;
  112. *red = redValue;
  113. *green = greenValue;
  114. *blue = blueValue;
  115. return;
  116. }
  117. #endif
  118. /**************************************************************************//**
  119. * @brief
  120. * Writes a value to a control register in the LCD controller
  121. *
  122. * @param reg
  123. * The register that will be written to
  124. * @param data
  125. * The value to write to the register
  126. *
  127. * @return
  128. * DMD_OK on success, otherwise error code
  129. ******************************************************************************/
  130. EMSTATUS DMDIF_writeReg(uint8_t reg, uint16_t data)
  131. {
  132. SPI_TFT_WriteRegister(reg, data);
  133. return DMD_OK;
  134. }
  135. /**************************************************************************//**
  136. * @brief
  137. * Initializes the LCD display
  138. *
  139. * @param cmdRegAddr
  140. * If set to 0, initialize SSD2119 for direct drive, if set to 1 update
  141. * frame buffer base pointer (offset to EBI bank) only
  142. * @param dataRegAddr
  143. * Address in memory for frame buffer base pointer
  144. *
  145. * @return
  146. * DMD_OK on success, otherwise error code
  147. ******************************************************************************/
  148. EMSTATUS DMD_init(uint32_t cmdRegAddr, uint32_t dataRegAddr)
  149. {
  150. uint16_t data;
  151. volatile uint32_t i;
  152. (void) cmdRegAddr;
  153. (void) dataRegAddr;
  154. /* Use data reg addr as pointer to frame buffer */
  155. frameBuffer = (uint16_t *) dataRegAddr;
  156. if(cmdRegAddr==1) return DMD_OK;
  157. SPI_TFT_Init();
  158. DMDIF_writeReg(DMD_SSD2119_VCOM_OTP_1, 0x0006);
  159. /* Oscillation driven DCLK */
  160. #if 0
  161. data = DMD_SSD2119_OSCILLATION_START_OSCEN;
  162. DMDIF_writeReg(DMD_SSD2119_OSCILLATION_START, data);
  163. #endif
  164. /* Display control */
  165. data = 0;
  166. // data |= DMD_SSD2119_DISPLAY_CONTROL_DTE;
  167. data |= DMD_SSD2119_DISPLAY_CONTROL_GON;
  168. data |= DMD_SSD2119_DISPLAY_CONTROL_D1;
  169. data |= DMD_SSD2119_DISPLAY_CONTROL_D0;
  170. DMDIF_writeReg(DMD_SSD2119_DISPLAY_CONTROL, data);
  171. /* Exit sleep mode */
  172. data = 0;
  173. DMDIF_writeReg(DMD_SSD2119_SLEEP_MODE_1, data);
  174. /* Wait */
  175. for (i = 0; i < 100000; i++);
  176. /* Display control */
  177. DMDIF_writeReg(DMD_SSD2119_DISPLAY_CONTROL, 0x33);
  178. /* Entry mode */
  179. data = DMD_SSD2119_ENTRY_MODE_DFM_65K << DMD_SSD2119_ENTRY_MODE_DFM_SHIFT;
  180. data |= DMD_SSD2119_ENTRY_MODE_WMODE;
  181. data |= DMD_SSD2119_ENTRY_MODE_NOSYNC;
  182. data |= DMD_SSD2119_ENTRY_MODE_DMODE;
  183. data |= DMD_SSD2119_ENTRY_MODE_ID1;
  184. data |= DMD_SSD2119_ENTRY_MODE_ID0;
  185. DMDIF_writeReg(DMD_SSD2119_ENTRY_MODE, data);
  186. // DMDIF_writeReg(DMD_SSD2119_DRIVER_OUTPUT_CONTROL, 0x3aef);
  187. /* Generic Interface Control */
  188. // data = DMD_SSD2119_GENERIC_INTERFACE_CONTROL_INVDEN;
  189. // DMDIF_writeReg(DMD_SSD2119_GENERIC_INTERFACE_CONTROL, data);
  190. /* Driver output control */
  191. data = 0;
  192. data |= DMD_SSD2119_DRIVER_OUTPUT_CONTROL_REV;
  193. data |= DMD_SSD2119_DRIVER_OUTPUT_CONTROL_GD;
  194. // data |= DMD_SSD2119_DRIVER_OUTPUT_CONTROL_TB;
  195. // data |= DMD_SSD2119_DRIVER_OUTPUT_CONTROL_SM;
  196. // data |= DMD_SSD2119_DRIVER_OUTPUT_CONTROL_RL;
  197. data |= ((DMD_VERTICAL_SIZE - 1) << DMD_SSD2119_DRIVER_OUTPUT_CONTROL_MUX_SHIFT);
  198. DMDIF_writeReg(DMD_SSD2119_DRIVER_OUTPUT_CONTROL, data);
  199. /* LCD AC control */
  200. data = DMD_SSD2119_LCD_AC_CONTROL_BC;
  201. data |= DMD_SSD2119_LCD_AC_CONTROL_EOR;
  202. /* data |= DMD_SSD2119_LCD_AC_CONTROL_FLC; */
  203. DMDIF_writeReg(DMD_SSD2119_LCD_AC_CONTROL, data);
  204. /* RAM data write */
  205. data = 0xff;
  206. DMDIF_writeReg(DMD_SSD2119_ACCESS_DATA, data);
  207. /* Mark graphics as initialized */
  208. initialized = 1;
  209. return DMD_OK;
  210. }
  211. /**************************************************************************//**
  212. * @brief
  213. * Get the dimensions of the display and of the current clipping area
  214. *
  215. * @return
  216. * DMD_Dimensions structure containing the size of the display and the
  217. * clipping area
  218. ******************************************************************************/
  219. EMSTATUS DMD_getDisplayGeometry(DMD_DisplayGeometry **geometry)
  220. {
  221. if (!initialized)
  222. {
  223. return DMD_ERROR_DRIVER_NOT_INITIALIZED;
  224. }
  225. *geometry = &dimensions;
  226. return DMD_OK;
  227. }
  228. /**************************************************************************//**
  229. * @brief
  230. * Sets the clipping area. All coordinates given to writeData/writeColor/readData
  231. * are relative to this clipping area.
  232. *
  233. * @param xStart
  234. * X coordinate of the upper left corner of the clipping area
  235. * @param yStart
  236. * Y coordinate of the upper left corner of the clipping area
  237. * @param width
  238. * Width of the clipping area
  239. * @param height
  240. * Height of the clipping area
  241. *
  242. * @return
  243. * DMD_OK on success, otherwise error code
  244. ******************************************************************************/
  245. EMSTATUS DMD_setClippingArea(uint16_t xStart, uint16_t yStart,
  246. uint16_t width, uint16_t height)
  247. {
  248. if (!initialized)
  249. {
  250. return DMD_ERROR_DRIVER_NOT_INITIALIZED;
  251. }
  252. /* Check parameters */
  253. if (xStart + width > dimensions.xSize ||
  254. yStart + height > dimensions.ySize)
  255. {
  256. return DMD_ERROR_PIXEL_OUT_OF_BOUNDS;
  257. }
  258. if (width == 0 || height == 0)
  259. {
  260. return DMD_ERROR_EMPTY_CLIPPING_AREA;
  261. }
  262. /* Update the dimensions structure */
  263. dimensions.xClipStart = xStart;
  264. dimensions.yClipStart = yStart;
  265. dimensions.clipWidth = width;
  266. dimensions.clipHeight = height;
  267. return DMD_OK;
  268. }
  269. /**************************************************************************//**
  270. * @brief
  271. * Draws pixels to the display
  272. *
  273. * @param x
  274. * X coordinate of the first pixel to be written, relative to the clipping area
  275. * @param y
  276. * Y coordinate of the first pixel to be written, relative to the clipping area
  277. * @param data
  278. * Array containing the pixel data. Each 8-bit element in the array are one color
  279. * component of the pixel, so that 3 bytes represent one pixel. The pixels are
  280. * ordered by increasing x coordinate, after the last pixel of a row, the next
  281. * pixel will be the first pixel on the next row.
  282. * @param numPixels
  283. * Number of pixels to be written
  284. *
  285. * @return
  286. * DMD_OK on success, otherwise error code
  287. ******************************************************************************/
  288. EMSTATUS DMD_writeData(uint16_t x, uint16_t y, const uint8_t data[],
  289. uint32_t numPixels)
  290. {
  291. uint8_t *dest = (uint8_t *)((uint32_t) frameBuffer +
  292. (uint32_t) (y*dimensions.xSize*sizeof(uint16_t)) +
  293. (uint32_t) (x*sizeof(uint16_t)));
  294. while(numPixels--)
  295. {
  296. *dest++ = *data++;
  297. }
  298. return DMD_OK;
  299. }
  300. /**************************************************************************//**
  301. * @brief
  302. * Reads data from display memory
  303. * DOESN'T WORK yet - TIMING ISSUE?
  304. *
  305. * @param x
  306. * X coordinate of the first pixel to be read, relative to the clipping area
  307. * @param y
  308. * Y coordinate of the first pixel to be read, relative to the clipping area
  309. * @param data
  310. * Pointer to where the pixel data will be stored
  311. * @param numPixels
  312. * Number of pixels to be read
  313. *
  314. * @return
  315. * DMD_OK on success, otherwise error code
  316. ******************************************************************************/
  317. EMSTATUS DMD_readData(uint16_t x, uint16_t y,
  318. uint8_t data[], uint32_t numPixels)
  319. {
  320. uint8_t *source = (uint8_t *)((uint32_t) frameBuffer +
  321. (uint32_t) (y*dimensions.xSize*sizeof(uint16_t)) +
  322. (uint32_t) (x*sizeof(uint16_t)));
  323. if (y > dimensions.ySize) return DMD_ERROR_PIXEL_OUT_OF_BOUNDS;
  324. while(numPixels--)
  325. {
  326. *data++ = *source++;
  327. }
  328. return DMD_OK;
  329. }
  330. /**************************************************************************//**
  331. * \brief
  332. * Draws a number of pixels of the same color to the display
  333. *
  334. * @param x
  335. * X coordinate of the first pixel to be written, relative to the clipping area
  336. * @param y
  337. * Y coordinate of the first pixel to be written, relative to the clipping area
  338. * @param red
  339. * Red component of the color
  340. * @param green
  341. * Green component of the color
  342. * @param blue
  343. * Blue component of the color
  344. * @param numPixels
  345. * Number of pixels to be written
  346. *
  347. * @return
  348. * DMD_OK on success, otherwise error code
  349. ******************************************************************************/
  350. EMSTATUS DMD_writeColor(uint16_t x, uint16_t y,
  351. uint8_t red, uint8_t green, uint8_t blue, uint32_t numPixels)
  352. {
  353. uint16_t color;
  354. uint16_t xStart = x;
  355. uint16_t *pixelPointer = (uint16_t *)
  356. ((uint32_t) frameBuffer +
  357. (uint32_t) ((y+dimensions.yClipStart)*dimensions.xSize*sizeof(uint16_t)) +
  358. (uint32_t) ((x+dimensions.xClipStart)*sizeof(uint16_t)));
  359. color = colorTransform24ToRGB565(red,green,blue);
  360. /* Draw the requied number of pixels */
  361. while(numPixels--)
  362. {
  363. x++;
  364. *pixelPointer++ = color;
  365. /* Increment line, start at the right x position inside clipping region */
  366. if (x>=dimensions.clipWidth)
  367. {
  368. x = xStart;
  369. pixelPointer = (uint16_t *)
  370. ((uint32_t) frameBuffer +
  371. (uint32_t) (((++y)+dimensions.yClipStart)*dimensions.xSize*sizeof(uint16_t)) +
  372. (uint32_t) ((xStart+dimensions.xClipStart)*sizeof(uint16_t)));
  373. }
  374. }
  375. return DMD_OK;
  376. }
  377. /**************************************************************************//**
  378. * @brief
  379. * Turns off the display and puts it into sleep mode
  380. * Does not turn off backlight
  381. *
  382. * @return
  383. * DMD_OK on success, otherwise error code
  384. ******************************************************************************/
  385. EMSTATUS DMD_sleep(void)
  386. {
  387. uint16_t data;
  388. if (!initialized)
  389. {
  390. return DMD_ERROR_DRIVER_NOT_INITIALIZED;
  391. }
  392. /* Put into sleep mode */
  393. data = DMD_SSD2119_SLEEP_MODE_1_SLP;
  394. DMDIF_writeReg(DMD_SSD2119_SLEEP_MODE_1, data);
  395. /* Turn off display */
  396. data = 0;
  397. DMDIF_writeReg(DMD_SSD2119_DISPLAY_CONTROL, 0x0000);
  398. /* Delay 1.5 frame */
  399. /*DMDIF_delay((1000 / DMD_FRAME_FREQUENCY) * 3 / 2);*/
  400. return DMD_OK;
  401. }
  402. /**************************************************************************//**
  403. * @brief
  404. * Wakes up the display from sleep mode
  405. *
  406. * @return
  407. * DMD_OK on success, otherwise error code
  408. ******************************************************************************/
  409. EMSTATUS DMD_wakeUp(void)
  410. {
  411. uint16_t data;
  412. if (!initialized)
  413. {
  414. return DMD_ERROR_DRIVER_NOT_INITIALIZED;
  415. }
  416. /* Get out of sleep mode */
  417. data = 0;
  418. DMDIF_writeReg(DMD_SSD2119_SLEEP_MODE_1, data);
  419. /* Turn on display */
  420. data = DMD_SSD2119_DISPLAY_CONTROL_DTE;
  421. data |= DMD_SSD2119_DISPLAY_CONTROL_GON;
  422. data |= DMD_SSD2119_DISPLAY_CONTROL_D1;
  423. data |= DMD_SSD2119_DISPLAY_CONTROL_D0;
  424. DMDIF_writeReg(DMD_SSD2119_DISPLAY_CONTROL, data);
  425. /* Delay 10 frames */
  426. /*DMDIF_delay((1000 / DMD_FRAME_FREQUENCY) * 10);*/
  427. return DMD_OK;
  428. }
  429. /**************************************************************************//**
  430. * @brief
  431. * Set horizontal and vertical flip mode of display controller
  432. *
  433. * @param hor
  434. * Set to flip display horizontally
  435. *
  436. * @param ver
  437. * Set to flip display vertically
  438. *
  439. * @return
  440. * Returns DMD_OK is successful, error otherwise.
  441. ******************************************************************************/
  442. EMSTATUS DMD_flipDisplay(int horizontal, int vertical)
  443. {
  444. uint16_t reg;
  445. reg = rcDriverOutputControl;
  446. if (horizontal) reg &= ~DMD_SSD2119_DRIVER_OUTPUT_CONTROL_RL;
  447. else reg |= DMD_SSD2119_DRIVER_OUTPUT_CONTROL_RL;
  448. if (vertical) reg &= ~DMD_SSD2119_DRIVER_OUTPUT_CONTROL_TB;
  449. else reg |= DMD_SSD2119_DRIVER_OUTPUT_CONTROL_TB;
  450. rcDriverOutputControl = reg;
  451. DMDIF_writeReg(DMD_SSD2119_DRIVER_OUTPUT_CONTROL, rcDriverOutputControl);
  452. return DMD_OK;
  453. }