ST7305_U8g2.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. #include "ST7305_U8g2.h"
  2. #define SPI_CLK 24000000
  3. #define ST7305_TILE_WIDTH 38
  4. #define ST7305_TILE_HEIGHT 50
  5. #define ST7305_BUFFER_ROW_BYTES (ST7305_TILE_WIDTH * 8)
  6. static ST7305_U8g2 *g_lcd_instance = nullptr;
  7. static u8x8_display_info_t st7305_display_info = {
  8. /* chip_enable_level = */ 0,
  9. /* chip_disable_level = */ 1,
  10. /* post_chip_enable_wait_ns = */ 0,
  11. /* pre_chip_disable_wait_ns = */ 0,
  12. /* reset_pulse_width_ms = */ 20,
  13. /* post_reset_wait_ms = */ 50,
  14. /* sda_setup_time_ns = */ 0,
  15. /* sck_pulse_width_ns = */ 0,
  16. /* sck_clock_hz = */ SPI_CLK,
  17. /* spi_mode = */ 0,
  18. /* i2c_bus_clock_100kHz = */ 4,
  19. /* data_setup_time_ns = */ 0,
  20. /* write_pulse_width_ns = */ 0,
  21. /* tile_width = */ ST7305_TILE_WIDTH,
  22. /* tile_height = */ ST7305_TILE_HEIGHT,
  23. /* default_x_offset = */ 0,
  24. /* flip_mode_x_offset = */ 0,
  25. /* pixel_width = */ 300,
  26. /* pixel_height = */ 400
  27. };
  28. ST7305_U8g2::ST7305_U8g2(int sck, int mosi, int dc, int cs, int rst)
  29. : _sck(sck), _mosi(mosi), _dc(dc), _cs(cs), _rst(rst)
  30. {
  31. _spi = new SPIClass(HSPI);
  32. g_lcd_instance = this;
  33. }
  34. ST7305_U8g2::~ST7305_U8g2()
  35. {
  36. if (_spi) {
  37. _spi->end();
  38. delete _spi;
  39. }
  40. if (_my_buf) {
  41. free(_my_buf);
  42. }
  43. if (g_lcd_instance == this) {
  44. g_lcd_instance = nullptr;
  45. }
  46. }
  47. void ST7305_U8g2::_cmd(uint8_t cmd)
  48. {
  49. digitalWrite(_dc, LOW);
  50. digitalWrite(_cs, LOW);
  51. _spi->transfer(cmd);
  52. digitalWrite(_cs, HIGH);
  53. }
  54. void ST7305_U8g2::_data(const uint8_t *data, size_t len)
  55. {
  56. digitalWrite(_dc, HIGH);
  57. digitalWrite(_cs, LOW);
  58. _spi->transferBytes((uint8_t *)data, nullptr, len);
  59. digitalWrite(_cs, HIGH);
  60. }
  61. void ST7305_U8g2::_cmd_data(uint8_t cmd, const uint8_t *data, size_t len)
  62. {
  63. digitalWrite(_dc, LOW);
  64. digitalWrite(_cs, LOW);
  65. _spi->transfer(cmd);
  66. if (len > 0) {
  67. digitalWrite(_dc, HIGH);
  68. _spi->transferBytes((uint8_t *)data, nullptr, len);
  69. }
  70. digitalWrite(_cs, HIGH);
  71. }
  72. void ST7305_U8g2::reset()
  73. {
  74. digitalWrite(_rst, HIGH);
  75. delay(50);
  76. digitalWrite(_rst, LOW);
  77. delay(20);
  78. digitalWrite(_rst, HIGH);
  79. delay(50);
  80. }
  81. uint8_t ST7305_U8g2::u8x8_byte_custom(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  82. {
  83. (void)u8x8;
  84. (void)arg_int;
  85. (void)arg_ptr;
  86. switch (msg) {
  87. case U8X8_MSG_BYTE_INIT:
  88. case U8X8_MSG_BYTE_START_TRANSFER:
  89. case U8X8_MSG_BYTE_END_TRANSFER:
  90. case U8X8_MSG_BYTE_SET_DC:
  91. case U8X8_MSG_BYTE_SEND:
  92. default:
  93. return 1;
  94. }
  95. }
  96. uint8_t ST7305_U8g2::u8x8_d_st7305_custom(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
  97. {
  98. (void)arg_int;
  99. if (!g_lcd_instance) {
  100. return 0;
  101. }
  102. switch (msg) {
  103. case U8X8_MSG_DISPLAY_SETUP_MEMORY:
  104. u8x8_d_helper_display_setup_memory(u8x8, &st7305_display_info);
  105. break;
  106. case U8X8_MSG_DISPLAY_INIT:
  107. g_lcd_instance->fullInit();
  108. break;
  109. case U8X8_MSG_DISPLAY_DRAW_TILE: {
  110. u8x8_tile_t *tile = (u8x8_tile_t *)arg_ptr;
  111. uint8_t cnt = tile->cnt;
  112. uint8_t y_pos = tile->y_pos;
  113. uint8_t x_pos = tile->x_pos;
  114. int first_col = x_pos * 8;
  115. int last_col = (x_pos + cnt) * 8 - 1;
  116. if (last_col >= 300) {
  117. last_col = 299;
  118. }
  119. int addr_start = 0x12 + first_col / 12;
  120. int addr_end = 0x12 + last_col / 12;
  121. int send_start = (addr_start - 0x12) * 3;
  122. int send_cnt = (addr_end - addr_start + 1) * 3;
  123. int addr_first_col = (addr_start - 0x12) * 12;
  124. int addr_last_col = (addr_end - 0x12) * 12 + 11;
  125. if (addr_last_col >= 300) {
  126. addr_last_col = 299;
  127. }
  128. uint8_t *row_base = tile->tile_ptr - ((uint16_t)x_pos * 8U);
  129. uint8_t col_bounds[] = {(uint8_t)(0x3C - addr_end), (uint8_t)(0x3C - addr_start)};
  130. g_lcd_instance->_cmd_data(0x2A, col_bounds, sizeof(col_bounds));
  131. uint8_t row_bounds[] = {(uint8_t)(y_pos * 4), (uint8_t)(y_pos * 4 + 3)};
  132. g_lcd_instance->_cmd_data(0x2B, row_bounds, sizeof(row_bounds));
  133. static const uint8_t st_lut[4][4] = {
  134. {0x00, 0x80, 0x40, 0xC0},
  135. {0x00, 0x20, 0x10, 0x30},
  136. {0x00, 0x08, 0x04, 0x0C},
  137. {0x00, 0x02, 0x01, 0x03},
  138. };
  139. uint8_t all_rows[300] = {0};
  140. for (int sr = 0; sr < 4; sr++) {
  141. int shift = sr * 2;
  142. int base_off = sr * send_cnt;
  143. int idx = base_off + (addr_first_col >> 2) - send_start;
  144. for (int col = addr_first_col; col <= addr_last_col; col += 4, idx++) {
  145. all_rows[idx] = st_lut[0][(row_base[col] >> shift) & 3]
  146. | st_lut[1][(row_base[col + 1] >> shift) & 3]
  147. | st_lut[2][(row_base[col + 2] >> shift) & 3]
  148. | st_lut[3][(row_base[col + 3] >> shift) & 3];
  149. }
  150. }
  151. g_lcd_instance->_cmd_data(0x2C, all_rows, (size_t)send_cnt * 4U);
  152. break;
  153. }
  154. default:
  155. return 0;
  156. }
  157. return 1;
  158. }
  159. void ST7305_U8g2::begin(uint8_t tile_buf_height, const u8g2_cb_t *rotation)
  160. {
  161. pinMode(_dc, OUTPUT);
  162. pinMode(_cs, OUTPUT);
  163. pinMode(_rst, OUTPUT);
  164. digitalWrite(_cs, HIGH);
  165. digitalWrite(_dc, HIGH);
  166. digitalWrite(_rst, HIGH);
  167. _spi->begin(_sck, -1, _mosi, -1);
  168. _spi->beginTransaction(SPISettings(SPI_CLK, MSBFIRST, SPI_MODE0));
  169. u8g2_t *u = u8g2_wrapper.getU8g2();
  170. u8x8_Setup(u8g2_GetU8x8(u), u8x8_d_st7305_custom, u8x8_dummy_cb, u8x8_byte_custom, u8x8_dummy_cb);
  171. uint8_t tbh = tile_buf_height == 0 ? ST7305_TILE_HEIGHT : tile_buf_height;
  172. if (tbh > ST7305_TILE_HEIGHT) {
  173. tbh = ST7305_TILE_HEIGHT;
  174. }
  175. size_t buf_sz = ST7305_BUFFER_ROW_BYTES * tbh;
  176. _my_buf = (uint8_t *)malloc(buf_sz);
  177. if (!_my_buf) {
  178. return;
  179. }
  180. memset(_my_buf, 0, buf_sz);
  181. u8g2_SetupBuffer(u, _my_buf, tbh, u8g2_ll_hvline_vertical_top_lsb, rotation);
  182. u8g2_InitDisplay(u);
  183. u8g2_SetPowerSave(u, 0);
  184. }
  185. void ST7305_U8g2::fullInit()
  186. {
  187. reset();
  188. const uint8_t d6[] = {0x17, 0x02};
  189. const uint8_t d1[] = {0x01};
  190. const uint8_t c0[] = {0x11, 0x04};
  191. const uint8_t c1[] = {0x69, 0x69, 0x69, 0x69};
  192. const uint8_t c2[] = {0x19, 0x19, 0x19, 0x19};
  193. const uint8_t c4[] = {0x4B, 0x4B, 0x4B, 0x4B};
  194. const uint8_t d8[] = {0x80, 0xE9};
  195. const uint8_t b2[] = {0x02};
  196. const uint8_t b3[] = {0xE5, 0xF6, 0x05, 0x46, 0x77, 0x77, 0x77, 0x77, 0x76, 0x45};
  197. const uint8_t b4[] = {0x05, 0x46, 0x77, 0x77, 0x77, 0x77, 0x76, 0x45};
  198. const uint8_t g_timing[] = {0x32, 0x03, 0x1F};
  199. const uint8_t b7[] = {0x13};
  200. const uint8_t b0[] = {0x64};
  201. const uint8_t c9[] = {0x00};
  202. const uint8_t m36[] = {0x48};
  203. const uint8_t m3a[] = {0x11};
  204. const uint8_t b9[] = {0x20};
  205. const uint8_t b8[] = {0x29};
  206. const uint8_t win_a[] = {0x12, 0x2A};
  207. const uint8_t win_b[] = {0x00, 0xC7};
  208. const uint8_t m35[] = {0x00};
  209. const uint8_t d0[] = {0xFF};
  210. _cmd_data(0xD6, d6, sizeof(d6));
  211. _cmd_data(0xD1, d1, sizeof(d1));
  212. _cmd_data(0xC0, c0, sizeof(c0));
  213. _cmd_data(0xC1, c1, sizeof(c1));
  214. _cmd_data(0xC2, c2, sizeof(c2));
  215. _cmd_data(0xC4, c4, sizeof(c4));
  216. _cmd_data(0xC5, c2, sizeof(c2));
  217. _cmd_data(0xD8, d8, sizeof(d8));
  218. _cmd_data(0xB2, b2, sizeof(b2));
  219. _cmd_data(0xB3, b3, sizeof(b3));
  220. _cmd_data(0xB4, b4, sizeof(b4));
  221. _cmd_data(0x62, g_timing, sizeof(g_timing));
  222. _cmd_data(0xB7, b7, sizeof(b7));
  223. _cmd_data(0xB0, b0, sizeof(b0));
  224. _cmd(0x11);
  225. delay(120);
  226. _cmd_data(0xC9, c9, sizeof(c9));
  227. _cmd_data(0x36, m36, sizeof(m36));
  228. _cmd_data(0x3A, m3a, sizeof(m3a));
  229. _cmd_data(0xB9, b9, sizeof(b9));
  230. _cmd_data(0xB8, b8, sizeof(b8));
  231. _cmd(0x21);
  232. _cmd_data(0x2A, win_a, sizeof(win_a));
  233. _cmd_data(0x2B, win_b, sizeof(win_b));
  234. _cmd_data(0x35, m35, sizeof(m35));
  235. _cmd_data(0xD0, d0, sizeof(d0));
  236. _cmd(0x38);
  237. _cmd(0x29);
  238. }