u8x8_d_st7305.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694
  1. /*
  2. u8x8_d_st7305.c
  3. Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
  4. Copyright (c) 2025, 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. st7305: 240 x 320 122x250
  27. st7305: 264 x 320 168x384, 200x200
  28. Mono TFT Display Driver with Controller
  29. st7305 seems to be almost compatible to the st7303, however they have a different memory architecture
  30. https://github.com/olikraus/u8g2/issues/2436
  31. No Hardware Flip
  32. No U8x8 Support
  33. */
  34. #include "u8x8.h"
  35. #include <string.h>
  36. static const uint8_t u8x8_d_st7305_122x250_powersave0_seq[] = {
  37. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  38. U8X8_C(0x29), // display on
  39. U8X8_END_TRANSFER(), /* disable chip */
  40. U8X8_END() /* end of sequence */
  41. };
  42. static const uint8_t u8x8_d_st7305_122x250_powersave1_seq[] = {
  43. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  44. U8X8_C(0x028), /* display off */
  45. U8X8_END_TRANSFER(), /* disable chip */
  46. U8X8_END() /* end of sequence */
  47. };
  48. static const uint8_t u8x8_d_st7305_122x250_flip0_seq[] = {
  49. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  50. //U8X8_CA(0x36, 0x60), // Memory Control
  51. U8X8_END_TRANSFER(), /* disable chip */
  52. U8X8_END() /* end of sequence */
  53. };
  54. static const uint8_t u8x8_d_st7305_122x250_flip1_seq[] = {
  55. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  56. //U8X8_CA(0x36, 0xa0), // Memory Control
  57. U8X8_END_TRANSFER(), /* disable chip */
  58. U8X8_END() /* end of sequence */
  59. };
  60. /*===================================================*/
  61. /* see also: http://www.technoblogy.com/show?3YB0 */
  62. static uint8_t *u8x8_st7305_convert_a0(u8x8_t *u8x8, uint8_t *p)
  63. {
  64. static uint8_t buf[6];
  65. #ifdef NOT_WORKING
  66. /* u8g2 first row */
  67. static uint8_t map1[16] = {
  68. /* 0x00 0000 */ 0,
  69. /* 0x01 0001 */0x04,
  70. /* 0x02 0010 */0x01,
  71. /* 0x03 0011 */0x04+0x01,
  72. /* 0x04 0100 */0x40,
  73. /* 0x05 0101 */0x40+0x04,
  74. /* 0x06 0110 */0x40+0x01,
  75. /* 0x07 0111 */0x40+0x04+0x01,
  76. /* 0x08 1000 */ 0x10,
  77. /* 0x09 1001 */ 0x10+0x04,
  78. /* 0x0a 1010 */ 0x10+0x01,
  79. /* 0x0b 1011 */ 0x10+0x04+0x01,
  80. /* 0x0c 1100 */ 0x40+0x10,
  81. /* 0x0d 1101 */ 0x40+0x10+0x04,
  82. /* 0x0e 1110 */ 0x40+0x10+0x01,
  83. /* 0x0f 1111 */ 0x40+0x10+0x04+0x01
  84. };
  85. /* u8g2 second row */
  86. static uint8_t map2[16] = {
  87. /* 0x00 0000 */ 0,
  88. /* 0x01 0001 */0x08,
  89. /* 0x02 0010 */0x02,
  90. /* 0x03 0011 */0x08+0x02,
  91. /* 0x04 0100 */0x80,
  92. /* 0x05 0101 */0x80+0x08,
  93. /* 0x06 0110 */0x80+0x02,
  94. /* 0x07 0111 */0x80+0x08+0x02,
  95. /* 0x08 1000 */ 0x20,
  96. /* 0x09 1001 */ 0x20+0x08,
  97. /* 0x0a 1010 */ 0x20+0x02,
  98. /* 0x0b 1011 */ 0x20+0x08+0x02,
  99. /* 0x0c 1100 */ 0x80+0x20,
  100. /* 0x0d 1101 */ 0x80+0x20+0x08,
  101. /* 0x0e 1110 */ 0x80+0x20+0x02,
  102. /* 0x0f 1111 */ 0x80+0x20+0x08+0x02
  103. };
  104. #endif
  105. /* contributed by https://github.com/ischenz */
  106. /* u8g2 first row */
  107. static uint8_t map1[16] = {
  108. 0x00, 0x02, 0x08, 0x0A,
  109. 0x20, 0x22, 0x28, 0x2A,
  110. 0x80, 0x82, 0x88, 0x8A,
  111. 0xA0, 0xA2, 0xA8, 0xAA };
  112. /* u8g2 second row */
  113. static uint8_t map2[16] = {
  114. 0x00, 0x01, 0x04, 0x05,
  115. 0x10, 0x11, 0x14, 0x15,
  116. 0x40, 0x41, 0x44, 0x45,
  117. 0x50, 0x51, 0x54, 0x55 };
  118. memset(buf, 0, 6);
  119. // first row, left 12 pixel out of 24 pixel (=3 bytes)
  120. buf[0] |= map1[p[0]>>4];
  121. buf[1] |= map1[p[0] & 0x0f];
  122. buf[2] |= map1[p[1]>>4];
  123. // first row, right 12 pixel
  124. buf[3] |= map1[p[1] & 0x0f];
  125. buf[4] |= map1[p[2]>>4];
  126. buf[5] |= map1[p[2] & 0x0f];
  127. p += u8x8->display_info->tile_width;
  128. // second row, left 12 pixel
  129. buf[0] |= map2[p[0]>>4];
  130. buf[1] |= map2[p[0] & 0x0f];
  131. buf[2] |= map2[p[1]>>4];
  132. // second row, right 12 pixel
  133. buf[3] |= map2[p[1] & 0x0f];
  134. buf[4] |= map2[p[2]>>4];
  135. buf[5] |= map2[p[2] & 0x0f];
  136. return buf;
  137. }
  138. /*===================================================*/
  139. /*
  140. see also:
  141. https://github.com/zhcong/st7302-for-arduino/blob/c9390fabcacefe7c36a113cd3e62959418c13b97/libraries/st7305SPI/st7305SPI.cpp#L21
  142. */
  143. static const uint8_t u8x8_d_st7305_122x250_init_seq[] = {
  144. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  145. U8X8_C(0x01), // software resets
  146. U8X8_DLY(100),
  147. U8X8_C(0x28), // display off
  148. U8X8_CAA(0xC7, 0x26, 0xE9), // disable OSC
  149. U8X8_CA(0xD1, 0x00), // Booster disable
  150. U8X8_DLY(20),
  151. U8X8_C(0x10), // sleep in: enter sleep mode
  152. U8X8_DLY(20),
  153. U8X8_C(0x01), // software reset
  154. U8X8_DLY(20), // wait
  155. //U8X8_C(0x38), // High Power Mode
  156. //U8X8_CA(0xEB, 0x02), // Disable NVM Load
  157. //U8X8_CA(0xD7, 0x68), // NVM Load Control: Enable ID1 ID2 ID3 Load
  158. //U8X8_CA(0xD1, 0x01), // Booster Enable
  159. //U8X8_CA(0xC0, 0x80), // Gate Voltage Setting VGH=12V (upper 4 bit, 8V-15V); VGL=-5V (lower 4 bit, -5V .. -10V)
  160. U8X8_CAA(0xD6, 0x17, 0x02),
  161. U8X8_CA(0xD1, 0x01),
  162. U8X8_CAA(0xC0, 0x12, 0x0a),//chen.x
  163. U8X8_C(0x0C1), // Source Voltage Control 1
  164. U8X8_A4(115,0x3E,0x3C,0x3C),
  165. U8X8_C(0x0C2), // Source Voltage Control 1
  166. U8X8_A4(0,0x21,0x23,0x23), // Source low voltage in reflective and transmissive mode
  167. U8X8_C(0x0C4), //ischen.x
  168. U8X8_A4(50,0x5C,0x5A,0x5A),
  169. U8X8_C(0x0C5), //ischen.x
  170. U8X8_A4(50,0x35,0x37,0x37),
  171. U8X8_CAA(0xD8, 0x80, 0xE9),
  172. //U8X8_CA(0xCB, 0x14), // VCOMH: 0x14 = 4V (0x28 = 5V)
  173. U8X8_CA(0xB2, 0x12),
  174. U8X8_CAA(0xB3, 0xE5, 0xF6), // Update Period Gate EQ Control, why 0x77??? it should be 0x66 according to the datasheet
  175. U8X8_A8(0x17, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x71),
  176. U8X8_CAA(0xB4, 0x05, 0x46), // Update Period Gate EQ Control, why 0x77??? it should be 0x66 according to the datasheet
  177. U8X8_A6(0x77, 0x77, 0x77, 0x77, 0x76, 0x45),
  178. U8X8_CAAA(0x62, 0x32, 0x03, 0x1f),
  179. U8X8_CA(0xB7, 0x13),
  180. U8X8_CA(0xB0, 0x32), // Duty Cycle... this must be before sleep out, 200x200 display: 0x64 --> 0x32
  181. U8X8_C(0x11), // sleep out: furn off sleep mode
  182. U8X8_DLY(120),
  183. U8X8_CA(0xC9, 0x00),
  184. U8X8_CA(0x36, 0xa4), // Memory Control, 0xa4 for the 200x200 display
  185. U8X8_CA(0x3A, 0x11), // Data Format
  186. U8X8_CA(0xB9, 0x20), // Source Setting: Clear RAM off *******<-----
  187. U8X8_CA(0xB8, 0x29), // Panel Setting / Panel Layout
  188. U8X8_CAA(0x2A, 0x16, 0x27), // col addr
  189. U8X8_CAA(0x2B, 0x00, 0x63), // row addr
  190. U8X8_CA(0x35, 0x00),
  191. U8X8_CA(0xD0, 0xFF), // Not in datasheet
  192. //U8X8_CA(0x72, 0x00), // Not in datasheet
  193. //U8X8_CAA(0xB2,1, 5), // Frame Rate for High and Low Power Mode (hier: 32Hz and 8Hz)
  194. U8X8_C(0x38), // enable Low Power Mode...: 8Hz, see above
  195. U8X8_C(0x29), // display on
  196. U8X8_C(0x20),
  197. U8X8_CA(0xBB, 0x4F),
  198. U8X8_DLY(100),
  199. U8X8_END_TRANSFER(), /* disable chip */
  200. U8X8_END() /* end of sequence */
  201. };
  202. static const u8x8_display_info_t u8x8_st7305_122x250_display_info =
  203. {
  204. /* chip_enable_level = */ 0,
  205. /* chip_disable_level = */ 1,
  206. /* post_chip_enable_wait_ns = */ 20,
  207. /* pre_chip_disable_wait_ns = */ 20,
  208. /* reset_pulse_width_ms = */ 3,
  209. /* post_reset_wait_ms = */ 3, /**/
  210. /* sda_setup_time_ns = */ 10, /* */
  211. /* sck_pulse_width_ns = */ 30, /* */
  212. /* sck_clock_hz = */ 2000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
  213. /* spi_mode = */ 0, /* active high, rising edge */
  214. /* i2c_bus_clock_100kHz = */ 4, /* 400KHz */
  215. /* data_setup_time_ns = */ 15,
  216. /* write_pulse_width_ns = */ 70,
  217. /* tile_width = */ 16,
  218. /* tile_height = */ 32,
  219. /* default_x_offset = */ 0,
  220. /* flipmode_x_offset = */ 0,
  221. /* pixel_width = */ 122,
  222. /* pixel_height = */ 250
  223. };
  224. uint8_t u8x8_d_st7305_122x250(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  225. {
  226. uint16_t x;
  227. uint8_t c, i, y;
  228. uint8_t *ptr;
  229. switch(msg)
  230. {
  231. case U8X8_MSG_DISPLAY_INIT:
  232. u8x8_d_helper_display_init(u8x8);
  233. u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_init_seq);
  234. break;
  235. case U8X8_MSG_DISPLAY_SETUP_MEMORY:
  236. u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7305_122x250_display_info);
  237. break;
  238. case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
  239. if ( arg_int == 0 )
  240. u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_powersave0_seq);
  241. else
  242. u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_powersave1_seq);
  243. break;
  244. case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
  245. if ( arg_int == 0 )
  246. {
  247. u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_flip0_seq);
  248. u8x8->x_offset = u8x8->display_info->default_x_offset;
  249. }
  250. else
  251. {
  252. u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_flip1_seq);
  253. u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
  254. }
  255. break;
  256. #ifdef U8X8_WITH_SET_CONTRAST
  257. case U8X8_MSG_DISPLAY_SET_CONTRAST:
  258. u8x8_cad_StartTransfer(u8x8);
  259. u8x8_cad_SendCmd(u8x8, 0x081 );
  260. u8x8_cad_SendArg(u8x8, arg_int<<2 );
  261. u8x8_cad_SendArg(u8x8, arg_int>>6 );
  262. u8x8_cad_EndTransfer(u8x8);
  263. break;
  264. #endif
  265. case U8X8_MSG_DISPLAY_DRAW_TILE:
  266. x = ((u8x8_tile_t *)arg_ptr)->x_pos;
  267. x *= 8;
  268. x += u8x8->x_offset;
  269. y= (((u8x8_tile_t *)arg_ptr)->y_pos);
  270. y*=4;
  271. y+=115; // specific for the 122x250 LCD
  272. u8x8_cad_StartTransfer(u8x8);
  273. for( i = 0; i < 4; i++ )
  274. {
  275. u8x8_cad_SendCmd(u8x8, 0x2a);
  276. u8x8_cad_SendArg(u8x8, 0x19); // specific for the 122x250 LCD
  277. u8x8_cad_SendArg(u8x8, 0x3a );
  278. u8x8_cad_SendCmd(u8x8, 0x2b );
  279. u8x8_cad_SendArg(u8x8, y+i);
  280. u8x8_cad_SendArg(u8x8, y+i);
  281. u8x8_cad_SendCmd(u8x8, 0x02c ); // write data
  282. c = ((u8x8_tile_t *)arg_ptr)->cnt;
  283. ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
  284. ptr += u8x8->display_info->tile_width*i*2;
  285. c = (c+2)/3; // calculate the number of 24 bit blocks to send
  286. while( c > 0 )
  287. {
  288. u8x8_cad_SendData(u8x8, 6, u8x8_st7305_convert_a0(u8x8, ptr));
  289. ptr+=3;
  290. --c;
  291. }
  292. }
  293. u8x8_cad_EndTransfer(u8x8);
  294. break;
  295. default:
  296. return 0;
  297. }
  298. return 1;
  299. }
  300. /*=====================================================================*/
  301. /* 200x200, https://admin.osptek.com/uploads/YDP_154_H008_V3_c24b455ff9.pdf */
  302. static const u8x8_display_info_t u8x8_st7305_200x200_display_info =
  303. {
  304. /* chip_enable_level = */ 0,
  305. /* chip_disable_level = */ 1,
  306. /* post_chip_enable_wait_ns = */ 20,
  307. /* pre_chip_disable_wait_ns = */ 20,
  308. /* reset_pulse_width_ms = */ 3,
  309. /* post_reset_wait_ms = */ 3, /**/
  310. /* sda_setup_time_ns = */ 10, /* */
  311. /* sck_pulse_width_ns = */ 30, /* */
  312. /* sck_clock_hz = */ 2000000UL, /* 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, /* 400KHz */
  315. /* data_setup_time_ns = */ 15,
  316. /* write_pulse_width_ns = */ 70,
  317. /* tile_width = */ 26, /* tile width is 26*8=208, because this display requires 12 bit blocks, which would be 204 pixel, so next tile is at 208 */
  318. /* tile_height = */ 25,
  319. /* default_x_offset = */ 0,
  320. /* flipmode_x_offset = */ 0,
  321. /* pixel_width = */ 200, /* not 100% sure, whether this works with the tile_width of 26... */
  322. /* pixel_height = */ 200
  323. };
  324. uint8_t u8x8_d_st7305_200x200(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  325. {
  326. uint16_t x;
  327. uint8_t c, i, y;
  328. uint8_t *ptr;
  329. switch(msg)
  330. {
  331. case U8X8_MSG_DISPLAY_INIT:
  332. u8x8_d_helper_display_init(u8x8);
  333. u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_init_seq);
  334. break;
  335. case U8X8_MSG_DISPLAY_SETUP_MEMORY:
  336. u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7305_200x200_display_info);
  337. break;
  338. case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
  339. if ( arg_int == 0 )
  340. u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_powersave0_seq);
  341. else
  342. u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_powersave1_seq);
  343. break;
  344. case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
  345. if ( arg_int == 0 )
  346. {
  347. u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_flip0_seq);
  348. u8x8->x_offset = u8x8->display_info->default_x_offset;
  349. }
  350. else
  351. {
  352. u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_flip1_seq);
  353. u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
  354. }
  355. break;
  356. #ifdef U8X8_WITH_SET_CONTRAST
  357. case U8X8_MSG_DISPLAY_SET_CONTRAST:
  358. u8x8_cad_StartTransfer(u8x8);
  359. u8x8_cad_SendCmd(u8x8, 0x081 );
  360. u8x8_cad_SendArg(u8x8, arg_int<<2 );
  361. u8x8_cad_SendArg(u8x8, arg_int>>6 );
  362. u8x8_cad_EndTransfer(u8x8);
  363. break;
  364. #endif
  365. case U8X8_MSG_DISPLAY_DRAW_TILE:
  366. x = ((u8x8_tile_t *)arg_ptr)->x_pos;
  367. x *= 8;
  368. x += u8x8->x_offset;
  369. y= (((u8x8_tile_t *)arg_ptr)->y_pos);
  370. y*=4;
  371. y+=0; // 200x200 display
  372. u8x8_cad_StartTransfer(u8x8);
  373. for( i = 0; i < 4; i++ )
  374. {
  375. u8x8_cad_SendCmd(u8x8, 0x2a); // column address set
  376. u8x8_cad_SendArg(u8x8, 0x16); // 0x019 for the 122x250 LCD --> 0x016 for the 200x200 display
  377. u8x8_cad_SendArg(u8x8, 0x27 ); // 204 pixel for the 200x200 display
  378. u8x8_cad_SendCmd(u8x8, 0x2b );
  379. u8x8_cad_SendArg(u8x8, y+i);
  380. u8x8_cad_SendArg(u8x8, y+i);
  381. u8x8_cad_SendCmd(u8x8, 0x02c ); // write data
  382. c = ((u8x8_tile_t *)arg_ptr)->cnt;
  383. ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
  384. ptr += u8x8->display_info->tile_width*i*2;
  385. c = (c+2)/3; // calculate the number of 24 bit blocks to send
  386. while( c > 0 )
  387. {
  388. u8x8_cad_SendData(u8x8, 6, u8x8_st7305_convert_a0(u8x8, ptr));
  389. ptr+=3;
  390. --c;
  391. }
  392. }
  393. u8x8_cad_EndTransfer(u8x8);
  394. break;
  395. default:
  396. return 0;
  397. }
  398. return 1;
  399. }
  400. /*=====================================================================*/
  401. /* 168x384, https://github.com/olikraus/u8g2/issues/2661 */
  402. #ifdef NOT_USED
  403. static const uint8_t u8x8_d_st7305_168x384_powersave0_seq[] = {
  404. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  405. U8X8_C(0x29), // display on
  406. U8X8_END_TRANSFER(), /* disable chip */
  407. U8X8_END() /* end of sequence */
  408. };
  409. static const uint8_t u8x8_d_st7305_168x384_powersave1_seq[] = {
  410. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  411. U8X8_C(0x028), /* display off */
  412. U8X8_END_TRANSFER(), /* disable chip */
  413. U8X8_END() /* end of sequence */
  414. };
  415. static const uint8_t u8x8_d_st7305_168x384_flip0_seq[] = {
  416. U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
  417. // U8X8_CA(0x36, 0x60), // Memory Control
  418. U8X8_END_TRANSFER(), /* disable chip */
  419. U8X8_END() /* end of sequence */
  420. };
  421. #endif
  422. static const uint8_t u8x8_d_st7305_168x384_init_seq[] = {
  423. U8X8_START_TRANSFER(),
  424. /* Software Reset */
  425. U8X8_C(0x01),
  426. U8X8_DLY(100),
  427. /* Settings */
  428. // 以下在芯片手册基础上,按照显示屏厂家给的示例代码调整
  429. U8X8_CAA(0xD6, 0x13, 0x02), // NVM Load Control
  430. U8X8_CA(0xD1, 0x01), // Booster Enable
  431. U8X8_CAA(0xC0, 0x12, 0x0A), // Gate Voltage Setting: VGH=15V, VGL=-10V
  432. U8X8_CAAAA(0xC1, 0x3C, 0x3E, 0x3C, 0x3C), // VSHP Setting: VSHP1~4 = 4.8V
  433. U8X8_CAAAA(0xC2, 0x23, 0x21, 0x23, 0x23), // VSLP Setting: VSHP1~4 = 0.98V
  434. U8X8_CAAAA(0xC4, 0x5A, 0x5C, 0x5A, 0x5A), // VSHN Setting: VSHP1~4 = -3.6V
  435. U8X8_CAAAA(0xC5, 0x37, 0x35, 0x37, 0x37), // VSLN Setting: VSHP1~4 = 0.22V
  436. U8X8_CAA(0xD8, 0xA6, 0xE9), // OSC Setting
  437. U8X8_CA(0xB2, 0x12), // Frame Rate Control: HPM=32Hz, LPM=1Hz
  438. U8X8_CAAAA(0xB3, 0xE5, 0xF6, 0x17, 0x77), // Update Period Gate EQ Control in HPM
  439. U8X8_A6(0x77, 0x77, 0x77, 0x77, 0x77, 0x71),
  440. U8X8_CAA(0xB4, 0x05, 0x46), // Update Period Gate EQ Control in LPM
  441. U8X8_A6(0x77, 0x77, 0x77, 0x77, 0x76, 0x45),
  442. U8X8_CAAA(0x62, 0x32, 0x03, 0x1F), // Gate Timing Control
  443. U8X8_CA(0xB7, 0x13), // Source EQ Enable
  444. U8X8_CA(0xB0, 0x60), // Gate Line Setting: 384 line
  445. U8X8_C(0x11), // Sleep Out
  446. U8X8_DLY(10),
  447. U8X8_CA(0xC9, 0x00), // Source Voltage Select: VSHP1; VSLP1 ; VSHN1 ; VSLN1
  448. U8X8_CA(0x36, 0x48), // Memory Data Access Control
  449. U8X8_CA(0x3A, 0x11), // Data Format Select
  450. U8X8_CA(0xB9, 0x20), // Gamma Mode Setting: Mono 00:4GS
  451. U8X8_CA(0xB8, 0x29), // Panel Setting, 1-Dot inversion, Frame inversion, One Line Interlace
  452. U8X8_CAA(0x2A, 0x17, 0x24), // Column Address Setting: 0X24-0X16=14, 14*12=168
  453. U8X8_CAA(0x2B, 0x00, 0xBF), // Row Address Setting: 192*2=384
  454. U8X8_CA(0x35, 0x00), // TE Setting
  455. U8X8_CA(0xD0, 0xFF), // Enable Auto Power down
  456. U8X8_C(0x38), // High Power Mode ON
  457. // U8X8_C(0x39), // Low Power Mode ON
  458. /* Display ON */
  459. U8X8_C(0x29), // Display ON
  460. U8X8_C(0x20), // Display Inversion Off
  461. U8X8_CA(0xBB, 0x4F), // Enable Clear RAM to 0
  462. U8X8_END_TRANSFER(),
  463. U8X8_END()
  464. };
  465. static const u8x8_display_info_t u8x8_st7305_168x384_display_info =
  466. {
  467. /* chip_enable_level = */ 0,
  468. /* chip_disable_level = */ 1,
  469. /* post_chip_enable_wait_ns = */ 20,
  470. /* pre_chip_disable_wait_ns = */ 20,
  471. /* reset_pulse_width_ms = */ 3,
  472. /* post_reset_wait_ms = */ 3, /**/
  473. /* sda_setup_time_ns = */ 10, /* */
  474. /* sck_pulse_width_ns = */ 30, /* */
  475. /* sck_clock_hz = */ 2000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
  476. /* spi_mode = */ 0, /* active high, rising edge */
  477. /* i2c_bus_clock_100kHz = */ 4, /* 400KHz */
  478. /* data_setup_time_ns = */ 15,
  479. /* write_pulse_width_ns = */ 70,
  480. /* tile_width = */ 21, /* tile width is 21*8=168, because this display requires 12 bit blocks, which would be 168 pixel, so next tile is at 168 */
  481. /* tile_height = */ 48,
  482. /* default_x_offset = */ 0,
  483. /* flipmode_x_offset = */ 0,
  484. /* pixel_width = */ 168, /* not 100% sure, whether this works with the tile_width of 21... */
  485. /* pixel_height = */ 384};
  486. uint8_t u8x8_d_st7305_168x384(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  487. {
  488. uint16_t x;
  489. uint8_t c, i, y;
  490. uint8_t *ptr;
  491. switch(msg)
  492. {
  493. case U8X8_MSG_DISPLAY_INIT:
  494. u8x8_d_helper_display_init(u8x8);
  495. u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_168x384_init_seq);
  496. break;
  497. case U8X8_MSG_DISPLAY_SETUP_MEMORY:
  498. u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7305_168x384_display_info);
  499. break;
  500. case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
  501. if ( arg_int == 0 )
  502. u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_powersave0_seq);
  503. else
  504. u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_powersave1_seq);
  505. break;
  506. case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
  507. if ( arg_int == 0 )
  508. {
  509. u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_flip0_seq);
  510. u8x8->x_offset = u8x8->display_info->default_x_offset;
  511. }
  512. else
  513. {
  514. u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_flip1_seq);
  515. u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
  516. }
  517. break;
  518. #ifdef U8X8_WITH_SET_CONTRAST
  519. case U8X8_MSG_DISPLAY_SET_CONTRAST:
  520. u8x8_cad_StartTransfer(u8x8);
  521. u8x8_cad_SendCmd(u8x8, 0x081 );
  522. u8x8_cad_SendArg(u8x8, arg_int<<2 );
  523. u8x8_cad_SendArg(u8x8, arg_int>>6 );
  524. u8x8_cad_EndTransfer(u8x8);
  525. break;
  526. #endif
  527. case U8X8_MSG_DISPLAY_DRAW_TILE:
  528. x = ((u8x8_tile_t *)arg_ptr)->x_pos;
  529. x *= 8;
  530. x += u8x8->x_offset;
  531. y= (((u8x8_tile_t *)arg_ptr)->y_pos);
  532. y*=4;
  533. y+=0; // specific for the 168x384 LCD
  534. u8x8_cad_StartTransfer(u8x8);
  535. for( i = 0; i < 4; i++ )
  536. {
  537. u8x8_cad_SendCmd(u8x8, 0x2a); // column address set
  538. u8x8_cad_SendArg(u8x8, 0x17); // 0x019 for the 122x250 LCD --> 0x016 for the 200x200 display
  539. u8x8_cad_SendArg(u8x8, 0x24); // 204 pixel for the 200x200 display
  540. u8x8_cad_SendCmd(u8x8, 0x2b);
  541. u8x8_cad_SendArg(u8x8, y+i);
  542. u8x8_cad_SendArg(u8x8, y+i);
  543. u8x8_cad_SendCmd(u8x8, 0x2c); // write data
  544. c = ((u8x8_tile_t *)arg_ptr)->cnt;
  545. ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
  546. ptr += u8x8->display_info->tile_width*i*2;
  547. c = (c+2)/3; // calculate the number of 24 bit blocks to send
  548. while( c > 0 )
  549. {
  550. u8x8_cad_SendData(u8x8, 6, u8x8_st7305_convert_a0(u8x8, ptr));
  551. ptr+=3;
  552. --c;
  553. }
  554. }
  555. u8x8_cad_EndTransfer(u8x8);
  556. break;
  557. default:
  558. return 0;
  559. }
  560. return 1;
  561. }