Krolyxon
Commit 1d55752

Branches

Tags

Refs →

orion-rf.piolibdepsesp32-s3-n16r8U8g2srcclibu8x8_d_st7302.c

500 lines · 14.3 KB · C

1/*
2
3 u8x8_d_st7302.c
4
5 Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
6
7 Copyright (c) 2024, 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 st7302:
36 Ultra-Low Power Active Matrix 240 x 320
37 Mono TFT Display Driver with Controller
38
39 https://github.com/olikraus/u8g2/issues/2436
40
41 No Hardware Flip
42 No U8x8 Support
43
44*/
45
46#include "u8x8.h"
47#include <string.h>
48
49static const uint8_t u8x8_d_st7302_122x250_powersave0_seq[] = {
50 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
51 U8X8_C(0x29), // display on
52 U8X8_END_TRANSFER(), /* disable chip */
53 U8X8_END() /* end of sequence */
54};
55
56static const uint8_t u8x8_d_st7302_122x250_powersave1_seq[] = {
57 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
58 U8X8_C(0x028), /* display off */
59 U8X8_END_TRANSFER(), /* disable chip */
60 U8X8_END() /* end of sequence */
61};
62
63static const uint8_t u8x8_d_st7302_122x250_flip0_seq[] = {
64 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
65 //U8X8_CA(0x36, 0x60), // Memory Control
66 U8X8_END_TRANSFER(), /* disable chip */
67 U8X8_END() /* end of sequence */
68};
69
70static const uint8_t u8x8_d_st7302_122x250_flip1_seq[] = {
71 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
72 //U8X8_CA(0x36, 0xa0), // Memory Control
73 U8X8_END_TRANSFER(), /* disable chip */
74 U8X8_END() /* end of sequence */
75};
76
77
78
79
80/*===================================================*/
81/* see also: http://www.technoblogy.com/show?3YB0 */
82
83
84#ifdef NOT_USED
85static uint8_t *u8x8_st7302_convert_60(u8x8_t *u8x8, uint8_t *p)
86{
87 static uint8_t buf[6];
88 uint8_t bytes_per_row = u8x8->display_info->tile_width;
89
90
91 memset(buf, 0, 6);
92
93 // U8X8_CA(0x36, 0x60), // Memory Control
94
95
96 // first row, left 12 pixel
97
98 if ( p[0] & 0x80 )
99 buf[2] |= 0x02;
100 if ( p[0] & 0x40 )
101 buf[2] |= 0x08;
102 if ( p[0] & 0x20 )
103 buf[2] |= 0x20;
104 if ( p[0] & 0x10 )
105 buf[2] |= 0x80;
106
107 if ( p[0] & 0x08 )
108 buf[1] |= 0x02;
109 if ( p[0] & 0x04 )
110 buf[1] |= 0x08;
111 if ( p[0] & 0x02 )
112 buf[1] |= 0x20;
113 if ( p[0] & 0x01 )
114 buf[1] |= 0x80;
115
116 if ( p[1] & 0x80 )
117 buf[0] |= 0x02;
118 if ( p[1] & 0x40 )
119 buf[0] |= 0x08;
120 if ( p[1] & 0x20 )
121 buf[0] |= 0x20;
122 if ( p[1] & 0x10 )
123 buf[0] |= 0x80;
124
125 // first row, right 12 pixel
126
127 if ( p[1] & 0x08 )
128 buf[5] |= 0x02;
129 if ( p[1] & 0x04 )
130 buf[5] |= 0x08;
131 if ( p[1] & 0x02 )
132 buf[5] |= 0x20;
133 if ( p[1] & 0x01 )
134 buf[5] |= 0x80;
135
136 if ( p[2] & 0x80 )
137 buf[4] |= 0x02;
138 if ( p[2] & 0x40 )
139 buf[4] |= 0x08;
140 if ( p[2] & 0x20 )
141 buf[4] |= 0x20;
142 if ( p[2] & 0x10 )
143 buf[4] |= 0x80;
144
145 if ( p[2] & 0x08 )
146 buf[3] |= 0x02;
147 if ( p[2] & 0x04 )
148 buf[3] |= 0x08;
149 if ( p[2] & 0x02 )
150 buf[3] |= 0x20;
151 if ( p[2] & 0x01 )
152 buf[3] |= 0x80;
153
154 p += u8x8->display_info->tile_width;
155
156 // second row, left 12 pixel
157
158 if ( p[0] & 0x80 )
159 buf[2] |= 0x01;
160 if ( p[0] & 0x40 )
161 buf[2] |= 0x04;
162 if ( p[0] & 0x20 )
163 buf[2] |= 0x10;
164 if ( p[0] & 0x10 )
165 buf[2] |= 0x40;
166
167 if ( p[0] & 0x08 )
168 buf[1] |= 0x01;
169 if ( p[0] & 0x04 )
170 buf[1] |= 0x04;
171 if ( p[0] & 0x02 )
172 buf[1] |= 0x10;
173 if ( p[0] & 0x01 )
174 buf[1] |= 0x40;
175
176 if ( p[1] & 0x80 )
177 buf[0] |= 0x01;
178 if ( p[1] & 0x40 )
179 buf[0] |= 0x04;
180 if ( p[1] & 0x20 )
181 buf[0] |= 0x10;
182 if ( p[1] & 0x10 )
183 buf[0] |= 0x40;
184
185 // second row, right 12 pixel
186
187 if ( p[1] & 0x08 )
188 buf[5] |= 0x01;
189 if ( p[1] & 0x04 )
190 buf[5] |= 0x04;
191 if ( p[1] & 0x02 )
192 buf[5] |= 0x10;
193 if ( p[1] & 0x01 )
194 buf[5] |= 0x40;
195
196 if ( p[2] & 0x80 )
197 buf[4] |= 0x01;
198 if ( p[2] & 0x40 )
199 buf[4] |= 0x04;
200 if ( p[2] & 0x20 )
201 buf[4] |= 0x10;
202 if ( p[2] & 0x10 )
203 buf[4] |= 0x40;
204
205 if ( p[2] & 0x08 )
206 buf[3] |= 0x01;
207 if ( p[2] & 0x04 )
208 buf[3] |= 0x04;
209 if ( p[2] & 0x02 )
210 buf[3] |= 0x10;
211 if ( p[2] & 0x01 )
212 buf[3] |= 0x40;
213
214 return buf;
215}
216#endif
217
218static uint8_t *u8x8_st7302_convert_a0(u8x8_t *u8x8, uint8_t *p)
219{
220 static uint8_t buf[6];
221 static uint8_t map1[16] = {
222 /* 0x00 0000 */ 0,
223 /* 0x01 0001 */0x01,
224 /* 0x02 0010 */0x04,
225 /* 0x03 0011 */0x04+0x01,
226 /* 0x04 0100 */0x10,
227 /* 0x05 0101 */0x10+0x01,
228 /* 0x06 0110 */0x10+0x04,
229 /* 0x07 0111 */0x10+0x04+0x01,
230 /* 0x08 1000 */ 0x40,
231 /* 0x09 1001 */ 0x40+0x01,
232 /* 0x0a 1010 */ 0x40+0x04,
233 /* 0x0b 1011 */ 0x40+0x04+0x01,
234 /* 0x0c 1100 */ 0x40+0x10,
235 /* 0x0d 1101 */ 0x40+0x10+0x01,
236 /* 0x0e 1110 */ 0x40+0x10+0x04,
237 /* 0x0f 1111 */ 0x40+0x10+0x04+0x01
238 };
239 static uint8_t map2[16] = {
240 /* 0x00 0000 */ 0,
241 /* 0x01 0001 */0x02,
242 /* 0x02 0010 */0x08,
243 /* 0x03 0011 */0x08+0x02,
244 /* 0x04 0100 */0x20,
245 /* 0x05 0101 */0x20+0x02,
246 /* 0x06 0110 */0x20+0x08,
247 /* 0x07 0111 */0x20+0x08+0x02,
248 /* 0x08 1000 */ 0x80,
249 /* 0x09 1001 */ 0x80+0x02,
250 /* 0x0a 1010 */ 0x80+0x08,
251 /* 0x0b 1011 */ 0x80+0x08+0x02,
252 /* 0x0c 1100 */ 0x80+0x20,
253 /* 0x0d 1101 */ 0x80+0x20+0x02,
254 /* 0x0e 1110 */ 0x80+0x20+0x08,
255 /* 0x0f 1111 */ 0x80+0x20+0x08+0x02
256 };
257
258
259 memset(buf, 0, 6);
260
261 // U8X8_CA(0x36, 0x0), // Memory Control
262
263
264 // first row, left 12 pixel
265
266 buf[0] |= map1[p[0]>>4];
267 buf[1] |= map1[p[0] & 0x0f];
268 buf[2] |= map1[p[1]>>4];
269
270 // first row, right 12 pixel
271
272 buf[3] |= map1[p[1] & 0x0f];
273 buf[4] |= map1[p[2]>>4];
274 buf[5] |= map1[p[2] & 0x0f];
275
276 p += u8x8->display_info->tile_width;
277
278 // second row, left 12 pixel
279
280 buf[0] |= map2[p[0]>>4];
281 buf[1] |= map2[p[0] & 0x0f];
282 buf[2] |= map2[p[1]>>4];
283
284 // second row, right 12 pixel
285
286 buf[3] |= map2[p[1] & 0x0f];
287 buf[4] |= map2[p[2]>>4];
288 buf[5] |= map2[p[2] & 0x0f];
289 return buf;
290}
291
292
293
294
295/*===================================================*/
296/*
297 see also:
298 https://github.com/zhcong/ST7302-for-arduino/blob/c9390fabcacefe7c36a113cd3e62959418c13b97/libraries/ST7302SPI/ST7302SPI.cpp#L21
299*/
300static const uint8_t u8x8_d_st7302_122x250_init_seq[] = {
301
302 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
303
304 U8X8_C(0x01), // software reset
305 U8X8_DLY(100),
306 U8X8_C(0x28), // display off
307 U8X8_CAA(0xC7, 0x26, 0xE9), // disable OSC
308 U8X8_CA(0xD1, 0x00), // Booster disable
309 U8X8_DLY(20),
310 U8X8_C(0x10), // sleep in: enter sleep mode
311 U8X8_DLY(20),
312 U8X8_C(0x01), // software reset
313 U8X8_DLY(20), // wait
314 U8X8_C(0x38), // High Power Mode
315 U8X8_CA(0xEB, 0x02), // Disable NVM Load
316 U8X8_CA(0xD7, 0x68), // NVM Load Control: Enable ID1 ID2 ID3 Load
317 U8X8_CA(0xD1, 0x01), // Booster Enable
318 U8X8_CA(0xC0, 0x80), // Gate Voltage Setting VGH=12V (upper 4 bit, 8V-15V); VGL=-5V (lower 4 bit, -5V .. -10V)
319 U8X8_C(0x0C1), // Source Voltage Control 1
320 U8X8_A6(0x28,0x28,0x28,0x28,0x14,0x00), // Source high voltage in reflective and transmissive mode, gamma voltage 1&2
321 U8X8_C(0x0C2), // Source Voltage Control 1
322 U8X8_A4(0x00,0x00,0x00,0x00), // Source low voltage in reflective and transmissive mode
323 U8X8_CA(0xCB, 0x14), // VCOMH: 0x14 = 4V (0x28 = 5V)
324 U8X8_CAA(0xB4, 0xE5, 0x77), // Update Period Gate EQ Control, why 0x77??? it should be 0x66 according to the datasheet
325 U8X8_A8(0xF1, 0xFF, 0xFF, 0x4F, 0xF1, 0xFF, 0xFF, 0X4F),
326 U8X8_CA(0xB0, 0x64), // Duty Cycle... this must be before sleep out
327 U8X8_C(0x11), // sleep out: furn off sleep mode
328 U8X8_DLY(120),
329 U8X8_CAA(0xC7, 0xA6, 0xE9), // Enable OSC
330 U8X8_CA(0x36, 0xa0), // Memory Control
331
332 U8X8_CA(0x3A, 0x11), // Data Format
333 U8X8_CA(0xB9, 0x23), // Source Setting: Clear RAM off
334 U8X8_CA(0xB8, 0x09), // Panel Setting / Panel Layout
335 U8X8_CAA(0x2A, 0x05, 0x36), // col addr
336 U8X8_CAA(0x2B, 0x00, 0xC7), // row addr
337 U8X8_CA(0xD0, 0x1F), // Not in datasheet
338 U8X8_C(0x29), // display on
339 U8X8_CA(0x72, 0x00), // Not in datasheet
340 U8X8_CAA(0xB2,1, 5), // Frame Rate for High and Low Power Mode (hier: 32Hz and 8Hz)
341 U8X8_C(0x39), // enable Low Power Mode...: 8Hz, see above
342 U8X8_DLY(100),
343
344 /*
345 U8X8_CAA(0x2A, 0x19, 0x3a), // col addr 0x14 < col < 0x3b
346 U8X8_CAA(0x2B, 115, 115), // row addr (0..250, y in u8g2), 0 is top row in u8g2
347 U8X8_C(0x2C), // write start
348 U8X8_D1(0xff), // pixel data
349 U8X8_D1(0xff), // pixel data
350 U8X8_D1(0xff), // pixel data
351
352 U8X8_D1(0xff), // pixel data
353 U8X8_D1(0xff), // pixel data
354 U8X8_D1(0xff), // pixel data
355
356 U8X8_D1(0xff), // pixel data
357 U8X8_D1(0xff), // pixel data
358 U8X8_D1(0xff), // pixel data
359
360 U8X8_D1(0xff), // pixel data
361 U8X8_D1(0xff), // pixel data
362 U8X8_D1(0xff), // pixel data
363
364 U8X8_CAA(0x2A, 0x19, 0x3a), // col addr 0x14 < col < 0x3b
365 U8X8_CAA(0x2B, 116, 116), // row addr (0..250, y in u8g2), 0 is top row in u8g2
366 U8X8_C(0x2C), // write start
367 U8X8_D1(0x80), // pixel data
368 U8X8_D1(0x00), // pixel data
369 U8X8_D1(0x00), // pixel data
370
371 U8X8_D1(0x00), // pixel data
372 U8X8_D1(0x00), // pixel data
373 U8X8_D1(0x00), // pixel data
374
375 U8X8_D1(0x00), // pixel data
376 U8X8_D1(0x00), // pixel data
377 U8X8_D1(0x00), // pixel data
378
379 U8X8_D1(0x00), // pixel data
380 U8X8_D1(0x00), // pixel data
381 U8X8_D1(0x00), // pixel data
382 */
383
384 U8X8_END_TRANSFER(), /* disable chip */
385 U8X8_END() /* end of sequence */
386};
387
388
389
390
391static const u8x8_display_info_t u8x8_st7302_122x250_display_info =
392{
393 /* chip_enable_level = */ 0,
394 /* chip_disable_level = */ 1,
395
396 /* post_chip_enable_wait_ns = */ 20,
397 /* pre_chip_disable_wait_ns = */ 20,
398 /* reset_pulse_width_ms = */ 3,
399 /* post_reset_wait_ms = */ 3, /**/
400 /* sda_setup_time_ns = */ 10, /* */
401 /* sck_pulse_width_ns = */ 30, /* */
402 /* sck_clock_hz = */ 2000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
403 /* spi_mode = */ 0, /* active high, rising edge */
404 /* i2c_bus_clock_100kHz = */ 4, /* 400KHz */
405 /* data_setup_time_ns = */ 15,
406 /* write_pulse_width_ns = */ 70,
407 /* tile_width = */ 16,
408 /* tile_height = */ 32,
409 /* default_x_offset = */ 0, /* not used: x offset is hard coded into cmd sequence */
410 /* flipmode_x_offset = */ 0,
411 /* pixel_width = */ 122,
412 /* pixel_height = */ 250
413};
414
415uint8_t u8x8_d_st7302_122x250(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
416{
417 // uint16_t x;
418 uint8_t c, i, y;
419 uint8_t *ptr;
420 switch(msg)
421 {
422 case U8X8_MSG_DISPLAY_INIT:
423 u8x8_d_helper_display_init(u8x8);
424 u8x8_cad_SendSequence(u8x8, u8x8_d_st7302_122x250_init_seq);
425 break;
426 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
427 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7302_122x250_display_info);
428 break;
429 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
430 if ( arg_int == 0 )
431 u8x8_cad_SendSequence(u8x8, u8x8_d_st7302_122x250_powersave0_seq);
432 else
433 u8x8_cad_SendSequence(u8x8, u8x8_d_st7302_122x250_powersave1_seq);
434 break;
435 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
436 if ( arg_int == 0 )
437 {
438 u8x8_cad_SendSequence(u8x8, u8x8_d_st7302_122x250_flip0_seq);
439 u8x8->x_offset = u8x8->display_info->default_x_offset;
440 }
441 else
442 {
443 u8x8_cad_SendSequence(u8x8, u8x8_d_st7302_122x250_flip1_seq);
444 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
445 }
446 break;
447#ifdef U8X8_WITH_SET_CONTRAST
448 case U8X8_MSG_DISPLAY_SET_CONTRAST:
449 u8x8_cad_StartTransfer(u8x8);
450 u8x8_cad_SendCmd(u8x8, 0x081 );
451 u8x8_cad_SendArg(u8x8, arg_int<<2 );
452 u8x8_cad_SendArg(u8x8, arg_int>>6 );
453 u8x8_cad_EndTransfer(u8x8);
454 break;
455#endif
456 case U8X8_MSG_DISPLAY_DRAW_TILE:
457 // x = ((u8x8_tile_t *)arg_ptr)->x_pos;
458 // x *= 8;
459 // x += u8x8->x_offset;
460 y= (((u8x8_tile_t *)arg_ptr)->y_pos);
461 y*=4;
462
463 y+=115; // specific for the 122x250 LCD
464
465 u8x8_cad_StartTransfer(u8x8);
466
467 for( i = 0; i < 4; i++ )
468 {
469
470 u8x8_cad_SendCmd(u8x8, 0x2a);
471 u8x8_cad_SendArg(u8x8, 0x19); // specific for the 122x250 LCD
472 u8x8_cad_SendArg(u8x8, 0x3a );
473
474 u8x8_cad_SendCmd(u8x8, 0x2b );
475 u8x8_cad_SendArg(u8x8, y+i);
476 u8x8_cad_SendArg(u8x8, y+i);
477 u8x8_cad_SendCmd(u8x8, 0x02c ); // write data
478
479 c = ((u8x8_tile_t *)arg_ptr)->cnt;
480 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
481
482 ptr += u8x8->display_info->tile_width*i*2;
483
484 c = (c+2)/3; // calculate the number of 24 bit blocks to send
485
486
487 while( c > 0 )
488 {
489 u8x8_cad_SendData(u8x8, 6, u8x8_st7302_convert_a0(u8x8, ptr));
490 ptr+=3;
491 --c;
492 }
493 }
494 u8x8_cad_EndTransfer(u8x8);
495 break;
496 default:
497 return 0;
498 }
499 return 1;
500}