u8x8_d_uc1611.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  1. /*
  2. u8x8_d_uc1611.c
  3. Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
  4. Copyright (c) 2016, olikraus@gmail.com
  5. All rights reserved.
  6. Redistribution and use in source and binary forms, with or without modification,
  7. are permitted provided that the following conditions are met:
  8. * Redistributions of source code must retain the above copyright notice, this list
  9. of conditions and the following disclaimer.
  10. * Redistributions in binary form must reproduce the above copyright notice, this
  11. list of conditions and the following disclaimer in the documentation and/or other
  12. materials provided with the distribution.
  13. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  14. CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  15. INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  16. MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  17. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
  18. CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  19. SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20. NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  21. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  22. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  23. STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  24. ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  25. ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. 6 Nov 2016: Not yet finished
  27. There are two controller:
  28. UC1611s 160x256
  29. UC1611 160x240
  30. Differences:
  31. UC1611 0xa8 cmd: enables 80 display rows
  32. UC1611s 0xa8 cmd: controlls graylevels
  33. UC1611 0xc0 cmd: single byte command for LCD mapping control
  34. UC1611s 0xc0 cmd: double byte command for LCD mapping control
  35. */
  36. #include "u8x8.h"
  37. static const uint8_t u8x8_d_uc1611s_powersave0_seq[] = {
  38. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  39. U8X8_C(0x0a9), /* display on, UC1611s */
  40. U8X8_END_TRANSFER(), /* disable chip */
  41. U8X8_END() /* end of sequence */
  42. };
  43. static const uint8_t u8x8_d_uc1611s_powersave1_seq[] = {
  44. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  45. U8X8_C(0x0a8), /* display off, enter sleep mode, UC1611s */
  46. U8X8_END_TRANSFER(), /* disable chip */
  47. U8X8_END() /* end of sequence */
  48. };
  49. static const uint8_t u8x8_d_uc1611s_flip0_seq[] = {
  50. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  51. U8X8_CA(0x0c0, 0x004), /* LCD Mapping */
  52. U8X8_END_TRANSFER(), /* disable chip */
  53. U8X8_END() /* end of sequence */
  54. };
  55. static const uint8_t u8x8_d_uc1611s_flip1_seq[] = {
  56. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  57. U8X8_CA(0x0c0, 0x002), /* LCD Mapping */
  58. U8X8_END_TRANSFER(), /* disable chip */
  59. U8X8_END() /* end of sequence */
  60. };
  61. uint8_t u8x8_d_uc1611_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  62. {
  63. uint8_t x, y, c;
  64. uint8_t *ptr;
  65. switch(msg)
  66. {
  67. case U8X8_MSG_DISPLAY_DRAW_TILE:
  68. u8x8_cad_StartTransfer(u8x8);
  69. x = ((u8x8_tile_t *)arg_ptr)->x_pos;
  70. x *= 8;
  71. x += u8x8->x_offset;
  72. u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
  73. u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
  74. y = ((u8x8_tile_t *)arg_ptr)->y_pos;
  75. u8x8_cad_SendCmd(u8x8, 0x060 | (y&15));
  76. u8x8_cad_SendCmd(u8x8, 0x070 | (y>>4));
  77. c = ((u8x8_tile_t *)arg_ptr)->cnt;
  78. c *= 8;
  79. ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
  80. do
  81. {
  82. u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
  83. arg_int--;
  84. } while( arg_int > 0 );
  85. u8x8_cad_EndTransfer(u8x8);
  86. break;
  87. /* handled in the calling procedure
  88. case U8X8_MSG_DISPLAY_SETUP_MEMORY:
  89. u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1611_128x64_display_info);
  90. break;
  91. case U8X8_MSG_DISPLAY_INIT:
  92. u8x8_d_helper_display_init(u8x8);
  93. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_dogs102_init_seq);
  94. break;
  95. */
  96. #ifdef U8X8_WITH_SET_CONTRAST
  97. case U8X8_MSG_DISPLAY_SET_CONTRAST:
  98. u8x8_cad_StartTransfer(u8x8);
  99. u8x8_cad_SendCmd(u8x8, 0x081 );
  100. u8x8_cad_SendArg(u8x8, arg_int ); /* uc1611 has range from 0 to 255 */
  101. u8x8_cad_EndTransfer(u8x8);
  102. break;
  103. #endif
  104. default:
  105. return 0;
  106. }
  107. return 1;
  108. }
  109. /*================================================*/
  110. /* EA DOGM240 */
  111. /*
  112. UC1611 has two chip select inputs (CS0 and CS1).
  113. CS0 is low active, CS1 is high active. It will depend on the display
  114. module whether the display has a is low or high active chip select.
  115. */
  116. static const u8x8_display_info_t u8x8_uc1611_240x64_display_info =
  117. {
  118. /* chip_enable_level = */ 0,
  119. /* chip_disable_level = */ 1,
  120. /* post_chip_enable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
  121. /* pre_chip_disable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
  122. /* reset_pulse_width_ms = */ 1,
  123. /* post_reset_wait_ms = */ 10, /* uc1611 datasheet, page 67 */
  124. /* sda_setup_time_ns = */ 10, /* uc1611 datasheet, page 64, actually 0 */
  125. /* sck_pulse_width_ns = */ 60, /* half of cycle time */
  126. /* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
  127. /* spi_mode = */ 0, /* active high, rising edge */
  128. /* i2c_bus_clock_100kHz = */ 4,
  129. /* data_setup_time_ns = */ 30, /* uc1611 datasheet, page 60 */
  130. /* write_pulse_width_ns = */ 80, /* uc1611 datasheet, page 60 */
  131. /* tile_width = */ 30, /* width of 30*8=240 pixel */
  132. /* tile_height = */ 8,
  133. /* default_x_offset = */ 0,
  134. /* flipmode_x_offset = */ 0,
  135. /* pixel_width = */ 240,
  136. /* pixel_height = */ 64
  137. };
  138. static const uint8_t u8x8_d_uc1611_ea_dogm240_init_seq[] = {
  139. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  140. U8X8_C(0x02f), /* internal pump control */
  141. U8X8_CA(0x0f1, 63), /* set COM end */
  142. U8X8_CA(0x0f2, 0x000), /* display line start */
  143. U8X8_CA(0x0f3, 63), /* display line end */
  144. U8X8_C(0x0a3), /* line rate */
  145. U8X8_CA(0x081, 0x0a4), /* set contrast, EA default: 0x0b7 */
  146. //U8X8_C(0x0a9), /* display enable */
  147. U8X8_C(0x0d1), /* display pattern */
  148. U8X8_C(0x089), /* auto increment */
  149. U8X8_CA(0x0c0, 0x004), /* LCD Mapping */
  150. U8X8_C(0x000), /* column low nibble */
  151. U8X8_C(0x010), /* column high nibble */
  152. U8X8_C(0x060), /* page adr low */
  153. U8X8_C(0x070), /* page adr high */
  154. U8X8_END_TRANSFER(), /* disable chip */
  155. U8X8_END() /* end of sequence */
  156. };
  157. /* UC1611s 240x64 display */
  158. uint8_t u8x8_d_uc1611_ea_dogm240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  159. {
  160. /* call common procedure first and handle messages there */
  161. if ( u8x8_d_uc1611_common(u8x8, msg, arg_int, arg_ptr) == 0 )
  162. {
  163. /* msg not handled, then try here */
  164. switch(msg)
  165. {
  166. case U8X8_MSG_DISPLAY_SETUP_MEMORY:
  167. u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1611_240x64_display_info);
  168. break;
  169. case U8X8_MSG_DISPLAY_INIT:
  170. u8x8_d_helper_display_init(u8x8);
  171. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_ea_dogm240_init_seq);
  172. break;
  173. case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
  174. if ( arg_int == 0 )
  175. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave0_seq);
  176. else
  177. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave1_seq);
  178. break;
  179. case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
  180. if ( arg_int == 0 )
  181. {
  182. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip0_seq);
  183. u8x8->x_offset = u8x8->display_info->default_x_offset;
  184. }
  185. else
  186. {
  187. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip1_seq);
  188. u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
  189. }
  190. break;
  191. default:
  192. return 0; /* msg unknown */
  193. }
  194. }
  195. return 1;
  196. }
  197. /*================================================*/
  198. /* EA DOGXL240 */
  199. static const uint8_t u8x8_d_uc1611_ea_dogxl240_init_seq[] = {
  200. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  201. U8X8_C(0x02f), /* internal pump control */
  202. U8X8_CA(0x0f1, 0x07f), /* set COM end */
  203. U8X8_CA(0x0f2, 0x000), /* display line start */
  204. U8X8_CA(0x0f3, 127), /* display line end */
  205. U8X8_C(0x0a3), /* line rate */
  206. U8X8_CA(0x081, 0x08f), /* set contrast */
  207. //U8X8_C(0x0a9), /* display enable */
  208. U8X8_C(0x0d1), /* display pattern */
  209. U8X8_C(0x089), /* auto increment */
  210. U8X8_CA(0x0c0, 0x004), /* LCD Mapping */
  211. U8X8_C(0x000), /* column low nibble */
  212. U8X8_C(0x010), /* column high nibble */
  213. U8X8_C(0x060), /* page adr low */
  214. U8X8_C(0x070), /* page adr high */
  215. U8X8_END_TRANSFER(), /* disable chip */
  216. U8X8_END() /* end of sequence */
  217. };
  218. static const u8x8_display_info_t u8x8_uc1611_240x128_display_info =
  219. {
  220. /* chip_enable_level = */ 0,
  221. /* chip_disable_level = */ 1,
  222. /* post_chip_enable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
  223. /* pre_chip_disable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
  224. /* reset_pulse_width_ms = */ 1,
  225. /* post_reset_wait_ms = */ 10, /* uc1611 datasheet, page 67 */
  226. /* sda_setup_time_ns = */ 10, /* uc1611 datasheet, page 64, actually 0 */
  227. /* sck_pulse_width_ns = */ 60, /* half of cycle time */
  228. /* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
  229. /* spi_mode = */ 0, /* active high, rising edge */
  230. /* i2c_bus_clock_100kHz = */ 4,
  231. /* data_setup_time_ns = */ 30, /* uc1611 datasheet, page 60 */
  232. /* write_pulse_width_ns = */ 80, /* uc1611 datasheet, page 60 */
  233. /* tile_width = */ 30, /* width of 30*8=240 pixel */
  234. /* tile_height = */ 16,
  235. /* default_x_offset = */ 0,
  236. /* flipmode_x_offset = */ 0,
  237. /* pixel_width = */ 240,
  238. /* pixel_height = */ 128
  239. };
  240. /* UC1611s 240x128 display */
  241. uint8_t u8x8_d_uc1611_ea_dogxl240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  242. {
  243. /* call common procedure first and handle messages there */
  244. if ( u8x8_d_uc1611_common(u8x8, msg, arg_int, arg_ptr) == 0 )
  245. {
  246. /* msg not handled, then try here */
  247. switch(msg)
  248. {
  249. case U8X8_MSG_DISPLAY_SETUP_MEMORY:
  250. u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1611_240x128_display_info);
  251. break;
  252. case U8X8_MSG_DISPLAY_INIT:
  253. u8x8_d_helper_display_init(u8x8);
  254. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_ea_dogxl240_init_seq);
  255. break;
  256. case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
  257. if ( arg_int == 0 )
  258. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave0_seq);
  259. else
  260. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave1_seq);
  261. break;
  262. case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
  263. if ( arg_int == 0 )
  264. {
  265. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip0_seq);
  266. u8x8->x_offset = u8x8->display_info->default_x_offset;
  267. }
  268. else
  269. {
  270. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip1_seq);
  271. u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
  272. }
  273. break;
  274. default:
  275. return 0; /* msg unknown */
  276. }
  277. }
  278. return 1;
  279. }
  280. /*================================================*/
  281. /* EMERGING DISPLAY, EW50850FLWP 240x160 */
  282. /* active high CS (CS1), UC1611 display */
  283. static const uint8_t u8x8_d_uc1611_ew50850_init_seq[] = {
  284. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  285. U8X8_C(0x02f), /* internal pump control */
  286. U8X8_CA(0x0f1, 159), /* set COM end */
  287. U8X8_CA(0x0f2, 0), /* display line start */
  288. U8X8_CA(0x0f3, 159), /* display line end */
  289. U8X8_C(0x0a3), /* line rate */
  290. U8X8_CA(0x081, 75), /* set contrast */
  291. //U8X8_C(0x0a9), /* display enable */
  292. U8X8_C(0x0d2), /* gray level mode: 16 gray shades */
  293. U8X8_C(0x089), /* auto increment */
  294. U8X8_C(0x0c0), /* LCD Mapping Bit 0: MSF, Bit 1: MX, Bit 2: MY */
  295. U8X8_C(0x000), /* column low nibble */
  296. U8X8_C(0x010), /* column high nibble */
  297. U8X8_C(0x060), /* page adr low */
  298. U8X8_C(0x070), /* page adr high */
  299. U8X8_END_TRANSFER(), /* disable chip */
  300. U8X8_END() /* end of sequence */
  301. };
  302. static const u8x8_display_info_t u8x8_uc1611_ew50850_display_info =
  303. {
  304. /* chip_enable_level = */ 1, /* active high */
  305. /* chip_disable_level = */ 0,
  306. /* post_chip_enable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
  307. /* pre_chip_disable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
  308. /* reset_pulse_width_ms = */ 1,
  309. /* post_reset_wait_ms = */ 10, /* uc1611 datasheet, page 67 */
  310. /* sda_setup_time_ns = */ 10, /* uc1611 datasheet, page 64, actually 0 */
  311. /* sck_pulse_width_ns = */ 60, /* half of cycle time */
  312. /* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
  313. /* spi_mode = */ 0, /* active high, rising edge */
  314. /* i2c_bus_clock_100kHz = */ 4,
  315. /* data_setup_time_ns = */ 30, /* uc1611 datasheet, page 60 */
  316. /* write_pulse_width_ns = */ 80, /* uc1611 datasheet, page 60 */
  317. /* tile_width = */ 30, /* width of 30*8=240 pixel */
  318. /* tile_height = */ 20, /* height: 160 pixel */
  319. /* default_x_offset = */ 0,
  320. /* flipmode_x_offset = */ 0,
  321. /* pixel_width = */ 240,
  322. /* pixel_height = */ 160
  323. };
  324. static const uint8_t u8x8_d_uc1611_alt_flip0_seq[] = {
  325. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  326. U8X8_C(0x0c0), /* LCD Mapping Bit 0: MSF, Bit 1: MX, Bit 2: MY */
  327. U8X8_END_TRANSFER(), /* disable chip */
  328. U8X8_END() /* end of sequence */
  329. };
  330. static const uint8_t u8x8_d_uc1611_alt_flip1_seq[] = {
  331. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  332. U8X8_C(0x0c6), /* LCD Mapping Bit 0: MSF, Bit 1: MX, Bit 2: MY */
  333. U8X8_END_TRANSFER(), /* disable chip */
  334. U8X8_END() /* end of sequence */
  335. };
  336. static const uint8_t u8x8_d_uc1611_powersave0_seq[] = {
  337. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  338. U8X8_C(0x0af), /* display on, UC1611 */
  339. U8X8_END_TRANSFER(), /* disable chip */
  340. U8X8_END() /* end of sequence */
  341. };
  342. static const uint8_t u8x8_d_uc1611_powersave1_seq[] = {
  343. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  344. U8X8_C(0x0a8), /* display off, enter sleep mode, UC1611 */
  345. U8X8_END_TRANSFER(), /* disable chip */
  346. U8X8_END() /* end of sequence */
  347. };
  348. /* EW50850, 240x160 */
  349. uint8_t u8x8_d_uc1611_ew50850(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  350. {
  351. uint8_t x, y, c, i, v, m0, m1, ai;
  352. uint8_t *ptr;
  353. /* msg not handled, then try here */
  354. switch(msg)
  355. {
  356. case U8X8_MSG_DISPLAY_DRAW_TILE:
  357. u8x8_cad_StartTransfer(u8x8);
  358. x = ((u8x8_tile_t *)arg_ptr)->x_pos;
  359. x *= 8;
  360. x += u8x8->x_offset;
  361. y = ((u8x8_tile_t *)arg_ptr)->y_pos;
  362. y*=4;
  363. m0 = 1;
  364. m1 = 2;
  365. for( i = 0; i < 4; i++ )
  366. {
  367. u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
  368. u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
  369. u8x8_cad_SendCmd(u8x8, 0x060 | (y&15));
  370. u8x8_cad_SendCmd(u8x8, 0x070 | (y>>4));
  371. ai = arg_int;
  372. do
  373. {
  374. c = ((u8x8_tile_t *)arg_ptr)->cnt;
  375. c *= 8;
  376. ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
  377. while( c > 0 )
  378. {
  379. v = 0;
  380. if ( *ptr & m0 )
  381. v|= 0x0f;
  382. if ( *ptr & m1 )
  383. v|= 0xf0;
  384. u8x8_cad_SendData(u8x8, 1, &v); /* note: SendData can not handle more than 255 bytes */
  385. c--;
  386. ptr++;
  387. }
  388. ai--;
  389. } while( ai > 0 );
  390. m0 <<= 2;
  391. m1 <<= 2;
  392. y++;
  393. }
  394. u8x8_cad_EndTransfer(u8x8);
  395. break;
  396. case U8X8_MSG_DISPLAY_SETUP_MEMORY:
  397. u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1611_ew50850_display_info);
  398. break;
  399. case U8X8_MSG_DISPLAY_INIT:
  400. u8x8_d_helper_display_init(u8x8);
  401. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_ew50850_init_seq);
  402. break;
  403. case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
  404. if ( arg_int == 0 )
  405. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_powersave0_seq);
  406. else
  407. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_powersave1_seq);
  408. break;
  409. case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
  410. if ( arg_int == 0 )
  411. {
  412. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_alt_flip0_seq);
  413. u8x8->x_offset = u8x8->display_info->default_x_offset;
  414. }
  415. else
  416. {
  417. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_alt_flip1_seq);
  418. u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
  419. }
  420. break;
  421. #ifdef U8X8_WITH_SET_CONTRAST
  422. case U8X8_MSG_DISPLAY_SET_CONTRAST:
  423. u8x8_cad_StartTransfer(u8x8);
  424. u8x8_cad_SendCmd(u8x8, 0x081 );
  425. u8x8_cad_SendArg(u8x8, arg_int ); /* uc1611 has range from 0 to 255 */
  426. u8x8_cad_EndTransfer(u8x8);
  427. break;
  428. #endif
  429. default:
  430. return 0; /* msg unknown */
  431. }
  432. return 1;
  433. }
  434. /*================================================*/
  435. /* CG160160D, http://www.cloverdisplay.com/pdf/CG160160D.pdf */
  436. /*
  437. UC1611 has two chip select inputs (CS0 and CS1).
  438. CS0 is low active, CS1 is high active. It will depend on the display
  439. module whether the display has a is low or high active chip select.
  440. Connect CS1 to 3.3V and CS0 to GPIO
  441. */
  442. static const u8x8_display_info_t u8x8_uc1611_cg160160_display_info =
  443. {
  444. /* chip_enable_level = */ 0, /* use CS0 of the UC1611 */
  445. /* chip_disable_level = */ 1,
  446. /* post_chip_enable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
  447. /* pre_chip_disable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
  448. /* reset_pulse_width_ms = */ 1,
  449. /* post_reset_wait_ms = */ 10, /* uc1611 datasheet, page 67 */
  450. /* sda_setup_time_ns = */ 10, /* uc1611 datasheet, page 64, actually 0 */
  451. /* sck_pulse_width_ns = */ 60, /* half of cycle time */
  452. /* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
  453. /* spi_mode = */ 0, /* active high, rising edge */
  454. /* i2c_bus_clock_100kHz = */ 4,
  455. /* data_setup_time_ns = */ 30, /* uc1611 datasheet, page 60 */
  456. /* write_pulse_width_ns = */ 80, /* uc1611 datasheet, page 60 */
  457. /* tile_width = */ 20, /* width of 20*8=160 pixel */
  458. /* tile_height = */ 20,
  459. /* default_x_offset = */ 0,
  460. /* flipmode_x_offset = */ 0,
  461. /* pixel_width = */ 160,
  462. /* pixel_height = */ 160
  463. };
  464. /*
  465. System Reset: E2H --> DONE
  466. Set Temp. Compensation: 24H --> DONE
  467. Set up LCD format specific parameters MX,MY,etc(double-byte command): C0H,04H --> FLIP0
  468. Set line rate: A3H --> DONE
  469. Set Pump Control (internal Vlcd): 2FH --> DONE
  470. Set Isolation Clock Front (3 bytes command): 82H, 13H, 01H --> DONE
  471. Set Isolation Clock Back (3 bytes command): 82H, 14H, 00H --> DONE
  472. Set LCD Bias Ratio: EAH
  473. LCD Specific Operation Voltage Setting (double-byte command): 81H, 90H --> DONE
  474. Set RAM Address Control: 80H --> DOES NOT MAKE SENSE
  475. Set Page Addr. MSB: 72H --> DONE
  476. Set Page Addr. LSB : 60H --> DONE
  477. Set Column Addr. LSB: 00H --> DONE
  478. Set Column Addr.MSB: 10H --> DONE
  479. Window Program Enable : F8H --> NOT REQURED
  480. Window Starting Column (double-byte command): F4H , 00H --> NOT REQURED
  481. Window Ending Column (double-byte command): F6H, 9FH --> NOT REQURED
  482. Set one bit for one pixel: D1H --> DONE
  483. Set Display Enable: A9H
  484. */
  485. static const uint8_t u8x8_d_uc1611_cg160160_init_seq[] = {
  486. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  487. U8X8_C(0x0e2), /* system reset */
  488. U8X8_DLY(2),
  489. U8X8_C(0x024), /* Temp. Compensation to 0 = -0.05%/ Grad C */
  490. U8X8_C(0x0a3), /* line rate */
  491. U8X8_C(0x02f), /* internal pump control */
  492. U8X8_CAA(0x082, 0x013, 0x001), /* Isolation front clock, "1" is the default value */
  493. U8X8_CAA(0x082, 0x014, 0x000), /* Isolation back clock, "0" is the default value */
  494. U8X8_C(0x0ea), /* bias ratio, default: 0x0ea */
  495. U8X8_CA(0x081, 0x090), /* set contrast, CG160160: 0x090 */
  496. //U8X8_CA(0x0f1, 159), /* set COM end */
  497. //U8X8_CA(0x0f2, 0), /* display line start */
  498. //U8X8_CA(0x0f3, 159), /* display line end */
  499. //U8X8_C(0x0a9), /* display enable */
  500. U8X8_C(0x089), /* RAM Address Control: auto increment */
  501. U8X8_C(0x0d1), /* display pattern */
  502. U8X8_CA(0x0c0, 0x004), /* LCD Mapping */
  503. U8X8_C(0x000), /* column low nibble */
  504. U8X8_C(0x010), /* column high nibble */
  505. U8X8_C(0x060), /* page adr low */
  506. U8X8_C(0x070), /* page adr high */
  507. U8X8_END_TRANSFER(), /* disable chip */
  508. U8X8_END() /* end of sequence */
  509. };
  510. /* cg160160 display */
  511. uint8_t u8x8_d_uc1611_cg160160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  512. {
  513. /* call common procedure first and handle messages there */
  514. if ( u8x8_d_uc1611_common(u8x8, msg, arg_int, arg_ptr) == 0 )
  515. {
  516. /* msg not handled, then try here */
  517. switch(msg)
  518. {
  519. case U8X8_MSG_DISPLAY_SETUP_MEMORY:
  520. u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1611_cg160160_display_info);
  521. break;
  522. case U8X8_MSG_DISPLAY_INIT:
  523. u8x8_d_helper_display_init(u8x8);
  524. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_cg160160_init_seq);
  525. break;
  526. case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
  527. if ( arg_int == 0 )
  528. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave0_seq);
  529. else
  530. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave1_seq);
  531. break;
  532. case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
  533. if ( arg_int == 0 )
  534. {
  535. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip0_seq);
  536. u8x8->x_offset = u8x8->display_info->default_x_offset;
  537. }
  538. else
  539. {
  540. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip1_seq);
  541. u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
  542. }
  543. break;
  544. default:
  545. return 0; /* msg unknown */
  546. }
  547. }
  548. return 1;
  549. }
  550. /*================================================*/
  551. /* CI064-4073-06 (Intelligent Display Solutions), IDS4073*/
  552. /* https://docs.rs-online.com/7e6e/0900766b8156b018.pdf */
  553. static const uint8_t u8x8_d_uc1611_ids4073_init_seq[] = {
  554. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  555. U8X8_C(0x02f), /* internal pump control */
  556. U8X8_CA(0x0f1, 0x07f), /* set COM end */
  557. U8X8_CA(0x0f2, 0x000), /* display line start */
  558. U8X8_CA(0x0f3, 127), /* display line end */
  559. U8X8_C(0x0a3), /* line rate */
  560. U8X8_CA(0x081, 0x08f), /* set contrast */
  561. //U8X8_C(0x0a9), /* display enable */
  562. U8X8_C(0x0d1), /* display pattern */
  563. U8X8_C(0x089), /* auto increment */
  564. U8X8_CA(0x0c0, 0x004), /* LCD Mapping */
  565. U8X8_C(0x000), /* column low nibble */
  566. U8X8_C(0x010), /* column high nibble */
  567. U8X8_C(0x060), /* page adr low */
  568. U8X8_C(0x070), /* page adr high */
  569. U8X8_END_TRANSFER(), /* disable chip */
  570. U8X8_END() /* end of sequence */
  571. };
  572. static const u8x8_display_info_t u8x8_uc1611_256x128_display_info =
  573. {
  574. /* chip_enable_level = */ 0,
  575. /* chip_disable_level = */ 1,
  576. /* post_chip_enable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
  577. /* pre_chip_disable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
  578. /* reset_pulse_width_ms = */ 1,
  579. /* post_reset_wait_ms = */ 10, /* uc1611 datasheet, page 67 */
  580. /* sda_setup_time_ns = */ 10, /* uc1611 datasheet, page 64, actually 0 */
  581. /* sck_pulse_width_ns = */ 60, /* half of cycle time */
  582. /* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
  583. /* spi_mode = */ 0, /* active high, rising edge */
  584. /* i2c_bus_clock_100kHz = */ 4,
  585. /* data_setup_time_ns = */ 30, /* uc1611 datasheet, page 60 */
  586. /* write_pulse_width_ns = */ 80, /* uc1611 datasheet, page 60 */
  587. /* tile_width = */ 32, /* width of 32*8=256 pixel */
  588. /* tile_height = */ 16,
  589. /* default_x_offset = */ 0,
  590. /* flipmode_x_offset = */ 0,
  591. /* pixel_width = */ 256,
  592. /* pixel_height = */ 128
  593. };
  594. /* UC1611s 256x128 display */
  595. uint8_t u8x8_d_uc1611_ids4073(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  596. {
  597. uint8_t x, y, c;
  598. uint8_t *ptr;
  599. switch(msg)
  600. {
  601. case U8X8_MSG_DISPLAY_DRAW_TILE:
  602. u8x8_cad_StartTransfer(u8x8);
  603. x = ((u8x8_tile_t *)arg_ptr)->x_pos;
  604. x *= 8;
  605. x += u8x8->x_offset;
  606. u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
  607. u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
  608. y = ((u8x8_tile_t *)arg_ptr)->y_pos;
  609. u8x8_cad_SendCmd(u8x8, 0x060 | (y&15));
  610. u8x8_cad_SendCmd(u8x8, 0x070 | (y>>4));
  611. do
  612. {
  613. c = ((u8x8_tile_t *)arg_ptr)->cnt;
  614. ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
  615. /* SendData can not handle more than 255 bytes */
  616. if ( c > 31 )
  617. {
  618. u8x8_cad_SendData(u8x8, 248, ptr); /* 31*8=248 */
  619. ptr+=248;
  620. c -= 31;
  621. }
  622. u8x8_cad_SendData(u8x8, c*8, ptr);
  623. arg_int--;
  624. } while( arg_int > 0 );
  625. u8x8_cad_EndTransfer(u8x8);
  626. break;
  627. #ifdef U8X8_WITH_SET_CONTRAST
  628. case U8X8_MSG_DISPLAY_SET_CONTRAST:
  629. u8x8_cad_StartTransfer(u8x8);
  630. u8x8_cad_SendCmd(u8x8, 0x081 );
  631. u8x8_cad_SendArg(u8x8, arg_int ); /* uc1611 has range from 0 to 255 */
  632. u8x8_cad_EndTransfer(u8x8);
  633. break;
  634. #endif
  635. case U8X8_MSG_DISPLAY_SETUP_MEMORY:
  636. u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1611_256x128_display_info);
  637. break;
  638. case U8X8_MSG_DISPLAY_INIT:
  639. u8x8_d_helper_display_init(u8x8);
  640. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_ids4073_init_seq);
  641. break;
  642. case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
  643. if ( arg_int == 0 )
  644. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave0_seq);
  645. else
  646. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave1_seq);
  647. break;
  648. case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
  649. if ( arg_int == 0 )
  650. {
  651. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip0_seq);
  652. u8x8->x_offset = u8x8->display_info->default_x_offset;
  653. }
  654. else
  655. {
  656. u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip1_seq);
  657. u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
  658. }
  659. break;
  660. default:
  661. return 0; /* msg unknown */
  662. }
  663. return 1;
  664. }