Krolyxon
Commit 1d55752

Branches

Tags

Refs →

orion-rf.piolibdepsesp32-s3-n16r8U8g2srcclibu8x8_d_st7567.c

1809 lines · 58.8 KB · C

1/*
2
3 u8x8_d_st7567.c
4
5 Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
6
7 Copyright (c) 2016, 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 ST7567: 65x132 controller
36
37
38*/
39#include "u8x8.h"
40
41
42
43
44static const uint8_t u8x8_d_st7567_132x64_powersave0_seq[] = {
45 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
46 U8X8_C(0x0a4), /* all pixel off, issue 142 */
47 U8X8_C(0x0af), /* display on */
48 U8X8_END_TRANSFER(), /* disable chip */
49 U8X8_END() /* end of sequence */
50};
51
52static const uint8_t u8x8_d_st7567_132x64_powersave1_seq[] = {
53 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
54 U8X8_C(0x0ae), /* display off */
55 U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
56 U8X8_END_TRANSFER(), /* disable chip */
57 U8X8_END() /* end of sequence */
58};
59
60static const uint8_t u8x8_d_st7567_132x64_flip0_seq[] = {
61 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
62 U8X8_C(0x0a1), /* segment remap a0/a1*/
63 U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
64 U8X8_END_TRANSFER(), /* disable chip */
65 U8X8_END() /* end of sequence */
66};
67
68static const uint8_t u8x8_d_st7567_132x64_flip1_seq[] = {
69 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
70 U8X8_C(0x0a0), /* segment remap a0/a1*/
71 U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
72 U8X8_END_TRANSFER(), /* disable chip */
73 U8X8_END() /* end of sequence */
74};
75
76#define u8x8_d_st7567_128x64_powersave0_seq u8x8_d_st7567_132x64_powersave0_seq
77#define u8x8_d_st7567_128x64_powersave1_seq u8x8_d_st7567_132x64_powersave1_seq
78#define u8x8_d_st7567_128x64_flip0_seq u8x8_d_st7567_132x64_flip0_seq
79#define u8x8_d_st7567_128x64_flip1_seq u8x8_d_st7567_132x64_flip1_seq
80
81static const uint8_t u8x8_d_st7567_n_flip0_seq[] = {
82 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
83 U8X8_C(0x0a0), /* segment remap a0/a1*/
84 U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
85 U8X8_END_TRANSFER(), /* disable chip */
86 U8X8_END() /* end of sequence */
87};
88
89static const uint8_t u8x8_d_st7567_n_flip1_seq[] = {
90 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
91 U8X8_C(0x0a1), /* segment remap a0/a1*/
92 U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
93 U8X8_END_TRANSFER(), /* disable chip */
94 U8X8_END() /* end of sequence */
95};
96
97
98
99/*=====================================================*/
100
101
102static const u8x8_display_info_t u8x8_st7567_132x64_display_info =
103{
104 /* chip_enable_level = */ 0,
105 /* chip_disable_level = */ 1,
106
107 /* post_chip_enable_wait_ns = */ 150, /* */
108 /* pre_chip_disable_wait_ns = */ 50, /* */
109 /* reset_pulse_width_ms = */ 1,
110 /* post_reset_wait_ms = */ 1,
111 /* sda_setup_time_ns = */ 50, /* */
112 /* sck_pulse_width_ns = */ 120, /* */
113 /* sck_clock_hz = */ 4000000UL, /* */
114 /* spi_mode = */ 0, /* active high, rising edge */
115 /* i2c_bus_clock_100kHz = */ 4,
116 /* data_setup_time_ns = */ 40, /* */
117 /* write_pulse_width_ns = */ 80, /* */
118 /* tile_width = */ 17, /* width of 17*8=136 pixel */
119 /* tile_height = */ 8,
120 /* default_x_offset = */ 0,
121 /* flipmode_x_offset = */ 0,
122 /* pixel_width = */ 132,
123 /* pixel_height = */ 64
124};
125
126static const uint8_t u8x8_d_st7567_132x64_init_seq[] = {
127
128 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
129
130 U8X8_C(0x0e2), /* soft reset */
131 U8X8_C(0x0ae), /* display off */
132 U8X8_C(0x040), /* set display start line to 0 */
133
134 U8X8_C(0x0a1), /* ADC set to reverse */
135 U8X8_C(0x0c0), /* common output mode */
136 // Flipmode
137 //U8X8_C(0x0a0), /* ADC set to reverse */
138 //U8X8_C(0x0c8), /* common output mode */
139
140 U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
141 U8X8_C(0x0a3), /* LCD bias 1/7 */
142 /* power on sequence from paxinstruments */
143 U8X8_C(0x028|4), /* all power control circuits on */
144 U8X8_DLY(50),
145 U8X8_C(0x028|6), /* all power control circuits on */
146 U8X8_DLY(50),
147 U8X8_C(0x028|7), /* all power control circuits on */
148 U8X8_DLY(50),
149
150 U8X8_C(0x026), /* v0 voltage resistor ratio */
151 U8X8_CA(0x081, 0x027), /* set contrast, contrast value*/
152
153 U8X8_C(0x0ae), /* display off */
154 U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
155
156 U8X8_END_TRANSFER(), /* disable chip */
157 U8X8_END() /* end of sequence */
158};
159
160/* pax instruments 132x64 display */
161uint8_t u8x8_d_st7567_pi_132x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
162{
163 uint8_t x, c;
164 uint8_t *ptr;
165 switch(msg)
166 {
167 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
168 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_132x64_display_info);
169 break;
170 case U8X8_MSG_DISPLAY_INIT:
171 u8x8_d_helper_display_init(u8x8);
172 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_init_seq);
173 break;
174 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
175 if ( arg_int == 0 )
176 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave0_seq);
177 else
178 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave1_seq);
179 break;
180 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
181 if ( arg_int == 0 )
182 {
183 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip0_seq);
184 u8x8->x_offset = u8x8->display_info->default_x_offset;
185 }
186 else
187 {
188 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip1_seq);
189 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
190 }
191 break;
192#ifdef U8X8_WITH_SET_CONTRAST
193 case U8X8_MSG_DISPLAY_SET_CONTRAST:
194 u8x8_cad_StartTransfer(u8x8);
195 u8x8_cad_SendCmd(u8x8, 0x081 );
196 u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7567 has range from 0 to 63 */
197 u8x8_cad_EndTransfer(u8x8);
198 break;
199#endif
200 case U8X8_MSG_DISPLAY_DRAW_TILE:
201 u8x8_cad_StartTransfer(u8x8);
202
203 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
204 x *= 8;
205 x += u8x8->x_offset;
206 u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
207 u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
208 u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
209
210 c = ((u8x8_tile_t *)arg_ptr)->cnt;
211 c *= 8;
212 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
213 /*
214 The following if condition checks the hardware limits of the st7567
215 controller: It is not allowed to write beyond the display limits.
216 This is in fact an issue within flip mode.
217 */
218 if ( c + x > 132u )
219 {
220 c = 132u;
221 c -= x;
222 }
223 do
224 {
225 u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
226 arg_int--;
227 } while( arg_int > 0 );
228
229 u8x8_cad_EndTransfer(u8x8);
230 break;
231 default:
232 return 0;
233 }
234 return 1;
235}
236
237
238
239
240/*=====================================================*/
241
242
243static const u8x8_display_info_t u8x8_st7567_jlx12864_display_info =
244{
245 /* chip_enable_level = */ 0,
246 /* chip_disable_level = */ 1,
247
248 /* post_chip_enable_wait_ns = */ 150, /* */
249 /* pre_chip_disable_wait_ns = */ 50, /* */
250 /* reset_pulse_width_ms = */ 1,
251 /* post_reset_wait_ms = */ 1,
252 /* sda_setup_time_ns = */ 50, /* */
253 /* sck_pulse_width_ns = */ 120, /* */
254 /* sck_clock_hz = */ 4000000UL, /* */
255 /* spi_mode = */ 0, /* active high, rising edge */
256 /* i2c_bus_clock_100kHz = */ 4,
257 /* data_setup_time_ns = */ 40, /* */
258 /* write_pulse_width_ns = */ 80, /* */
259 /* tile_width = */ 16, /* width of 16*8=128 pixel */
260 /* tile_height = */ 8,
261 /* default_x_offset = */ 4,
262 /* flipmode_x_offset = */ 0,
263 /* pixel_width = */ 128,
264 /* pixel_height = */ 64
265};
266
267static const uint8_t u8x8_st7567_jlx12864_init_seq[] = {
268
269 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
270
271 U8X8_C(0x0e2), /* soft reset */
272 U8X8_C(0x0ae), /* display off */
273 U8X8_C(0x040), /* set display start line to 0 */
274
275 U8X8_C(0x0a1), /* ADC set to reverse */
276 U8X8_C(0x0c0), /* common output mode */
277 // Flipmode
278 //U8X8_C(0x0a0), /* ADC set to reverse */
279 //U8X8_C(0x0c8), /* common output mode */
280
281 U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
282 U8X8_C(0x0a3), /* LCD bias 1/7 */
283 /* power on sequence from paxinstruments */
284 U8X8_C(0x028|4), /* all power control circuits on */
285 U8X8_DLY(50),
286 U8X8_C(0x028|6), /* all power control circuits on */
287 U8X8_DLY(50),
288 U8X8_C(0x028|7), /* all power control circuits on */
289 U8X8_DLY(50),
290
291 U8X8_C(0x023), /* v0 voltage resistor ratio */
292 U8X8_CA(0x081, 42>>2), /* set contrast, contrast value*/
293
294 U8X8_C(0x0ae), /* display off */
295 U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
296
297 U8X8_END_TRANSFER(), /* disable chip */
298 U8X8_END() /* end of sequence */
299};
300
301/* JLX12864 display */
302uint8_t u8x8_d_st7567_jlx12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
303{
304 uint8_t x, c;
305 uint8_t *ptr;
306 switch(msg)
307 {
308 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
309 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_jlx12864_display_info);
310 break;
311 case U8X8_MSG_DISPLAY_INIT:
312 u8x8_d_helper_display_init(u8x8);
313 u8x8_cad_SendSequence(u8x8, u8x8_st7567_jlx12864_init_seq);
314 break;
315 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
316 if ( arg_int == 0 )
317 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave0_seq);
318 else
319 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave1_seq);
320 break;
321 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
322 if ( arg_int == 0 )
323 {
324 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip0_seq);
325 u8x8->x_offset = u8x8->display_info->default_x_offset;
326 }
327 else
328 {
329 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip1_seq);
330 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
331 }
332 break;
333#ifdef U8X8_WITH_SET_CONTRAST
334 case U8X8_MSG_DISPLAY_SET_CONTRAST:
335 u8x8_cad_StartTransfer(u8x8);
336 u8x8_cad_SendCmd(u8x8, 0x081 );
337 u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7567 has range from 0 to 63 */
338 u8x8_cad_EndTransfer(u8x8);
339 break;
340#endif
341 case U8X8_MSG_DISPLAY_DRAW_TILE:
342 u8x8_cad_StartTransfer(u8x8);
343
344 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
345 x *= 8;
346 x += u8x8->x_offset;
347 u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
348 u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
349 u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
350
351 c = ((u8x8_tile_t *)arg_ptr)->cnt;
352 c *= 8;
353 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
354 /*
355 The following if condition checks the hardware limits of the st7567
356 controller: It is not allowed to write beyond the display limits.
357 This is in fact an issue within flip mode.
358 */
359 if ( c + x > 132u )
360 {
361 c = 132u;
362 c -= x;
363 }
364 do
365 {
366 u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
367 arg_int--;
368 } while( arg_int > 0 );
369
370 u8x8_cad_EndTransfer(u8x8);
371 break;
372 default:
373 return 0;
374 }
375 return 1;
376}
377
378
379/*=====================================================*/
380
381/* Sinda Display (sindadisplay.com), SDGG 2232-07 */
382/* Issue 1759, 122x32 display, https://github.com/olikraus/u8g2/files/7894362/SDGG12232-07.pdf */
383/* copied from jlx12864 */
384
385static const uint8_t u8x8_d_st7567_122x32_flip0_seq[] = {
386 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
387 U8X8_C(0x040+32), /* set display start line to 32 */
388 U8X8_C(0x0a1), /* segment remap a0/a1*/
389 U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
390 U8X8_END_TRANSFER(), /* disable chip */
391 U8X8_END() /* end of sequence */
392};
393
394static const uint8_t u8x8_d_st7567_122x32_flip1_seq[] = {
395 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
396 U8X8_C(0x040+0), /* set display start line to 0 */
397 U8X8_C(0x0a0), /* segment remap a0/a1*/
398 U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
399 U8X8_END_TRANSFER(), /* disable chip */
400 U8X8_END() /* end of sequence */
401};
402
403static const u8x8_display_info_t u8x8_st7567_122x32_display_info =
404{
405 /* chip_enable_level = */ 0,
406 /* chip_disable_level = */ 1,
407
408 /* post_chip_enable_wait_ns = */ 150, /* */
409 /* pre_chip_disable_wait_ns = */ 50, /* */
410 /* reset_pulse_width_ms = */ 1,
411 /* post_reset_wait_ms = */ 1,
412 /* sda_setup_time_ns = */ 50, /* */
413 /* sck_pulse_width_ns = */ 120, /* */
414 /* sck_clock_hz = */ 4000000UL, /* */
415 /* spi_mode = */ 0, /* active high, rising edge */
416 /* i2c_bus_clock_100kHz = */ 4,
417 /* data_setup_time_ns = */ 40, /* */
418 /* write_pulse_width_ns = */ 80, /* */
419 /* tile_width = */ 16, /* width of 16*8=128 pixel */
420 /* tile_height = */ 4,
421 /* default_x_offset = */ 4,
422 /* flipmode_x_offset = */ 0,
423 /* pixel_width = */ 122,
424 /* pixel_height = */ 32
425};
426
427static const uint8_t u8x8_st7567_122x32_init_seq[] = {
428
429 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
430
431 U8X8_C(0x0e2), /* soft reset */
432 U8X8_C(0x0ae), /* display off */
433 U8X8_C(0x040+32), /* set display start line to 32 */
434
435 U8X8_C(0x0a1), /* ADC set to reverse */
436 U8X8_C(0x0c0), /* common output mode */
437 // Flipmode
438 //U8X8_C(0x0a0), /* ADC set to reverse */
439 //U8X8_C(0x0c8), /* common output mode */
440
441 U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
442
443
444 /* I think datasheet of the 122x32 display suggest to use 0x0a2 instead of 0xa3 here */
445 U8X8_C(0x0a2), /* LCD bias 1/6 @1/33 duty */
446 /* power on sequence from paxinstruments */
447 U8X8_C(0x028|4), /* all power control circuits on */
448 U8X8_DLY(50),
449 U8X8_C(0x028|6), /* all power control circuits on */
450 U8X8_DLY(50),
451 U8X8_C(0x028|7), /* all power control circuits on */
452 U8X8_DLY(50),
453
454 U8X8_C(0x023), /* v0 voltage resistor ratio */
455 U8X8_CA(0x081, 42>>2), /* set contrast, contrast value*/
456
457 U8X8_C(0x0ae), /* display off */
458 U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
459
460 U8X8_END_TRANSFER(), /* disable chip */
461 U8X8_END() /* end of sequence */
462};
463
464/* 122x32 display, issue 1759 */
465uint8_t u8x8_d_st7567_122x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
466{
467 uint8_t x, c;
468 uint8_t *ptr;
469 switch(msg)
470 {
471 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
472 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_122x32_display_info);
473 break;
474 case U8X8_MSG_DISPLAY_INIT:
475 u8x8_d_helper_display_init(u8x8);
476 u8x8_cad_SendSequence(u8x8, u8x8_st7567_122x32_init_seq);
477 break;
478 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
479 if ( arg_int == 0 )
480 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave0_seq);
481 else
482 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave1_seq);
483 break;
484 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
485 if ( arg_int == 0 )
486 {
487 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_122x32_flip0_seq);
488 u8x8->x_offset = u8x8->display_info->default_x_offset;
489 }
490 else
491 {
492 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_122x32_flip1_seq);
493 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
494 }
495 break;
496#ifdef U8X8_WITH_SET_CONTRAST
497 case U8X8_MSG_DISPLAY_SET_CONTRAST:
498 u8x8_cad_StartTransfer(u8x8);
499 u8x8_cad_SendCmd(u8x8, 0x081 );
500 u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7567 has range from 0 to 63 */
501 u8x8_cad_EndTransfer(u8x8);
502 break;
503#endif
504 case U8X8_MSG_DISPLAY_DRAW_TILE:
505 u8x8_cad_StartTransfer(u8x8);
506
507 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
508 x *= 8;
509 x += u8x8->x_offset;
510 u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
511 u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
512 u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
513
514 c = ((u8x8_tile_t *)arg_ptr)->cnt;
515 c *= 8;
516 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
517 /*
518 The following if condition checks the hardware limits of the st7567
519 controller: It is not allowed to write beyond the display limits.
520 This is in fact an issue within flip mode.
521 */
522 if ( c + x > 132u )
523 {
524 c = 132u;
525 c -= x;
526 }
527 do
528 {
529 u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
530 arg_int--;
531 } while( arg_int > 0 );
532
533 u8x8_cad_EndTransfer(u8x8);
534 break;
535 default:
536 return 0;
537 }
538 return 1;
539}
540
541
542/*=====================================================*/
543
544
545
546static const u8x8_display_info_t u8x8_st7567_enh_dg128064_display_info =
547{
548 /* chip_enable_level = */ 0,
549 /* chip_disable_level = */ 1,
550
551 /* post_chip_enable_wait_ns = */ 150, /* */
552 /* pre_chip_disable_wait_ns = */ 50, /* */
553 /* reset_pulse_width_ms = */ 1,
554 /* post_reset_wait_ms = */ 1,
555 /* sda_setup_time_ns = */ 50, /* */
556 /* sck_pulse_width_ns = */ 120, /* */
557 /* sck_clock_hz = */ 4000000UL, /* */
558 /* spi_mode = */ 0, /* active high, rising edge */
559 /* i2c_bus_clock_100kHz = */ 4,
560 /* data_setup_time_ns = */ 40, /* */
561 /* write_pulse_width_ns = */ 80, /* */
562 /* tile_width = */ 16, /* width of 16*8=128 pixel */
563 /* tile_height = */ 8,
564 /* default_x_offset = */ 0,
565 /* flipmode_x_offset = */ 4,
566 /* pixel_width = */ 128,
567 /* pixel_height = */ 64
568};
569
570static const u8x8_display_info_t u8x8_st7567_enh_dg128064i_display_info =
571{
572 /* chip_enable_level = */ 0,
573 /* chip_disable_level = */ 1,
574
575 /* post_chip_enable_wait_ns = */ 150, /* */
576 /* pre_chip_disable_wait_ns = */ 50, /* */
577 /* reset_pulse_width_ms = */ 1,
578 /* post_reset_wait_ms = */ 1,
579 /* sda_setup_time_ns = */ 50, /* */
580 /* sck_pulse_width_ns = */ 120, /* */
581 /* sck_clock_hz = */ 4000000UL, /* */
582 /* spi_mode = */ 0, /* active high, rising edge */
583 /* i2c_bus_clock_100kHz = */ 4,
584 /* data_setup_time_ns = */ 40, /* */
585 /* write_pulse_width_ns = */ 80, /* */
586 /* tile_width = */ 16, /* width of 16*8=128 pixel */
587 /* tile_height = */ 8,
588 /* default_x_offset = */ 4,
589 /* flipmode_x_offset = */ 0,
590 /* pixel_width = */ 128,
591 /* pixel_height = */ 64
592};
593
594static const uint8_t u8x8_st7567_enh_dg128064_init_seq[] = {
595
596 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
597
598 U8X8_C(0x0e2), /* soft reset */
599 U8X8_C(0x0ae), /* display off */
600 U8X8_C(0x040), /* set display start line to 0 */
601
602 U8X8_C(0x0a1), /* ADC set to reverse */
603 U8X8_C(0x0c0), /* common output mode */
604 // Flipmode
605 //U8X8_C(0x0a0), /* ADC set to reverse */
606 //U8X8_C(0x0c8), /* common output mode */
607
608 U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
609 U8X8_C(0x0a2), /* LCD bias 1/9 */
610 /* power on sequence from paxinstruments */
611 U8X8_C(0x028|4), /* all power control circuits on */
612 U8X8_DLY(50),
613 U8X8_C(0x028|6), /* all power control circuits on */
614 U8X8_DLY(50),
615 U8X8_C(0x028|7), /* all power control circuits on */
616 U8X8_DLY(50),
617
618 U8X8_C(0x023), /* v0 voltage resistor ratio */
619 U8X8_CA(0x081, 200>>2), /* set contrast, contrast value*/
620
621 U8X8_C(0x0ae), /* display off */
622 U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
623
624 U8X8_END_TRANSFER(), /* disable chip */
625 U8X8_END() /* end of sequence */
626};
627
628/* ENH-DG128064 transparent display */
629static uint8_t u8x8_d_st7567_enh_dg128064_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
630{
631 uint8_t x, c;
632 uint8_t *ptr;
633 switch(msg)
634 {
635 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
636 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_enh_dg128064_display_info);
637 break;
638 case U8X8_MSG_DISPLAY_INIT:
639 u8x8_d_helper_display_init(u8x8);
640 u8x8_cad_SendSequence(u8x8, u8x8_st7567_enh_dg128064_init_seq);
641 break;
642 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
643 if ( arg_int == 0 )
644 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave0_seq);
645 else
646 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave1_seq);
647 break;
648#ifdef U8X8_WITH_SET_CONTRAST
649 case U8X8_MSG_DISPLAY_SET_CONTRAST:
650 u8x8_cad_StartTransfer(u8x8);
651 u8x8_cad_SendCmd(u8x8, 0x081 );
652 u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7567 has range from 0 to 63 */
653 u8x8_cad_EndTransfer(u8x8);
654 break;
655#endif
656 case U8X8_MSG_DISPLAY_DRAW_TILE:
657 u8x8_cad_StartTransfer(u8x8);
658
659 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
660 x *= 8;
661 x += u8x8->x_offset;
662 u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
663 u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
664 u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
665
666 c = ((u8x8_tile_t *)arg_ptr)->cnt;
667 c *= 8;
668 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
669 /*
670 The following if condition checks the hardware limits of the st7567
671 controller: It is not allowed to write beyond the display limits.
672 This is in fact an issue within flip mode.
673 */
674 if ( c + x > 132u )
675 {
676 c = 132u;
677 c -= x;
678 }
679 do
680 {
681 u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
682 arg_int--;
683 } while( arg_int > 0 );
684
685 u8x8_cad_EndTransfer(u8x8);
686 break;
687 default:
688 return 0;
689 }
690 return 1;
691}
692
693uint8_t u8x8_d_st7567_enh_dg128064(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
694{
695 switch(msg)
696 {
697 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
698 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_enh_dg128064_display_info);
699 break;
700 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
701 if ( arg_int == 0 )
702 {
703 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_n_flip0_seq);
704 u8x8->x_offset = u8x8->display_info->default_x_offset;
705 }
706 else
707 {
708 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_n_flip1_seq);
709 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
710 }
711 break;
712 default:
713 return u8x8_d_st7567_enh_dg128064_generic(u8x8, msg, arg_int, arg_ptr);
714 }
715 return 1;
716}
717
718uint8_t u8x8_d_st7567_enh_dg128064i(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
719{
720 switch(msg)
721 {
722 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
723 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_enh_dg128064i_display_info);
724 break;
725 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
726 if ( arg_int == 0 )
727 {
728 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip0_seq);
729 u8x8->x_offset = u8x8->display_info->default_x_offset;
730 }
731 else
732 {
733 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip1_seq);
734 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
735 }
736 break;
737 default:
738 return u8x8_d_st7567_enh_dg128064_generic(u8x8, msg, arg_int, arg_ptr);
739 }
740 return 1;
741}
742
743
744/*=====================================================*/
745/* issue 657 */
746
747static const u8x8_display_info_t u8x8_st7567_64x32_display_info =
748{
749 /* chip_enable_level = */ 0,
750 /* chip_disable_level = */ 1,
751
752 /* post_chip_enable_wait_ns = */ 150, /* */
753 /* pre_chip_disable_wait_ns = */ 50, /* */
754 /* reset_pulse_width_ms = */ 1,
755 /* post_reset_wait_ms = */ 1,
756 /* sda_setup_time_ns = */ 50, /* */
757 /* sck_pulse_width_ns = */ 120, /* */
758 /* sck_clock_hz = */ 4000000UL, /* */
759 /* spi_mode = */ 0, /* active high, rising edge */
760 /* i2c_bus_clock_100kHz = */ 4,
761 /* data_setup_time_ns = */ 40, /* */
762 /* write_pulse_width_ns = */ 80, /* */
763 /* tile_width = */ 8,
764 /* tile_height = */ 4,
765 /* default_x_offset = */ 32,
766 /* flipmode_x_offset = */ 32,
767 /* pixel_width = */ 64,
768 /* pixel_height = */ 32
769};
770
771static const uint8_t u8x8_st7567_64x32_init_seq[] = {
772
773 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
774
775 U8X8_C(0x0e2), /* soft reset */
776 U8X8_C(0x0ae), /* display off */
777 U8X8_C(0x040), /* set display start line to 0 */
778
779 U8X8_C(0x0a1), /* ADC */
780 U8X8_C(0x0c0), /* common output mode */
781 // Flipmode
782 //U8X8_C(0x0a0), /* ADC */
783 //U8X8_C(0x0c8), /* common output mode */
784
785 U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
786 U8X8_C(0x0a2), /* LCD bias 1/9 */
787 U8X8_C(0x028|4), /* all power control circuits on */
788 U8X8_DLY(50),
789 U8X8_C(0x028|6), /* all power control circuits on */
790 U8X8_DLY(50),
791 U8X8_C(0x028|7), /* all power control circuits on */
792 U8X8_DLY(50),
793
794 U8X8_C(0x024), /* v0 voltage resistor ratio, taken from issue 657 */
795 U8X8_CA(0x081, 0x020), /* set contrast, contrast value*/
796 /* 18 Apr 2020: the value 0x080 does not make sense, only 6 bit are supported
797 for contrast, changed to 0x040 */
798
799 U8X8_C(0x0ae), /* display off */
800 U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
801
802 U8X8_END_TRANSFER(), /* disable chip */
803 U8X8_END() /* end of sequence */
804};
805
806
807uint8_t u8x8_d_st7567_64x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
808{
809 uint8_t x, c;
810 uint8_t *ptr;
811 switch(msg)
812 {
813 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
814 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_64x32_display_info);
815 break;
816 case U8X8_MSG_DISPLAY_INIT:
817 u8x8_d_helper_display_init(u8x8);
818 u8x8_cad_SendSequence(u8x8, u8x8_st7567_64x32_init_seq);
819 break;
820 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
821 if ( arg_int == 0 )
822 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave0_seq);
823 else
824 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave1_seq);
825 break;
826 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
827 if ( arg_int == 0 )
828 {
829 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip0_seq);
830 u8x8->x_offset = u8x8->display_info->default_x_offset;
831 }
832 else
833 {
834 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip1_seq);
835 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
836 }
837 break;
838#ifdef U8X8_WITH_SET_CONTRAST
839 case U8X8_MSG_DISPLAY_SET_CONTRAST:
840 u8x8_cad_StartTransfer(u8x8);
841 u8x8_cad_SendCmd(u8x8, 0x081 );
842 u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7567 has range from 0 to 63 */
843 u8x8_cad_EndTransfer(u8x8);
844 break;
845#endif
846 case U8X8_MSG_DISPLAY_DRAW_TILE:
847 u8x8_cad_StartTransfer(u8x8);
848
849 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
850 x *= 8;
851 x += u8x8->x_offset;
852 u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
853 u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
854 u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
855
856 c = ((u8x8_tile_t *)arg_ptr)->cnt;
857 c *= 8;
858 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
859 /*
860 The following if condition checks the hardware limits of the st7567
861 controller: It is not allowed to write beyond the display limits.
862 This is in fact an issue within flip mode.
863 */
864 if ( c + x > 132u )
865 {
866 c = 132u;
867 c -= x;
868 }
869 do
870 {
871 u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
872 arg_int--;
873 } while( arg_int > 0 );
874
875 u8x8_cad_EndTransfer(u8x8);
876 break;
877 default:
878 return 0;
879 }
880 return 1;
881}
882
883/*=====================================================*/
884/* issue 1159, Lummax HEM6432-03 */
885
886
887static const u8x8_display_info_t u8x8_st7567_hem6432_display_info =
888{
889 /* chip_enable_level = */ 0,
890 /* chip_disable_level = */ 1,
891
892 /* post_chip_enable_wait_ns = */ 150, /* */
893 /* pre_chip_disable_wait_ns = */ 50, /* */
894 /* reset_pulse_width_ms = */ 1,
895 /* post_reset_wait_ms = */ 1,
896 /* sda_setup_time_ns = */ 50, /* */
897 /* sck_pulse_width_ns = */ 120, /* */
898 /* sck_clock_hz = */ 4000000UL, /* */
899 /* spi_mode = */ 0, /* active high, rising edge */
900 /* i2c_bus_clock_100kHz = */ 4,
901 /* data_setup_time_ns = */ 40, /* */
902 /* write_pulse_width_ns = */ 80, /* */
903 /* tile_width = */ 8,
904 /* tile_height = */ 4,
905 /* default_x_offset = */ 36, /* issue 1159 */
906 /* flipmode_x_offset = */ 32, /* issue 1159 */
907 /* pixel_width = */ 64,
908 /* pixel_height = */ 32
909};
910
911static const uint8_t u8x8_st7567_hem6432_init_seq[] = {
912
913 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
914
915 U8X8_C(0x0e2), /* soft reset */
916 U8X8_C(0x0ae), /* display off */
917 U8X8_C(0x040), /* set display start line to 0 */
918
919 U8X8_C(0x0a1), /* ADC */
920 U8X8_C(0x0c0), /* common output mode */
921 // Flipmode
922 //U8X8_C(0x0a0), /* ADC */
923 //U8X8_C(0x0c8), /* common output mode */
924
925 U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
926 U8X8_C(0x0a2), /* LCD bias 1/9 */
927 U8X8_C(0x028|4), /* all power control circuits on */
928 U8X8_DLY(50),
929 U8X8_C(0x028|6), /* all power control circuits on */
930 U8X8_DLY(50),
931 U8X8_C(0x028|7), /* all power control circuits on */
932 U8X8_DLY(50),
933
934 U8X8_C(0x024), /* v0 voltage resistor ratio, taken from issue 657 */
935 U8X8_CA(0x081, 225/4), /* set contrast, contrast value as suggested inissue 1159 */
936
937 U8X8_C(0x0ae), /* display off */
938 U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
939
940 U8X8_END_TRANSFER(), /* disable chip */
941 U8X8_END() /* end of sequence */
942};
943
944
945uint8_t u8x8_d_st7567_hem6432(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
946{
947 uint8_t x, c;
948 uint8_t *ptr;
949 switch(msg)
950 {
951 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
952 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_hem6432_display_info);
953 u8x8->i2c_address = 0x07e; /* issue 1159, use different i2c address */
954 break;
955 case U8X8_MSG_DISPLAY_INIT:
956 u8x8_d_helper_display_init(u8x8);
957 u8x8_cad_SendSequence(u8x8, u8x8_st7567_hem6432_init_seq);
958 break;
959 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
960 if ( arg_int == 0 )
961 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave0_seq);
962 else
963 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave1_seq);
964 break;
965 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
966 if ( arg_int == 0 )
967 {
968 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip0_seq);
969 u8x8->x_offset = u8x8->display_info->default_x_offset;
970 }
971 else
972 {
973 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip1_seq);
974 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
975 }
976 break;
977#ifdef U8X8_WITH_SET_CONTRAST
978 case U8X8_MSG_DISPLAY_SET_CONTRAST:
979 u8x8_cad_StartTransfer(u8x8);
980 u8x8_cad_SendCmd(u8x8, 0x081 );
981 u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7567 has range from 0 to 63 */
982 u8x8_cad_EndTransfer(u8x8);
983 break;
984#endif
985 case U8X8_MSG_DISPLAY_DRAW_TILE:
986 u8x8_cad_StartTransfer(u8x8);
987
988 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
989 x *= 8;
990 x += u8x8->x_offset;
991 u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
992 u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
993 u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
994
995 c = ((u8x8_tile_t *)arg_ptr)->cnt;
996 c *= 8;
997 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
998 /*
999 The following if condition checks the hardware limits of the st7567
1000 controller: It is not allowed to write beyond the display limits.
1001 This is in fact an issue within flip mode.
1002 */
1003 if ( c + x > 132u )
1004 {
1005 c = 132u;
1006 c -= x;
1007 }
1008 do
1009 {
1010 u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
1011 arg_int--;
1012 } while( arg_int > 0 );
1013
1014 u8x8_cad_EndTransfer(u8x8);
1015 break;
1016 default:
1017 return 0;
1018 }
1019 return 1;
1020}
1021
1022
1023/*=====================================================*/
1024/*
1025 https://github.com/olikraus/u8g2/issues/1088
1026 https://www.dx.com/p/opensmart-33v-26-inch-128x64-serial-spi-monochrome-lcd-breakout-board-module-with-backlight-for-arduino-nano-pro-mini-2710499.html
1027*/
1028
1029
1030
1031static const u8x8_display_info_t u8x8_st7567_os12864_display_info =
1032{
1033 /* chip_enable_level = */ 0,
1034 /* chip_disable_level = */ 1,
1035
1036 /* post_chip_enable_wait_ns = */ 150, /* */
1037 /* pre_chip_disable_wait_ns = */ 50, /* */
1038 /* reset_pulse_width_ms = */ 1,
1039 /* post_reset_wait_ms = */ 1,
1040 /* sda_setup_time_ns = */ 50, /* */
1041 /* sck_pulse_width_ns = */ 120, /* */
1042 /* sck_clock_hz = */ 4000000UL, /* */
1043 /* spi_mode = */ 0, /* active high, rising edge */
1044 /* i2c_bus_clock_100kHz = */ 4,
1045 /* data_setup_time_ns = */ 40, /* */
1046 /* write_pulse_width_ns = */ 80, /* */
1047 /* tile_width = */ 16, /* width of 16*8=128 pixel */
1048 /* tile_height = */ 8,
1049 /* default_x_offset = */ 4,
1050 /* flipmode_x_offset = */ 0,
1051 /* pixel_width = */ 128,
1052 /* pixel_height = */ 64
1053};
1054
1055static const uint8_t u8x8_st7567_os12864_init_seq[] = {
1056
1057 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
1058
1059 U8X8_C(0x0e2), /* soft reset */
1060 U8X8_C(0x0ae), /* display off */
1061 U8X8_C(0x040), /* set display start line to 0 */
1062
1063 U8X8_C(0x0a1), /* ADC set to reverse */
1064 U8X8_C(0x0c0), /* common output mode */
1065 // Flipmode
1066 //U8X8_C(0x0a0), /* ADC set to reverse */
1067 //U8X8_C(0x0c8), /* common output mode */
1068
1069 U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
1070 U8X8_C(0x0a3), /* LCD bias 1/7 */
1071 /* power on sequence from paxinstruments */
1072 U8X8_C(0x028|4), /* all power control circuits on */
1073 U8X8_DLY(50),
1074 U8X8_C(0x028|6), /* all power control circuits on */
1075 U8X8_DLY(50),
1076 U8X8_C(0x028|7), /* all power control circuits on */
1077 U8X8_DLY(50),
1078
1079 U8X8_C(0x026), /* v0 voltage resistor ratio */
1080 U8X8_CA(0x081, 50>>2), /* set contrast, contrast value*/
1081
1082 U8X8_C(0x0ae), /* display off */
1083 U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
1084
1085 U8X8_END_TRANSFER(), /* disable chip */
1086 U8X8_END() /* end of sequence */
1087};
1088
1089/* open-smart 12864 display */
1090uint8_t u8x8_d_st7567_os12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
1091{
1092 uint8_t x, c;
1093 uint8_t *ptr;
1094 switch(msg)
1095 {
1096 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
1097 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_os12864_display_info);
1098 break;
1099 case U8X8_MSG_DISPLAY_INIT:
1100 u8x8_d_helper_display_init(u8x8);
1101 u8x8_cad_SendSequence(u8x8, u8x8_st7567_os12864_init_seq);
1102 break;
1103 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
1104 if ( arg_int == 0 )
1105 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave0_seq);
1106 else
1107 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave1_seq);
1108 break;
1109 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
1110 if ( arg_int == 0 )
1111 {
1112 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip0_seq);
1113 u8x8->x_offset = u8x8->display_info->default_x_offset;
1114 }
1115 else
1116 {
1117 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip1_seq);
1118 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
1119 }
1120 break;
1121#ifdef U8X8_WITH_SET_CONTRAST
1122 case U8X8_MSG_DISPLAY_SET_CONTRAST:
1123 u8x8_cad_StartTransfer(u8x8);
1124 u8x8_cad_SendCmd(u8x8, 0x081 );
1125 u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7567 has range from 0 to 63 */
1126 u8x8_cad_EndTransfer(u8x8);
1127 break;
1128#endif
1129 case U8X8_MSG_DISPLAY_DRAW_TILE:
1130 u8x8_cad_StartTransfer(u8x8);
1131
1132 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
1133 x *= 8;
1134 x += u8x8->x_offset;
1135 u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
1136 u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
1137 u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
1138
1139 c = ((u8x8_tile_t *)arg_ptr)->cnt;
1140 c *= 8;
1141 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
1142 /*
1143 The following if condition checks the hardware limits of the st7567
1144 controller: It is not allowed to write beyond the display limits.
1145 This is in fact an issue within flip mode.
1146 */
1147 if ( c + x > 132u )
1148 {
1149 c = 132u;
1150 c -= x;
1151 }
1152 do
1153 {
1154 u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
1155 arg_int--;
1156 } while( arg_int > 0 );
1157
1158 u8x8_cad_EndTransfer(u8x8);
1159 break;
1160 default:
1161 return 0;
1162 }
1163 return 1;
1164}
1165
1166
1167/*=====================================================*/
1168/*
1169
1170 https://github.com/olikraus/u8g2/discussions/1868
1171 https://github.com/olikraus/u8g2/issues/1869
1172 https://www.buydisplay.com/cog-serial-spi-132x32-graphic-lcd-display-no-backlight-st7567a
1173
1174 ERC13232
1175
1176 copied from U8G2_ST7567_PI_132X64
1177
1178*/
1179
1180static const u8x8_display_info_t u8x8_st7567_132x32_display_info =
1181{
1182 /* chip_enable_level = */ 0,
1183 /* chip_disable_level = */ 1,
1184
1185 /* post_chip_enable_wait_ns = */ 150, /* */
1186 /* pre_chip_disable_wait_ns = */ 50, /* */
1187 /* reset_pulse_width_ms = */ 1,
1188 /* post_reset_wait_ms = */ 1,
1189 /* sda_setup_time_ns = */ 50, /* */
1190 /* sck_pulse_width_ns = */ 120, /* */
1191 /* sck_clock_hz = */ 4000000UL, /* */
1192 /* spi_mode = */ 0, /* active high, rising edge */
1193 /* i2c_bus_clock_100kHz = */ 4,
1194 /* data_setup_time_ns = */ 40, /* */
1195 /* write_pulse_width_ns = */ 80, /* */
1196 /* tile_width = */ 17, /* width of 17*8=136 pixel */
1197 /* tile_height = */ 4,
1198 /* default_x_offset = */ 0,
1199 /* flipmode_x_offset = */ 0,
1200 /* pixel_width = */ 132,
1201 /* pixel_height = */ 32
1202};
1203
1204static const uint8_t u8x8_d_st7567_erc13232_init_seq[] = {
1205
1206 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
1207
1208 U8X8_C(0x0e2), /* soft reset */
1209 U8X8_C(0x0ae), /* display off */
1210 U8X8_C(0x040), /* set display start line to 0 */
1211
1212 U8X8_C(0x0a1), /* ADC set to reverse */
1213 U8X8_C(0x0c0), /* common output mode */
1214 // Flipmode
1215 //U8X8_C(0x0a0), /* ADC set to reverse */
1216 //U8X8_C(0x0c8), /* common output mode */
1217
1218 U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
1219 U8X8_C(0x0a3), /* LCD bias 1/7 */
1220 /* power on sequence from paxinstruments */
1221 U8X8_C(0x028|4), /* all power control circuits on */
1222 U8X8_DLY(50),
1223 U8X8_C(0x028|6), /* all power control circuits on */
1224 U8X8_DLY(50),
1225 U8X8_C(0x028|7), /* all power control circuits on */
1226 U8X8_DLY(50),
1227
1228 U8X8_C(0x026), /* v0 voltage resistor ratio */
1229 U8X8_CA(0x081, 0x027), /* set contrast, contrast value*/
1230
1231 U8X8_C(0x0ae), /* display off */
1232 U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
1233
1234 U8X8_END_TRANSFER(), /* disable chip */
1235 U8X8_END() /* end of sequence */
1236};
1237
1238/* ERC13232 */
1239uint8_t u8x8_d_st7567_erc13232(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
1240{
1241 uint8_t x, c;
1242 uint8_t *ptr;
1243 switch(msg)
1244 {
1245 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
1246 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_132x32_display_info);
1247 break;
1248 case U8X8_MSG_DISPLAY_INIT:
1249 u8x8_d_helper_display_init(u8x8);
1250 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_erc13232_init_seq);
1251 break;
1252 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
1253 if ( arg_int == 0 )
1254 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave0_seq);
1255 else
1256 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave1_seq);
1257 break;
1258 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
1259 if ( arg_int == 0 )
1260 {
1261 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip0_seq);
1262 u8x8->x_offset = u8x8->display_info->default_x_offset;
1263 }
1264 else
1265 {
1266 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip1_seq);
1267 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
1268 }
1269 break;
1270#ifdef U8X8_WITH_SET_CONTRAST
1271 case U8X8_MSG_DISPLAY_SET_CONTRAST:
1272 u8x8_cad_StartTransfer(u8x8);
1273 u8x8_cad_SendCmd(u8x8, 0x081 );
1274 u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7567 has range from 0 to 63 */
1275 u8x8_cad_EndTransfer(u8x8);
1276 break;
1277#endif
1278 case U8X8_MSG_DISPLAY_DRAW_TILE:
1279 u8x8_cad_StartTransfer(u8x8);
1280
1281 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
1282 x *= 8;
1283 x += u8x8->x_offset;
1284 u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
1285 u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
1286 u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
1287
1288 c = ((u8x8_tile_t *)arg_ptr)->cnt;
1289 c *= 8;
1290 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
1291 /*
1292 The following if condition checks the hardware limits of the st7567
1293 controller: It is not allowed to write beyond the display limits.
1294 This is in fact an issue within flip mode.
1295 */
1296 if ( c + x > 132u )
1297 {
1298 c = 132u;
1299 c -= x;
1300 }
1301 do
1302 {
1303 u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
1304 arg_int--;
1305 } while( arg_int > 0 );
1306
1307 u8x8_cad_EndTransfer(u8x8);
1308 break;
1309 default:
1310 return 0;
1311 }
1312 return 1;
1313}
1314
1315
1316/*=====================================================*/
1317/*
1318
1319 https://www.buydisplay.com/2-inch-low-cost-white-128x64-graphic-cog-lcd-display-st7567-spi
1320
1321 ERC12864FSF-20
1322
1323 copied from u8x8_st7567_132x32
1324*/
1325
1326static const u8x8_display_info_t u8x8_st7567_128x64_display_info =
1327{
1328 /* chip_enable_level = */ 0,
1329 /* chip_disable_level = */ 1,
1330
1331 /* post_chip_enable_wait_ns = */ 150,
1332 /* pre_chip_disable_wait_ns = */ 50,
1333 /* reset_pulse_width_ms = */ 1,
1334 /* post_reset_wait_ms = */ 1,
1335 /* sda_setup_time_ns = */ 50,
1336 /* sck_pulse_width_ns = */ 120,
1337 /* sck_clock_hz = */ 4000000UL,
1338 /* spi_mode = */ 0, /* active high, rising edge */
1339 /* i2c_bus_clock_100kHz = */ 4,
1340 /* data_setup_time_ns = */ 40,
1341 /* write_pulse_width_ns = */ 80,
1342 /* tile_width = */ 16, /* width of 16*8=128 pixels */
1343 /* tile_height = */ 8, /* height of 8*8= 64 pixels */
1344 /* default_x_offset = */ 4,
1345 /* flipmode_x_offset = */ 0,
1346 /* pixel_width = */ 128,
1347 /* pixel_height = */ 64
1348};
1349
1350static const uint8_t u8x8_d_st7567_erc12864_init_seq[] = {
1351
1352 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
1353
1354 U8X8_C(0x0e2), /* soft reset */
1355 U8X8_C(0x0ae), /* display off */
1356 U8X8_C(0x040), /* set display start line to 0 */
1357
1358 U8X8_C(0x0a1), /* ADC set to reverse */
1359 U8X8_C(0x0c0), /* common output mode */
1360
1361 U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
1362 U8X8_C(0x0a3), /* LCD bias 1/7 */
1363 /* power on sequence from paxinstruments */
1364 U8X8_C(0x028|4), /* all power control circuits on */
1365 U8X8_DLY(50),
1366 U8X8_C(0x028|6), /* all power control circuits on */
1367 U8X8_DLY(50),
1368 U8X8_C(0x028|7), /* all power control circuits on */
1369 U8X8_DLY(50),
1370
1371 U8X8_C(0x026), /* v0 voltage resistor ratio */
1372 U8X8_CA(0x081, 0x027), /* set contrast, contrast value*/
1373
1374 U8X8_C(0x0ae), /* display off */
1375 U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
1376
1377 U8X8_END_TRANSFER(), /* disable chip */
1378 U8X8_END() /* end of sequence */
1379};
1380
1381/* ERC12864 */
1382uint8_t u8x8_d_st7567_erc12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
1383{
1384 uint8_t x, c;
1385 uint8_t *ptr;
1386 switch(msg)
1387 {
1388 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
1389 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_128x64_display_info);
1390 break;
1391 case U8X8_MSG_DISPLAY_INIT:
1392 u8x8_d_helper_display_init(u8x8);
1393 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_erc12864_init_seq);
1394 break;
1395 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
1396 if ( arg_int == 0 )
1397 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_128x64_powersave0_seq);
1398 else
1399 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_128x64_powersave1_seq);
1400 break;
1401 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
1402 if ( arg_int == 0 )
1403 {
1404 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_128x64_flip0_seq);
1405 u8x8->x_offset = u8x8->display_info->default_x_offset;
1406 }
1407 else
1408 {
1409 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_128x64_flip1_seq);
1410 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
1411 }
1412 break;
1413#ifdef U8X8_WITH_SET_CONTRAST
1414 case U8X8_MSG_DISPLAY_SET_CONTRAST:
1415 u8x8_cad_StartTransfer(u8x8);
1416 u8x8_cad_SendCmd(u8x8, 0x081 );
1417 u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7567 has range from 0 to 63 */
1418 u8x8_cad_EndTransfer(u8x8);
1419 break;
1420#endif
1421 case U8X8_MSG_DISPLAY_DRAW_TILE:
1422 u8x8_cad_StartTransfer(u8x8);
1423
1424 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
1425 x *= 8;
1426 x += u8x8->x_offset;
1427 u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
1428 u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
1429 u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
1430
1431 c = ((u8x8_tile_t *)arg_ptr)->cnt;
1432 c *= 8;
1433 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
1434 /*
1435 The following if condition checks the hardware limits of the st7567
1436 controller: It is not allowed to write beyond the display limits.
1437 This is in fact an issue within flip mode.
1438 */
1439 if ( c + x > 132u )
1440 {
1441 c = 132u;
1442 c -= x;
1443 }
1444 do
1445 {
1446 u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
1447 arg_int--;
1448 } while( arg_int > 0 );
1449
1450 u8x8_cad_EndTransfer(u8x8);
1451 break;
1452 default:
1453 return 0;
1454 }
1455 return 1;
1456}
1457
1458
1459/*=====================================================*/
1460
1461/* LW12864 display, 128x32 (actually 142x36, but with border of weird behavior) */
1462/* copied from jlx12864 */
1463
1464static const u8x8_display_info_t u8x8_st7567_lw12832_display_info =
1465{
1466 /* chip_enable_level = */ 0,
1467 /* chip_disable_level = */ 1,
1468
1469 /* post_chip_enable_wait_ns = */ 150, /* */
1470 /* pre_chip_disable_wait_ns = */ 50, /* */
1471 /* reset_pulse_width_ms = */ 1,
1472 /* post_reset_wait_ms = */ 1,
1473 /* sda_setup_time_ns = */ 50, /* */
1474 /* sck_pulse_width_ns = */ 120, /* */
1475 /* sck_clock_hz = */ 4000000UL, /* */
1476 /* spi_mode = */ 0, /* active high, rising edge */
1477 /* i2c_bus_clock_100kHz = */ 4,
1478 /* data_setup_time_ns = */ 40, /* */
1479 /* write_pulse_width_ns = */ 80, /* */
1480 /* tile_width = */ 17, /* rounded up to 17 tiles */
1481 /* tile_height = */ 9, /* also rounded */
1482 /* default_x_offset = */ 4,
1483 /* flipmode_x_offset = */ 0,
1484 /* pixel_width = */ 128,
1485 /* pixel_height = */ 32
1486};
1487
1488static const uint8_t u8x8_st7567_lw12832_init_seq[] = {
1489
1490 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
1491
1492 U8X8_C(0x0e2), /* soft reset */
1493 U8X8_C(0x0ae), /* display off */
1494 U8X8_C(0x040), /* set display start line to 0 */
1495
1496 U8X8_C(0x0a1), /* ADC set to reverse */
1497 U8X8_C(0x0c0), /* common output mode */
1498 // Flipmode
1499 //U8X8_C(0x0a0), /* ADC set to reverse */
1500 //U8X8_C(0x0c8), /* common output mode */
1501
1502 U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
1503 U8X8_C(0x0a3), /* LCD bias 1/7 */
1504 /* power on sequence from paxinstruments */
1505 U8X8_C(0x028|4), /* all power control circuits on */
1506 U8X8_DLY(50),
1507 U8X8_C(0x028|6), /* all power control circuits on */
1508 U8X8_DLY(50),
1509 U8X8_C(0x028|7), /* all power control circuits on */
1510 U8X8_DLY(50),
1511
1512 U8X8_C(0x023), /* v0 voltage resistor ratio */
1513 U8X8_CA(0x081, 42>>2), /* set contrast, contrast value*/
1514
1515 U8X8_C(0x0ae), /* display off */
1516 U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
1517
1518 U8X8_END_TRANSFER(), /* disable chip */
1519 U8X8_END() /* end of sequence */
1520};
1521
1522static void st7567_lw12832_clear_ddram(u8x8_t *u8x8)
1523{
1524 // A combination of
1525 // - void u8x8_ClearDisplayWithTile(u8x8_t *u8x8, const uint8_t *buf)
1526 // and
1527 // - uint8_t u8x8_d_st7567_jlx12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
1528
1529 uint8_t buf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
1530 uint8_t h = u8x8->display_info->tile_height;
1531
1532 u8x8_tile_t tile;
1533 tile.x_pos = 0;
1534 tile.y_pos = 0;
1535 tile.cnt = 1;
1536 tile.tile_ptr = buf;
1537
1538 do
1539 {
1540 // Args
1541 uint8_t arg_int = u8x8->display_info->tile_width;
1542 void *arg_ptr = (void *)&tile;
1543
1544 // ---------------- START OF u8x8_d_st7567_jlx12864 case U8X8_MSG_DISPLAY_DRAW_TILE ----------------
1545 uint8_t x, c;
1546 uint8_t *ptr;
1547
1548 u8x8_cad_StartTransfer(u8x8);
1549
1550 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
1551 x *= 8;
1552 /* x += u8x8->x_offset; */ // Note that this is removed intentionally
1553 u8x8_cad_SendCmd(u8x8, 0x010 | (x >> 4)); // Set Column Address (MSB)
1554 u8x8_cad_SendCmd(u8x8, 0x000 | ((x & 15))); // Set Column Address (LSB)
1555 u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos)); // Set Page Address
1556
1557 c = ((u8x8_tile_t *)arg_ptr)->cnt;
1558 c *= 8;
1559 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
1560 /*
1561 The following if condition checks the hardware limits of the st7567
1562 controller: It is not allowed to write beyond the display limits.
1563 This is in fact an issue within flip mode.
1564 */
1565 if (c + x > 132u)
1566 {
1567 c = 132u;
1568 c -= x;
1569 }
1570 do
1571 {
1572 u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
1573 arg_int--;
1574 } while (arg_int > 0);
1575
1576 u8x8_cad_EndTransfer(u8x8);
1577 // ---------------- END OF u8x8_d_st7567_jlx12864 case U8X8_MSG_DISPLAY_DRAW_TILE ----------------
1578
1579 tile.y_pos++;
1580 } while (tile.y_pos < h);
1581}
1582
1583/* LW12832 display */
1584uint8_t u8x8_d_st7567_lw12832(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
1585{
1586 uint8_t x, c;
1587 uint8_t *ptr;
1588 switch(msg)
1589 {
1590 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
1591 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_lw12832_display_info);
1592 break;
1593 case U8X8_MSG_DISPLAY_INIT:
1594 u8x8_d_helper_display_init(u8x8);
1595 u8x8_cad_SendSequence(u8x8, u8x8_st7567_lw12832_init_seq);
1596 st7567_lw12832_clear_ddram(u8x8);
1597 break;
1598 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
1599 if ( arg_int == 0 )
1600 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave0_seq);
1601 else
1602 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave1_seq);
1603 break;
1604 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
1605 if ( arg_int == 0 )
1606 {
1607 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip0_seq);
1608 u8x8->x_offset = u8x8->display_info->default_x_offset;
1609 }
1610 else
1611 {
1612 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip1_seq);
1613 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
1614 }
1615 break;
1616#ifdef U8X8_WITH_SET_CONTRAST
1617 case U8X8_MSG_DISPLAY_SET_CONTRAST:
1618 u8x8_cad_StartTransfer(u8x8);
1619 u8x8_cad_SendCmd(u8x8, 0x081 );
1620 u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7567 has range from 0 to 63 */
1621 u8x8_cad_EndTransfer(u8x8);
1622 break;
1623#endif
1624 case U8X8_MSG_DISPLAY_DRAW_TILE:
1625 u8x8_cad_StartTransfer(u8x8);
1626
1627 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
1628 x *= 8;
1629 x += u8x8->x_offset;
1630 u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
1631 u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
1632 u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
1633
1634 c = ((u8x8_tile_t *)arg_ptr)->cnt;
1635 c *= 8;
1636 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
1637 /*
1638 The following if condition checks the hardware limits of the st7567
1639 controller: It is not allowed to write beyond the display limits.
1640 This is in fact an issue within flip mode.
1641 */
1642 if ( c + x > 132u )
1643 {
1644 c = 132u;
1645 c -= x;
1646 }
1647 do
1648 {
1649 u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
1650 arg_int--;
1651 } while( arg_int > 0 );
1652
1653 u8x8_cad_EndTransfer(u8x8);
1654 break;
1655 default:
1656 return 0;
1657 }
1658 return 1;
1659}
1660
1661/* https://github.com/olikraus/u8g2/issues/2344 */
1662uint8_t u8x8_d_st7567_yxd12832(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
1663{
1664 return u8x8_d_st7567_lw12832(u8x8, msg, arg_int, arg_ptr);
1665}
1666
1667
1668
1669/*=====================================================*/
1670/*
1671 96x65
1672 https://github.com/olikraus/u8g2/issues/2332
1673*/
1674
1675static const u8x8_display_info_t u8x8_st7567_96x65_display_info =
1676{
1677 /* chip_enable_level = */ 0,
1678 /* chip_disable_level = */ 1,
1679
1680 /* post_chip_enable_wait_ns = */ 150, /* */
1681 /* pre_chip_disable_wait_ns = */ 50, /* */
1682 /* reset_pulse_width_ms = */ 1,
1683 /* post_reset_wait_ms = */ 1,
1684 /* sda_setup_time_ns = */ 50, /* */
1685 /* sck_pulse_width_ns = */ 120, /* */
1686 /* sck_clock_hz = */ 4000000UL, /* */
1687 /* spi_mode = */ 0, /* active high, rising edge */
1688 /* i2c_bus_clock_100kHz = */ 4,
1689 /* data_setup_time_ns = */ 40, /* */
1690 /* write_pulse_width_ns = */ 80, /* */
1691 /* tile_width = */ 12, /* width of 12*8=96 pixel */
1692 /* tile_height = */ 9,
1693 /* default_x_offset = */ 0,
1694 /* flipmode_x_offset = */ 0,
1695 /* pixel_width = */ 96,
1696 /* pixel_height = */ 65
1697};
1698
1699static const uint8_t u8x8_st7567_96x65_init_seq[] = {
1700
1701 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
1702
1703 U8X8_C(0x0e2), /* soft reset */
1704 U8X8_C(0x0ae), /* display off */
1705 U8X8_C(0x040), /* set display start line to 0 */
1706
1707 U8X8_C(0x0a1), /* ADC set to reverse */
1708 U8X8_C(0x0c0), /* common output mode */
1709 // Flipmode
1710 //U8X8_C(0x0a0), /* ADC set to reverse */
1711 //U8X8_C(0x0c8), /* common output mode */
1712
1713 U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
1714 U8X8_C(0x0a3), /* LCD bias 1/7 */
1715 /* power on sequence from paxinstruments */
1716 U8X8_C(0x028|4), /* all power control circuits on */
1717 U8X8_DLY(50),
1718 U8X8_C(0x028|6), /* all power control circuits on */
1719 U8X8_DLY(50),
1720 U8X8_C(0x028|7), /* all power control circuits on */
1721 U8X8_DLY(50),
1722
1723 U8X8_C(0x023), /* v0 voltage resistor ratio */
1724 U8X8_CA(0x081, 42>>2), /* set contrast, contrast value*/
1725
1726 U8X8_C(0x0ae), /* display off */
1727 U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
1728
1729 U8X8_END_TRANSFER(), /* disable chip */
1730 U8X8_END() /* end of sequence */
1731};
1732
1733uint8_t u8x8_d_st7567_96x65(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
1734{
1735 uint8_t x, c;
1736 uint8_t *ptr;
1737 switch(msg)
1738 {
1739 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
1740 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_96x65_display_info);
1741 break;
1742 case U8X8_MSG_DISPLAY_INIT:
1743 u8x8_d_helper_display_init(u8x8);
1744 u8x8_cad_SendSequence(u8x8, u8x8_st7567_96x65_init_seq);
1745 break;
1746 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
1747 if ( arg_int == 0 )
1748 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave0_seq);
1749 else
1750 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave1_seq);
1751 break;
1752 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
1753 if ( arg_int == 0 )
1754 {
1755 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip0_seq);
1756 u8x8->x_offset = u8x8->display_info->default_x_offset;
1757 }
1758 else
1759 {
1760 u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip1_seq);
1761 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
1762 }
1763 break;
1764#ifdef U8X8_WITH_SET_CONTRAST
1765 case U8X8_MSG_DISPLAY_SET_CONTRAST:
1766 u8x8_cad_StartTransfer(u8x8);
1767 u8x8_cad_SendCmd(u8x8, 0x081 );
1768 u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7567 has range from 0 to 63 */
1769 u8x8_cad_EndTransfer(u8x8);
1770 break;
1771#endif
1772 case U8X8_MSG_DISPLAY_DRAW_TILE:
1773 u8x8_cad_StartTransfer(u8x8);
1774
1775 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
1776 x *= 8;
1777 x += u8x8->x_offset;
1778 u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
1779 u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
1780 u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
1781
1782 c = ((u8x8_tile_t *)arg_ptr)->cnt;
1783 c *= 8;
1784 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
1785 /*
1786 The following if condition checks the hardware limits of the st7567
1787 controller: It is not allowed to write beyond the display limits.
1788 This is in fact an issue within flip mode.
1789 */
1790 if ( c + x > 132u )
1791 {
1792 c = 132u;
1793 c -= x;
1794 }
1795 do
1796 {
1797 u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
1798 arg_int--;
1799 } while( arg_int > 0 );
1800
1801 u8x8_cad_EndTransfer(u8x8);
1802 break;
1803 default:
1804 return 0;
1805 }
1806 return 1;
1807}
1808
1809