components/u8g2/csrc/u8x8_cad.c

changeset 0
88d965579617
equal deleted inserted replaced
-1:000000000000 0:88d965579617
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 /*
53 uint8_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
88 uint8_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
93 uint8_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
98 uint8_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
108 uint8_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
113 uint8_t u8x8_cad_StartTransfer(u8x8_t *u8x8)
114 {
115 return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 0, NULL);
116 }
117
118 uint8_t u8x8_cad_EndTransfer(u8x8_t *u8x8)
119 {
120 return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
121 }
122
123 void 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
141 void 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
159 void 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
197 uint8_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 */
224 uint8_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 t6963
256 */
257 uint8_t u8x8_cad_100(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
258 {
259 switch(msg)
260 {
261 case U8X8_MSG_CAD_SEND_CMD:
262 u8x8_byte_SetDC(u8x8, 1);
263 u8x8_byte_SendByte(u8x8, arg_int);
264 break;
265 case U8X8_MSG_CAD_SEND_ARG:
266 u8x8_byte_SetDC(u8x8, 0);
267 u8x8_byte_SendByte(u8x8, arg_int);
268 break;
269 case U8X8_MSG_CAD_SEND_DATA:
270 u8x8_byte_SetDC(u8x8, 0);
271 //u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
272 //break;
273 /* fall through */
274 case U8X8_MSG_CAD_INIT:
275 case U8X8_MSG_CAD_START_TRANSFER:
276 case U8X8_MSG_CAD_END_TRANSFER:
277 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
278 default:
279 return 0;
280 }
281 return 1;
282 }
283
284 /*
285 convert to bytes by using
286 dc = 0 for commands and args and
287 dc = 1 for data
288 */
289 uint8_t u8x8_cad_001(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
290 {
291 switch(msg)
292 {
293 case U8X8_MSG_CAD_SEND_CMD:
294 u8x8_byte_SetDC(u8x8, 0);
295 u8x8_byte_SendByte(u8x8, arg_int);
296 break;
297 case U8X8_MSG_CAD_SEND_ARG:
298 u8x8_byte_SetDC(u8x8, 0);
299 u8x8_byte_SendByte(u8x8, arg_int);
300 break;
301 case U8X8_MSG_CAD_SEND_DATA:
302 u8x8_byte_SetDC(u8x8, 1);
303 //u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
304 //break;
305 /* fall through */
306 case U8X8_MSG_CAD_INIT:
307 case U8X8_MSG_CAD_START_TRANSFER:
308 case U8X8_MSG_CAD_END_TRANSFER:
309 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
310 default:
311 return 0;
312 }
313 return 1;
314 }
315
316 /*
317 convert to bytes by using
318 dc = 0 for commands
319 dc = 1 for args and data
320 */
321 uint8_t u8x8_cad_011(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
322 {
323 switch(msg)
324 {
325 case U8X8_MSG_CAD_SEND_CMD:
326 u8x8_byte_SetDC(u8x8, 0);
327 u8x8_byte_SendByte(u8x8, arg_int);
328 break;
329 case U8X8_MSG_CAD_SEND_ARG:
330 u8x8_byte_SetDC(u8x8, 1);
331 u8x8_byte_SendByte(u8x8, arg_int);
332 break;
333 case U8X8_MSG_CAD_SEND_DATA:
334 u8x8_byte_SetDC(u8x8, 1);
335 //u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
336 //break;
337 /* fall through */
338 case U8X8_MSG_CAD_INIT:
339 case U8X8_MSG_CAD_START_TRANSFER:
340 case U8X8_MSG_CAD_END_TRANSFER:
341 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
342 default:
343 return 0;
344 }
345 return 1;
346 }
347
348 /* cad procedure for the ST7920 in SPI mode */
349 /* u8x8_byte_SetDC is not used */
350 uint8_t u8x8_cad_st7920_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
351 {
352 uint8_t *data;
353 uint8_t b;
354 uint8_t i;
355 static uint8_t buf[16];
356 uint8_t *ptr;
357
358 switch(msg)
359 {
360 case U8X8_MSG_CAD_SEND_CMD:
361 u8x8_byte_SendByte(u8x8, 0x0f8);
362 u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
363 u8x8_byte_SendByte(u8x8, arg_int & 0x0f0);
364 u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
365 u8x8_byte_SendByte(u8x8, arg_int << 4);
366 u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
367 break;
368 case U8X8_MSG_CAD_SEND_ARG:
369 u8x8_byte_SendByte(u8x8, 0x0f8);
370 u8x8_byte_SendByte(u8x8, arg_int & 0x0f0);
371 u8x8_byte_SendByte(u8x8, arg_int << 4);
372 break;
373 case U8X8_MSG_CAD_SEND_DATA:
374
375 u8x8_byte_SendByte(u8x8, 0x0fa);
376 u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
377
378 /* this loop should be optimized: multiple bytes should be sent */
379 /* u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr); */
380 data = (uint8_t *)arg_ptr;
381
382 /* the following loop increases speed by 20% */
383 while( arg_int >= 8 )
384 {
385 i = 8;
386 ptr = buf;
387 do
388 {
389 b = *data++;
390 *ptr++= b & 0x0f0;
391 b <<= 4;
392 *ptr++= b;
393 i--;
394 } while( i > 0 );
395 arg_int -= 8;
396 u8x8_byte_SendBytes(u8x8, 16, buf);
397 }
398
399
400 while( arg_int > 0 )
401 {
402 b = *data;
403 u8x8_byte_SendByte(u8x8, b & 0x0f0);
404 u8x8_byte_SendByte(u8x8, b << 4);
405 data++;
406 arg_int--;
407 }
408 u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
409 break;
410 case U8X8_MSG_CAD_INIT:
411 case U8X8_MSG_CAD_START_TRANSFER:
412 case U8X8_MSG_CAD_END_TRANSFER:
413 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
414 default:
415 return 0;
416 }
417 return 1;
418 }
419
420
421 /* cad procedure for the SSD13xx family in I2C mode */
422 /* this procedure is also used by the ST7588 */
423 /* u8x8_byte_SetDC is not used */
424 /* U8X8_MSG_BYTE_START_TRANSFER starts i2c transfer, U8X8_MSG_BYTE_END_TRANSFER stops transfer */
425 /* After transfer start, a full byte indicates command or data mode */
426
427 static void u8x8_i2c_data_transfer(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr) U8X8_NOINLINE;
428 static void u8x8_i2c_data_transfer(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr)
429 {
430 u8x8_byte_StartTransfer(u8x8);
431 u8x8_byte_SendByte(u8x8, 0x040);
432 u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, arg_ptr);
433 u8x8_byte_EndTransfer(u8x8);
434 }
435
436 /* classic version: will put a start/stop condition around each command and arg */
437 uint8_t u8x8_cad_ssd13xx_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
438 {
439 uint8_t *p;
440 switch(msg)
441 {
442 case U8X8_MSG_CAD_SEND_CMD:
443 case U8X8_MSG_CAD_SEND_ARG:
444 /* 7 Nov 2016: Can this be improved? */
445 //u8x8_byte_SetDC(u8x8, 0);
446 u8x8_byte_StartTransfer(u8x8);
447 //u8x8_byte_SendByte(u8x8, u8x8_GetI2CAddress(u8x8));
448 u8x8_byte_SendByte(u8x8, 0x000);
449 u8x8_byte_SendByte(u8x8, arg_int);
450 u8x8_byte_EndTransfer(u8x8);
451 break;
452 case U8X8_MSG_CAD_SEND_DATA:
453 //u8x8_byte_SetDC(u8x8, 1);
454
455 /* the FeatherWing OLED with the 32u4 transfer of long byte */
456 /* streams was not possible. This is broken down to */
457 /* smaller streams, 32 seems to be the limit... */
458 /* I guess this is related to the size of the Wire buffers in Arduino */
459 /* Unfortunately, this can not be handled in the byte level drivers, */
460 /* so this is done here. Even further, only 24 bytes will be sent, */
461 /* because there will be another byte (DC) required during the transfer */
462 p = arg_ptr;
463 while( arg_int > 24 )
464 {
465 u8x8_i2c_data_transfer(u8x8, 24, p);
466 arg_int-=24;
467 p+=24;
468 }
469 u8x8_i2c_data_transfer(u8x8, arg_int, p);
470 break;
471 case U8X8_MSG_CAD_INIT:
472 /* apply default i2c adr if required so that the start transfer msg can use this */
473 if ( u8x8->i2c_address == 255 )
474 u8x8->i2c_address = 0x078;
475 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
476 case U8X8_MSG_CAD_START_TRANSFER:
477 case U8X8_MSG_CAD_END_TRANSFER:
478 /* cad transfer commands are ignored */
479 break;
480 default:
481 return 0;
482 }
483 return 1;
484 }
485
486
487 /* fast version with reduced data start/stops, issue 735 */
488 uint8_t u8x8_cad_ssd13xx_fast_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
489 {
490 static uint8_t in_transfer = 0;
491 uint8_t *p;
492 switch(msg)
493 {
494 case U8X8_MSG_CAD_SEND_CMD:
495 /* improved version, takeover from ld7032 */
496 /* assumes, that the args of a command is not longer than 31 bytes */
497 /* speed improvement is about 4% compared to the classic version */
498 if ( in_transfer != 0 )
499 u8x8_byte_EndTransfer(u8x8);
500
501 u8x8_byte_StartTransfer(u8x8);
502 u8x8_byte_SendByte(u8x8, 0x000); /* cmd byte for ssd13xx controller */
503 u8x8_byte_SendByte(u8x8, arg_int);
504 in_transfer = 1;
505 /* lightning version: can replace the improved version from above */
506 /* the drawback of the lightning version is this: The complete init sequence */
507 /* must fit into the 32 byte Arduino Wire buffer, which might not always be the case */
508 /* speed improvement is about 6% compared to the classic version */
509 // if ( in_transfer == 0 )
510 // {
511 // u8x8_byte_StartTransfer(u8x8);
512 // u8x8_byte_SendByte(u8x8, 0x000); /* cmd byte for ssd13xx controller */
513 // in_transfer = 1;
514 // }
515 //u8x8_byte_SendByte(u8x8, arg_int);
516 break;
517 case U8X8_MSG_CAD_SEND_ARG:
518 u8x8_byte_SendByte(u8x8, arg_int);
519 break;
520 case U8X8_MSG_CAD_SEND_DATA:
521 if ( in_transfer != 0 )
522 u8x8_byte_EndTransfer(u8x8);
523
524
525 /* the FeatherWing OLED with the 32u4 transfer of long byte */
526 /* streams was not possible. This is broken down to */
527 /* smaller streams, 32 seems to be the limit... */
528 /* I guess this is related to the size of the Wire buffers in Arduino */
529 /* Unfortunately, this can not be handled in the byte level drivers, */
530 /* so this is done here. Even further, only 24 bytes will be sent, */
531 /* because there will be another byte (DC) required during the transfer */
532 p = arg_ptr;
533 while( arg_int > 24 )
534 {
535 u8x8_i2c_data_transfer(u8x8, 24, p);
536 arg_int-=24;
537 p+=24;
538 }
539 u8x8_i2c_data_transfer(u8x8, arg_int, p);
540 in_transfer = 0;
541 break;
542 case U8X8_MSG_CAD_INIT:
543 /* apply default i2c adr if required so that the start transfer msg can use this */
544 if ( u8x8->i2c_address == 255 )
545 u8x8->i2c_address = 0x078;
546 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
547 case U8X8_MSG_CAD_START_TRANSFER:
548 in_transfer = 0;
549 break;
550 case U8X8_MSG_CAD_END_TRANSFER:
551 if ( in_transfer != 0 )
552 u8x8_byte_EndTransfer(u8x8);
553 in_transfer = 0;
554 break;
555 default:
556 return 0;
557 }
558 return 1;
559 }
560
561
562
563 /* the st75256 i2c driver is a copy of the ssd13xx driver, but with arg=1 */
564 /* modified from cad001 (ssd13xx) to cad011 */
565 uint8_t u8x8_cad_st75256_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
566 {
567 uint8_t *p;
568 switch(msg)
569 {
570 case U8X8_MSG_CAD_SEND_CMD:
571 u8x8_byte_StartTransfer(u8x8);
572 u8x8_byte_SendByte(u8x8, 0x000);
573 u8x8_byte_SendByte(u8x8, arg_int);
574 u8x8_byte_EndTransfer(u8x8);
575 break;
576 case U8X8_MSG_CAD_SEND_ARG:
577 u8x8_byte_StartTransfer(u8x8);
578 u8x8_byte_SendByte(u8x8, 0x040);
579 u8x8_byte_SendByte(u8x8, arg_int);
580 u8x8_byte_EndTransfer(u8x8);
581 break;
582 case U8X8_MSG_CAD_SEND_DATA:
583 /* see ssd13xx driver */
584 p = arg_ptr;
585 while( arg_int > 24 )
586 {
587 u8x8_i2c_data_transfer(u8x8, 24, p);
588 arg_int-=24;
589 p+=24;
590 }
591 u8x8_i2c_data_transfer(u8x8, arg_int, p);
592 break;
593 case U8X8_MSG_CAD_INIT:
594 /* apply default i2c adr if required so that the start transfer msg can use this */
595 if ( u8x8->i2c_address == 255 )
596 u8x8->i2c_address = 0x078; /* ST75256, often this is 0x07e */
597 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
598 case U8X8_MSG_CAD_START_TRANSFER:
599 case U8X8_MSG_CAD_END_TRANSFER:
600 /* cad transfer commands are ignored */
601 break;
602 default:
603 return 0;
604 }
605 return 1;
606 }
607
608 /* cad i2c procedure for the ld7032 controller */
609 /* Issue https://github.com/olikraus/u8g2/issues/865 mentiones, that I2C does not work */
610 /* Workaround is to remove the while loop (or increase the value in the condition) */
611 uint8_t u8x8_cad_ld7032_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
612 {
613 static uint8_t in_transfer = 0;
614 uint8_t *p;
615 switch(msg)
616 {
617 case U8X8_MSG_CAD_SEND_CMD:
618 if ( in_transfer != 0 )
619 u8x8_byte_EndTransfer(u8x8);
620 u8x8_byte_StartTransfer(u8x8);
621 u8x8_byte_SendByte(u8x8, arg_int);
622 in_transfer = 1;
623 break;
624 case U8X8_MSG_CAD_SEND_ARG:
625 u8x8_byte_SendByte(u8x8, arg_int);
626 break;
627 case U8X8_MSG_CAD_SEND_DATA:
628 //u8x8_byte_SetDC(u8x8, 1);
629
630 /* the FeatherWing OLED with the 32u4 transfer of long byte */
631 /* streams was not possible. This is broken down to */
632 /* smaller streams, 32 seems to be the limit... */
633 /* I guess this is related to the size of the Wire buffers in Arduino */
634 /* Unfortunately, this can not be handled in the byte level drivers, */
635 /* so this is done here. Even further, only 24 bytes will be sent, */
636 /* because there will be another byte (DC) required during the transfer */
637 p = arg_ptr;
638 while( arg_int > 24 )
639 {
640 u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, 24, p);
641 arg_int-=24;
642 p+=24;
643 u8x8_byte_EndTransfer(u8x8);
644 u8x8_byte_StartTransfer(u8x8);
645 u8x8_byte_SendByte(u8x8, 0x08); /* data write for LD7032 */
646 }
647 u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, p);
648 break;
649 case U8X8_MSG_CAD_INIT:
650 /* apply default i2c adr if required so that the start transfer msg can use this */
651 if ( u8x8->i2c_address == 255 )
652 u8x8->i2c_address = 0x060;
653 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
654 case U8X8_MSG_CAD_START_TRANSFER:
655 in_transfer = 0;
656 break;
657 case U8X8_MSG_CAD_END_TRANSFER:
658 if ( in_transfer != 0 )
659 u8x8_byte_EndTransfer(u8x8);
660 break;
661 default:
662 return 0;
663 }
664 return 1;
665 }
666
667 /* cad procedure for the UC16xx family in I2C mode */
668 /* u8x8_byte_SetDC is not used */
669 /* DC bit is encoded into the adr byte */
670 uint8_t u8x8_cad_uc16xx_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
671 {
672 static uint8_t in_transfer = 0;
673 static uint8_t is_data = 0;
674 uint8_t *p;
675 switch(msg)
676 {
677 case U8X8_MSG_CAD_SEND_CMD:
678 case U8X8_MSG_CAD_SEND_ARG:
679 if ( in_transfer != 0 )
680 {
681 if ( is_data != 0 )
682 {
683 /* transfer mode is active, but data transfer */
684 u8x8_byte_EndTransfer(u8x8);
685 /* clear the lowest two bits of the adr */
686 u8x8_SetI2CAddress( u8x8, u8x8_GetI2CAddress(u8x8)&0x0fc );
687 u8x8_byte_StartTransfer(u8x8);
688 }
689 }
690 else
691 {
692 /* clear the lowest two bits of the adr */
693 u8x8_SetI2CAddress( u8x8, u8x8_GetI2CAddress(u8x8)&0x0fc );
694 u8x8_byte_StartTransfer(u8x8);
695 }
696 u8x8_byte_SendByte(u8x8, arg_int);
697 in_transfer = 1;
698 break;
699 case U8X8_MSG_CAD_SEND_DATA:
700 if ( in_transfer != 0 )
701 {
702 if ( is_data == 0 )
703 {
704 /* transfer mode is active, but data transfer */
705 u8x8_byte_EndTransfer(u8x8);
706 /* clear the lowest two bits of the adr */
707 u8x8_SetI2CAddress( u8x8, (u8x8_GetI2CAddress(u8x8)&0x0fc)|2 );
708 u8x8_byte_StartTransfer(u8x8);
709 }
710 }
711 else
712 {
713 /* clear the lowest two bits of the adr */
714 u8x8_SetI2CAddress( u8x8, (u8x8_GetI2CAddress(u8x8)&0x0fc)|2 );
715 u8x8_byte_StartTransfer(u8x8);
716 }
717 in_transfer = 1;
718
719 p = arg_ptr;
720 while( arg_int > 24 )
721 {
722 u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, 24, p);
723 arg_int-=24;
724 p+=24;
725 u8x8_byte_EndTransfer(u8x8);
726 u8x8_byte_StartTransfer(u8x8);
727 }
728 u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, p);
729
730 break;
731 case U8X8_MSG_CAD_INIT:
732 /* apply default i2c adr if required so that the start transfer msg can use this */
733 if ( u8x8->i2c_address == 255 )
734 u8x8->i2c_address = 0x070;
735 return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
736 case U8X8_MSG_CAD_START_TRANSFER:
737 in_transfer = 0;
738 /* actual start is delayed, because we do not whether this is data or cmd transfer */
739 break;
740 case U8X8_MSG_CAD_END_TRANSFER:
741 if ( in_transfer != 0 )
742 u8x8_byte_EndTransfer(u8x8);
743 in_transfer = 0;
744 break;
745 default:
746 return 0;
747 }
748 return 1;
749 }

mercurial