Krolyxon
Commit 3120783

Branches

Tags

Refs →

orion-rf.piolibdepsesp32-s3-n16r8U8g2srcclibu8x8_d_st7305.c

920 lines · 29.9 KB · C

1/*
2
3 u8x8_d_st7305.c
4
5 Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
6
7 Copyright (c) 2025, 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 st7305: 240 x 320 122x250
36 st7305: 264 x 320 168x384, 200x200
37 Mono TFT Display Driver with Controller
38
39 st7305 seems to be almost compatible to the st7303, however they have a different memory architecture
40
41 https://github.com/olikraus/u8g2/issues/2436
42
43 This driver will use "u8g2_ll_hvline_horizontal_right_lsb"
44 --> No Hardware Flip
45 --> No U8x8 Support
46
47
48*/
49
50
51#include "u8x8.h"
52#include <string.h>
53
54static const uint8_t u8x8_d_st7305_122x250_powersave0_seq[] = {
55 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
56 U8X8_C(0x29), // display on
57 U8X8_END_TRANSFER(), /* disable chip */
58 U8X8_END() /* end of sequence */
59};
60
61static const uint8_t u8x8_d_st7305_122x250_powersave1_seq[] = {
62 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
63 U8X8_C(0x028), /* display off */
64 U8X8_END_TRANSFER(), /* disable chip */
65 U8X8_END() /* end of sequence */
66};
67
68static const uint8_t u8x8_d_st7305_122x250_flip0_seq[] = {
69 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
70 //U8X8_CA(0x36, 0x60), // Memory Control
71 U8X8_END_TRANSFER(), /* disable chip */
72 U8X8_END() /* end of sequence */
73};
74
75static const uint8_t u8x8_d_st7305_122x250_flip1_seq[] = {
76 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
77 //U8X8_CA(0x36, 0xa0), // Memory Control
78 U8X8_END_TRANSFER(), /* disable chip */
79 U8X8_END() /* end of sequence */
80};
81
82
83
84
85/*===================================================*/
86/* see also: http://www.technoblogy.com/show?3YB0 */
87
88
89static uint8_t *u8x8_st7305_convert_a0(u8x8_t *u8x8, uint8_t *p)
90{
91 static uint8_t buf[6];
92
93#ifdef NOT_WORKING
94 /* u8g2 first row */
95 static uint8_t map1[16] = {
96 /* 0x00 0000 */ 0,
97 /* 0x01 0001 */0x04,
98 /* 0x02 0010 */0x01,
99 /* 0x03 0011 */0x04+0x01,
100 /* 0x04 0100 */0x40,
101 /* 0x05 0101 */0x40+0x04,
102 /* 0x06 0110 */0x40+0x01,
103 /* 0x07 0111 */0x40+0x04+0x01,
104 /* 0x08 1000 */ 0x10,
105 /* 0x09 1001 */ 0x10+0x04,
106 /* 0x0a 1010 */ 0x10+0x01,
107 /* 0x0b 1011 */ 0x10+0x04+0x01,
108 /* 0x0c 1100 */ 0x40+0x10,
109 /* 0x0d 1101 */ 0x40+0x10+0x04,
110 /* 0x0e 1110 */ 0x40+0x10+0x01,
111 /* 0x0f 1111 */ 0x40+0x10+0x04+0x01
112 };
113 /* u8g2 second row */
114 static uint8_t map2[16] = {
115 /* 0x00 0000 */ 0,
116 /* 0x01 0001 */0x08,
117 /* 0x02 0010 */0x02,
118 /* 0x03 0011 */0x08+0x02,
119 /* 0x04 0100 */0x80,
120 /* 0x05 0101 */0x80+0x08,
121 /* 0x06 0110 */0x80+0x02,
122 /* 0x07 0111 */0x80+0x08+0x02,
123 /* 0x08 1000 */ 0x20,
124 /* 0x09 1001 */ 0x20+0x08,
125 /* 0x0a 1010 */ 0x20+0x02,
126 /* 0x0b 1011 */ 0x20+0x08+0x02,
127 /* 0x0c 1100 */ 0x80+0x20,
128 /* 0x0d 1101 */ 0x80+0x20+0x08,
129 /* 0x0e 1110 */ 0x80+0x20+0x02,
130 /* 0x0f 1111 */ 0x80+0x20+0x08+0x02
131 };
132 #endif
133
134 /* contributed by https://github.com/ischenz */
135 /* u8g2 first row */
136 static uint8_t map1[16] = {
137 0x00, 0x02, 0x08, 0x0A,
138 0x20, 0x22, 0x28, 0x2A,
139 0x80, 0x82, 0x88, 0x8A,
140 0xA0, 0xA2, 0xA8, 0xAA };
141 /* u8g2 second row */
142 static uint8_t map2[16] = {
143 0x00, 0x01, 0x04, 0x05,
144 0x10, 0x11, 0x14, 0x15,
145 0x40, 0x41, 0x44, 0x45,
146 0x50, 0x51, 0x54, 0x55 };
147
148 memset(buf, 0, 6);
149
150
151 // first row, left 12 pixel out of 24 pixel (=3 bytes)
152
153 buf[0] |= map1[p[0]>>4];
154 buf[1] |= map1[p[0] & 0x0f];
155 buf[2] |= map1[p[1]>>4];
156
157 // first row, right 12 pixel
158
159 buf[3] |= map1[p[1] & 0x0f];
160 buf[4] |= map1[p[2]>>4];
161 buf[5] |= map1[p[2] & 0x0f];
162
163 p += u8x8->display_info->tile_width;
164
165 // second row, left 12 pixel
166
167 buf[0] |= map2[p[0]>>4];
168 buf[1] |= map2[p[0] & 0x0f];
169 buf[2] |= map2[p[1]>>4];
170
171 // second row, right 12 pixel
172
173 buf[3] |= map2[p[1] & 0x0f];
174 buf[4] |= map2[p[2]>>4];
175 buf[5] |= map2[p[2] & 0x0f];
176 return buf;
177}
178
179
180
181
182/*===================================================*/
183/*
184 see also:
185 https://github.com/zhcong/st7302-for-arduino/blob/c9390fabcacefe7c36a113cd3e62959418c13b97/libraries/st7305SPI/st7305SPI.cpp#L21
186*/
187static const uint8_t u8x8_d_st7305_122x250_init_seq[] = {
188
189 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
190
191 U8X8_C(0x01), // software resets
192 U8X8_DLY(100),
193 U8X8_C(0x28), // display off
194 U8X8_CAA(0xC7, 0x26, 0xE9), // disable OSC
195 U8X8_CA(0xD1, 0x00), // Booster disable
196 U8X8_DLY(20),
197 U8X8_C(0x10), // sleep in: enter sleep mode
198 U8X8_DLY(20),
199 U8X8_C(0x01), // software reset
200 U8X8_DLY(20), // wait
201 //U8X8_C(0x38), // High Power Mode
202 //U8X8_CA(0xEB, 0x02), // Disable NVM Load
203 //U8X8_CA(0xD7, 0x68), // NVM Load Control: Enable ID1 ID2 ID3 Load
204 //U8X8_CA(0xD1, 0x01), // Booster Enable
205 //U8X8_CA(0xC0, 0x80), // Gate Voltage Setting VGH=12V (upper 4 bit, 8V-15V); VGL=-5V (lower 4 bit, -5V .. -10V)
206 U8X8_CAA(0xD6, 0x17, 0x02),
207 U8X8_CA(0xD1, 0x01),
208 U8X8_CAA(0xC0, 0x12, 0x0a),//chen.x
209 U8X8_C(0x0C1), // Source Voltage Control 1
210 U8X8_A4(115,0x3E,0x3C,0x3C),
211 U8X8_C(0x0C2), // Source Voltage Control 1
212 U8X8_A4(0,0x21,0x23,0x23), // Source low voltage in reflective and transmissive mode
213 U8X8_C(0x0C4), //ischen.x
214 U8X8_A4(50,0x5C,0x5A,0x5A),
215 U8X8_C(0x0C5), //ischen.x
216 U8X8_A4(50,0x35,0x37,0x37),
217 U8X8_CAA(0xD8, 0x80, 0xE9),
218
219 //U8X8_CA(0xCB, 0x14), // VCOMH: 0x14 = 4V (0x28 = 5V)
220 U8X8_CA(0xB2, 0x12),
221 U8X8_CAA(0xB3, 0xE5, 0xF6), // Update Period Gate EQ Control, why 0x77??? it should be 0x66 according to the datasheet
222 U8X8_A8(0x17, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x71),
223 U8X8_CAA(0xB4, 0x05, 0x46), // Update Period Gate EQ Control, why 0x77??? it should be 0x66 according to the datasheet
224 U8X8_A6(0x77, 0x77, 0x77, 0x77, 0x76, 0x45),
225 U8X8_CAAA(0x62, 0x32, 0x03, 0x1f),
226 U8X8_CA(0xB7, 0x13),
227 U8X8_CA(0xB0, 0x32), // Duty Cycle... this must be before sleep out, 200x200 display: 0x64 --> 0x32
228
229 U8X8_C(0x11), // sleep out: furn off sleep mode
230 U8X8_DLY(120),
231 U8X8_CA(0xC9, 0x00),
232 U8X8_CA(0x36, 0xa4), // Memory Control, 0xa4 for the 200x200 display
233
234 U8X8_CA(0x3A, 0x11), // Data Format
235 U8X8_CA(0xB9, 0x20), // Source Setting: Clear RAM off *******<-----
236 U8X8_CA(0xB8, 0x29), // Panel Setting / Panel Layout
237 U8X8_CAA(0x2A, 0x16, 0x27), // col addr
238 U8X8_CAA(0x2B, 0x00, 0x63), // row addr
239 U8X8_CA(0x35, 0x00),
240 U8X8_CA(0xD0, 0xFF), // Not in datasheet
241 //U8X8_CA(0x72, 0x00), // Not in datasheet
242 //U8X8_CAA(0xB2,1, 5), // Frame Rate for High and Low Power Mode (hier: 32Hz and 8Hz)
243 U8X8_C(0x38), // enable Low Power Mode...: 8Hz, see above
244 U8X8_C(0x29), // display on
245 U8X8_C(0x20),
246 U8X8_CA(0xBB, 0x4F),
247 U8X8_DLY(100),
248
249 U8X8_END_TRANSFER(), /* disable chip */
250 U8X8_END() /* end of sequence */
251};
252
253
254static const u8x8_display_info_t u8x8_st7305_122x250_display_info =
255{
256 /* chip_enable_level = */ 0,
257 /* chip_disable_level = */ 1,
258
259 /* post_chip_enable_wait_ns = */ 20,
260 /* pre_chip_disable_wait_ns = */ 20,
261 /* reset_pulse_width_ms = */ 3,
262 /* post_reset_wait_ms = */ 3, /**/
263 /* sda_setup_time_ns = */ 10, /* */
264 /* sck_pulse_width_ns = */ 30, /* */
265 /* sck_clock_hz = */ 2000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
266 /* spi_mode = */ 0, /* active high, rising edge */
267 /* i2c_bus_clock_100kHz = */ 4, /* 400KHz */
268 /* data_setup_time_ns = */ 15,
269 /* write_pulse_width_ns = */ 70,
270 /* tile_width = */ 16,
271 /* tile_height = */ 32,
272 /* default_x_offset = */ 0, /* not used: x offset is hard coded into cmd sequence */
273 /* flipmode_x_offset = */ 0,
274 /* pixel_width = */ 122,
275 /* pixel_height = */ 250
276};
277
278uint8_t u8x8_d_st7305_122x250(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
279{
280 // uint16_t x;
281 uint8_t c, i, y;
282 uint8_t *ptr;
283 switch(msg)
284 {
285 case U8X8_MSG_DISPLAY_INIT:
286 u8x8_d_helper_display_init(u8x8);
287 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_init_seq);
288 break;
289 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
290 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7305_122x250_display_info);
291 break;
292 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
293 if ( arg_int == 0 )
294 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_powersave0_seq);
295 else
296 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_powersave1_seq);
297 break;
298 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
299 if ( arg_int == 0 )
300 {
301 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_flip0_seq);
302 u8x8->x_offset = u8x8->display_info->default_x_offset;
303 }
304 else
305 {
306 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_flip1_seq);
307 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
308 }
309 break;
310#ifdef U8X8_WITH_SET_CONTRAST
311 case U8X8_MSG_DISPLAY_SET_CONTRAST:
312 u8x8_cad_StartTransfer(u8x8);
313 u8x8_cad_SendCmd(u8x8, 0x081 );
314 u8x8_cad_SendArg(u8x8, arg_int<<2 );
315 u8x8_cad_SendArg(u8x8, arg_int>>6 );
316 u8x8_cad_EndTransfer(u8x8);
317 break;
318#endif
319 case U8X8_MSG_DISPLAY_DRAW_TILE:
320 // x offset is ignored
321 //x = ((u8x8_tile_t *)arg_ptr)->x_pos;
322 //x *= 8;
323 //x += u8x8->x_offset;
324 y= (((u8x8_tile_t *)arg_ptr)->y_pos);
325 y*=4;
326
327 y+=115; // specific for the 122x250 LCD
328
329 u8x8_cad_StartTransfer(u8x8);
330
331 for( i = 0; i < 4; i++ )
332 {
333
334 u8x8_cad_SendCmd(u8x8, 0x2a);
335 u8x8_cad_SendArg(u8x8, 0x19); // specific for the 122x250 LCD
336 u8x8_cad_SendArg(u8x8, 0x3a );
337
338 u8x8_cad_SendCmd(u8x8, 0x2b );
339 u8x8_cad_SendArg(u8x8, y+i);
340 u8x8_cad_SendArg(u8x8, y+i);
341 u8x8_cad_SendCmd(u8x8, 0x02c ); // write data
342
343 c = ((u8x8_tile_t *)arg_ptr)->cnt;
344 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
345
346 ptr += u8x8->display_info->tile_width*i*2;
347
348 c = (c+2)/3; // calculate the number of 24 bit blocks to send
349
350
351 while( c > 0 )
352 {
353 u8x8_cad_SendData(u8x8, 6, u8x8_st7305_convert_a0(u8x8, ptr));
354 ptr+=3;
355 --c;
356 }
357 }
358 u8x8_cad_EndTransfer(u8x8);
359 break;
360 default:
361 return 0;
362 }
363 return 1;
364}
365
366
367/*=====================================================================*/
368/* 200x200, https://admin.osptek.com/uploads/YDP_154_H008_V3_c24b455ff9.pdf */
369
370
371static const u8x8_display_info_t u8x8_st7305_200x200_display_info =
372{
373 /* chip_enable_level = */ 0,
374 /* chip_disable_level = */ 1,
375
376 /* post_chip_enable_wait_ns = */ 20,
377 /* pre_chip_disable_wait_ns = */ 20,
378 /* reset_pulse_width_ms = */ 3,
379 /* post_reset_wait_ms = */ 3, /**/
380 /* sda_setup_time_ns = */ 10, /* */
381 /* sck_pulse_width_ns = */ 30, /* */
382 /* sck_clock_hz = */ 2000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
383 /* spi_mode = */ 0, /* active high, rising edge */
384 /* i2c_bus_clock_100kHz = */ 4, /* 400KHz */
385 /* data_setup_time_ns = */ 15,
386 /* write_pulse_width_ns = */ 70,
387 /* 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 */
388 /* tile_height = */ 25,
389 /* default_x_offset = */ 0, /* not used: x offset is hard coded into cmd sequence */
390 /* flipmode_x_offset = */ 0,
391 /* pixel_width = */ 200, /* not 100% sure, whether this works with the tile_width of 26... */
392 /* pixel_height = */ 200
393};
394
395uint8_t u8x8_d_st7305_200x200(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
396{
397 //uint16_t x;
398 uint8_t c, i, y;
399 uint8_t *ptr;
400 switch(msg)
401 {
402 case U8X8_MSG_DISPLAY_INIT:
403 u8x8_d_helper_display_init(u8x8);
404 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_init_seq);
405 break;
406 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
407 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7305_200x200_display_info);
408 break;
409 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
410 if ( arg_int == 0 )
411 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_powersave0_seq);
412 else
413 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_powersave1_seq);
414 break;
415 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
416 if ( arg_int == 0 )
417 {
418 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_flip0_seq);
419 u8x8->x_offset = u8x8->display_info->default_x_offset;
420 }
421 else
422 {
423 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_flip1_seq);
424 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
425 }
426 break;
427#ifdef U8X8_WITH_SET_CONTRAST
428 case U8X8_MSG_DISPLAY_SET_CONTRAST:
429 u8x8_cad_StartTransfer(u8x8);
430 u8x8_cad_SendCmd(u8x8, 0x081 );
431 u8x8_cad_SendArg(u8x8, arg_int<<2 );
432 u8x8_cad_SendArg(u8x8, arg_int>>6 );
433 u8x8_cad_EndTransfer(u8x8);
434 break;
435#endif
436 case U8X8_MSG_DISPLAY_DRAW_TILE:
437 //x = ((u8x8_tile_t *)arg_ptr)->x_pos;
438 //x *= 8;
439 //x += u8x8->x_offset;
440 y= (((u8x8_tile_t *)arg_ptr)->y_pos);
441 y*=4;
442
443 y+=0; // 200x200 display
444
445 u8x8_cad_StartTransfer(u8x8);
446
447 for( i = 0; i < 4; i++ )
448 {
449
450 u8x8_cad_SendCmd(u8x8, 0x2a); // column address set
451 u8x8_cad_SendArg(u8x8, 0x16); // 0x019 for the 122x250 LCD --> 0x016 for the 200x200 display
452 u8x8_cad_SendArg(u8x8, 0x27 ); // 204 pixel for the 200x200 display
453
454 u8x8_cad_SendCmd(u8x8, 0x2b );
455 u8x8_cad_SendArg(u8x8, y+i);
456 u8x8_cad_SendArg(u8x8, y+i);
457 u8x8_cad_SendCmd(u8x8, 0x02c ); // write data
458
459 c = ((u8x8_tile_t *)arg_ptr)->cnt;
460 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
461
462 ptr += u8x8->display_info->tile_width*i*2;
463
464 c = (c+2)/3; // calculate the number of 24 bit blocks to send
465
466
467 while( c > 0 )
468 {
469 u8x8_cad_SendData(u8x8, 6, u8x8_st7305_convert_a0(u8x8, ptr));
470 ptr+=3;
471 --c;
472 }
473 }
474 u8x8_cad_EndTransfer(u8x8);
475 break;
476 default:
477 return 0;
478 }
479 return 1;
480}
481
482
483/*=====================================================================*/
484/* 168x384, https://github.com/olikraus/u8g2/issues/2661 */
485
486
487#ifdef NOT_USED
488static const uint8_t u8x8_d_st7305_168x384_powersave0_seq[] = {
489 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
490 U8X8_C(0x29), // display on
491 U8X8_END_TRANSFER(), /* disable chip */
492 U8X8_END() /* end of sequence */
493};
494
495
496static const uint8_t u8x8_d_st7305_168x384_powersave1_seq[] = {
497 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
498 U8X8_C(0x028), /* display off */
499 U8X8_END_TRANSFER(), /* disable chip */
500 U8X8_END() /* end of sequence */
501};
502
503
504static const uint8_t u8x8_d_st7305_168x384_flip0_seq[] = {
505 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
506 // U8X8_CA(0x36, 0x60), // Memory Control
507 U8X8_END_TRANSFER(), /* disable chip */
508 U8X8_END() /* end of sequence */
509};
510#endif
511
512
513static const uint8_t u8x8_d_st7305_168x384_init_seq[] = {
514 U8X8_START_TRANSFER(),
515
516
517 /* Software Reset */
518 U8X8_C(0x01),
519 U8X8_DLY(100),
520
521
522 /* Settings */
523 // 以下在芯片手册基础上,按照显示屏厂家给的示例代码调整
524 U8X8_CAA(0xD6, 0x13, 0x02), // NVM Load Control
525 U8X8_CA(0xD1, 0x01), // Booster Enable
526 U8X8_CAA(0xC0, 0x12, 0x0A), // Gate Voltage Setting: VGH=15V, VGL=-10V
527
528
529 U8X8_CAAAA(0xC1, 0x3C, 0x3E, 0x3C, 0x3C), // VSHP Setting: VSHP1~4 = 4.8V
530 U8X8_CAAAA(0xC2, 0x23, 0x21, 0x23, 0x23), // VSLP Setting: VSHP1~4 = 0.98V
531 U8X8_CAAAA(0xC4, 0x5A, 0x5C, 0x5A, 0x5A), // VSHN Setting: VSHP1~4 = -3.6V
532 U8X8_CAAAA(0xC5, 0x37, 0x35, 0x37, 0x37), // VSLN Setting: VSHP1~4 = 0.22V
533
534
535 U8X8_CAA(0xD8, 0xA6, 0xE9), // OSC Setting
536 U8X8_CA(0xB2, 0x12), // Frame Rate Control: HPM=32Hz, LPM=1Hz
537
538
539 U8X8_CAAAA(0xB3, 0xE5, 0xF6, 0x17, 0x77), // Update Period Gate EQ Control in HPM
540 U8X8_A6(0x77, 0x77, 0x77, 0x77, 0x77, 0x71),
541
542
543 U8X8_CAA(0xB4, 0x05, 0x46), // Update Period Gate EQ Control in LPM
544 U8X8_A6(0x77, 0x77, 0x77, 0x77, 0x76, 0x45),
545
546
547 U8X8_CAAA(0x62, 0x32, 0x03, 0x1F), // Gate Timing Control
548 U8X8_CA(0xB7, 0x13), // Source EQ Enable
549 U8X8_CA(0xB0, 0x60), // Gate Line Setting: 384 line
550
551
552 U8X8_C(0x11), // Sleep Out
553 U8X8_DLY(10),
554
555
556 U8X8_CA(0xC9, 0x00), // Source Voltage Select: VSHP1; VSLP1 ; VSHN1 ; VSLN1
557 U8X8_CA(0x36, 0x48), // Memory Data Access Control
558 U8X8_CA(0x3A, 0x11), // Data Format Select
559 U8X8_CA(0xB9, 0x20), // Gamma Mode Setting: Mono 00:4GS
560 U8X8_CA(0xB8, 0x29), // Panel Setting, 1-Dot inversion, Frame inversion, One Line Interlace
561
562
563 U8X8_CAA(0x2A, 0x17, 0x24), // Column Address Setting: 0X24-0X16=14, 14*12=168
564 U8X8_CAA(0x2B, 0x00, 0xBF), // Row Address Setting: 192*2=384
565 U8X8_CA(0x35, 0x00), // TE Setting
566 U8X8_CA(0xD0, 0xFF), // Enable Auto Power down
567 U8X8_C(0x38), // High Power Mode ON
568 // U8X8_C(0x39), // Low Power Mode ON
569
570
571 /* Display ON */
572 U8X8_C(0x29), // Display ON
573 U8X8_C(0x20), // Display Inversion Off
574 U8X8_CA(0xBB, 0x4F), // Enable Clear RAM to 0
575
576
577 U8X8_END_TRANSFER(),
578 U8X8_END()
579
580
581};
582
583
584static const u8x8_display_info_t u8x8_st7305_168x384_display_info =
585 {
586 /* chip_enable_level = */ 0,
587 /* chip_disable_level = */ 1,
588
589
590 /* post_chip_enable_wait_ns = */ 20,
591 /* pre_chip_disable_wait_ns = */ 20,
592 /* reset_pulse_width_ms = */ 3,
593 /* post_reset_wait_ms = */ 3, /**/
594 /* sda_setup_time_ns = */ 10, /* */
595 /* sck_pulse_width_ns = */ 30, /* */
596 /* sck_clock_hz = */ 2000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
597 /* spi_mode = */ 0, /* active high, rising edge */
598 /* i2c_bus_clock_100kHz = */ 4, /* 400KHz */
599 /* data_setup_time_ns = */ 15,
600 /* write_pulse_width_ns = */ 70,
601 /* 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 */
602 /* tile_height = */ 48,
603 /* default_x_offset = */ 0, /* not used: x offset is hard coded into cmd sequence */
604 /* flipmode_x_offset = */ 0,
605 /* pixel_width = */ 168, /* not 100% sure, whether this works with the tile_width of 21... */
606 /* pixel_height = */ 384};
607
608
609uint8_t u8x8_d_st7305_168x384(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
610{
611 //uint16_t x;
612 uint8_t c, i, y;
613 uint8_t *ptr;
614 switch(msg)
615 {
616 case U8X8_MSG_DISPLAY_INIT:
617 u8x8_d_helper_display_init(u8x8);
618 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_168x384_init_seq);
619 break;
620 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
621 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7305_168x384_display_info);
622 break;
623 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
624 if ( arg_int == 0 )
625 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_powersave0_seq);
626 else
627 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_powersave1_seq);
628 break;
629 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
630 if ( arg_int == 0 )
631 {
632 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_flip0_seq);
633 u8x8->x_offset = u8x8->display_info->default_x_offset;
634 }
635 else
636 {
637 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_flip1_seq);
638 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
639 }
640 break;
641#ifdef U8X8_WITH_SET_CONTRAST
642 case U8X8_MSG_DISPLAY_SET_CONTRAST:
643 u8x8_cad_StartTransfer(u8x8);
644 u8x8_cad_SendCmd(u8x8, 0x081 );
645 u8x8_cad_SendArg(u8x8, arg_int<<2 );
646 u8x8_cad_SendArg(u8x8, arg_int>>6 );
647 u8x8_cad_EndTransfer(u8x8);
648 break;
649#endif
650 case U8X8_MSG_DISPLAY_DRAW_TILE:
651 // x = ((u8x8_tile_t *)arg_ptr)->x_pos;
652 // x *= 8;
653 // x += u8x8->x_offset;
654 y= (((u8x8_tile_t *)arg_ptr)->y_pos);
655 y*=4;
656
657 y+=0; // specific for the 168x384 LCD
658
659
660 u8x8_cad_StartTransfer(u8x8);
661
662
663 for( i = 0; i < 4; i++ )
664 {
665
666 u8x8_cad_SendCmd(u8x8, 0x2a); // column address set
667 u8x8_cad_SendArg(u8x8, 0x17); // 0x019 for the 122x250 LCD --> 0x016 for the 200x200 display
668 u8x8_cad_SendArg(u8x8, 0x24); // 204 pixel for the 200x200 display
669
670 u8x8_cad_SendCmd(u8x8, 0x2b);
671 u8x8_cad_SendArg(u8x8, y+i);
672 u8x8_cad_SendArg(u8x8, y+i);
673 u8x8_cad_SendCmd(u8x8, 0x2c); // write data
674
675 c = ((u8x8_tile_t *)arg_ptr)->cnt;
676 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
677
678 ptr += u8x8->display_info->tile_width*i*2;
679
680 c = (c+2)/3; // calculate the number of 24 bit blocks to send
681
682
683 while( c > 0 )
684 {
685 u8x8_cad_SendData(u8x8, 6, u8x8_st7305_convert_a0(u8x8, ptr));
686 ptr+=3;
687 --c;
688 }
689 }
690 u8x8_cad_EndTransfer(u8x8);
691 break;
692 default:
693 return 0;
694 }
695 return 1;
696}
697
698
699/*=====================================================================*/
700/* 300x400, https://github.com/olikraus/u8g2/issues/2661 */
701
702
703#ifdef NOT_USED
704static const uint8_t u8x8_d_st7305_168x384_powersave0_seq[] = {
705 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
706 U8X8_C(0x29), // display on
707 U8X8_END_TRANSFER(), /* disable chip */
708 U8X8_END() /* end of sequence */
709};
710
711
712static const uint8_t u8x8_d_st7305_168x384_powersave1_seq[] = {
713 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
714 U8X8_C(0x028), /* display off */
715 U8X8_END_TRANSFER(), /* disable chip */
716 U8X8_END() /* end of sequence */
717};
718
719
720static const uint8_t u8x8_d_st7305_168x384_flip0_seq[] = {
721 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
722 // U8X8_CA(0x36, 0x60), // Memory Control
723 U8X8_END_TRANSFER(), /* disable chip */
724 U8X8_END() /* end of sequence */
725};
726#endif
727
728
729static const uint8_t u8x8_d_st7305_300x400_init_seq[] = {
730 U8X8_START_TRANSFER(),
731
732
733 /* Software Reset */
734 U8X8_C(0x01),
735 U8X8_DLY(100),
736
737
738 /* Settings */
739 // 以下在芯片手册基础上,按照显示屏厂家给的示例代码调整
740 U8X8_CAA(0xD6, 0x13, 0x02), // NVM Load Control
741 U8X8_CA(0xD1, 0x01), // Booster Enable
742 U8X8_CAA(0xC0, 0x12, 0x0A), // Gate Voltage Setting: VGH=15V, VGL=-10V
743 //U8X8_CAA(0xC0, 0x11, 0x04), // Gate Voltage Setting: VGH=15V, VGL=-10V
744
745
746 U8X8_CAAAA(0xC1, 0x3C, 0x3E, 0x3C, 0x3C), // VSHP Setting: VSHP1~4 = 4.8V
747 U8X8_CAAAA(0xC2, 0x23, 0x21, 0x23, 0x23), // VSLP Setting: VSHP1~4 = 0.98V
748 U8X8_CAAAA(0xC4, 0x5A, 0x5C, 0x5A, 0x5A), // VSHN Setting: VSHP1~4 = -3.6V
749 U8X8_CAAAA(0xC5, 0x37, 0x35, 0x37, 0x37), // VSLN Setting: VSHP1~4 = 0.22V
750
751
752 U8X8_CAA(0xD8, 0xA6, 0xE9), // OSC Setting
753 U8X8_CA(0xB2, 0x12), // Frame Rate Control: HPM=32Hz, LPM=1Hz
754
755
756 U8X8_CAAAA(0xB3, 0xE5, 0xF6, 0x17, 0x77), // Update Period Gate EQ Control in HPM
757 U8X8_A6(0x77, 0x77, 0x77, 0x77, 0x77, 0x71),
758
759 //U8X8_CAAAA(0xB3, 0xE5, 0xF6, 0x05, 0x46), // 300x400, however this has lower contrast
760 //U8X8_A6(0x77, 0x77, 0x77, 0x77, 0x76, 0x45),
761
762
763
764 U8X8_CAA(0xB4, 0x05, 0x46), // Update Period Gate EQ Control in LPM
765 U8X8_A6(0x77, 0x77, 0x77, 0x77, 0x76, 0x45),
766
767
768 U8X8_CAAA(0x62, 0x32, 0x03, 0x1F), // Gate Timing Control
769 U8X8_CA(0xB7, 0x13), // Source EQ Enable
770 U8X8_CA(0xB0, 0x64), // Duty setting 400 line (300x400 display)
771
772
773 U8X8_C(0x11), // Sleep Out
774 U8X8_DLY(10),
775
776
777 U8X8_CA(0xC9, 0x00), // Source Voltage Select: VSHP1; VSLP1 ; VSHN1 ; VSLN1
778 U8X8_CA(0x36, 0x48), // Memory Data Access Control
779 U8X8_CA(0x3A, 0x11), // Data Format Select
780 U8X8_CA(0xB9, 0x20), // Gamma Mode Setting: Mono 00:4GS
781 U8X8_CA(0xB8, 0x29), // Panel Setting, 1-Dot inversion, Frame inversion, One Line Interlace
782
783
784 // 0x2A and 0x2B are not required here, will be done below
785 //U8X8_CAA(0x2A, 0x00, 0x24), // Column Address Setting: 0X24-0X16=14, 14*12=168
786 //U8X8_CAA(0x2B, 0x00, 0xc1), // Row Address Setting: 192*2=384
787 U8X8_CA(0x35, 0x00), // TE Setting
788 U8X8_CA(0xD0, 0xFF), // Enable Auto Power down
789 U8X8_C(0x38), // High Power Mode ON
790 // U8X8_C(0x39), // Low Power Mode ON
791
792
793 /* Display ON */
794 U8X8_C(0x29), // Display ON
795 U8X8_C(0x20), // Display Inversion Off
796 U8X8_CA(0xBB, 0x4F), // Enable Clear RAM to 0
797
798
799 U8X8_END_TRANSFER(),
800 U8X8_END()
801
802
803};
804
805
806static const u8x8_display_info_t u8x8_st7305_300x400_display_info =
807 {
808 /* chip_enable_level = */ 0,
809 /* chip_disable_level = */ 1,
810
811
812 /* post_chip_enable_wait_ns = */ 20,
813 /* pre_chip_disable_wait_ns = */ 20,
814 /* reset_pulse_width_ms = */ 3,
815 /* post_reset_wait_ms = */ 3, /**/
816 /* sda_setup_time_ns = */ 10, /* */
817 /* sck_pulse_width_ns = */ 30, /* */
818 /* sck_clock_hz = */ 2000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
819 /* spi_mode = */ 0, /* active high, rising edge */
820 /* i2c_bus_clock_100kHz = */ 4, /* 400KHz */
821 /* data_setup_time_ns = */ 15,
822 /* write_pulse_width_ns = */ 70,
823 /* tile_width = */ 38, /* tile width is 21*8=168, because this display requires 12 bit blocks, which would be 168 pixel, so next tile is at 168 */
824 /* tile_height = */ 50,
825 /* default_x_offset = */ 0, /* not used: x offset is hard coded into cmd sequence */
826 /* flipmode_x_offset = */ 0,
827 /* pixel_width = */ 300, /* not 100% sure, whether this works with the tile_width of 21... */
828 /* pixel_height = */ 400};
829
830
831uint8_t u8x8_d_st7305_300x400(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
832{
833 //uint16_t x;
834 uint8_t y;
835 uint8_t c, i;
836 uint8_t *ptr;
837 switch(msg)
838 {
839 case U8X8_MSG_DISPLAY_INIT:
840 u8x8_d_helper_display_init(u8x8);
841 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_300x400_init_seq);
842 break;
843 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
844 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7305_300x400_display_info);
845 break;
846 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
847 if ( arg_int == 0 )
848 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_powersave0_seq);
849 else
850 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_powersave1_seq);
851 break;
852 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
853 if ( arg_int == 0 )
854 {
855 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_flip0_seq);
856 u8x8->x_offset = u8x8->display_info->default_x_offset;
857 }
858 else
859 {
860 u8x8_cad_SendSequence(u8x8, u8x8_d_st7305_122x250_flip1_seq);
861 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
862 }
863 break;
864#ifdef U8X8_WITH_SET_CONTRAST
865 case U8X8_MSG_DISPLAY_SET_CONTRAST:
866 u8x8_cad_StartTransfer(u8x8);
867 u8x8_cad_SendCmd(u8x8, 0x081 );
868 u8x8_cad_SendArg(u8x8, arg_int<<2 );
869 u8x8_cad_SendArg(u8x8, arg_int>>6 );
870 u8x8_cad_EndTransfer(u8x8);
871 break;
872#endif
873 case U8X8_MSG_DISPLAY_DRAW_TILE:
874 // x = ((u8x8_tile_t *)arg_ptr)->x_pos;
875 // x *= 8;
876 // x += u8x8->x_offset;
877 y= (((u8x8_tile_t *)arg_ptr)->y_pos);
878 y*=4;
879
880 y+=0; // 300x400
881
882
883 u8x8_cad_StartTransfer(u8x8);
884
885
886 for( i = 0; i < 4; i++ )
887 {
888
889 u8x8_cad_SendCmd(u8x8, 0x2a); // column address set
890 u8x8_cad_SendArg(u8x8, 0x01); // 300x400
891 u8x8_cad_SendArg(u8x8, 0x2a); // 300x400
892
893 u8x8_cad_SendCmd(u8x8, 0x2b);
894 u8x8_cad_SendArg(u8x8, y+i);
895 u8x8_cad_SendArg(u8x8, y+i);
896 u8x8_cad_SendCmd(u8x8, 0x2c); // write data
897
898 c = ((u8x8_tile_t *)arg_ptr)->cnt;
899 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
900
901 ptr += u8x8->display_info->tile_width*i*2;
902
903 c = (c+2)/3; // calculate the number of 24 bit blocks to send
904
905
906 while( c > 0 )
907 {
908 u8x8_cad_SendData(u8x8, 6, u8x8_st7305_convert_a0(u8x8, ptr));
909 ptr+=3;
910 --c;
911 }
912 }
913 u8x8_cad_EndTransfer(u8x8);
914 break;
915 default:
916 return 0;
917 }
918 return 1;
919}
920