p14201.c 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184
  1. /**************************************************************************************
  2. * drivers/lcd/p14201.c
  3. * Driver for RiT P14201 series display (wih SD1329 IC controller)
  4. *
  5. * Copyright (C) 2010, 2012 Gregory Nutt. All rights reserved.
  6. * Author: Gregory Nutt <gnutt@nuttx.org>
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. * 3. Neither the name NuttX nor the names of its contributors may be
  19. * used to endorse or promote products derived from this software
  20. * without specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  25. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  26. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  27. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  28. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  29. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  30. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  31. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  32. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33. * POSSIBILITY OF SUCH DAMAGE.
  34. *
  35. **************************************************************************************/
  36. /**************************************************************************************
  37. * Included Files
  38. **************************************************************************************/
  39. #include <nuttx/config.h>
  40. #include <sys/types.h>
  41. #include <stdint.h>
  42. #include <stdbool.h>
  43. #include <string.h>
  44. #include <errno.h>
  45. #include <debug.h>
  46. #include <nuttx/arch.h>
  47. #include <nuttx/spi/spi.h>
  48. #include <nuttx/lcd/lcd.h>
  49. #include <nuttx/lcd/p14201.h>
  50. #include <arch/irq.h>
  51. #include "sd1329.h"
  52. #ifdef CONFIG_LCD_P14201
  53. /**************************************************************************************
  54. * Pre-processor Definitions
  55. **************************************************************************************/
  56. /* Configuration **********************************************************************/
  57. /* P14201 Configuration Settings:
  58. *
  59. * CONFIG_P14201_SPIMODE - Controls the SPI mode
  60. * CONFIG_P14201_FREQUENCY - Define to use a different bus frequency
  61. * CONFIG_P14201_NINTERFACES - Specifies the number of physical P14201 devices that
  62. * will be supported.
  63. * CONFIG_P14201_FRAMEBUFFER - If defined, accesses will be performed using an in-memory
  64. * copy of the OLEDs GDDRAM. This cost of this buffer is 128 * 96 / 2 = 6Kb. If this
  65. * is defined, then the driver will be fully functional. If not, then it will have the
  66. * following limitations:
  67. *
  68. * - Reading graphics memory cannot be supported, and
  69. * - All pixel writes must be aligned to byte boundaries.
  70. *
  71. * The latter limitation effectively reduces the 128x96 disply to 64x96.
  72. *
  73. * Required LCD driver settings:
  74. * CONFIG_LCD_P14201 - Enable P14201 support
  75. * CONFIG_LCD_MAXCONTRAST should be 255, but any value >0 and <=255 will be accepted.
  76. * CONFIG_LCD_MAXPOWER must be 1
  77. *
  78. * Required SPI driver settings:
  79. * CONFIG_SPI_CMDDATA - Include support for cmd/data selection.
  80. */
  81. #ifndef CONFIG_SPI_CMDDATA
  82. # error "CONFIG_SPI_CMDDATA must be defined in your NuttX configuration"
  83. #endif
  84. /* The P14201 spec says that is supports SPI mode 0,0 only. However,
  85. * somtimes you need to tinker with these things.
  86. */
  87. #ifndef CONFIG_P14201_SPIMODE
  88. # define CONFIG_P14201_SPIMODE SPIDEV_MODE2
  89. #endif
  90. /* CONFIG_P14201_NINTERFACES determines the number of physical interfaces
  91. * that will be supported.
  92. */
  93. #ifndef CONFIG_P14201_NINTERFACES
  94. # define CONFIG_P14201_NINTERFACES 1
  95. #endif
  96. #if CONFIG_P14201_NINTERFACES != 1
  97. # error "This implementation supports only a single OLED device"
  98. #endif
  99. /* Check contrast selection */
  100. #if !defined(CONFIG_LCD_MAXCONTRAST)
  101. # define CONFIG_LCD_MAXCONTRAST 255
  102. #endif
  103. #if CONFIG_LCD_MAXCONTRAST <= 0|| CONFIG_LCD_MAXCONTRAST > 255
  104. # error "CONFIG_LCD_MAXCONTRAST exceeds supported maximum"
  105. #endif
  106. /* Check power setting */
  107. #if !defined(CONFIG_LCD_MAXPOWER)
  108. # define CONFIG_LCD_MAXPOWER 1
  109. #endif
  110. #if CONFIG_LCD_MAXPOWER != 1
  111. # warning "CONFIG_LCD_MAXPOWER exceeds supported maximum"
  112. # undef CONFIG_LCD_MAXPOWER
  113. # define CONFIG_LCD_MAXPOWER 1
  114. #endif
  115. /* Define the CONFIG_LCD_RITDEBUG to enable detailed debug output (stuff you would
  116. * never want to see unless you are debugging this file).
  117. *
  118. * Verbose debug must also be enabled
  119. */
  120. #ifndef CONFIG_DEBUG_FEATURES
  121. # undef CONFIG_DEBUG_INFO
  122. # undef CONFIG_DEBUG_GRAPHICS
  123. #endif
  124. #ifndef CONFIG_DEBUG_INFO
  125. # undef CONFIG_LCD_RITDEBUG
  126. #endif
  127. /* Color Properties *******************************************************************/
  128. /* Display Resolution */
  129. #define RIT_XRES 128
  130. #define RIT_YRES 96
  131. /* Color depth and format */
  132. #define RIT_BPP 4
  133. #define RIT_COLORFMT FB_FMT_Y4
  134. /* Default contrast */
  135. #define RIT_CONTRAST ((23 * (CONFIG_LCD_MAXCONTRAST+1) / 32) - 1)
  136. /* Helper Macros **********************************************************************/
  137. #define rit_sndcmd(p,b,l) rit_sndbytes(p,b,l,true);
  138. #define rit_snddata(p,b,l) rit_sndbytes(p,b,l,false);
  139. /* Debug ******************************************************************************/
  140. #ifdef CONFIG_LCD_RITDEBUG
  141. # define riterr(format, ...) _err(format, ##__VA_ARGS__)
  142. # define ritwarn(format, ...) _warn(format, ##__VA_ARGS__)
  143. # define ritinfo(format, ...) _info(format, ##__VA_ARGS__)
  144. #else
  145. # define riterr(x...)
  146. # define ritwarn(x...)
  147. # define ritinfo(x...)
  148. #endif
  149. /**************************************************************************************
  150. * Private Type Definition
  151. **************************************************************************************/
  152. /* This structure describes the state of this driver */
  153. struct rit_dev_s
  154. {
  155. struct lcd_dev_s dev; /* Publically visible device structure */
  156. FAR struct spi_dev_s *spi; /* Cached SPI device reference */
  157. uint8_t contrast; /* Current contrast setting */
  158. bool on; /* true: display is on */
  159. };
  160. /**************************************************************************************
  161. * Private Function Protototypes
  162. **************************************************************************************/
  163. /* Low-level SPI helpers */
  164. static void rit_select(FAR struct spi_dev_s *spi);
  165. static void rit_deselect(FAR struct spi_dev_s *spi);
  166. static void rit_sndbytes(FAR struct rit_dev_s *priv, FAR const uint8_t *buffer,
  167. size_t buflen, bool cmd);
  168. static void rit_sndcmds(FAR struct rit_dev_s *priv, FAR const uint8_t *table);
  169. /* LCD Data Transfer Methods */
  170. static int rit_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer,
  171. size_t npixels);
  172. static int rit_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer,
  173. size_t npixels);
  174. /* LCD Configuration */
  175. static int rit_getvideoinfo(FAR struct lcd_dev_s *dev,
  176. FAR struct fb_videoinfo_s *vinfo);
  177. static int rit_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno,
  178. FAR struct lcd_planeinfo_s *pinfo);
  179. /* LCD RGB Mapping */
  180. #ifdef CONFIG_FB_CMAP
  181. # error "RGB color mapping not supported by this driver"
  182. #endif
  183. /* Cursor Controls */
  184. #ifdef CONFIG_FB_HWCURSOR
  185. # error "Cursor control not supported by this driver"
  186. #endif
  187. /* LCD Specific Controls */
  188. static int rit_getpower(struct lcd_dev_s *dev);
  189. static int rit_setpower(struct lcd_dev_s *dev, int power);
  190. static int rit_getcontrast(struct lcd_dev_s *dev);
  191. static int rit_setcontrast(struct lcd_dev_s *dev, unsigned int contrast);
  192. /**************************************************************************************
  193. * Private Data
  194. **************************************************************************************/
  195. /* This is working memory allocated by the LCD driver for each LCD device
  196. * and for each color plane. This memory will hold one raster line of data.
  197. * The size of the allocated run buffer must therefore be at least
  198. * (bpp * xres / 8). Actual alignment of the buffer must conform to the
  199. * bitwidth of the underlying pixel type.
  200. *
  201. * If there are multiple planes, they may share the same working buffer
  202. * because different planes will not be operate on concurrently. However,
  203. * if there are multiple LCD devices, they must each have unique run buffers.
  204. */
  205. static uint8_t g_runbuffer[RIT_XRES / 2];
  206. /* CONFIG_P14201_FRAMEBUFFER - If defined, accesses will be performed using an in-memory
  207. * copy of the OLEDs GDDRAM. This cost of this buffer is 128 * 64 / 2 = 4Kb. If this
  208. * is defined, then the driver will be full functional. If not, then:
  209. *
  210. * - Reading graphics memory cannot be supported, and
  211. * - All pixel writes must be aligned to byte boundaries.
  212. */
  213. #ifdef CONFIG_P14201_FRAMEBUFFER
  214. static uint8_t g_framebuffer[RIT_YRES * RIT_XRES / 2];
  215. #endif
  216. /* This structure describes the overall LCD video controller */
  217. static const struct fb_videoinfo_s g_videoinfo =
  218. {
  219. .fmt = RIT_COLORFMT, /* Color format: RGB16-565: RRRR RGGG GGGB BBBB */
  220. .xres = RIT_XRES, /* Horizontal resolution in pixel columns */
  221. .yres = RIT_YRES, /* Vertical resolution in pixel rows */
  222. .nplanes = 1, /* Number of color planes supported */
  223. };
  224. /* This is the standard, NuttX Plane information object */
  225. static const struct lcd_planeinfo_s g_planeinfo =
  226. {
  227. .putrun = rit_putrun, /* Put a run into LCD memory */
  228. .getrun = rit_getrun, /* Get a run from LCD memory */
  229. .buffer = (FAR uint8_t *)g_runbuffer, /* Run scratch buffer */
  230. .bpp = RIT_BPP, /* Bits-per-pixel */
  231. };
  232. /* This is the OLED driver instance (only a single device is supported for now) */
  233. static struct rit_dev_s g_oleddev =
  234. {
  235. .dev =
  236. {
  237. /* LCD Configuration */
  238. .getvideoinfo = rit_getvideoinfo,
  239. .getplaneinfo = rit_getplaneinfo,
  240. /* LCD RGB Mapping -- Not supported */
  241. /* Cursor Controls -- Not supported */
  242. /* LCD Specific Controls */
  243. .getpower = rit_getpower,
  244. .setpower = rit_setpower,
  245. .getcontrast = rit_getcontrast,
  246. .setcontrast = rit_setcontrast,
  247. },
  248. };
  249. /* A table of magic initialization commands. This initialization sequence is
  250. * derived from RiT Application Note for the P14201 (with a few tweaked values
  251. * as discovered in some Luminary code examples).
  252. */
  253. static const uint8_t g_initcmds[] =
  254. {
  255. 3, SSD1329_CMD_LOCK, /* Set lock command */
  256. SSD1329_LOCK_OFF, /* Disable locking */
  257. SSD1329_NOOP,
  258. 2, SSD1329_SLEEP_ON, /* Matrix display OFF */
  259. SSD1329_NOOP,
  260. 3, SSD1329_ICON_ALL, /* Set all ICONs to OFF */
  261. SSD1329_ICON_OFF, /* OFF selection */
  262. SSD1329_NOOP,
  263. 3, SSD1329_MUX_RATIO, /* Set MUX ratio */
  264. 95, /* 96 MUX */
  265. SSD1329_NOOP,
  266. 3, SSD1329_SET_CONTRAST, /* Set contrast */
  267. RIT_CONTRAST, /* Default contrast */
  268. SSD1329_NOOP,
  269. 3, SSD1329_PRECHRG2_SPEED, /* Set second pre-charge speed */
  270. (31 << 1) | SSD1329_PRECHRG2_DBL, /* Pre-charge speed == 32, doubled */
  271. SSD1329_NOOP,
  272. 3, SSD1329_GDDRAM_REMAP, /* Set GDDRAM re-map */
  273. (SSD1329_COM_SPLIT | /* Enable COM slip even/odd */
  274. SSD1329_COM_REMAP | /* Enable COM re-map */
  275. SSD1329_NIBBLE_REMAP), /* Enable nibble re-map */
  276. SSD1329_NOOP,
  277. 3, SSD1329_VERT_START, /* Set Display Start Line */
  278. 0, /* Line = 0 */
  279. SSD1329_NOOP,
  280. 3, SSD1329_VERT_OFFSET, /* Set Display Offset */
  281. 0, /* Offset = 0 */
  282. SSD1329_NOOP,
  283. 2, SSD1329_DISP_NORMAL, /* Display mode normal */
  284. SSD1329_NOOP,
  285. 3, SSD1329_PHASE_LENGTH, /* Set Phase Length */
  286. 1 | /* Phase 1 period = 1 DCLK */
  287. (1 << 4), /* Phase 2 period = 1 DCLK */
  288. SSD1329_NOOP,
  289. 3, SSD1329_FRAME_FREQ,
  290. 35, /* 35 DCLK's per row */
  291. SSD1329_NOOP,
  292. 3, SSD1329_DCLK_DIV, /* Set Front Clock Divider / Oscillator Frequency */
  293. 2 | /* Divide ration = 3 */
  294. (14 << 4), /* Oscillator Frequency, FOSC, setting */
  295. SSD1329_NOOP,
  296. 17, SSD1329_GSCALE_LOOKUP, /* Look Up Table for Gray Scale Pulse width */
  297. 1, 2, 3, 4, 5, /* Value for GS1-5 level Pulse width */
  298. 6, 8, 10, 12, 14, /* Value for GS6-10 level Pulse width */
  299. 16, 19, 22, 26, 30, /* Value for GS11-15 level Pulse width */
  300. SSD1329_NOOP,
  301. 3, SSD1329_PRECHRG2_PERIOD, /* Set Second Pre-charge Period */
  302. 1, /* 1 DCLK */
  303. SSD1329_NOOP,
  304. 3, SSD1329_PRECHRG1_VOLT, /* Set First Precharge voltage, VP */
  305. 0x3f, /* 1.00 x Vcc */
  306. SSD1329_NOOP,
  307. 0 /* Zero length command terminates table */
  308. };
  309. /* Turn the maxtrix display on (sleep mode off) */
  310. static const uint8_t g_sleepoff[] =
  311. {
  312. SSD1329_SLEEP_OFF, /* Matrix display ON */
  313. SSD1329_NOOP,
  314. };
  315. /* Turn the maxtrix display off (sleep mode on) */
  316. static const uint8_t g_sleepon[] =
  317. {
  318. SSD1329_SLEEP_ON, /* Matrix display OFF */
  319. SSD1329_NOOP,
  320. };
  321. /* Set horizontal increment mode */
  322. static const uint8_t g_horzinc[] =
  323. {
  324. SSD1329_GDDRAM_REMAP,
  325. (SSD1329_COM_SPLIT | SSD1329_COM_REMAP | SSD1329_NIBBLE_REMAP),
  326. };
  327. /* The following set a window that covers the entire display */
  328. static const uint8_t g_setallcol[] =
  329. {
  330. SSD1329_SET_COLADDR,
  331. 0,
  332. (RIT_XRES/2)-1
  333. };
  334. static const uint8_t g_setallrow[] =
  335. {
  336. SSD1329_SET_ROWADDR,
  337. 0,
  338. RIT_YRES-1
  339. };
  340. /**************************************************************************************
  341. * Private Functions
  342. **************************************************************************************/
  343. /**************************************************************************************
  344. * Name: rit_select
  345. *
  346. * Description:
  347. * Select the SPI, locking and re-configuring if necessary
  348. *
  349. * Input Parameters:
  350. * spi - Reference to the SPI driver structure
  351. *
  352. * Returned Value:
  353. * None
  354. *
  355. * Assumptions:
  356. *
  357. **************************************************************************************/
  358. static void rit_select(FAR struct spi_dev_s *spi)
  359. {
  360. /* Select P14201 chip (locking the SPI bus in case there are multiple
  361. * devices competing for the SPI bus
  362. */
  363. SPI_LOCK(spi, true);
  364. SPI_SELECT(spi, SPIDEV_DISPLAY(0), true);
  365. /* Now make sure that the SPI bus is configured for the P14201 (it
  366. * might have gotten configured for a different device while unlocked)
  367. */
  368. SPI_SETMODE(spi, CONFIG_P14201_SPIMODE);
  369. SPI_SETBITS(spi, 8);
  370. (void)SPI_HWFEATURES(spi, 0);
  371. #ifdef CONFIG_P14201_FREQUENCY
  372. (void)SPI_SETFREQUENCY(spi, CONFIG_P14201_FREQUENCY);
  373. #endif
  374. }
  375. /**************************************************************************************
  376. * Name: rit_deselect
  377. *
  378. * Description:
  379. * De-select the SPI
  380. *
  381. * Input Parameters:
  382. * spi - Reference to the SPI driver structure
  383. *
  384. * Returned Value:
  385. * None
  386. *
  387. * Assumptions:
  388. *
  389. **************************************************************************************/
  390. static void rit_deselect(FAR struct spi_dev_s *spi)
  391. {
  392. /* De-select P14201 chip and relinquish the SPI bus. */
  393. SPI_SELECT(spi, SPIDEV_DISPLAY(0), false);
  394. SPI_LOCK(spi, false);
  395. }
  396. /**************************************************************************************
  397. * Name: rit_sndbytes
  398. *
  399. * Description:
  400. * Send a sequence of command or data bytes to the SSD1329 controller.
  401. *
  402. * Input Parameters:
  403. * spi - Reference to the SPI driver structure
  404. * buffer - A reference to memory containing the command bytes to be sent.
  405. * buflen - The number of command bytes in buffer to be sent
  406. *
  407. * Returned Value:
  408. * None
  409. *
  410. * Assumptions:
  411. * The caller as selected the OLED device.
  412. *
  413. **************************************************************************************/
  414. static void rit_sndbytes(FAR struct rit_dev_s *priv, FAR const uint8_t *buffer,
  415. size_t buflen, bool cmd)
  416. {
  417. FAR struct spi_dev_s *spi = priv->spi;
  418. uint8_t tmp;
  419. ritinfo("buflen: %d cmd: %s [%02x %02x %02x]\n",
  420. buflen, cmd ? "YES" : "NO", buffer[0], buffer[1], buffer[2]);
  421. DEBUGASSERT(spi);
  422. /* Clear/set the D/Cn bit to enable command or data mode */
  423. (void)SPI_CMDDATA(spi, SPIDEV_DISPLAY(0), cmd);
  424. /* Loop until the entire command/data block is transferred */
  425. while (buflen-- > 0)
  426. {
  427. /* Write the next byte to the controller */
  428. tmp = *buffer++;
  429. (void)SPI_SEND(spi, tmp);
  430. }
  431. }
  432. /**************************************************************************************
  433. * Name: rit_sndcmd
  434. *
  435. * Description:
  436. * Send multiple commands from a table of commands.
  437. *
  438. * Input Parameters:
  439. * spi - Reference to the SPI driver structure
  440. * table - A reference to table containing all of the commands to be sent.
  441. *
  442. * Returned Value:
  443. * None
  444. *
  445. * Assumptions:
  446. *
  447. **************************************************************************************/
  448. static void rit_sndcmds(FAR struct rit_dev_s *priv, FAR const uint8_t *table)
  449. {
  450. int cmdlen;
  451. /* Table terminates with a zero length command */
  452. while ((cmdlen = *table++) != 0)
  453. {
  454. ritinfo("command: %02x cmdlen: %d\n", *table, cmdlen);
  455. rit_sndcmd(priv, table, cmdlen);
  456. table += cmdlen;
  457. }
  458. }
  459. /**************************************************************************************
  460. * Name: rit_clear
  461. *
  462. * Description:
  463. * This method can be used to clear the entire display.
  464. *
  465. * Input Parameters:
  466. * priv - Reference to private driver structure
  467. *
  468. * Assumptions:
  469. * Caller has selected the OLED section.
  470. *
  471. **************************************************************************************/
  472. #ifdef CONFIG_P14201_FRAMEBUFFER
  473. static inline void rit_clear(FAR struct rit_dev_s *priv)
  474. {
  475. FAR uint8_t *ptr = g_framebuffer;
  476. unsigned int row;
  477. ritinfo("Clear display\n");
  478. /* Initialize the framebuffer */
  479. memset(g_framebuffer, (RIT_Y4_BLACK << 4) | RIT_Y4_BLACK, RIT_YRES * RIT_XRES / 2);
  480. /* Set a window to fill the entire display */
  481. rit_sndcmd(priv, g_setallcol, sizeof(g_setallcol));
  482. rit_sndcmd(priv, g_setallrow, sizeof(g_setallrow));
  483. rit_sndcmd(priv, g_horzinc, sizeof(g_horzinc));
  484. /* Display each row */
  485. for (row = 0; row < RIT_YRES; row++)
  486. {
  487. /* Display a horizontal run */
  488. rit_snddata(priv, ptr, RIT_XRES / 2);
  489. ptr += RIT_XRES / 2;
  490. }
  491. }
  492. #else
  493. static inline void rit_clear(FAR struct rit_dev_s *priv)
  494. {
  495. unsigned int row;
  496. ritinfo("Clear display\n");
  497. /* Create a black row */
  498. memset(g_runbuffer, (RIT_Y4_BLACK << 4) | RIT_Y4_BLACK, RIT_XRES / 2);
  499. /* Set a window to fill the entire display */
  500. rit_sndcmd(priv, g_setallcol, sizeof(g_setallcol));
  501. rit_sndcmd(priv, g_setallrow, sizeof(g_setallrow));
  502. rit_sndcmd(priv, g_horzinc, sizeof(g_horzinc));
  503. /* Display each row */
  504. for (row = 0; row < RIT_YRES; row++)
  505. {
  506. /* Display a horizontal run */
  507. rit_snddata(priv, g_runbuffer, RIT_XRES / 2);
  508. }
  509. }
  510. #endif
  511. /**************************************************************************************
  512. * Name: rit_putrun
  513. *
  514. * Description:
  515. * This method can be used to write a partial raster line to the LCD.
  516. *
  517. * Input Parameters:
  518. * row - Starting row to write to (range: 0 <= row < yres)
  519. * col - Starting column to write to (range: 0 <= col <= xres-npixels)
  520. * buffer - The buffer containing the run to be written to the LCD
  521. * npixels - The number of pixels to write to the LCD
  522. * (range: 0 < npixels <= xres-col)
  523. *
  524. **************************************************************************************/
  525. #ifdef CONFIG_P14201_FRAMEBUFFER
  526. static int rit_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer,
  527. size_t npixels)
  528. {
  529. FAR struct rit_dev_s *priv = (FAR struct rit_dev_s *)&g_oleddev;
  530. uint8_t cmd[3];
  531. uint8_t *run;
  532. int start;
  533. int end;
  534. int aend;
  535. int i;
  536. ritinfo("row: %d col: %d npixels: %d\n", row, col, npixels);
  537. DEBUGASSERT(buffer);
  538. /* Toss out the special case of the empty run now */
  539. if (npixels < 1)
  540. {
  541. return OK;
  542. }
  543. /* Get the beginning of the line containing run in the framebuffer */
  544. run = g_framebuffer + row * RIT_XRES / 2;
  545. /* Get the starting and ending byte offsets containing the run.
  546. * the run starts at &run[start] and continues through run[end-1].
  547. * However, the first and final pixels at these locations may
  548. * not be byte aligned.
  549. */
  550. start = col >> 1;
  551. aend = (col + npixels) >> 1;
  552. end = (col + npixels + 1) >> 1;
  553. ritinfo("start: %d aend: %d end: %d\n", start, aend, end);
  554. /* Copy the run into the framebuffer, handling nibble alignment.
  555. *
  556. * CASE 1: First pixel X position is byte aligned
  557. *
  558. * example col=6 npixels = 8 example col=6 npixels=7
  559. *
  560. * Run: |AB|AB|AB|AB| |AB|AB|AB|AB|
  561. * GDDRAM row:
  562. * Byte | 0| 1| 2| 3| 4| 5| 6| | 0| 1| 2| 3| 4| 5| 6|
  563. * Pixel: |--|--|--|AB|AB|AB|AB| |--|--|--|AB|AB|AB|A-|
  564. *
  565. * start = 3 start = 3
  566. * aend = 6 aend = 6
  567. * end = 6 end = 7
  568. *
  569. */
  570. if ((col & 1) == 0)
  571. {
  572. /* Check for the special case of only 1 pixel being blitted */
  573. if (npixels > 1)
  574. {
  575. /* Beginning of buffer is properly aligned, from start to aend */
  576. memcpy(&run[start], buffer, aend - start);
  577. }
  578. /* An even number of byte-aligned pixel pairs have been written (where
  579. * zero counts as an even number). If npixels was was odd (including
  580. * npixels == 1), then handle the final, byte aligned pixel.
  581. */
  582. if (aend != end)
  583. {
  584. /* The leftmost column is contained in source bits 7:4 and in
  585. * destination bits 7:4
  586. */
  587. run[aend] = (run[aend] & 0x0f) | (buffer[aend - start] & 0xf0);
  588. }
  589. }
  590. /* CASE 2: First pixel X position is byte aligned
  591. *
  592. * example col=7 npixels = 8 example col=7 npixels=7
  593. *
  594. * Run: |AB|AB|AB|AB| |AB|AB|AB|AB|
  595. * GDDRAM row:
  596. * Byte | 0| 1| 2| 3| 4| 5| 6| 7| | 0| 1| 2| 3| 4| 5| 6|
  597. * Pixel: |--|--|--|-A|BA|BA|BA|B-| |--|--|--|-A|BA|BA|BA|
  598. *
  599. * start = 3 start = 3
  600. * aend = 7 aend = 7
  601. * end = 8 end = 7
  602. */
  603. else
  604. {
  605. uint8_t curr = buffer[0];
  606. uint8_t last;
  607. /* Handle the initial unaligned pixel. Source bits 7:4 into
  608. * destination bits 3:0. In the special case of npixel == 1,
  609. * this finished the job.
  610. */
  611. run[start] = (run[start] & 0xf0) | (curr >> 4);
  612. /* Now construct the rest of the bytes in the run (possibly special
  613. * casing the final, partial byte below).
  614. */
  615. for (i = start + 1; i < aend; i++)
  616. {
  617. /* bits 3:0 from previous byte to run bits 7:4;
  618. * bits 7:4 of current byte to run bits 3:0
  619. */
  620. last = curr;
  621. curr = buffer[i-start];
  622. run[i] = (last << 4) | (curr >> 4);
  623. }
  624. /* An odd number of unaligned pixel have been written (where npixels
  625. * may have been as small as one). If npixels was was even, then handle
  626. * the final, unaligned pixel.
  627. */
  628. if (aend != end)
  629. {
  630. /* The leftmost column is contained in source bits 3:0 and in
  631. * destination bits 7:4
  632. */
  633. run[aend] = (run[aend] & 0x0f) | (curr << 4);
  634. }
  635. }
  636. /* Select the SD1329 controller */
  637. rit_select(priv->spi);
  638. /* Setup a window that describes a run starting at the specified column
  639. * and row, and ending at the column + npixels on the same row.
  640. */
  641. cmd[0] = SSD1329_SET_COLADDR;
  642. cmd[1] = start;
  643. cmd[2] = end - 1;
  644. rit_sndcmd(priv, cmd, 3);
  645. cmd[0] = SSD1329_SET_ROWADDR;
  646. cmd[1] = row;
  647. cmd[2] = row;
  648. rit_sndcmd(priv, cmd, 3);
  649. /* Write the run to GDDRAM. */
  650. rit_sndcmd(priv, g_horzinc, sizeof(g_horzinc));
  651. rit_snddata(priv, &run[start], end - start);
  652. /* De-select the SD1329 controller */
  653. rit_deselect(priv->spi);
  654. return OK;
  655. }
  656. #else
  657. static int rit_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer,
  658. size_t npixels)
  659. {
  660. FAR struct rit_dev_s *priv = (FAR struct rit_dev_s *)&g_oleddev;
  661. uint8_t cmd[3];
  662. ritinfo("row: %d col: %d npixels: %d\n", row, col, npixels);
  663. DEBUGASSERT(buffer);
  664. if (npixels > 0)
  665. {
  666. /* Check that the X and Y coordinates are within range */
  667. DEBUGASSERT(col < RIT_XRES && (col + npixels) <= RIT_XRES && row < RIT_YRES);
  668. /* Check that the X coordinates are aligned to 8-bit boundaries
  669. * (this needs to get fixed somehow)
  670. */
  671. DEBUGASSERT((col & 1) == 0 && (npixels & 1) == 0);
  672. /* Select the SD1329 controller */
  673. rit_select(priv->spi);
  674. /* Setup a window that describes a run starting at the specified column
  675. * and row, and ending at the column + npixels on the same row.
  676. */
  677. cmd[0] = SSD1329_SET_COLADDR;
  678. cmd[1] = col >> 1;
  679. cmd[2] = ((col + npixels) >> 1) - 1;
  680. rit_sndcmd(priv, cmd, 3);
  681. cmd[0] = SSD1329_SET_ROWADDR;
  682. cmd[1] = row;
  683. cmd[2] = row;
  684. rit_sndcmd(priv, cmd, 3);
  685. /* Write the run to GDDRAM. */
  686. rit_sndcmd(priv, g_horzinc, sizeof(g_horzinc));
  687. rit_snddata(priv, buffer, npixels >> 1);
  688. /* De-select the SD1329 controller */
  689. rit_deselect(priv->spi);
  690. }
  691. return OK;
  692. }
  693. #endif
  694. /**************************************************************************************
  695. * Name: rit_getrun
  696. *
  697. * Description:
  698. * This method can be used to read a partial raster line from the LCD:
  699. *
  700. * row - Starting row to read from (range: 0 <= row < yres)
  701. * col - Starting column to read read (range: 0 <= col <= xres-npixels)
  702. * buffer - The buffer in which to return the run read from the LCD
  703. * npixels - The number of pixels to read from the LCD
  704. * (range: 0 < npixels <= xres-col)
  705. *
  706. **************************************************************************************/
  707. #ifdef CONFIG_P14201_FRAMEBUFFER
  708. static int rit_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer,
  709. size_t npixels)
  710. {
  711. uint8_t *run;
  712. int start;
  713. int end;
  714. int aend;
  715. int i;
  716. ritinfo("row: %d col: %d npixels: %d\n", row, col, npixels);
  717. DEBUGASSERT(buffer);
  718. /* Can't read from OLED GDDRAM in SPI mode, but we can read from the framebuffer */
  719. /* Toss out the special case of the empty run now */
  720. if (npixels < 1)
  721. {
  722. return OK;
  723. }
  724. /* Get the beginning of the line containing run in the framebuffer */
  725. run = g_framebuffer + row * RIT_XRES / 2;
  726. /* Get the starting and ending byte offsets containing the run.
  727. * the run starts at &run[start] and continues through run[end-1].
  728. * However, the first and final pixels at these locations may
  729. * not be byte aligned (see examples in putrun()).
  730. */
  731. start = col >> 1;
  732. aend = (col + npixels) >> 1;
  733. end = (col + npixels + 1) >> 1;
  734. /* Copy the run into the framebuffer, handling nibble alignment */
  735. if ((col & 1) == 0)
  736. {
  737. /* Check for the special case of only 1 pixels being copied */
  738. if (npixels > 1)
  739. {
  740. /* Beginning of buffer is properly aligned, from start to aend */
  741. memcpy(buffer, &run[start], aend - start + 1);
  742. }
  743. /* Handle any final pixel (including the special case where npixels == 1). */
  744. if (aend != end)
  745. {
  746. /* The leftmost column is contained in source bits 7:4 and in
  747. * destination bits 7:4
  748. */
  749. buffer[aend - start] = run[aend] & 0xf0;
  750. }
  751. }
  752. else
  753. {
  754. uint8_t curr = run[start];
  755. uint8_t last;
  756. /* Now construct the rest of the bytes in the run (possibly special
  757. * casing the final, partial byte below).
  758. */
  759. for (i = start + 1; i < aend; i++)
  760. {
  761. /* bits 3:0 from previous byte to run bits 7:4;
  762. * bits 7:4 of current byte to run bits 3:0
  763. */
  764. last = curr;
  765. curr = run[i];
  766. *buffer++ = (last << 4) | (curr >> 4);
  767. }
  768. /* Handle any final pixel (including the special case where npixels == 1). */
  769. if (aend != end)
  770. {
  771. /* The leftmost column is contained in source bits 3:0 and in
  772. * destination bits 7:4
  773. */
  774. *buffer = (curr << 4);
  775. }
  776. }
  777. return OK;
  778. }
  779. #else
  780. static int rit_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer,
  781. size_t npixels)
  782. {
  783. /* Can't read from OLED GDDRAM in SPI mode */
  784. return -ENOSYS;
  785. }
  786. #endif
  787. /**************************************************************************************
  788. * Name: rit_getvideoinfo
  789. *
  790. * Description:
  791. * Get information about the LCD video controller configuration.
  792. *
  793. **************************************************************************************/
  794. static int rit_getvideoinfo(FAR struct lcd_dev_s *dev,
  795. FAR struct fb_videoinfo_s *vinfo)
  796. {
  797. DEBUGASSERT(dev && vinfo);
  798. ginfo("fmt: %d xres: %d yres: %d nplanes: %d\n",
  799. g_videoinfo.fmt, g_videoinfo.xres, g_videoinfo.yres, g_videoinfo.nplanes);
  800. memcpy(vinfo, &g_videoinfo, sizeof(struct fb_videoinfo_s));
  801. return OK;
  802. }
  803. /**************************************************************************************
  804. * Name: rit_getplaneinfo
  805. *
  806. * Description:
  807. * Get information about the configuration of each LCD color plane.
  808. *
  809. **************************************************************************************/
  810. static int rit_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno,
  811. FAR struct lcd_planeinfo_s *pinfo)
  812. {
  813. DEBUGASSERT(pinfo && planeno == 0);
  814. ginfo("planeno: %d bpp: %d\n", planeno, g_planeinfo.bpp);
  815. memcpy(pinfo, &g_planeinfo, sizeof(struct lcd_planeinfo_s));
  816. return OK;
  817. }
  818. /**************************************************************************************
  819. * Name: rit_getpower
  820. *
  821. * Description:
  822. * Get the LCD panel power status (0: full off - CONFIG_LCD_MAXPOWER: full on. On
  823. * backlit LCDs, this setting may correspond to the backlight setting.
  824. *
  825. **************************************************************************************/
  826. static int rit_getpower(FAR struct lcd_dev_s *dev)
  827. {
  828. FAR struct rit_dev_s *priv = (FAR struct rit_dev_s *)dev;
  829. DEBUGASSERT(priv);
  830. ginfo("power: %s\n", priv->on ? "ON" : "OFF");
  831. return priv->on ? CONFIG_LCD_MAXPOWER : 0;
  832. }
  833. /**************************************************************************************
  834. * Name: rit_setpower
  835. *
  836. * Description:
  837. * Enable/disable LCD panel power (0: full off - CONFIG_LCD_MAXPOWER: full on). On
  838. * backlit LCDs, this setting may correspond to the backlight setting.
  839. *
  840. **************************************************************************************/
  841. static int rit_setpower(struct lcd_dev_s *dev, int power)
  842. {
  843. struct rit_dev_s *priv = (struct rit_dev_s *)dev;
  844. DEBUGASSERT(priv && (unsigned)power <= CONFIG_LCD_MAXPOWER && priv->spi);
  845. ginfo("power: %d\n", power);
  846. /* Select the SD1329 controller */
  847. rit_select(priv->spi);
  848. /* Only two power settings -- 0: sleep on, 1: sleep off */
  849. if (power > 0)
  850. {
  851. /* Re-initialize the SSD1329 controller */
  852. rit_sndcmds(priv, g_initcmds);
  853. /* Take the display out of sleep mode */
  854. rit_sndcmd(priv, g_sleepoff, sizeof(g_sleepoff));
  855. priv->on = true;
  856. }
  857. else
  858. {
  859. /* Put the display into sleep mode */
  860. rit_sndcmd(priv, g_sleepon, sizeof(g_sleepon));
  861. priv->on = false;
  862. }
  863. /* De-select the SD1329 controller */
  864. rit_deselect(priv->spi);
  865. return OK;
  866. }
  867. /**************************************************************************************
  868. * Name: rit_getcontrast
  869. *
  870. * Description:
  871. * Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST).
  872. *
  873. **************************************************************************************/
  874. static int rit_getcontrast(struct lcd_dev_s *dev)
  875. {
  876. struct rit_dev_s *priv = (struct rit_dev_s *)dev;
  877. ginfo("contrast: %d\n", priv->contrast);
  878. return priv->contrast;
  879. }
  880. /**************************************************************************************
  881. * Name: rit_setcontrast
  882. *
  883. * Description:
  884. * Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST).
  885. *
  886. **************************************************************************************/
  887. static int rit_setcontrast(struct lcd_dev_s *dev, unsigned int contrast)
  888. {
  889. struct rit_dev_s *priv = (struct rit_dev_s *)dev;
  890. uint8_t cmd[3];
  891. ginfo("contrast: %d\n", contrast);
  892. DEBUGASSERT(contrast <= CONFIG_LCD_MAXCONTRAST);
  893. /* Select the SD1329 controller */
  894. rit_select(priv->spi);
  895. /* Set new contrast */
  896. cmd[0] = SSD1329_SET_CONTRAST;
  897. cmd[1] = contrast;
  898. cmd[2] = SSD1329_NOOP;
  899. rit_sndcmd(priv, cmd, 3);
  900. /* De-select the SD1329 controller */
  901. rit_deselect(priv->spi);
  902. priv->contrast = contrast;
  903. return OK;
  904. }
  905. /**************************************************************************************
  906. * Public Functions
  907. **************************************************************************************/
  908. /**************************************************************************************
  909. * Name: rit_initialize
  910. *
  911. * Description:
  912. * Initialize the P14201 video hardware. The initial state of the OLED is fully
  913. * initialized, display memory cleared, and the OLED ready to use, but with the power
  914. * setting at 0 (full off == sleep mode).
  915. *
  916. * Input Parameters:
  917. * spi - A reference to the SPI driver instance.
  918. * devno - A value in the range of 0 throuh CONFIG_P14201_NINTERFACES-1. This allows
  919. * support for multiple OLED devices.
  920. *
  921. * Returned Value:
  922. * On success, this function returns a reference to the LCD object for the specified
  923. * OLED. NULL is returned on any failure.
  924. *
  925. **************************************************************************************/
  926. FAR struct lcd_dev_s *rit_initialize(FAR struct spi_dev_s *spi, unsigned int devno)
  927. {
  928. FAR struct rit_dev_s *priv = (FAR struct rit_dev_s *)&g_oleddev;
  929. DEBUGASSERT(devno == 0 && spi);
  930. ginfo("Initializing devno: %d\n", devno);
  931. /* Driver state data */
  932. priv->spi = spi;
  933. priv->contrast = RIT_CONTRAST;
  934. priv->on = false;
  935. /* Select the SD1329 controller */
  936. rit_select(spi);
  937. /* Clear the display */
  938. rit_clear(priv);
  939. /* Configure (but don't enable) the OLED */
  940. rit_sndcmds(priv, g_initcmds);
  941. /* De-select the SD1329 controller */
  942. rit_deselect(spi);
  943. return &priv->dev;
  944. }
  945. #endif /* CONFIG_LCD_P14201 */