Krolyxon
Commit 1d55752

Branches

Tags

Refs →

orion-rf.piolibdepsesp32-s3-n16r8U8g2srcclibu8x8_d_st7571.c

439 lines · 13.5 KB · C

1/*
2
3 u8x8_d_st7571.c
4
5 Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
6
7 Copyright (c) 2020, olikraus@gmail.com
8 All rights reserved.
9
10 Redistribution and use in source and binary forms, with or without modification,
11 are permitted provided that the following conditions are met:
12
13 * Redistributions of source code must retain the above copyright notice, this list
14 of conditions and the following disclaimer.
15
16 * Redistributions in binary form must reproduce the above copyright notice, this
17 list of conditions and the following disclaimer in the documentation and/or other
18 materials provided with the distribution.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
21 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
22 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
25 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
30 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
32 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34
35 ST7571: 128x129 2-bit graylevel LCD
36
37 https://github.com/olikraus/u8g2/issues/921
38 https://github.com/olikraus/u8g2/issues/1575 128x96
39 https://github.com/olikraus/u8g2/issues/2575 another 128x96 display
40
41*/
42
43
44#include "u8x8.h"
45
46static const uint8_t u8x8_d_st7571_128x128_powersave0_seq[] = {
47 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
48 U8X8_C(0x071), /* exit power save mode */
49 U8X8_C(0x0a8), /* disable powersave mode */
50 U8X8_C(0x0af), /* display on */
51 U8X8_END_TRANSFER(), /* disable chip */
52 U8X8_END() /* end of sequence */
53};
54
55static const uint8_t u8x8_d_st7571_128x128_powersave1_seq[] = {
56 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
57 U8X8_C(0x0ae), /* display off */
58 U8X8_C(0x0a9), /* enter powersave mode */
59 U8X8_END_TRANSFER(), /* disable chip */
60 U8X8_END() /* end of sequence */
61};
62
63static const uint8_t u8x8_d_st7571_128x128_flip0_seq[] = {
64 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
65 U8X8_C(0x0a0), /* segment remap a0/a1*/
66 U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
67 U8X8_END_TRANSFER(), /* disable chip */
68 U8X8_END() /* end of sequence */
69};
70
71static const uint8_t u8x8_d_st7571_128x128_flip1_seq[] = {
72 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
73 U8X8_C(0x0a1), /* segment remap a0/a1*/
74 U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
75 U8X8_END_TRANSFER(), /* disable chip */
76 U8X8_END() /* end of sequence */
77};
78
79
80
81
82/*===================================================*/
83
84static uint8_t u8x8_d_st7571_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
85{
86 uint16_t x;
87 uint8_t c;
88 uint8_t *ptr;
89 switch(msg)
90 {
91 /* handled by the calling function
92 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
93 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7571_128x128_display_info);
94 break;
95 */
96 /* handled by the calling function
97 case U8X8_MSG_DISPLAY_INIT:
98 u8x8_d_helper_display_init(u8x8);
99 u8x8_cad_SendSequence(u8x8, u8x8_d_st7571_128x128_init_seq);
100 break;
101 */
102 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
103 if ( arg_int == 0 )
104 u8x8_cad_SendSequence(u8x8, u8x8_d_st7571_128x128_powersave0_seq);
105 else
106 u8x8_cad_SendSequence(u8x8, u8x8_d_st7571_128x128_powersave1_seq);
107 break;
108 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
109 if ( arg_int == 0 )
110 {
111 u8x8_cad_SendSequence(u8x8, u8x8_d_st7571_128x128_flip0_seq);
112 u8x8->x_offset = u8x8->display_info->default_x_offset;
113 }
114 else
115 {
116 u8x8_cad_SendSequence(u8x8, u8x8_d_st7571_128x128_flip1_seq);
117 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
118 }
119 break;
120#ifdef U8X8_WITH_SET_CONTRAST
121 case U8X8_MSG_DISPLAY_SET_CONTRAST:
122 u8x8_cad_StartTransfer(u8x8);
123 u8x8_cad_SendCmd(u8x8, 0x081 );
124 u8x8_cad_SendArg(u8x8, arg_int>>2); // 6 bit for the ST7571
125 u8x8_cad_EndTransfer(u8x8);
126 break;
127#endif
128 case U8X8_MSG_DISPLAY_DRAW_TILE:
129 u8x8_cad_StartTransfer(u8x8);
130
131
132 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
133 x *= 8;
134 x += u8x8->x_offset;
135 u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
136 u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
137 u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
138
139
140
141 do
142 {
143 c = ((u8x8_tile_t *)arg_ptr)->cnt;
144 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
145 /* SendData can not handle more than 255 bytes */
146 /*
147 if ( c > 31 )
148 {
149 u8x8_cad_SendData(u8x8, 31*8, ptr);
150 ptr+=31*8;
151 c -= 31;
152 }
153 */
154
155 u8x8_cad_SendData(u8x8, c*8, ptr);
156 arg_int--;
157 } while( arg_int > 0 );
158
159
160 u8x8_cad_EndTransfer(u8x8);
161 break;
162 default:
163 return 0;
164 }
165 return 1;
166}
167
168/*===================================================*/
169
170
171/* QT-2832TSWUG02/ZJY-2832TSWZG02 */
172/* fixed the 0x40 and 0x48 commands, verified with FlipMode example: All ok */
173static const uint8_t u8x8_d_st7571_128x128_init_seq[] = {
174
175 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
176
177
178 U8X8_C(0xAE), // Display OFF
179 U8X8_C(0x38), // Mode Set
180 U8X8_C(0xB8), // FR=1011 (85Hz), BE[1:0]=10, level 3 booster
181
182
183 U8X8_C(0xA0), // ADC select
184 U8X8_C(0xC8), // SHL select
185 U8X8_CA(0x44, 0x00), // COM0 register
186 U8X8_CA(0x40, 0x0), // initial display line (0x7f... strange but ok... maybe specific for the JLX128128)
187 // 2 sep 2021: maybe this also wrong because the 0x44 command is overwritten later.
188 // 4 Mar 2022: Changed to 0
189
190 U8X8_C(0xAB), // OSC ON
191 U8X8_C(0x25), // Voltage regulator
192 U8X8_CA(0x81, 0x33), // Volume
193 U8X8_C(0x54), // LCD Bias: 0x056=1/11 (1/11 according to JLX128128 datasheet), 0x054=1/9
194 U8X8_CA(0x48, 0x80), // Duty 1/128 // 2 Sep 2021: Should this be 00x48???
195 // 4 Mar 2022, cmd changed to 0x48, arg changed to 0x80
196
197 U8X8_C(0x2C), // Power Control, VC: ON, VR: OFF, VF: OFF
198 U8X8_DLY(200),
199 U8X8_C(0x2E), // Power Control, VC: ON, VR: ON, VF: OFF
200 U8X8_DLY(200),
201 U8X8_C(0x2F), // Power Control, VC: ON, VR: ON, VF: ON
202 U8X8_DLY(10),
203
204 U8X8_C(0x7B), // command set 3
205 U8X8_C(0x11), // black white mode
206 U8X8_C(0x00), // exit command set 3
207
208
209 U8X8_C(0xA6), // Display Inverse OFF
210 U8X8_C(0xA4), // Disable Display All Pixel ON
211
212 //U8X8_C(0xAF), // Display on
213
214
215 U8X8_END_TRANSFER(), /* disable chip */
216 U8X8_END() /* end of sequence */
217};
218
219
220
221
222static const u8x8_display_info_t u8x8_st7571_128x128_display_info =
223{
224 /* chip_enable_level = */ 0,
225 /* chip_disable_level = */ 1,
226
227 /* post_chip_enable_wait_ns = */ 20,
228 /* pre_chip_disable_wait_ns = */ 20,
229 /* reset_pulse_width_ms = */ 5,
230 /* post_reset_wait_ms = */ 5, /**/
231 /* sda_setup_time_ns = */ 20, /* */
232 /* sck_pulse_width_ns = */ 40, /* */
233 /* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
234 /* spi_mode = */ 0, /* active high, rising edge */
235 /* i2c_bus_clock_100kHz = */ 4, /* 400KHz */
236 /* data_setup_time_ns = */ 15,
237 /* write_pulse_width_ns = */ 70,
238 /* tile_width = */ 16,
239 /* tile_height = */ 16,
240 /* default_x_offset = */ 0,
241 /* flipmode_x_offset = */ 0,
242 /* pixel_width = */ 128,
243 /* pixel_height = */ 128
244};
245
246uint8_t u8x8_d_st7571_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
247{
248
249 if ( u8x8_d_st7571_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
250 return 1;
251
252 switch(msg)
253 {
254 case U8X8_MSG_DISPLAY_INIT:
255 u8x8_d_helper_display_init(u8x8);
256 u8x8_cad_SendSequence(u8x8, u8x8_d_st7571_128x128_init_seq);
257 break;
258 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
259 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7571_128x128_display_info);
260 break;
261 default:
262 return 0;
263 }
264 return 1;
265}
266
267
268
269
270/*===================================================*/
271/*
272 https://github.com/olikraus/u8g2/issues/1575
273 http://www.jlxlcd.cn/html/zh-detail-1211.html
274*/
275static const uint8_t u8x8_d_st7571_128x96_init_seq[] = {
276
277 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
278
279
280 U8X8_C(0xAE), // Display OFF
281 U8X8_C(0x38), // Mode Set
282 //U8X8_C(0xB8), // FR=1011 (85Hz), BE[1:0]=10, level 3 booster
283 U8X8_C(0x94), // 128x96: 75 Hz
284
285 U8X8_C(0xA0), // ADC select
286 U8X8_C(0xC8), // SHL select
287 U8X8_CA(0x44, 0x20), // 128x96: COM0 register
288 U8X8_CA(0x40, 0x00), // 128x96 datasheet
289
290 U8X8_C(0xAB), // OSC ON
291 U8X8_C(0x27), // 128x96: Voltage regulator
292 U8X8_CA(0x81, 0x28), // 128x96: Volume
293 U8X8_C(0x57), // 128x96: LCD Bias: 1/12
294 U8X8_CA(0x48, 0x61), // 128x96: Duty 1/96
295
296 U8X8_C(0x2C), // Power Control, VC: ON, VR: OFF, VF: OFF
297 U8X8_DLY(200),
298 U8X8_C(0x2E), // Power Control, VC: ON, VR: ON, VF: OFF
299 U8X8_DLY(200),
300 U8X8_C(0x2F), // Power Control, VC: ON, VR: ON, VF: ON
301 U8X8_DLY(10),
302
303 U8X8_C(0x7B), // command set 3
304 U8X8_C(0x11), // black white mode
305 U8X8_C(0x00), // exit command set 3
306
307
308 U8X8_C(0xA6), // Display Inverse OFF
309 U8X8_C(0xA4), // Disable Display All Pixel ON
310
311 //U8X8_C(0xAF), // Display on
312
313
314 U8X8_END_TRANSFER(), /* disable chip */
315 U8X8_END() /* end of sequence */
316};
317
318
319
320
321static const u8x8_display_info_t u8x8_st7571_128x96_display_info =
322{
323 /* chip_enable_level = */ 0,
324 /* chip_disable_level = */ 1,
325
326 /* post_chip_enable_wait_ns = */ 20,
327 /* pre_chip_disable_wait_ns = */ 20,
328 /* reset_pulse_width_ms = */ 5,
329 /* post_reset_wait_ms = */ 5, /**/
330 /* sda_setup_time_ns = */ 20, /* */
331 /* sck_pulse_width_ns = */ 40, /* */
332 /* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
333 /* spi_mode = */ 0, /* active high, rising edge */
334 /* i2c_bus_clock_100kHz = */ 4, /* 400KHz */
335 /* data_setup_time_ns = */ 15,
336 /* write_pulse_width_ns = */ 70,
337 /* tile_width = */ 16,
338 /* tile_height = */ 12,
339 /* default_x_offset = */ 0,
340 /* flipmode_x_offset = */ 0,
341 /* pixel_width = */ 128,
342 /* pixel_height = */ 96
343};
344
345uint8_t u8x8_d_st7571_128x96(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
346{
347
348 if ( u8x8_d_st7571_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
349 return 1;
350
351 switch(msg)
352 {
353 case U8X8_MSG_DISPLAY_INIT:
354 u8x8_d_helper_display_init(u8x8);
355 u8x8_cad_SendSequence(u8x8, u8x8_d_st7571_128x96_init_seq);
356 break;
357 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
358 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7571_128x96_display_info);
359 break;
360 default:
361 return 0;
362 }
363 return 1;
364}
365
366
367/*===================================================*/
368/*
369 ccsb4736w g12896 display
370
371 https://github.com/olikraus/u8g2/issues/2575
372
373 reusing u8x8_st7571_128x96_display_info
374
375*/
376static const uint8_t u8x8_d_st7571_g12896_init_seq[] = {
377
378 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
379
380
381 U8X8_C(0xAE), // Display OFF
382 U8X8_C(0x38), // Mode Set
383 //U8X8_C(0xB8), // FR=1011 (85Hz), BE[1:0]=10, level 3 booster
384 U8X8_C(0x94), // 128x96: 75 Hz
385
386 U8X8_C(0xA0), // ADC select
387 U8X8_C(0xC8), // SHL select
388 U8X8_CA(0x44, 0x00), // 128x96: COM0 register https://github.com/olikraus/u8g2/issues/2575
389 U8X8_CA(0x40, 0x00), // 128x96 datasheet
390
391 U8X8_C(0xAB), // OSC ON
392 U8X8_C(0x27), // 128x96: Voltage regulator
393 U8X8_CA(0x81, 0x28), // 128x96: Volume
394 U8X8_C(0x57), // 128x96: LCD Bias: 1/12
395 U8X8_CA(0x48, 0x61), // 128x96: Duty 1/96
396
397 U8X8_C(0x2C), // Power Control, VC: ON, VR: OFF, VF: OFF
398 U8X8_DLY(200),
399 U8X8_C(0x2E), // Power Control, VC: ON, VR: ON, VF: OFF
400 U8X8_DLY(200),
401 U8X8_C(0x2F), // Power Control, VC: ON, VR: ON, VF: ON
402 U8X8_DLY(10),
403
404 U8X8_C(0x7B), // command set 3
405 U8X8_C(0x11), // black white mode
406 U8X8_C(0x00), // exit command set 3
407
408
409 U8X8_C(0xA6), // Display Inverse OFF
410 U8X8_C(0xA4), // Disable Display All Pixel ON
411
412 //U8X8_C(0xAF), // Display on
413
414
415 U8X8_END_TRANSFER(), /* disable chip */
416 U8X8_END() /* end of sequence */
417};
418
419
420uint8_t u8x8_d_st7571_g12896(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
421{
422
423 if ( u8x8_d_st7571_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
424 return 1;
425
426 switch(msg)
427 {
428 case U8X8_MSG_DISPLAY_INIT:
429 u8x8_d_helper_display_init(u8x8);
430 u8x8_cad_SendSequence(u8x8, u8x8_d_st7571_g12896_init_seq);
431 break;
432 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
433 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7571_128x96_display_info);
434 break;
435 default:
436 return 0;
437 }
438 return 1;
439}