memlcd.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. /****************************************************************************
  2. * drivers/lcd/memlcd.c
  3. * Driver for Sharp Memory LCD.
  4. *
  5. * Copyright (C) 2013 Gregory Nutt. All rights reserved.
  6. * Author: Gregory Nutt <gnutt@nuttx.org>
  7. * Librae <librae8226@gmail.com>
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions
  11. * are met:
  12. *
  13. * 1. Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. * 3. Neither the name NuttX nor the names of its contributors may be
  20. * used to endorse or promote products derived from this software
  21. * without specific prior writen permission.
  22. *
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  24. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  25. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  26. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  27. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  28. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  29. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  30. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  31. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  33. * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  34. * POSSIBILITY OF SUCH DAMAGE.
  35. *
  36. ****************************************************************************/
  37. /****************************************************************************
  38. * Included Files
  39. ****************************************************************************/
  40. #include <nuttx/config.h>
  41. #include <sys/types.h>
  42. #include <stdint.h>
  43. #include <stdbool.h>
  44. #include <string.h>
  45. #include <errno.h>
  46. #include <debug.h>
  47. #include <nuttx/arch.h>
  48. #include <nuttx/spi/spi.h>
  49. #include <nuttx/lcd/lcd.h>
  50. #include <nuttx/lcd/memlcd.h>
  51. #include <arch/irq.h>
  52. /****************************************************************************
  53. * Pre-processor Definitions
  54. ****************************************************************************/
  55. /* Bit order H/W feature must be enabled in order to support LSB first
  56. * operation.
  57. */
  58. #if !defined(CONFIG_SPI_HWFEATURES) || !defined(CONFIG_SPI_BITORDER)
  59. # error CONFIG_SPI_HWFEATURES=y and CONFIG_SPI_BITORDER=y required by this driver
  60. #endif
  61. #ifndef CONFIG_ARCH_HAVE_SPI_BITORDER
  62. # warning This platform does not support SPI LSB-bit order
  63. #endif
  64. /* Cisplay resolution */
  65. #if defined CONFIG_MEMLCD_LS013B7DH01
  66. # define MEMLCD_XRES 144
  67. # define MEMLCD_YRES 168
  68. #elif defined CONFIG_MEMLCD_LS013B7DH03
  69. # define MEMLCD_XRES 128
  70. # define MEMLCD_YRES 128
  71. #else
  72. # error "This Memory LCD model is not supported yet."
  73. #endif
  74. /* lcd command */
  75. #define MEMLCD_CMD_UPDATE (0x01)
  76. #define MEMLCD_CMD_ALL_CLEAR (0x04)
  77. #define MEMLCD_CONTROL_BYTES (0)
  78. /* Dolor depth and format */
  79. #define MEMLCD_BPP 1
  80. #define MEMLCD_COLORFMT FB_FMT_Y1
  81. /* Bytes per logical row and column */
  82. #define MEMLCD_XSTRIDE (MEMLCD_XRES >> 3)
  83. #define MEMLCD_YSTRIDE (MEMLCD_YRES >> 3)
  84. /* display memory allocation */
  85. #define MEMLCD_FBSIZE (MEMLCD_XSTRIDE*MEMLCD_YRES)
  86. /* contrast setting, related to VCOM toggle frequency
  87. * higher frequency gives better contrast, instead, saves power
  88. */
  89. #define MEMLCD_CONTRAST 24
  90. #define MEMLCD_MAXCONTRAST 60
  91. #define MEMLCD_MINCONTRAST 1
  92. /* Other misc settings */
  93. #define MEMLCD_SPI_FREQUENCY 2250000
  94. #define MEMLCD_SPI_BITS 8
  95. #define MEMLCD_SPI_MODE SPIDEV_MODE0
  96. #define LS_BIT (1 << 0)
  97. #define MS_BIT (1 << 7)
  98. /****************************************************************************
  99. * Private Type Definition
  100. ****************************************************************************/
  101. struct memlcd_dev_s
  102. {
  103. /* Publically visible device structure */
  104. struct lcd_dev_s dev;
  105. /* Private lcd-specific information follows */
  106. FAR struct spi_dev_s *spi; /* Cached SPI device reference */
  107. FAR struct memlcd_priv_s *priv; /* Board specific structure */
  108. uint8_t contrast; /* Current contrast setting */
  109. uint8_t power; /* Current power setting */
  110. /* The memlcds does not support reading the display memory in SPI mode.
  111. * Since there is 1 BPP and is byte access, it is necessary to keep a
  112. * shadow copy of the framebuffer. At 128x128, it amounts to 2KB.
  113. */
  114. uint8_t fb[MEMLCD_FBSIZE];
  115. };
  116. /****************************************************************************
  117. * Private Function Protototypes
  118. ****************************************************************************/
  119. /* Low-level spi helpers */
  120. static void memlcd_select(FAR struct spi_dev_s *spi);
  121. static void memlcd_deselect(FAR struct spi_dev_s *spi);
  122. /* lcd data transfer methods */
  123. static int memlcd_putrun(fb_coord_t row, fb_coord_t col,
  124. FAR const uint8_t * buffer, size_t npixels);
  125. static int memlcd_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t * buffer,
  126. size_t npixels);
  127. /* lcd configuration */
  128. static int memlcd_getvideoinfo(FAR struct lcd_dev_s *dev,
  129. FAR struct fb_videoinfo_s *vinfo);
  130. static int memlcd_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno,
  131. FAR struct lcd_planeinfo_s *pinfo);
  132. /* lcd specific controls */
  133. static int memlcd_getpower(struct lcd_dev_s *dev);
  134. static int memlcd_setpower(struct lcd_dev_s *dev, int power);
  135. static int memlcd_getcontrast(struct lcd_dev_s *dev);
  136. static int memlcd_setcontrast(struct lcd_dev_s *dev, unsigned int contrast);
  137. /****************************************************************************
  138. * Private Data
  139. ****************************************************************************/
  140. static uint8_t g_runbuffer[MEMLCD_BPP * MEMLCD_XRES / 8];
  141. /* This structure describes the overall lcd video controller */
  142. static const struct fb_videoinfo_s g_videoinfo =
  143. {
  144. .fmt = MEMLCD_COLORFMT, /* Color format: rgb16-565: rrrr rggg gggb bbbb */
  145. .xres = MEMLCD_XRES, /* Horizontal resolution in pixel columns */
  146. .yres = MEMLCD_YRES, /* Vertical resolution in pixel rows */
  147. .nplanes = 1, /* Number of color planes supported */
  148. };
  149. /* This is the standard, nuttx plane information object */
  150. static const struct lcd_planeinfo_s g_planeinfo =
  151. {
  152. .putrun = memlcd_putrun, /* Put a run into lcd memory */
  153. .getrun = memlcd_getrun, /* Get a run from lcd memory */
  154. .buffer = (uint8_t *) g_runbuffer, /* Run scratch buffer */
  155. .bpp = MEMLCD_BPP, /* Bits-per-pixel */
  156. };
  157. /* This is the oled driver instance (only a single device is supported for now) */
  158. static struct memlcd_dev_s g_memlcddev =
  159. {
  160. .dev =
  161. {
  162. /* lcd configuration */
  163. .getvideoinfo = memlcd_getvideoinfo,
  164. .getplaneinfo = memlcd_getplaneinfo,
  165. /* lcd specific controls */
  166. .getpower = memlcd_getpower,
  167. .setpower = memlcd_setpower,
  168. .getcontrast = memlcd_getcontrast,
  169. .setcontrast = memlcd_setcontrast,
  170. },
  171. };
  172. /****************************************************************************
  173. * Private Functions
  174. ****************************************************************************/
  175. /****************************************************************************
  176. * __set_bit - Set a bit in memory
  177. *
  178. * @nr: the bit to set
  179. * @addr: the address to start counting from
  180. *
  181. * Unlike set_bit(), this function is non-atomic and may be reordered.
  182. * If it's called on the same region of memory simultaneously, the effect
  183. * may be that only one operation succeeds.
  184. *
  185. ****************************************************************************/
  186. #define BIT(nr) (1 << (nr))
  187. #define BITS_PER_BYTE 8
  188. #define BIT_MASK(nr) (1 << ((nr) % BITS_PER_BYTE))
  189. #define BIT_BYTE(nr) ((nr) / BITS_PER_BYTE)
  190. static inline void __set_bit(int nr, uint8_t * addr)
  191. {
  192. uint8_t mask = BIT_MASK(nr);
  193. uint8_t *p = ((uint8_t *) addr) + BIT_BYTE(nr);
  194. *p |= mask;
  195. }
  196. static inline void __clear_bit(int nr, uint8_t * addr)
  197. {
  198. uint8_t mask = BIT_MASK(nr);
  199. uint8_t *p = ((uint8_t *) addr) + BIT_BYTE(nr);
  200. *p &= ~mask;
  201. }
  202. static inline int __test_bit(int nr, const volatile uint8_t * addr)
  203. {
  204. return 1 & (addr[BIT_BYTE(nr)] >> (nr & (BITS_PER_BYTE - 1)));
  205. }
  206. /****************************************************************************
  207. * Name: memlcd_select
  208. *
  209. * Description:
  210. * Select the SPI, locking and re-configuring if necessary
  211. *
  212. * Input Parameters:
  213. * spi - Reference to the SPI driver structure
  214. *
  215. * Returned Value:
  216. * None
  217. *
  218. * Assumptions:
  219. *
  220. ****************************************************************************/
  221. static void memlcd_select(FAR struct spi_dev_s *spi)
  222. {
  223. int ret;
  224. /* Select memlcd (locking the SPI bus in case there are multiple
  225. * devices competing for the SPI bus
  226. */
  227. SPI_LOCK(spi, true);
  228. SPI_SELECT(spi, SPIDEV_DISPLAY(0), true);
  229. /* Now make sure that the SPI bus is configured for the memlcd (it
  230. * might have gotten configured for a different device while unlocked)
  231. */
  232. SPI_SETMODE(spi, MEMLCD_SPI_MODE);
  233. SPI_SETBITS(spi, MEMLCD_SPI_BITS);
  234. ret = SPI_HWFEATURES(spi, HWFEAT_LSBFIRST);
  235. if (ret < 0)
  236. {
  237. lcderr("ERROR: SPI_HWFEATURES failed to set bit order: %d\n", ret);
  238. }
  239. #ifdef CONFIG_MEMLCD_SPI_FREQUENCY
  240. (void)SPI_SETFREQUENCY(spi, CONFIG_MEMLCD_SPI_FREQUENCY);
  241. #else
  242. (void)SPI_SETFREQUENCY(spi, MEMLCD_SPI_FREQUENCY);
  243. #endif
  244. }
  245. /****************************************************************************
  246. * Name: memlcd_deselect
  247. *
  248. * Description:
  249. * De-select the SPI
  250. *
  251. * Input Parameters:
  252. * spi - Reference to the SPI driver structure
  253. *
  254. * Returned Value:
  255. * None
  256. *
  257. * Assumptions:
  258. *
  259. ****************************************************************************/
  260. static void memlcd_deselect(FAR struct spi_dev_s *spi)
  261. {
  262. /* De-select memlcd and relinquish the spi bus. */
  263. SPI_SELECT(spi, SPIDEV_DISPLAY(0), false);
  264. SPI_LOCK(spi, false);
  265. }
  266. /****************************************************************************
  267. * Name: memlcd_clear
  268. *
  269. * Description:
  270. * This method can be used to clear the entire display.
  271. *
  272. * Input Parameters:
  273. * mlcd - Reference to private driver structure
  274. *
  275. * Assumptions:
  276. *
  277. ****************************************************************************/
  278. static inline void memlcd_clear(FAR struct memlcd_dev_s *mlcd)
  279. {
  280. uint16_t cmd = MEMLCD_CMD_ALL_CLEAR;
  281. lcdinfo("Clear display\n");
  282. memlcd_select(mlcd->spi);
  283. /* XXX Ensure 2us here */
  284. SPI_SNDBLOCK(mlcd->spi, &cmd, 2);
  285. /* XXX Ensure 6us here */
  286. memlcd_deselect(mlcd->spi);
  287. }
  288. /****************************************************************************
  289. * Name: memlcd_extcominisr
  290. *
  291. * Description:
  292. * This method enables/disables the polarity (VCOM) toggling behavior for
  293. * the Memory LCD. Which is always used within setpower() call.
  294. * Basically, the frequency shall be 1Hz~60Hz.
  295. * If use hardware mode to toggle VCOM, we need to send specific command at a
  296. * constant frequency to trigger the LCD internal hardware logic.
  297. * While use software mode, we set up a timer to toggle EXTCOMIN connected IO,
  298. * basically, it is a hardware timer to ensure a constant frequency.
  299. *
  300. * Input Parameters:
  301. * mlcd - Reference to private driver structure
  302. *
  303. * Assumptions:
  304. * Board specific logic needs to be provided to support it.
  305. *
  306. ****************************************************************************/
  307. static int memlcd_extcominisr(int irq, FAR void *context, void *arg)
  308. {
  309. static bool pol = 0;
  310. struct memlcd_dev_s *mlcd = &g_memlcddev;
  311. #ifdef CONFIG_MEMLCD_EXTCOMIN_MODE_HW
  312. # error "CONFIG_MEMLCD_EXTCOMIN_MODE_HW unsupported yet!"
  313. /* Start a worker thread, do it in bottom half? */
  314. #else
  315. pol = !pol;
  316. mlcd->priv->setpolarity(pol);
  317. #endif
  318. return OK;
  319. }
  320. /****************************************************************************
  321. * Name: memlcd_putrun
  322. *
  323. * Description:
  324. * This method can be used to write a partial raster line to the LCD.
  325. *
  326. * Input Parameters:
  327. * row - Starting row to write to (range: 0 <= row < yres)
  328. * col - Starting column to write to (range: 0 <= col <= xres-npixels)
  329. * buffer - The buffer containing the run to be writen to the LCD
  330. * npixels - The number of pixels to write to the LCD
  331. * (range: 0 < npixels <= xres-col)
  332. *
  333. ****************************************************************************/
  334. static int memlcd_putrun(fb_coord_t row, fb_coord_t col,
  335. FAR const uint8_t * buffer, size_t npixels)
  336. {
  337. FAR struct memlcd_dev_s *mlcd = (FAR struct memlcd_dev_s *)&g_memlcddev;
  338. uint16_t cmd;
  339. uint8_t *p;
  340. uint8_t *pfb;
  341. uint8_t usrmask;
  342. int i;
  343. DEBUGASSERT(buffer);
  344. lcdinfo("row: %d col: %d npixels: %d\n", row, col, npixels);
  345. #ifdef CONFIG_LCD_PACKEDMSFIRST
  346. usrmask = MS_BIT;
  347. #else
  348. usrmask = LS_BIT;
  349. #endif
  350. pfb = &mlcd->fb[row * MEMLCD_XSTRIDE];
  351. p = pfb + (col >> 3);
  352. for (i = 0; i < npixels; i++)
  353. {
  354. if ((*buffer & usrmask) != 0)
  355. {
  356. __set_bit(col % 8 + i, p);
  357. }
  358. else
  359. {
  360. __clear_bit(col % 8 + i, p);
  361. }
  362. #ifdef CONFIG_LCD_PACKEDMSFIRST
  363. if (usrmask == LS_BIT)
  364. {
  365. buffer++;
  366. usrmask = MS_BIT;
  367. }
  368. else
  369. {
  370. usrmask >>= 1;
  371. }
  372. #else
  373. if (usrmask == MS_BIT)
  374. {
  375. buffer++;
  376. usrmask = LS_BIT;
  377. }
  378. else
  379. {
  380. usrmask <<= 1;
  381. }
  382. #endif
  383. }
  384. /* Need to adjust start row by one because Memory LCD starts counting
  385. * lines from 1, while the display interface starts from 0.
  386. */
  387. row++;
  388. memlcd_select(mlcd->spi);
  389. /* XXX Ensure 6us here */
  390. cmd = MEMLCD_CMD_UPDATE | row << 8;
  391. SPI_SNDBLOCK(mlcd->spi, &cmd, 2);
  392. SPI_SNDBLOCK(mlcd->spi, pfb, MEMLCD_YRES / 8 + MEMLCD_CONTROL_BYTES);
  393. cmd = 0xffff;
  394. SPI_SNDBLOCK(mlcd->spi, &cmd, 2);
  395. /* XXX Ensure 2us here */
  396. memlcd_deselect(mlcd->spi);
  397. return OK;
  398. }
  399. /****************************************************************************
  400. * Name: memlcd_getrun
  401. *
  402. * Description:
  403. * This method can be used to read a partial raster line from the LCD.
  404. *
  405. * row - Starting row to read from (range: 0 <= row < yres)
  406. * col - Starting column to read read (range: 0 <= col <= xres-npixels)
  407. * buffer - The buffer in which to return the run read from the LCD
  408. * npixels - The number of pixels to read from the LCD
  409. * (range: 0 < npixels <= xres-col)
  410. *
  411. ****************************************************************************/
  412. static int memlcd_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t * buffer,
  413. size_t npixels)
  414. {
  415. FAR struct memlcd_dev_s *mlcd = (FAR struct memlcd_dev_s *)&g_memlcddev;
  416. uint8_t *p;
  417. uint8_t *pfb;
  418. uint8_t usrmask;
  419. int i;
  420. DEBUGASSERT(buffer);
  421. lcdinfo("row: %d col: %d npixels: %d\n", row, col, npixels);
  422. #ifdef CONFIG_LCD_PACKEDMSFIRST
  423. usrmask = MS_BIT;
  424. #else
  425. usrmask = LS_BIT;
  426. #endif
  427. pfb = &mlcd->fb[row * MEMLCD_XSTRIDE];
  428. p = pfb + (col >> 3);
  429. for (i = 0; i < npixels; i++)
  430. {
  431. if (__test_bit(col % 8 + i, p))
  432. {
  433. *buffer |= usrmask;
  434. }
  435. else
  436. {
  437. *buffer &= ~usrmask;
  438. }
  439. #ifdef CONFIG_LCD_PACKEDMSFIRST
  440. if (usrmask == LS_BIT)
  441. {
  442. buffer++;
  443. usrmask = MS_BIT;
  444. }
  445. else
  446. {
  447. usrmask >>= 1;
  448. }
  449. #else
  450. if (usrmask == MS_BIT)
  451. {
  452. buffer++;
  453. usrmask = LS_BIT;
  454. }
  455. else
  456. {
  457. usrmask <<= 1;
  458. }
  459. #endif
  460. }
  461. return OK;
  462. }
  463. /****************************************************************************
  464. * Name: memlcd_getvideoinfo
  465. *
  466. * Description:
  467. * Get information about the LCD video controller configuration.
  468. *
  469. ****************************************************************************/
  470. static int memlcd_getvideoinfo(FAR struct lcd_dev_s *dev,
  471. FAR struct fb_videoinfo_s *vinfo)
  472. {
  473. DEBUGASSERT(dev && vinfo);
  474. lcdinfo("fmt: %d xres: %d yres: %d nplanes: %d\n",
  475. g_videoinfo.fmt, g_videoinfo.xres, g_videoinfo.yres,
  476. g_videoinfo.nplanes);
  477. memcpy(vinfo, &g_videoinfo, sizeof(struct fb_videoinfo_s));
  478. return OK;
  479. }
  480. /****************************************************************************
  481. * Name: memlcd_getplaneinfo
  482. *
  483. * Description:
  484. * Get information about the configuration of each LCD color plane.
  485. *
  486. ****************************************************************************/
  487. static int memlcd_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno,
  488. FAR struct lcd_planeinfo_s *pinfo)
  489. {
  490. DEBUGASSERT(pinfo && planeno == 0);
  491. lcdinfo("planeno: %d bpp: %d\n", planeno, g_planeinfo.bpp);
  492. memcpy(pinfo, &g_planeinfo, sizeof(struct lcd_planeinfo_s));
  493. return OK;
  494. }
  495. /****************************************************************************
  496. * Name: memlcd_getpower
  497. *
  498. * Description:
  499. * Get the LCD panel power status (0: full off - CONFIG_LCD_MAXPOWER: full on.
  500. * On backlit LCDs, this setting may correspond to the backlight setting.
  501. *
  502. ****************************************************************************/
  503. static int memlcd_getpower(FAR struct lcd_dev_s *dev)
  504. {
  505. FAR struct memlcd_dev_s *mlcd = (FAR struct memlcd_dev_s *)dev;
  506. DEBUGASSERT(mlcd);
  507. lcdinfo("%d\n", mlcd->power);
  508. return mlcd->power;
  509. }
  510. /****************************************************************************
  511. * Name: memlcd_setpower
  512. *
  513. * Description:
  514. * Enable/disable LCD panel power (0: full off - CONFIG_LCD_MAXPOWER: full on).
  515. * On backlit LCDs, this setting may correspond to the backlight setting.
  516. *
  517. ****************************************************************************/
  518. static int memlcd_setpower(FAR struct lcd_dev_s *dev, int power)
  519. {
  520. struct memlcd_dev_s *mlcd = (struct memlcd_dev_s *)dev;
  521. DEBUGASSERT(mlcd && (unsigned)power <= CONFIG_LCD_MAXPOWER && mlcd->spi);
  522. lcdinfo("%d\n", power);
  523. mlcd->power = power;
  524. if (power > 0)
  525. {
  526. mlcd->priv->dispcontrol(1);
  527. memlcd_clear(mlcd);
  528. }
  529. else
  530. {
  531. mlcd->priv->dispcontrol(0);
  532. }
  533. return OK;
  534. }
  535. /****************************************************************************
  536. * Name: memlcd_getcontrast
  537. *
  538. * Description:
  539. * Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST).
  540. *
  541. ****************************************************************************/
  542. static int memlcd_getcontrast(struct lcd_dev_s *dev)
  543. {
  544. struct memlcd_dev_s *mlcd = (struct memlcd_dev_s *)dev;
  545. DEBUGASSERT(mlcd);
  546. lcdinfo("contrast: %d\n", mlcd->contrast);
  547. return mlcd->contrast;
  548. }
  549. /****************************************************************************
  550. * Name: memlcd_setcontrast
  551. *
  552. * Description:
  553. * Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST).
  554. *
  555. ****************************************************************************/
  556. static int memlcd_setcontrast(struct lcd_dev_s *dev, unsigned int contrast)
  557. {
  558. struct memlcd_dev_s *mlcd = (struct memlcd_dev_s *)dev;
  559. DEBUGASSERT(mlcd);
  560. lcdinfo("contrast: %d\n", contrast);
  561. if (contrast > MEMLCD_MAXCONTRAST)
  562. {
  563. contrast = MEMLCD_MAXCONTRAST;
  564. }
  565. if (contrast < MEMLCD_MINCONTRAST)
  566. {
  567. contrast = MEMLCD_MINCONTRAST;
  568. }
  569. mlcd->contrast = contrast;
  570. mlcd->priv->setvcomfreq(contrast);
  571. return OK;
  572. }
  573. /****************************************************************************
  574. * Public Functions
  575. ****************************************************************************/
  576. /****************************************************************************
  577. * Name: memlcd_initialize
  578. *
  579. * Description:
  580. * Initialize the Sharp Memory LCD hardware. The initial state of the
  581. * OLED is fully initialized, display memory cleared, and the OLED ready
  582. * to use, but with the power setting at 0 (full off == sleep mode).
  583. *
  584. * Input Parameters:
  585. *
  586. * spi - A reference to the SPI driver instance.
  587. * devno - A value in the range of 0 through CONFIG_memlcd_NINTERFACES-1.
  588. * This allows support for multiple OLED devices.
  589. *
  590. * Returned Value:
  591. *
  592. * On success, this function returns a reference to the LCD object for
  593. * the specified LCD. NULL is returned on any failure.
  594. *
  595. ****************************************************************************/
  596. FAR struct lcd_dev_s *memlcd_initialize(FAR struct spi_dev_s *spi,
  597. FAR struct memlcd_priv_s *priv,
  598. unsigned int devno)
  599. {
  600. FAR struct memlcd_dev_s *mlcd = &g_memlcddev;
  601. DEBUGASSERT(spi && priv && devno == 0);
  602. /* Register board specific functions */
  603. mlcd->priv = priv;
  604. mlcd->spi = spi;
  605. mlcd->priv->attachirq(memlcd_extcominisr, mlcd);
  606. lcdinfo("done\n");
  607. return &mlcd->dev;
  608. }