Krolyxon
Commit 1d55752

Branches

Tags

Refs →

orion-rf.piolibdepsesp32-s3-n16r8U8g2srcclibu8x8_d_st7301.c

501 lines · 14.2 KB · C

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