Krolyxon
Commit 1d55752

Branches

Tags

Refs →

orion-rf.piolibdepsesp32-s3-n16r8U8g2srcclibu8x8_cad.c

951 lines · 26.4 KB · C

1/*
2
3 u8x8_cad.c
4
5 "command arg data" interface to the graphics controller
6
7 Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
8
9 Copyright (c) 2016, olikraus@gmail.com
10 All rights reserved.
11
12 Redistribution and use in source and binary forms, with or without modification,
13 are permitted provided that the following conditions are met:
14
15 * Redistributions of source code must retain the above copyright notice, this list
16 of conditions and the following disclaimer.
17
18 * Redistributions in binary form must reproduce the above copyright notice, this
19 list of conditions and the following disclaimer in the documentation and/or other
20 materials provided with the distribution.
21
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
27 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
29 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
32 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
34 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
36
37 The following sequence must be used for any data, which is set to the display:
38
39
40 uint8_t u8x8_cad_StartTransfer(u8x8_t *u8x8)
41
42 any of the following calls
43 uint8_t u8x8_cad_SendCmd(u8x8_t *u8x8, uint8_t cmd)
44 uint8_t u8x8_cad_SendArg(u8x8_t *u8x8, uint8_t arg)
45 uint8_t u8x8_cad_SendData(u8x8_t *u8x8, uint8_t cnt, uint8_t *data)
46
47 uint8_t u8x8_cad_EndTransfer(u8x8_t *u8x8)
48
49
50
51*/
52/*
53uint8_t u8x8_cad_template(u8x8_t *u8x8, uint8_t msg, uint16_t arg_int, void *arg_ptr)
54{
55 uint8_t i;
56
57 switch(msg)
58 {
59 case U8X8_MSG_CAD_SEND_CMD:
60 u8x8_mcd_byte_SetDC(mcd->next, 1);
61 u8x8_mcd_byte_Send(mcd->next, arg_int);
62 break;
63 case U8X8_MSG_CAD_SEND_ARG:
64 u8x8_mcd_byte_SetDC(mcd->next, 1);
65 u8x8_mcd_byte_Send(mcd->next, arg_int);
66 break;
67 case U8X8_MSG_CAD_SEND_DATA:
68 u8x8_mcd_byte_SetDC(mcd->next, 0);
69 for( i = 0; i < 8; i++ )
70 u8x8_mcd_byte_Send(mcd->next, ((uint8_t *)arg_ptr)[i]);
71 break;
72 case U8X8_MSG_CAD_RESET:
73 return mcd->next->cb(mcd->next, msg, arg_int, arg_ptr);
74 case U8X8_MSG_CAD_START_TRANSFER:
75 return mcd->next->cb(mcd->next, msg, arg_int, arg_ptr);
76 case U8X8_MSG_CAD_END_TRANSFER:
77 return mcd->next->cb(mcd->next, msg, arg_int, arg_ptr);
78 default:
79 break;
80 }
81 return 1;
82}
83
84*/
85
86#include "u8x8.h"
87
88uint8_t u8x8_cad_SendCmd(u8x8_t *u8x8, uint8_t cmd)
89{
90 return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_CMD, cmd, NULL);
91}
92
93uint8_t u8x8_cad_SendArg(u8x8_t *u8x8, uint8_t arg)
94{
95 return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_ARG, arg, NULL);
96}
97
98uint8_t u8x8_cad_SendMultipleArg(u8x8_t *u8x8, uint8_t cnt, uint8_t arg)
99{
100 while( cnt > 0 )
101 {
102 u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_ARG, arg, NULL);
103 cnt--;
104 }
105 return 1;
106}
107
108uint8_t u8x8_cad_SendData(u8x8_t *u8x8, uint8_t cnt, uint8_t *data)
109{
110 return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, cnt, data);
111}
112
113uint8_t u8x8_cad_StartTransfer(u8x8_t *u8x8)
114{
115 return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 0, NULL);
116}
117
118uint8_t u8x8_cad_EndTransfer(u8x8_t *u8x8)
119{
120 return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
121}
122
123void u8x8_cad_vsendf(u8x8_t * u8x8, const char *fmt, va_list va)
124{
125 uint8_t d;
126 u8x8_cad_StartTransfer(u8x8);
127 while( *fmt != '\0' )
128 {
129 d = (uint8_t)va_arg(va, int);
130 switch(*fmt)
131 {
132 case 'a': u8x8_cad_SendArg(u8x8, d); break;
133 case 'c': u8x8_cad_SendCmd(u8x8, d); break;
134 case 'd': u8x8_cad_SendData(u8x8, 1, &d); break;
135 }
136 fmt++;
137 }
138 u8x8_cad_EndTransfer(u8x8);
139}
140
141void u8x8_SendF(u8x8_t * u8x8, const char *fmt, ...)
142{
143 va_list va;
144 va_start(va, fmt);
145 u8x8_cad_vsendf(u8x8, fmt, va);
146 va_end(va);
147}
148
149/*
150 21 c send command c
151 22 a send arg a
152 23 d send data d
153 24 CS on
154 25 CS off
155 254 milli delay by milliseconds
156 255 end of sequence
157*/
158
159void u8x8_cad_SendSequence(u8x8_t *u8x8, uint8_t const *data)
160{
161 uint8_t cmd;
162 uint8_t v;
163
164 for(;;)
165 {
166 cmd = *data;
167 data++;
168 switch( cmd )
169 {
170 case U8X8_MSG_CAD_SEND_CMD:
171 case U8X8_MSG_CAD_SEND_ARG:
172 v = *data;
173 u8x8->cad_cb(u8x8, cmd, v, NULL);
174 data++;
175 break;
176 case U8X8_MSG_CAD_SEND_DATA:
177 v = *data;
178 u8x8_cad_SendData(u8x8, 1, &v);
179 data++;
180 break;
181 case U8X8_MSG_CAD_START_TRANSFER:
182 case U8X8_MSG_CAD_END_TRANSFER:
183 u8x8->cad_cb(u8x8, cmd, 0, NULL);
184 break;
185 case 0x0fe:
186 v = *data;
187 u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_MILLI, v);
188 data++;
189 break;
190 default:
191 return;
192 }
193 }
194}
195
196
197uint8_t u8x8_cad_empty(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
198{
199 switch(msg)
200 {
201 case U8X8_MSG_CAD_SEND_CMD:
202 u8x8_byte_SendByte(u8x8, arg_int);
203 break;
204 case U8X8_MSG_CAD_SEND_ARG:
205 u8x8_byte_SendByte(u8x8, arg_int);
206 break;
207 case U8X8_MSG_CAD_SEND_DATA:
208 case U8X8_MSG_CAD_INIT:
209 case U8X8_MSG_CAD_START_TRANSFER:
210 case U8X8_MSG_CAD_END_TRANSFER:
211 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
212 default:
213 return 0;
214 }
215 return 1;
216}
217
218
219/*
220 convert to bytes by using
221 dc = 1 for commands and args and
222 dc = 0 for data
223*/
224uint8_t u8x8_cad_110(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
225{
226 switch(msg)
227 {
228 case U8X8_MSG_CAD_SEND_CMD:
229 u8x8_byte_SetDC(u8x8, 1);
230 u8x8_byte_SendByte(u8x8, arg_int);
231 break;
232 case U8X8_MSG_CAD_SEND_ARG:
233 u8x8_byte_SetDC(u8x8, 1);
234 u8x8_byte_SendByte(u8x8, arg_int);
235 break;
236 case U8X8_MSG_CAD_SEND_DATA:
237 u8x8_byte_SetDC(u8x8, 0);
238 //u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
239 //break;
240 /* fall through */
241 case U8X8_MSG_CAD_INIT:
242 case U8X8_MSG_CAD_START_TRANSFER:
243 case U8X8_MSG_CAD_END_TRANSFER:
244 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
245 default:
246 return 0;
247 }
248 return 1;
249}
250
251/*
252 convert to bytes by using
253 dc = 1 for commands and args and
254 dc = 0 for data
255*/
256uint8_t u8x8_gu800_cad_110(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
257{
258 uint8_t *data;
259 switch(msg)
260 {
261 case U8X8_MSG_CAD_SEND_CMD:
262 u8x8_byte_SetDC(u8x8, 1);
263 u8x8_byte_StartTransfer(u8x8);
264 u8x8_byte_SendByte(u8x8, arg_int);
265 u8x8_byte_EndTransfer(u8x8);
266 break;
267 case U8X8_MSG_CAD_SEND_ARG:
268 u8x8_byte_SetDC(u8x8, 1);
269 u8x8_byte_StartTransfer(u8x8);
270 u8x8_byte_SendByte(u8x8, arg_int);
271 u8x8_byte_EndTransfer(u8x8);
272 break;
273 case U8X8_MSG_CAD_SEND_DATA:
274 u8x8_byte_SetDC(u8x8, 0);
275 data = (uint8_t *)arg_ptr;
276 while( arg_int > 0 )
277 {
278 u8x8_byte_StartTransfer(u8x8);
279 u8x8_byte_SendByte(u8x8, *data);
280 u8x8_byte_EndTransfer(u8x8);
281 data++;
282 arg_int--;
283 }
284 break;
285 case U8X8_MSG_CAD_INIT:
286 u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
287 break;
288 case U8X8_MSG_CAD_START_TRANSFER:
289 case U8X8_MSG_CAD_END_TRANSFER:
290 break;
291 default:
292 return 0;
293 }
294 return 1;
295}
296
297/*
298 convert to bytes by using
299 dc = 1 for commands and args and
300 dc = 0 for data
301 t6963
302*/
303uint8_t u8x8_cad_100(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
304{
305 switch(msg)
306 {
307 case U8X8_MSG_CAD_SEND_CMD:
308 u8x8_byte_SetDC(u8x8, 1);
309 u8x8_byte_SendByte(u8x8, arg_int);
310 break;
311 case U8X8_MSG_CAD_SEND_ARG:
312 u8x8_byte_SetDC(u8x8, 0);
313 u8x8_byte_SendByte(u8x8, arg_int);
314 break;
315 case U8X8_MSG_CAD_SEND_DATA:
316 u8x8_byte_SetDC(u8x8, 0);
317 //u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
318 //break;
319 /* fall through */
320 case U8X8_MSG_CAD_INIT:
321 case U8X8_MSG_CAD_START_TRANSFER:
322 case U8X8_MSG_CAD_END_TRANSFER:
323 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
324 default:
325 return 0;
326 }
327 return 1;
328}
329
330/*
331 convert to bytes by using
332 dc = 0 for commands and args and
333 dc = 1 for data
334*/
335uint8_t u8x8_cad_001(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
336{
337 switch(msg)
338 {
339 case U8X8_MSG_CAD_SEND_CMD:
340 u8x8_byte_SetDC(u8x8, 0);
341 u8x8_byte_SendByte(u8x8, arg_int);
342 break;
343 case U8X8_MSG_CAD_SEND_ARG:
344 u8x8_byte_SetDC(u8x8, 0);
345 u8x8_byte_SendByte(u8x8, arg_int);
346 break;
347 case U8X8_MSG_CAD_SEND_DATA:
348 u8x8_byte_SetDC(u8x8, 1);
349 //u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
350 //break;
351 /* fall through */
352 case U8X8_MSG_CAD_INIT:
353 case U8X8_MSG_CAD_START_TRANSFER:
354 case U8X8_MSG_CAD_END_TRANSFER:
355 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
356 default:
357 return 0;
358 }
359 return 1;
360}
361
362/*
363 convert to bytes by using
364 dc = 0 for commands
365 dc = 1 for args and data
366*/
367uint8_t u8x8_cad_011(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
368{
369 switch(msg)
370 {
371 case U8X8_MSG_CAD_SEND_CMD:
372 u8x8_byte_SetDC(u8x8, 0);
373 u8x8_byte_SendByte(u8x8, arg_int);
374 break;
375 case U8X8_MSG_CAD_SEND_ARG:
376 u8x8_byte_SetDC(u8x8, 1);
377 u8x8_byte_SendByte(u8x8, arg_int);
378 break;
379 case U8X8_MSG_CAD_SEND_DATA:
380 u8x8_byte_SetDC(u8x8, 1);
381 //u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
382 //break;
383 /* fall through */
384 case U8X8_MSG_CAD_INIT:
385 case U8X8_MSG_CAD_START_TRANSFER:
386 case U8X8_MSG_CAD_END_TRANSFER:
387 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
388 default:
389 return 0;
390 }
391 return 1;
392}
393
394/* cad procedure for the ST7920 in SPI mode */
395/* u8x8_byte_SetDC is not used */
396uint8_t u8x8_cad_st7920_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
397{
398 uint8_t *data;
399 uint8_t b;
400 uint8_t i;
401 static uint8_t buf[16];
402 uint8_t *ptr;
403
404 switch(msg)
405 {
406 case U8X8_MSG_CAD_SEND_CMD:
407 u8x8_byte_SendByte(u8x8, 0x0f8);
408 u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
409 u8x8_byte_SendByte(u8x8, arg_int & 0x0f0);
410 u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
411 u8x8_byte_SendByte(u8x8, arg_int << 4);
412 u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
413 break;
414 case U8X8_MSG_CAD_SEND_ARG:
415 u8x8_byte_SendByte(u8x8, 0x0f8);
416 u8x8_byte_SendByte(u8x8, arg_int & 0x0f0);
417 u8x8_byte_SendByte(u8x8, arg_int << 4);
418 break;
419 case U8X8_MSG_CAD_SEND_DATA:
420
421 u8x8_byte_SendByte(u8x8, 0x0fa);
422 u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
423
424 /* this loop should be optimized: multiple bytes should be sent */
425 /* u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr); */
426 data = (uint8_t *)arg_ptr;
427
428 /* the following loop increases speed by 20% */
429 while( arg_int >= 8 )
430 {
431 i = 8;
432 ptr = buf;
433 do
434 {
435 b = *data++;
436 *ptr++= b & 0x0f0;
437 b <<= 4;
438 *ptr++= b;
439 i--;
440 } while( i > 0 );
441 arg_int -= 8;
442 u8x8_byte_SendBytes(u8x8, 16, buf);
443 }
444
445
446 while( arg_int > 0 )
447 {
448 b = *data;
449 u8x8_byte_SendByte(u8x8, b & 0x0f0);
450 u8x8_byte_SendByte(u8x8, b << 4);
451 data++;
452 arg_int--;
453 }
454 u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
455 break;
456 case U8X8_MSG_CAD_INIT:
457 case U8X8_MSG_CAD_START_TRANSFER:
458 case U8X8_MSG_CAD_END_TRANSFER:
459 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
460 default:
461 return 0;
462 }
463 return 1;
464}
465
466
467/* cad procedure for the SSD13xx family in I2C mode */
468/* this procedure is also used by the ST7588 */
469/* u8x8_byte_SetDC is not used */
470/* U8X8_MSG_BYTE_START_TRANSFER starts i2c transfer, U8X8_MSG_BYTE_END_TRANSFER stops transfer */
471/* After transfer start, a full byte indicates command or data mode */
472
473static void u8x8_i2c_data_transfer(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr) U8X8_NOINLINE;
474static void u8x8_i2c_data_transfer(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr)
475{
476 u8x8_byte_StartTransfer(u8x8);
477 u8x8_byte_SendByte(u8x8, 0x040);
478 u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, arg_ptr);
479 u8x8_byte_EndTransfer(u8x8);
480}
481
482/* classic version: will put a start/stop condition around each command and arg */
483/* implements CAD = 001 */
484uint8_t u8x8_cad_ssd13xx_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
485{
486 uint8_t *p;
487 switch(msg)
488 {
489 case U8X8_MSG_CAD_SEND_CMD:
490 case U8X8_MSG_CAD_SEND_ARG:
491 /* 7 Nov 2016: Can this be improved? */
492 //u8x8_byte_SetDC(u8x8, 0);
493 u8x8_byte_StartTransfer(u8x8);
494 //u8x8_byte_SendByte(u8x8, u8x8_GetI2CAddress(u8x8));
495 u8x8_byte_SendByte(u8x8, 0x000);
496 u8x8_byte_SendByte(u8x8, arg_int);
497 u8x8_byte_EndTransfer(u8x8);
498 break;
499 case U8X8_MSG_CAD_SEND_DATA:
500 //u8x8_byte_SetDC(u8x8, 1);
501
502 /* the FeatherWing OLED with the 32u4 transfer of long byte */
503 /* streams was not possible. This is broken down to */
504 /* smaller streams, 32 seems to be the limit... */
505 /* I guess this is related to the size of the Wire buffers in Arduino */
506 /* Unfortunately, this can not be handled in the byte level drivers, */
507 /* so this is done here. Even further, only 24 bytes will be sent, */
508 /* because there will be another byte (DC) required during the transfer */
509 p = (uint8_t *)arg_ptr;
510 while( arg_int > 24 )
511 {
512 u8x8_i2c_data_transfer(u8x8, 24, p);
513 arg_int-=24;
514 p+=24;
515 }
516 u8x8_i2c_data_transfer(u8x8, arg_int, p);
517 break;
518 case U8X8_MSG_CAD_INIT:
519 /* apply default i2c adr if required so that the start transfer msg can use this */
520 if ( u8x8->i2c_address == 255 )
521 u8x8->i2c_address = 0x078;
522 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
523 case U8X8_MSG_CAD_START_TRANSFER:
524 case U8X8_MSG_CAD_END_TRANSFER:
525 /* cad transfer commands are ignored */
526 break;
527 default:
528 return 0;
529 }
530 return 1;
531}
532
533
534
535/* classic version: will put a start/stop condition around each command and arg */
536/* implements CAD = 011 for the SSD1363 */
537uint8_t u8x8_cad_011_ssd13xx_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
538{
539 uint8_t *p;
540 switch(msg)
541 {
542 case U8X8_MSG_CAD_SEND_CMD:
543 u8x8_byte_StartTransfer(u8x8);
544 u8x8_byte_SendByte(u8x8, 0x000);
545 u8x8_byte_SendByte(u8x8, arg_int);
546 u8x8_byte_EndTransfer(u8x8);
547 break;
548 case U8X8_MSG_CAD_SEND_ARG:
549 u8x8_byte_StartTransfer(u8x8);
550 u8x8_byte_SendByte(u8x8, 0x040);
551 u8x8_byte_SendByte(u8x8, arg_int);
552 u8x8_byte_EndTransfer(u8x8);
553 break;
554 case U8X8_MSG_CAD_SEND_DATA:
555 p = (uint8_t *)arg_ptr;
556 while( arg_int > 24 )
557 {
558 u8x8_i2c_data_transfer(u8x8, 24, p);
559 arg_int-=24;
560 p+=24;
561 }
562 u8x8_i2c_data_transfer(u8x8, arg_int, p);
563 break;
564 case U8X8_MSG_CAD_INIT:
565 /* apply default i2c adr if required so that the start transfer msg can use this */
566 if ( u8x8->i2c_address == 255 )
567 u8x8->i2c_address = 0x078;
568 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
569 case U8X8_MSG_CAD_START_TRANSFER:
570 case U8X8_MSG_CAD_END_TRANSFER:
571 /* cad transfer commands are ignored */
572 break;
573 default:
574 return 0;
575 }
576 return 1;
577}
578
579
580/* fast version with reduced data start/stops, issue 735 */
581uint8_t u8x8_cad_ssd13xx_fast_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
582{
583 static uint8_t in_transfer = 0;
584 uint8_t *p;
585 switch(msg)
586 {
587 case U8X8_MSG_CAD_SEND_CMD:
588 /* improved version, takeover from ld7032 */
589 /* assumes, that the args of a command is not longer than 31 bytes */
590 /* speed improvement is about 4% compared to the classic version */
591 if ( in_transfer != 0 )
592 u8x8_byte_EndTransfer(u8x8);
593
594 u8x8_byte_StartTransfer(u8x8);
595 u8x8_byte_SendByte(u8x8, 0x000); /* cmd byte for ssd13xx controller */
596 u8x8_byte_SendByte(u8x8, arg_int);
597 in_transfer = 1;
598 /* lightning version: can replace the improved version from above */
599 /* the drawback of the lightning version is this: The complete init sequence */
600 /* must fit into the 32 byte Arduino Wire buffer, which might not always be the case */
601 /* speed improvement is about 6% compared to the classic version */
602 // if ( in_transfer == 0 )
603 // {
604 // u8x8_byte_StartTransfer(u8x8);
605 // u8x8_byte_SendByte(u8x8, 0x000); /* cmd byte for ssd13xx controller */
606 // in_transfer = 1;
607 // }
608 //u8x8_byte_SendByte(u8x8, arg_int);
609 break;
610 case U8X8_MSG_CAD_SEND_ARG:
611 u8x8_byte_SendByte(u8x8, arg_int);
612 break;
613 case U8X8_MSG_CAD_SEND_DATA:
614 if ( in_transfer != 0 )
615 u8x8_byte_EndTransfer(u8x8);
616
617
618 /* the FeatherWing OLED with the 32u4 transfer of long byte */
619 /* streams was not possible. This is broken down to */
620 /* smaller streams, 32 seems to be the limit... */
621 /* I guess this is related to the size of the Wire buffers in Arduino */
622 /* Unfortunately, this can not be handled in the byte level drivers, */
623 /* so this is done here. Even further, only 24 bytes will be sent, */
624 /* because there will be another byte (DC) required during the transfer */
625 p = (uint8_t *)arg_ptr;
626 while( arg_int > 24 )
627 {
628 u8x8_i2c_data_transfer(u8x8, 24, p);
629 arg_int-=24;
630 p+=24;
631 }
632 u8x8_i2c_data_transfer(u8x8, arg_int, p);
633 in_transfer = 0;
634 break;
635 case U8X8_MSG_CAD_INIT:
636 /* apply default i2c adr if required so that the start transfer msg can use this */
637 if ( u8x8->i2c_address == 255 )
638 u8x8->i2c_address = 0x078;
639 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
640 case U8X8_MSG_CAD_START_TRANSFER:
641 in_transfer = 0;
642 break;
643 case U8X8_MSG_CAD_END_TRANSFER:
644 if ( in_transfer != 0 )
645 u8x8_byte_EndTransfer(u8x8);
646 in_transfer = 0;
647 break;
648 default:
649 return 0;
650 }
651 return 1;
652}
653
654
655
656/* the st75256 i2c driver is a copy of the ssd13xx driver, but with arg=1 */
657/* modified from cad001 (ssd13xx) to cad011 */
658uint8_t u8x8_cad_st75256_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
659{
660 uint8_t *p;
661 switch(msg)
662 {
663 case U8X8_MSG_CAD_SEND_CMD:
664 u8x8_byte_StartTransfer(u8x8);
665 u8x8_byte_SendByte(u8x8, 0x000);
666 u8x8_byte_SendByte(u8x8, arg_int);
667 u8x8_byte_EndTransfer(u8x8);
668 break;
669 case U8X8_MSG_CAD_SEND_ARG:
670 u8x8_byte_StartTransfer(u8x8);
671 u8x8_byte_SendByte(u8x8, 0x040);
672 u8x8_byte_SendByte(u8x8, arg_int);
673 u8x8_byte_EndTransfer(u8x8);
674 break;
675 case U8X8_MSG_CAD_SEND_DATA:
676 /* see ssd13xx driver */
677 p = (uint8_t *)arg_ptr;
678 while( arg_int > 24 )
679 {
680 u8x8_i2c_data_transfer(u8x8, 24, p);
681 arg_int-=24;
682 p+=24;
683 }
684 u8x8_i2c_data_transfer(u8x8, arg_int, p);
685 break;
686 case U8X8_MSG_CAD_INIT:
687 /* apply default i2c adr if required so that the start transfer msg can use this */
688 if ( u8x8->i2c_address == 255 )
689 u8x8->i2c_address = 0x078; /* ST75256, often this is 0x07e */
690 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
691 case U8X8_MSG_CAD_START_TRANSFER:
692 case U8X8_MSG_CAD_END_TRANSFER:
693 /* cad transfer commands are ignored */
694 break;
695 default:
696 return 0;
697 }
698 return 1;
699}
700
701/* cad i2c procedure for the ld7032 controller */
702/* Issue https://github.com/olikraus/u8g2/issues/865 mentiones, that I2C does not work */
703/* Workaround is to remove the while loop (or increase the value in the condition) */
704uint8_t u8x8_cad_ld7032_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
705{
706 static uint8_t in_transfer = 0;
707 uint8_t *p;
708 switch(msg)
709 {
710 case U8X8_MSG_CAD_SEND_CMD:
711 if ( in_transfer != 0 )
712 u8x8_byte_EndTransfer(u8x8);
713 u8x8_byte_StartTransfer(u8x8);
714 u8x8_byte_SendByte(u8x8, arg_int);
715 in_transfer = 1;
716 break;
717 case U8X8_MSG_CAD_SEND_ARG:
718 u8x8_byte_SendByte(u8x8, arg_int);
719 break;
720 case U8X8_MSG_CAD_SEND_DATA:
721 //u8x8_byte_SetDC(u8x8, 1);
722
723 /* the FeatherWing OLED with the 32u4 transfer of long byte */
724 /* streams was not possible. This is broken down to */
725 /* smaller streams, 32 seems to be the limit... */
726 /* I guess this is related to the size of the Wire buffers in Arduino */
727 /* Unfortunately, this can not be handled in the byte level drivers, */
728 /* so this is done here. Even further, only 24 bytes will be sent, */
729 /* because there will be another byte (DC) required during the transfer */
730 p = (uint8_t *)arg_ptr;
731 while( arg_int > 24 )
732 {
733 u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, 24, p);
734 arg_int-=24;
735 p+=24;
736 u8x8_byte_EndTransfer(u8x8);
737 u8x8_byte_StartTransfer(u8x8);
738 u8x8_byte_SendByte(u8x8, 0x08); /* data write for LD7032 */
739 }
740 u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, p);
741 break;
742 case U8X8_MSG_CAD_INIT:
743 /* apply default i2c adr if required so that the start transfer msg can use this */
744 if ( u8x8->i2c_address == 255 )
745 u8x8->i2c_address = 0x060;
746 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
747 case U8X8_MSG_CAD_START_TRANSFER:
748 in_transfer = 0;
749 break;
750 case U8X8_MSG_CAD_END_TRANSFER:
751 if ( in_transfer != 0 )
752 u8x8_byte_EndTransfer(u8x8);
753 break;
754 default:
755 return 0;
756 }
757 return 1;
758}
759
760/* cad procedure for the UC16xx family in I2C mode */
761/* u8x8_byte_SetDC is not used */
762/* DC bit is encoded into the adr byte, structure is CAD001 */
763uint8_t u8x8_cad_uc16xx_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
764{
765 static uint8_t in_transfer = 0;
766 static uint8_t is_data = 0;
767 uint8_t *p;
768 switch(msg)
769 {
770 case U8X8_MSG_CAD_SEND_CMD:
771 case U8X8_MSG_CAD_SEND_ARG:
772 if ( in_transfer != 0 )
773 {
774 if ( is_data != 0 )
775 {
776 /* transfer mode is active, but data transfer */
777 u8x8_byte_EndTransfer(u8x8);
778 /* clear the lowest two bits of the adr */
779 u8x8_SetI2CAddress( u8x8, u8x8_GetI2CAddress(u8x8)&0x0fc );
780 u8x8_byte_StartTransfer(u8x8);
781 }
782 }
783 else
784 {
785 /* clear the lowest two bits of the adr */
786 u8x8_SetI2CAddress( u8x8, u8x8_GetI2CAddress(u8x8)&0x0fc );
787 u8x8_byte_StartTransfer(u8x8);
788 }
789 u8x8_byte_SendByte(u8x8, arg_int);
790 in_transfer = 1;
791 // is_data = 0; // 20 Jun 2021: I assume that this is missing here
792 break;
793 case U8X8_MSG_CAD_SEND_DATA:
794 if ( in_transfer != 0 )
795 {
796 if ( is_data == 0 )
797 {
798 /* transfer mode is active, but data transfer */
799 u8x8_byte_EndTransfer(u8x8);
800 /* clear the lowest two bits of the adr */
801 u8x8_SetI2CAddress( u8x8, (u8x8_GetI2CAddress(u8x8)&0x0fc)|2 );
802 u8x8_byte_StartTransfer(u8x8);
803 }
804 }
805 else
806 {
807 /* clear the lowest two bits of the adr */
808 u8x8_SetI2CAddress( u8x8, (u8x8_GetI2CAddress(u8x8)&0x0fc)|2 );
809 u8x8_byte_StartTransfer(u8x8);
810 }
811 in_transfer = 1;
812 // is_data = 1; // 20 Jun 2021: I assume that this is missing here
813
814 p = (uint8_t *)arg_ptr;
815 while( arg_int > 24 )
816 {
817 u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, 24, p);
818 arg_int-=24;
819 p+=24;
820 u8x8_byte_EndTransfer(u8x8);
821 u8x8_byte_StartTransfer(u8x8);
822 }
823 u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, p);
824
825 break;
826 case U8X8_MSG_CAD_INIT:
827 /* apply default i2c adr if required so that the start transfer msg can use this */
828 if ( u8x8->i2c_address == 255 )
829 u8x8->i2c_address = 0x070;
830 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
831 case U8X8_MSG_CAD_START_TRANSFER:
832 in_transfer = 0;
833 /* actual start is delayed, because we do not whether this is data or cmd transfer */
834 break;
835 case U8X8_MSG_CAD_END_TRANSFER:
836 if ( in_transfer != 0 )
837 u8x8_byte_EndTransfer(u8x8);
838 in_transfer = 0;
839 break;
840 default:
841 return 0;
842 }
843 return 1;
844}
845
846
847/* cad procedure for the UC1638 in I2C mode */
848/* same as u8x8_cad_uc16xx_i2c but CAD structure is CAD011 */
849uint8_t u8x8_cad_uc1638_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
850{
851 static uint8_t in_transfer = 0;
852 static uint8_t is_data = 0;
853 uint8_t *p;
854 switch(msg)
855 {
856 case U8X8_MSG_CAD_SEND_CMD:
857 if ( in_transfer != 0 )
858 {
859 if ( is_data != 0 )
860 {
861 /* transfer mode is active, but data transfer */
862 u8x8_byte_EndTransfer(u8x8);
863 /* clear the lowest two bits of the adr */
864 u8x8_SetI2CAddress( u8x8, u8x8_GetI2CAddress(u8x8)&0x0fc );
865 u8x8_byte_StartTransfer(u8x8);
866 }
867 }
868 else
869 {
870 /* clear the lowest two bits of the adr */
871 u8x8_SetI2CAddress( u8x8, u8x8_GetI2CAddress(u8x8)&0x0fc );
872 u8x8_byte_StartTransfer(u8x8);
873 }
874 u8x8_byte_SendByte(u8x8, arg_int);
875 in_transfer = 1;
876 is_data = 0;
877 break;
878 case U8X8_MSG_CAD_SEND_ARG:
879 if ( in_transfer != 0 )
880 {
881 if ( is_data == 0 )
882 {
883 /* transfer mode is active, but data transfer */
884 u8x8_byte_EndTransfer(u8x8);
885 /* clear the lowest two bits of the adr */
886 u8x8_SetI2CAddress( u8x8, (u8x8_GetI2CAddress(u8x8)&0x0fc)|2 );
887 u8x8_byte_StartTransfer(u8x8);
888 }
889 }
890 else
891 {
892 /* clear the lowest two bits of the adr */
893 u8x8_SetI2CAddress( u8x8, (u8x8_GetI2CAddress(u8x8)&0x0fc)|2 );
894 u8x8_byte_StartTransfer(u8x8);
895 }
896 u8x8_byte_SendByte(u8x8, arg_int);
897 in_transfer = 1;
898 is_data = 1;
899 break;
900 case U8X8_MSG_CAD_SEND_DATA:
901 if ( in_transfer != 0 )
902 {
903 if ( is_data == 0 )
904 {
905 /* transfer mode is active, but data transfer */
906 u8x8_byte_EndTransfer(u8x8);
907 /* clear the lowest two bits of the adr */
908 u8x8_SetI2CAddress( u8x8, (u8x8_GetI2CAddress(u8x8)&0x0fc)|2 );
909 u8x8_byte_StartTransfer(u8x8);
910 }
911 }
912 else
913 {
914 /* clear the lowest two bits of the adr */
915 u8x8_SetI2CAddress( u8x8, (u8x8_GetI2CAddress(u8x8)&0x0fc)|2 );
916 u8x8_byte_StartTransfer(u8x8);
917 }
918 in_transfer = 1;
919 is_data = 1;
920
921 p = (uint8_t *)arg_ptr;
922 while( arg_int > 24 )
923 {
924 u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, 24, p);
925 arg_int-=24;
926 p+=24;
927 u8x8_byte_EndTransfer(u8x8);
928 u8x8_byte_StartTransfer(u8x8);
929 }
930 u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, p);
931
932 break;
933 case U8X8_MSG_CAD_INIT:
934 /* apply default i2c adr if required so that the start transfer msg can use this */
935 if ( u8x8->i2c_address == 255 )
936 u8x8->i2c_address = 0x078; /* see also https://github.com/olikraus/u8g2/issues/371 for a discussion on this value */
937 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
938 case U8X8_MSG_CAD_START_TRANSFER:
939 in_transfer = 0;
940 /* actual start is delayed, because we do not whether this is data or cmd transfer */
941 break;
942 case U8X8_MSG_CAD_END_TRANSFER:
943 if ( in_transfer != 0 )
944 u8x8_byte_EndTransfer(u8x8);
945 in_transfer = 0;
946 break;
947 default:
948 return 0;
949 }
950 return 1;
951}