Krolyxon
Commit 1d55752

Branches

Tags

Refs →

orion-rf.piolibdepsesp32-s3-n16r8U8g2srcclibu8x8_d_uc1611.c

767 lines · 26.4 KB · C

1/*
2
3 u8x8_d_uc1611.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 6 Nov 2016: Not yet finished
36
37 There are two controller:
38 UC1611s 160x256
39 UC1611 160x240
40
41 Differences:
42 UC1611 0xa8 cmd: enables 80 display rows
43 UC1611s 0xa8 cmd: controlls graylevels
44
45 UC1611 0xc0 cmd: single byte command for LCD mapping control
46 UC1611s 0xc0 cmd: double byte command for LCD mapping control
47
48
49*/
50#include "u8x8.h"
51
52
53
54
55
56static const uint8_t u8x8_d_uc1611s_powersave0_seq[] = {
57 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
58 U8X8_C(0x0a9), /* display on, UC1611s */
59 U8X8_END_TRANSFER(), /* disable chip */
60 U8X8_END() /* end of sequence */
61};
62
63static const uint8_t u8x8_d_uc1611s_powersave1_seq[] = {
64 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
65 U8X8_C(0x0a8), /* display off, enter sleep mode, UC1611s */
66 U8X8_END_TRANSFER(), /* disable chip */
67 U8X8_END() /* end of sequence */
68};
69
70static const uint8_t u8x8_d_uc1611s_flip0_seq[] = {
71 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
72 U8X8_CA(0x0c0, 0x004), /* LCD Mapping */
73 U8X8_END_TRANSFER(), /* disable chip */
74 U8X8_END() /* end of sequence */
75};
76
77static const uint8_t u8x8_d_uc1611s_flip1_seq[] = {
78 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
79 U8X8_CA(0x0c0, 0x002), /* LCD Mapping */
80 U8X8_END_TRANSFER(), /* disable chip */
81 U8X8_END() /* end of sequence */
82};
83
84uint8_t u8x8_d_uc1611_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
85{
86 uint8_t x, y, c;
87 uint8_t *ptr;
88 switch(msg)
89 {
90 case U8X8_MSG_DISPLAY_DRAW_TILE:
91 u8x8_cad_StartTransfer(u8x8);
92
93 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
94 x *= 8;
95 x += u8x8->x_offset;
96
97 u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
98 u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
99
100 y = ((u8x8_tile_t *)arg_ptr)->y_pos;
101 u8x8_cad_SendCmd(u8x8, 0x060 | (y&15));
102 u8x8_cad_SendCmd(u8x8, 0x070 | (y>>4));
103
104 c = ((u8x8_tile_t *)arg_ptr)->cnt;
105 c *= 8;
106 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
107 do
108 {
109 u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
110 arg_int--;
111 } while( arg_int > 0 );
112
113 u8x8_cad_EndTransfer(u8x8);
114 break;
115 /* handled in the calling procedure
116 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
117 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1611_128x64_display_info);
118 break;
119 case U8X8_MSG_DISPLAY_INIT:
120 u8x8_d_helper_display_init(u8x8);
121 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_dogs102_init_seq);
122 break;
123 */
124#ifdef U8X8_WITH_SET_CONTRAST
125 case U8X8_MSG_DISPLAY_SET_CONTRAST:
126 u8x8_cad_StartTransfer(u8x8);
127 u8x8_cad_SendCmd(u8x8, 0x081 );
128 u8x8_cad_SendArg(u8x8, arg_int ); /* uc1611 has range from 0 to 255 */
129 u8x8_cad_EndTransfer(u8x8);
130 break;
131#endif
132 default:
133 return 0;
134 }
135 return 1;
136}
137
138/*================================================*/
139/* EA DOGM240 */
140
141
142/*
143 UC1611 has two chip select inputs (CS0 and CS1).
144 CS0 is low active, CS1 is high active. It will depend on the display
145 module whether the display has a is low or high active chip select.
146*/
147
148static const u8x8_display_info_t u8x8_uc1611_240x64_display_info =
149{
150 /* chip_enable_level = */ 0,
151 /* chip_disable_level = */ 1,
152
153 /* post_chip_enable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
154 /* pre_chip_disable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
155 /* reset_pulse_width_ms = */ 1,
156 /* post_reset_wait_ms = */ 10, /* uc1611 datasheet, page 67 */
157 /* sda_setup_time_ns = */ 10, /* uc1611 datasheet, page 64, actually 0 */
158 /* sck_pulse_width_ns = */ 60, /* half of cycle time */
159 /* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
160 /* spi_mode = */ 0, /* active high, rising edge */
161 /* i2c_bus_clock_100kHz = */ 4,
162 /* data_setup_time_ns = */ 30, /* uc1611 datasheet, page 60 */
163 /* write_pulse_width_ns = */ 80, /* uc1611 datasheet, page 60 */
164 /* tile_width = */ 30, /* width of 30*8=240 pixel */
165 /* tile_height = */ 8,
166 /* default_x_offset = */ 0,
167 /* flipmode_x_offset = */ 0,
168 /* pixel_width = */ 240,
169 /* pixel_height = */ 64
170};
171
172static const uint8_t u8x8_d_uc1611_ea_dogm240_init_seq[] = {
173
174 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
175 U8X8_C(0x02f), /* internal pump control */
176 U8X8_CA(0x0f1, 63), /* set COM end */
177 U8X8_CA(0x0f2, 0x000), /* display line start */
178 U8X8_CA(0x0f3, 63), /* display line end */
179 U8X8_C(0x0a3), /* line rate */
180 U8X8_CA(0x081, 0x0a4), /* set contrast, EA default: 0x0b7 */
181
182 //U8X8_C(0x0a9), /* display enable */
183
184 U8X8_C(0x0d1), /* display pattern */
185 U8X8_C(0x089), /* auto increment */
186 U8X8_CA(0x0c0, 0x004), /* LCD Mapping */
187 U8X8_C(0x000), /* column low nibble */
188 U8X8_C(0x010), /* column high nibble */
189 U8X8_C(0x060), /* page adr low */
190 U8X8_C(0x070), /* page adr high */
191
192
193 U8X8_END_TRANSFER(), /* disable chip */
194 U8X8_END() /* end of sequence */
195};
196
197/* UC1611s 240x64 display */
198uint8_t u8x8_d_uc1611_ea_dogm240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
199{
200 /* call common procedure first and handle messages there */
201 if ( u8x8_d_uc1611_common(u8x8, msg, arg_int, arg_ptr) == 0 )
202 {
203 /* msg not handled, then try here */
204 switch(msg)
205 {
206 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
207 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1611_240x64_display_info);
208 break;
209 case U8X8_MSG_DISPLAY_INIT:
210 u8x8_d_helper_display_init(u8x8);
211 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_ea_dogm240_init_seq);
212 break;
213 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
214 if ( arg_int == 0 )
215 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave0_seq);
216 else
217 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave1_seq);
218 break;
219 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
220 if ( arg_int == 0 )
221 {
222 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip0_seq);
223 u8x8->x_offset = u8x8->display_info->default_x_offset;
224 }
225 else
226 {
227 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip1_seq);
228 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
229 }
230 break;
231 default:
232 return 0; /* msg unknown */
233 }
234 }
235 return 1;
236}
237
238/*================================================*/
239/* EA DOGXL240 */
240
241static const uint8_t u8x8_d_uc1611_ea_dogxl240_init_seq[] = {
242
243 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
244 U8X8_C(0x02f), /* internal pump control */
245 U8X8_CA(0x0f1, 0x07f), /* set COM end */
246 U8X8_CA(0x0f2, 0x000), /* display line start */
247 U8X8_CA(0x0f3, 127), /* display line end */
248 U8X8_C(0x0a3), /* line rate */
249 U8X8_CA(0x081, 0x08f), /* set contrast */
250
251 //U8X8_C(0x0a9), /* display enable */
252
253 U8X8_C(0x0d1), /* display pattern */
254 U8X8_C(0x089), /* auto increment */
255 U8X8_CA(0x0c0, 0x004), /* LCD Mapping */
256 U8X8_C(0x000), /* column low nibble */
257 U8X8_C(0x010), /* column high nibble */
258 U8X8_C(0x060), /* page adr low */
259 U8X8_C(0x070), /* page adr high */
260
261
262 U8X8_END_TRANSFER(), /* disable chip */
263 U8X8_END() /* end of sequence */
264};
265
266static const u8x8_display_info_t u8x8_uc1611_240x128_display_info =
267{
268 /* chip_enable_level = */ 0,
269 /* chip_disable_level = */ 1,
270
271 /* post_chip_enable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
272 /* pre_chip_disable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
273 /* reset_pulse_width_ms = */ 1,
274 /* post_reset_wait_ms = */ 10, /* uc1611 datasheet, page 67 */
275 /* sda_setup_time_ns = */ 10, /* uc1611 datasheet, page 64, actually 0 */
276 /* sck_pulse_width_ns = */ 60, /* half of cycle time */
277 /* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
278 /* spi_mode = */ 0, /* active high, rising edge */
279 /* i2c_bus_clock_100kHz = */ 4,
280 /* data_setup_time_ns = */ 30, /* uc1611 datasheet, page 60 */
281 /* write_pulse_width_ns = */ 80, /* uc1611 datasheet, page 60 */
282 /* tile_width = */ 30, /* width of 30*8=240 pixel */
283 /* tile_height = */ 16,
284 /* default_x_offset = */ 0,
285 /* flipmode_x_offset = */ 0,
286 /* pixel_width = */ 240,
287 /* pixel_height = */ 128
288};
289
290/* UC1611s 240x128 display */
291uint8_t u8x8_d_uc1611_ea_dogxl240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
292{
293 /* call common procedure first and handle messages there */
294 if ( u8x8_d_uc1611_common(u8x8, msg, arg_int, arg_ptr) == 0 )
295 {
296 /* msg not handled, then try here */
297 switch(msg)
298 {
299 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
300 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1611_240x128_display_info);
301 break;
302 case U8X8_MSG_DISPLAY_INIT:
303 u8x8_d_helper_display_init(u8x8);
304 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_ea_dogxl240_init_seq);
305 break;
306 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
307 if ( arg_int == 0 )
308 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave0_seq);
309 else
310 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave1_seq);
311 break;
312 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
313 if ( arg_int == 0 )
314 {
315 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip0_seq);
316 u8x8->x_offset = u8x8->display_info->default_x_offset;
317 }
318 else
319 {
320 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip1_seq);
321 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
322 }
323 break;
324 default:
325 return 0; /* msg unknown */
326 }
327 }
328 return 1;
329}
330
331/*================================================*/
332/* EMERGING DISPLAY, EW50850FLWP 240x160 */
333/* active high CS (CS1), UC1611 display */
334
335static const uint8_t u8x8_d_uc1611_ew50850_init_seq[] = {
336
337 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
338 U8X8_C(0x02f), /* internal pump control */
339 U8X8_CA(0x0f1, 159), /* set COM end */
340 U8X8_CA(0x0f2, 0), /* display line start */
341 U8X8_CA(0x0f3, 159), /* display line end */
342 U8X8_C(0x0a3), /* line rate */
343 U8X8_CA(0x081, 75), /* set contrast */
344
345 //U8X8_C(0x0a9), /* display enable */
346
347 U8X8_C(0x0d2), /* gray level mode: 16 gray shades */
348 U8X8_C(0x089), /* auto increment */
349 U8X8_C(0x0c0), /* LCD Mapping Bit 0: MSF, Bit 1: MX, Bit 2: MY */
350 U8X8_C(0x000), /* column low nibble */
351 U8X8_C(0x010), /* column high nibble */
352 U8X8_C(0x060), /* page adr low */
353 U8X8_C(0x070), /* page adr high */
354
355 U8X8_END_TRANSFER(), /* disable chip */
356 U8X8_END() /* end of sequence */
357};
358
359static const u8x8_display_info_t u8x8_uc1611_ew50850_display_info =
360{
361 /* chip_enable_level = */ 1, /* active high */
362 /* chip_disable_level = */ 0,
363
364 /* post_chip_enable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
365 /* pre_chip_disable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
366 /* reset_pulse_width_ms = */ 1,
367 /* post_reset_wait_ms = */ 10, /* uc1611 datasheet, page 67 */
368 /* sda_setup_time_ns = */ 10, /* uc1611 datasheet, page 64, actually 0 */
369 /* sck_pulse_width_ns = */ 60, /* half of cycle time */
370 /* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
371 /* spi_mode = */ 0, /* active high, rising edge */
372 /* i2c_bus_clock_100kHz = */ 4,
373 /* data_setup_time_ns = */ 30, /* uc1611 datasheet, page 60 */
374 /* write_pulse_width_ns = */ 80, /* uc1611 datasheet, page 60 */
375 /* tile_width = */ 30, /* width of 30*8=240 pixel */
376 /* tile_height = */ 20, /* height: 160 pixel */
377 /* default_x_offset = */ 0,
378 /* flipmode_x_offset = */ 0,
379 /* pixel_width = */ 240,
380 /* pixel_height = */ 160
381};
382
383static const uint8_t u8x8_d_uc1611_alt_flip0_seq[] = {
384 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
385 U8X8_C(0x0c0), /* LCD Mapping Bit 0: MSF, Bit 1: MX, Bit 2: MY */
386 U8X8_END_TRANSFER(), /* disable chip */
387 U8X8_END() /* end of sequence */
388};
389
390static const uint8_t u8x8_d_uc1611_alt_flip1_seq[] = {
391 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
392 U8X8_C(0x0c6), /* LCD Mapping Bit 0: MSF, Bit 1: MX, Bit 2: MY */
393 U8X8_END_TRANSFER(), /* disable chip */
394 U8X8_END() /* end of sequence */
395};
396
397static const uint8_t u8x8_d_uc1611_powersave0_seq[] = {
398 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
399 U8X8_C(0x0af), /* display on, UC1611 */
400 U8X8_END_TRANSFER(), /* disable chip */
401 U8X8_END() /* end of sequence */
402};
403
404static const uint8_t u8x8_d_uc1611_powersave1_seq[] = {
405 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
406 U8X8_C(0x0a8), /* display off, enter sleep mode, UC1611 */
407 U8X8_END_TRANSFER(), /* disable chip */
408 U8X8_END() /* end of sequence */
409};
410
411
412/* EW50850, 240x160 */
413uint8_t u8x8_d_uc1611_ew50850(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
414{
415 uint8_t x, y, c, i, v, m0, m1, ai;
416 uint8_t *ptr;
417 /* msg not handled, then try here */
418 switch(msg)
419 {
420 case U8X8_MSG_DISPLAY_DRAW_TILE:
421 u8x8_cad_StartTransfer(u8x8);
422
423 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
424 x *= 8;
425 x += u8x8->x_offset;
426
427 y = ((u8x8_tile_t *)arg_ptr)->y_pos;
428 y*=4;
429 m0 = 1;
430 m1 = 2;
431 for( i = 0; i < 4; i++ )
432 {
433 u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
434 u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
435
436 u8x8_cad_SendCmd(u8x8, 0x060 | (y&15));
437 u8x8_cad_SendCmd(u8x8, 0x070 | (y>>4));
438
439 ai = arg_int;
440 do
441 {
442 c = ((u8x8_tile_t *)arg_ptr)->cnt;
443 c *= 8;
444 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
445 while( c > 0 )
446 {
447 v = 0;
448 if ( *ptr & m0 )
449 v|= 0x0f;
450 if ( *ptr & m1 )
451 v|= 0xf0;
452 u8x8_cad_SendData(u8x8, 1, &v); /* note: SendData can not handle more than 255 bytes */
453 c--;
454 ptr++;
455 }
456 ai--;
457 } while( ai > 0 );
458
459 m0 <<= 2;
460 m1 <<= 2;
461 y++;
462 }
463 u8x8_cad_EndTransfer(u8x8);
464 break;
465 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
466 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1611_ew50850_display_info);
467 break;
468 case U8X8_MSG_DISPLAY_INIT:
469 u8x8_d_helper_display_init(u8x8);
470 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_ew50850_init_seq);
471 break;
472 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
473 if ( arg_int == 0 )
474 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_powersave0_seq);
475 else
476 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_powersave1_seq);
477 break;
478 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
479 if ( arg_int == 0 )
480 {
481 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_alt_flip0_seq);
482 u8x8->x_offset = u8x8->display_info->default_x_offset;
483 }
484 else
485 {
486 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_alt_flip1_seq);
487 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
488 }
489 break;
490#ifdef U8X8_WITH_SET_CONTRAST
491 case U8X8_MSG_DISPLAY_SET_CONTRAST:
492 u8x8_cad_StartTransfer(u8x8);
493 u8x8_cad_SendCmd(u8x8, 0x081 );
494 u8x8_cad_SendArg(u8x8, arg_int ); /* uc1611 has range from 0 to 255 */
495 u8x8_cad_EndTransfer(u8x8);
496 break;
497#endif
498 default:
499 return 0; /* msg unknown */
500 }
501 return 1;
502}
503
504
505/*================================================*/
506/* CG160160D, http://www.cloverdisplay.com/pdf/CG160160D.pdf */
507
508/*
509 UC1611 has two chip select inputs (CS0 and CS1).
510 CS0 is low active, CS1 is high active. It will depend on the display
511 module whether the display has a is low or high active chip select.
512
513 Connect CS1 to 3.3V and CS0 to GPIO
514*/
515
516static const u8x8_display_info_t u8x8_uc1611_cg160160_display_info =
517{
518 /* chip_enable_level = */ 0, /* use CS0 of the UC1611 */
519 /* chip_disable_level = */ 1,
520
521 /* post_chip_enable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
522 /* pre_chip_disable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
523 /* reset_pulse_width_ms = */ 1,
524 /* post_reset_wait_ms = */ 10, /* uc1611 datasheet, page 67 */
525 /* sda_setup_time_ns = */ 10, /* uc1611 datasheet, page 64, actually 0 */
526 /* sck_pulse_width_ns = */ 60, /* half of cycle time */
527 /* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
528 /* spi_mode = */ 0, /* active high, rising edge */
529 /* i2c_bus_clock_100kHz = */ 4,
530 /* data_setup_time_ns = */ 30, /* uc1611 datasheet, page 60 */
531 /* write_pulse_width_ns = */ 80, /* uc1611 datasheet, page 60 */
532 /* tile_width = */ 20, /* width of 20*8=160 pixel */
533 /* tile_height = */ 20,
534 /* default_x_offset = */ 0,
535 /* flipmode_x_offset = */ 0,
536 /* pixel_width = */ 160,
537 /* pixel_height = */ 160
538};
539
540/*
541System Reset: E2H --> DONE
542Set Temp. Compensation: 24H --> DONE
543Set up LCD format specific parameters MX,MY,etc(double-byte command): C0H,04H --> FLIP0
544Set line rate: A3H --> DONE
545Set Pump Control (internal Vlcd): 2FH --> DONE
546Set Isolation Clock Front (3 bytes command): 82H, 13H, 01H --> DONE
547Set Isolation Clock Back (3 bytes command): 82H, 14H, 00H --> DONE
548Set LCD Bias Ratio: EAH
549LCD Specific Operation Voltage Setting (double-byte command): 81H, 90H --> DONE
550Set RAM Address Control: 80H --> DOES NOT MAKE SENSE
551Set Page Addr. MSB: 72H --> DONE
552Set Page Addr. LSB : 60H --> DONE
553Set Column Addr. LSB: 00H --> DONE
554Set Column Addr.MSB: 10H --> DONE
555Window Program Enable : F8H --> NOT REQURED
556Window Starting Column (double-byte command): F4H , 00H --> NOT REQURED
557Window Ending Column (double-byte command): F6H, 9FH --> NOT REQURED
558Set one bit for one pixel: D1H --> DONE
559Set Display Enable: A9H
560*/
561
562static const uint8_t u8x8_d_uc1611_cg160160_init_seq[] = {
563
564 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
565 U8X8_C(0x0e2), /* system reset */
566 U8X8_DLY(2),
567 U8X8_C(0x024), /* Temp. Compensation to 0 = -0.05%/ Grad C */
568 U8X8_C(0x0a3), /* line rate */
569 U8X8_C(0x02f), /* internal pump control */
570 U8X8_CAA(0x082, 0x013, 0x001), /* Isolation front clock, "1" is the default value */
571 U8X8_CAA(0x082, 0x014, 0x000), /* Isolation back clock, "0" is the default value */
572 U8X8_C(0x0ea), /* bias ratio, default: 0x0ea */
573 U8X8_CA(0x081, 0x090), /* set contrast, CG160160: 0x090 */
574
575 //U8X8_CA(0x0f1, 159), /* set COM end */
576 //U8X8_CA(0x0f2, 0), /* display line start */
577 //U8X8_CA(0x0f3, 159), /* display line end */
578
579 //U8X8_C(0x0a9), /* display enable */
580
581 U8X8_C(0x089), /* RAM Address Control: auto increment */
582 U8X8_C(0x0d1), /* display pattern */
583 U8X8_CA(0x0c0, 0x004), /* LCD Mapping */
584 U8X8_C(0x000), /* column low nibble */
585 U8X8_C(0x010), /* column high nibble */
586 U8X8_C(0x060), /* page adr low */
587 U8X8_C(0x070), /* page adr high */
588
589
590 U8X8_END_TRANSFER(), /* disable chip */
591 U8X8_END() /* end of sequence */
592};
593
594/* cg160160 display */
595uint8_t u8x8_d_uc1611_cg160160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
596{
597 /* call common procedure first and handle messages there */
598 if ( u8x8_d_uc1611_common(u8x8, msg, arg_int, arg_ptr) == 0 )
599 {
600 /* msg not handled, then try here */
601 switch(msg)
602 {
603 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
604 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1611_cg160160_display_info);
605 break;
606 case U8X8_MSG_DISPLAY_INIT:
607 u8x8_d_helper_display_init(u8x8);
608 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_cg160160_init_seq);
609 break;
610 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
611 if ( arg_int == 0 )
612 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave0_seq);
613 else
614 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave1_seq);
615 break;
616 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
617 if ( arg_int == 0 )
618 {
619 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip0_seq);
620 u8x8->x_offset = u8x8->display_info->default_x_offset;
621 }
622 else
623 {
624 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip1_seq);
625 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
626 }
627 break;
628 default:
629 return 0; /* msg unknown */
630 }
631 }
632 return 1;
633}
634
635
636/*================================================*/
637/* CI064-4073-06 (Intelligent Display Solutions), IDS4073*/
638/* https://docs.rs-online.com/7e6e/0900766b8156b018.pdf */
639
640static const uint8_t u8x8_d_uc1611_ids4073_init_seq[] = {
641
642 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
643 U8X8_C(0x02f), /* internal pump control */
644 U8X8_CA(0x0f1, 0x07f), /* set COM end */
645 U8X8_CA(0x0f2, 0x000), /* display line start */
646 U8X8_CA(0x0f3, 127), /* display line end */
647 U8X8_C(0x0a3), /* line rate */
648 U8X8_CA(0x081, 0x08f), /* set contrast */
649
650 //U8X8_C(0x0a9), /* display enable */
651
652 U8X8_C(0x0d1), /* display pattern */
653 U8X8_C(0x089), /* auto increment */
654 U8X8_CA(0x0c0, 0x004), /* LCD Mapping */
655 U8X8_C(0x000), /* column low nibble */
656 U8X8_C(0x010), /* column high nibble */
657 U8X8_C(0x060), /* page adr low */
658 U8X8_C(0x070), /* page adr high */
659
660
661 U8X8_END_TRANSFER(), /* disable chip */
662 U8X8_END() /* end of sequence */
663};
664
665
666static const u8x8_display_info_t u8x8_uc1611_256x128_display_info =
667{
668 /* chip_enable_level = */ 0,
669 /* chip_disable_level = */ 1,
670
671 /* post_chip_enable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
672 /* pre_chip_disable_wait_ns = */ 10, /* uc1611 datasheet, page 60, actually 0 */
673 /* reset_pulse_width_ms = */ 1,
674 /* post_reset_wait_ms = */ 10, /* uc1611 datasheet, page 67 */
675 /* sda_setup_time_ns = */ 10, /* uc1611 datasheet, page 64, actually 0 */
676 /* sck_pulse_width_ns = */ 60, /* half of cycle time */
677 /* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
678 /* spi_mode = */ 0, /* active high, rising edge */
679 /* i2c_bus_clock_100kHz = */ 4,
680 /* data_setup_time_ns = */ 30, /* uc1611 datasheet, page 60 */
681 /* write_pulse_width_ns = */ 80, /* uc1611 datasheet, page 60 */
682 /* tile_width = */ 32, /* width of 32*8=256 pixel */
683 /* tile_height = */ 16,
684 /* default_x_offset = */ 0,
685 /* flipmode_x_offset = */ 0,
686 /* pixel_width = */ 256,
687 /* pixel_height = */ 128
688};
689
690/* UC1611s 256x128 display */
691uint8_t u8x8_d_uc1611_ids4073(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
692{
693 uint8_t x, y, c;
694 uint8_t *ptr;
695 switch(msg)
696 {
697 case U8X8_MSG_DISPLAY_DRAW_TILE:
698 u8x8_cad_StartTransfer(u8x8);
699
700 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
701 x *= 8;
702 x += u8x8->x_offset;
703
704 u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
705 u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
706
707 y = ((u8x8_tile_t *)arg_ptr)->y_pos;
708 u8x8_cad_SendCmd(u8x8, 0x060 | (y&15));
709 u8x8_cad_SendCmd(u8x8, 0x070 | (y>>4));
710
711 do
712 {
713 c = ((u8x8_tile_t *)arg_ptr)->cnt;
714 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
715 /* SendData can not handle more than 255 bytes */
716 if ( c > 31 )
717 {
718 u8x8_cad_SendData(u8x8, 248, ptr); /* 31*8=248 */
719 ptr+=248;
720 c -= 31;
721 }
722
723 u8x8_cad_SendData(u8x8, c*8, ptr);
724 arg_int--;
725 } while( arg_int > 0 );
726
727 u8x8_cad_EndTransfer(u8x8);
728 break;
729#ifdef U8X8_WITH_SET_CONTRAST
730 case U8X8_MSG_DISPLAY_SET_CONTRAST:
731 u8x8_cad_StartTransfer(u8x8);
732 u8x8_cad_SendCmd(u8x8, 0x081 );
733 u8x8_cad_SendArg(u8x8, arg_int ); /* uc1611 has range from 0 to 255 */
734 u8x8_cad_EndTransfer(u8x8);
735 break;
736#endif
737
738 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
739 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_uc1611_256x128_display_info);
740 break;
741 case U8X8_MSG_DISPLAY_INIT:
742 u8x8_d_helper_display_init(u8x8);
743 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611_ids4073_init_seq);
744 break;
745 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
746 if ( arg_int == 0 )
747 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave0_seq);
748 else
749 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_powersave1_seq);
750 break;
751 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
752 if ( arg_int == 0 )
753 {
754 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip0_seq);
755 u8x8->x_offset = u8x8->display_info->default_x_offset;
756 }
757 else
758 {
759 u8x8_cad_SendSequence(u8x8, u8x8_d_uc1611s_flip1_seq);
760 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
761 }
762 break;
763 default:
764 return 0; /* msg unknown */
765 }
766 return 1;
767}