Krolyxon
Commit 1d55752

Branches

Tags

Refs →

orion-rf.piolibdepsesp32-s3-n16r8U8g2srcclibu8x8_d_s1d15300.c

474 lines · 15.8 KB · C

1/*
2
3 u8x8_d_s1d15300.c
4
5 WARNING: As of today, flip mode 1 doesn't seem to work (see issue 2063)
6
7 Created as a copy of u8x8_d_st7565.c, see https://github.com/olikraus/u8g2/issues/2063
8
9 Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
10
11 Copyright (c) 2022, olikraus@gmail.com
12 All rights reserved.
13
14 Redistribution and use in source and binary forms, with or without modification,
15 are permitted provided that the following conditions are met:
16
17 * Redistributions of source code must retain the above copyright notice, this list
18 of conditions and the following disclaimer.
19
20 * Redistributions in binary form must reproduce the above copyright notice, this
21 list of conditions and the following disclaimer in the documentation and/or other
22 materials provided with the distribution.
23
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
25 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
26 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
29 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
34 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37
38
39*/
40#include "u8x8.h"
41
42
43
44
45
46static const uint8_t u8x8_d_s1d15300_powersave0_seq[] = {
47 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
48 U8X8_C(0x0a4), /* all pixel off, see datasheet for the s1d15300 */
49 U8X8_C(0x0af), /* display on */
50 U8X8_END_TRANSFER(), /* disable chip */
51 U8X8_END() /* end of sequence */
52};
53
54static const uint8_t u8x8_d_s1d15300_powersave1_seq[] = {
55 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
56 U8X8_C(0x0ae), /* display off */
57 U8X8_C(0x0a5), /* enter powersafe, see datasheet for the s1d15300 */
58 U8X8_END_TRANSFER(), /* disable chip */
59 U8X8_END() /* end of sequence */
60};
61
62static const uint8_t u8x8_d_s1d15300_flip0_seq[] = {
63 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
64 U8X8_C(0x0a0), /* segment remap a0/a1*/
65 U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
66 U8X8_END_TRANSFER(), /* disable chip */
67 U8X8_END() /* end of sequence */
68};
69
70static const uint8_t u8x8_d_s1d15300_flip1_seq[] = {
71 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
72 U8X8_C(0x0a1), /* segment remap a0/a1*/
73 U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
74 U8X8_END_TRANSFER(), /* disable chip */
75 U8X8_END() /* end of sequence */
76};
77
78uint8_t u8x8_d_s1d15300_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
79{
80 uint8_t x, c;
81 uint8_t *ptr;
82 switch(msg)
83 {
84 case U8X8_MSG_DISPLAY_DRAW_TILE:
85 u8x8_cad_StartTransfer(u8x8);
86
87 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
88 x *= 8;
89 x += u8x8->x_offset;
90 u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
91 u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
92 u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
93
94 c = ((u8x8_tile_t *)arg_ptr)->cnt;
95 c *= 8;
96 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
97 /*
98 The following if condition checks the hardware limits of the st7565
99 controller: It is not allowed to write beyond the display limits.
100 This is in fact an issue within flip mode.
101 */
102 if ( c + x > 132u )
103 {
104 c = 132u;
105 c -= x;
106 }
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 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
116 if ( arg_int == 0 )
117 u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_powersave0_seq);
118 else
119 u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_powersave1_seq);
120 break;
121#ifdef U8X8_WITH_SET_CONTRAST
122 case U8X8_MSG_DISPLAY_SET_CONTRAST:
123 u8x8_cad_StartTransfer(u8x8);
124 u8x8_cad_SendCmd(u8x8, 0x080 | (arg_int >> 3) ); /* s1d15300 has only 5 bits for contrast */
125 u8x8_cad_EndTransfer(u8x8);
126 break;
127#endif
128 default:
129 return 0;
130 }
131 return 1;
132}
133
134
135/*================================================*/
136/* LM6023, S1D15300 controller, issue 2063 */
137
138static const u8x8_display_info_t u8x8_s1d15300_lm6023_display_info =
139{
140 /* chip_enable_level = */ 0,
141 /* chip_disable_level = */ 1,
142
143 /* post_chip_enable_wait_ns = */ 250, /* */
144 /* pre_chip_disable_wait_ns = */ 120, /* */
145 /* reset_pulse_width_ms = */ 1,
146 /* post_reset_wait_ms = */ 1,
147 /* sda_setup_time_ns = */ 200, /* */
148 /* sck_pulse_width_ns = */ 200, /* half of cycle time (100ns according to datasheet), AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
149 /* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
150 /* spi_mode = */ 0, /* active high, rising edge */
151 /* i2c_bus_clock_100kHz = */ 4,
152 /* data_setup_time_ns = */ 200, /* st7565 datasheet, table 24, tds8 */
153 /* write_pulse_width_ns = */ 200, /* st7565 datasheet, table 24, tcclw */
154 /* tile_width = */ 16, /* width of 16*8=128 pixel */
155 /* tile_height = */ 8,
156 /* default_x_offset = */ 0,
157 /* flipmode_x_offset = */ 4,
158 /* pixel_width = */ 128,
159 /* pixel_height = */ 64
160};
161
162
163static const uint8_t u8x8_d_s1d15300_lm6023_init_seq[] = {
164
165#ifdef OBSOLETE
166 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
167
168 U8X8_C(0x0e2), /* soft reset */
169 U8X8_C(0x0ae), /* display off */
170 U8X8_C(0x040), /* set display start line to 0 */
171
172 U8X8_C(0x0a1), /* ADC set to reverse */
173 U8X8_C(0x0c0), /* common output mode */
174 // Flipmode
175 //U8X8_C(0x0a0), /* ADC set to reverse */
176 //U8X8_C(0x0c8), /* common output mode */
177
178 U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
179 U8X8_C(0x0a2), /* LCD bias 1/9 */
180 U8X8_C(0x02f), /* all power control circuits on */
181 U8X8_CA(0x0f8, 0x000), /* set booster ratio to 4x */
182 U8X8_C(0x025), /* set V0 voltage resistor ratio to large, issue 1678: changed from 0x23 to 0x25 */
183 U8X8_CA(0x081, 170), /* set contrast, contrast value NHD C12864, see issue 186, increased contrast to 180 (issue 219), reduced to 170 (issue 1678) */
184
185 U8X8_C(0x0ae), /* display off */
186 U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
187
188 U8X8_END_TRANSFER(), /* disable chip */
189 U8X8_END() /* end of sequence */
190#endif
191
192
193 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
194
195 U8X8_C(0x0e2), /* soft reset */
196
197 U8X8_C(0x0ae), /* display off */
198 U8X8_C(0x040), /* set display start line to 0 */
199 U8X8_C(0x0a0), /* ADC set to normal */
200 U8X8_C(0x0a6), /* Display normal */
201 U8X8_C(0x0a4), /* all point normal */
202
203 U8X8_C(0x0a2), /* LCD bias 1/8 */
204 U8X8_C(0x0c0), /* common output mode */
205 U8X8_C(0x02f), /* all power control circuits on */
206
207
208 U8X8_C(0x090), /* set contrast */
209 //U8X8_C(0x0af), /* display on */
210
211 U8X8_C(0x0b0), /* set page address */
212 U8X8_C(0x01f), /* set column address upper */
213 U8X8_C(0x000), /* set column address lower */
214
215 U8X8_END_TRANSFER(), /* disable chip */
216 U8X8_END() /* end of sequence */
217};
218
219uint8_t u8x8_d_s1d15300_lm6023(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
220{
221 /* call common procedure first and handle messages there */
222 if ( u8x8_d_s1d15300_common(u8x8, msg, arg_int, arg_ptr) == 0 )
223 {
224 /* msg not handled, then try here */
225 switch(msg)
226 {
227 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
228 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_s1d15300_lm6023_display_info);
229 break;
230 case U8X8_MSG_DISPLAY_INIT:
231 u8x8_d_helper_display_init(u8x8);
232 u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_lm6023_init_seq);
233 break;
234 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
235 if ( arg_int == 0 )
236 {
237 u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_flip0_seq);
238 u8x8->x_offset = u8x8->display_info->default_x_offset;
239 }
240 else
241 {
242 u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_flip1_seq);
243 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
244 }
245 break;
246 default:
247 return 0; /* msg unknown */
248 }
249 }
250 return 1;
251}
252
253/*================================================*/
254/* https://github.com/olikraus/u8g2/issues/2377 */
255
256static const u8x8_display_info_t u8x8_s1d15300_97x32_display_info =
257{
258 /* chip_enable_level = */ 0,
259 /* chip_disable_level = */ 1,
260
261 /* post_chip_enable_wait_ns = */ 250, /* */
262 /* pre_chip_disable_wait_ns = */ 120, /* */
263 /* reset_pulse_width_ms = */ 1,
264 /* post_reset_wait_ms = */ 1,
265 /* sda_setup_time_ns = */ 200, /* */
266 /* sck_pulse_width_ns = */ 200, /* half of cycle time (100ns according to datasheet), AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
267 /* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
268 /* spi_mode = */ 0, /* active high, rising edge */
269 /* i2c_bus_clock_100kHz = */ 4,
270 /* data_setup_time_ns = */ 200, /* st7565 datasheet, table 24, tds8 */
271 /* write_pulse_width_ns = */ 200, /* st7565 datasheet, table 24, tcclw */
272 /* tile_width = */ 13, /* width of 16*8=128 pixel */
273 /* tile_height = */ 4,
274 /* default_x_offset = */ 0,
275 /* flipmode_x_offset = */ 0,
276 /* pixel_width = */ 97,
277 /* pixel_height = */ 32
278};
279
280
281static const u8x8_display_info_t u8x8_s1d15300_100x32_display_info =
282{
283 /* chip_enable_level = */ 0,
284 /* chip_disable_level = */ 1,
285
286 /* post_chip_enable_wait_ns = */ 250, /* */
287 /* pre_chip_disable_wait_ns = */ 120, /* */
288 /* reset_pulse_width_ms = */ 1,
289 /* post_reset_wait_ms = */ 1,
290 /* sda_setup_time_ns = */ 200, /* */
291 /* sck_pulse_width_ns = */ 200, /* half of cycle time (100ns according to datasheet), AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
292 /* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
293 /* spi_mode = */ 0, /* active high, rising edge */
294 /* i2c_bus_clock_100kHz = */ 4,
295 /* data_setup_time_ns = */ 200, /* st7565 datasheet, table 24, tds8 */
296 /* write_pulse_width_ns = */ 200, /* st7565 datasheet, table 24, tcclw */
297 /* tile_width = */ 13, /* width of 16*8=128 pixel */
298 /* tile_height = */ 4,
299 /* default_x_offset = */ 0,
300 /* flipmode_x_offset = */ 0,
301 /* pixel_width = */ 100,
302 /* pixel_height = */ 32
303};
304
305static const u8x8_display_info_t u8x8_s1d15300_100x32i_display_info =
306{
307 /* chip_enable_level = */ 1,
308 /* chip_disable_level = */ 0,
309
310 /* post_chip_enable_wait_ns = */ 250, /* */
311 /* pre_chip_disable_wait_ns = */ 120, /* */
312 /* reset_pulse_width_ms = */ 1,
313 /* post_reset_wait_ms = */ 1,
314 /* sda_setup_time_ns = */ 200, /* */
315 /* sck_pulse_width_ns = */ 200, /* half of cycle time (100ns according to datasheet), AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
316 /* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
317 /* spi_mode = */ 0, /* active high, rising edge */
318 /* i2c_bus_clock_100kHz = */ 4,
319 /* data_setup_time_ns = */ 200, /* st7565 datasheet, table 24, tds8 */
320 /* write_pulse_width_ns = */ 200, /* st7565 datasheet, table 24, tcclw */
321 /* tile_width = */ 13, /* width of 16*8=128 pixel */
322 /* tile_height = */ 4,
323 /* default_x_offset = */ 0,
324 /* flipmode_x_offset = */ 0,
325 /* pixel_width = */ 100,
326 /* pixel_height = */ 32
327};
328
329
330static const uint8_t u8x8_d_s1d15300_100x32_init_seq[] = {
331
332
333 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
334
335 U8X8_C(0x0e2), /* soft reset */
336
337 U8X8_C(0x0ae), /* display off */
338 U8X8_C(0x040), /* set display start line to 0 */
339 U8X8_C(0x0a0), /* ADC set to normal */
340 U8X8_C(0x0a6), /* Display normal */
341 U8X8_C(0x0a4), /* all point normal */
342
343 U8X8_C(0x0a2), /* LCD bias 1/8 */
344 U8X8_C(0x0c8), /* common output mode */
345 U8X8_C(0x02f), /* power, might be 0x02c */
346
347
348 U8X8_C(0x094), /* set contrast */
349 //U8X8_C(0x0af), /* display on */
350
351 U8X8_C(0x0b0), /* set page address */
352 U8X8_C(0x010), /* set column address upper */
353 U8X8_C(0x000), /* set column address lower */
354
355 U8X8_END_TRANSFER(), /* disable chip */
356 U8X8_END() /* end of sequence */
357};
358
359uint8_t u8x8_d_s1d15300_97x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
360{
361 /* call common procedure first and handle messages there */
362 if ( u8x8_d_s1d15300_common(u8x8, msg, arg_int, arg_ptr) == 0 )
363 {
364 /* msg not handled, then try here */
365 switch(msg)
366 {
367 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
368 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_s1d15300_97x32_display_info);
369 break;
370 case U8X8_MSG_DISPLAY_INIT:
371 u8x8_d_helper_display_init(u8x8);
372 u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_100x32_init_seq);
373 break;
374 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
375 /* needs to be fixed regarding a0/c0 */
376 /*
377 if ( arg_int == 0 )
378 {
379 u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_flip0_seq);
380 u8x8->x_offset = u8x8->display_info->default_x_offset;
381 }
382 else
383 {
384 u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_flip1_seq);
385 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
386 }
387 */
388 break;
389 default:
390 return 0; /* msg unknown */
391 }
392 }
393 return 1;
394}
395
396
397uint8_t u8x8_d_s1d15300_100x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
398{
399 /* call common procedure first and handle messages there */
400 if ( u8x8_d_s1d15300_common(u8x8, msg, arg_int, arg_ptr) == 0 )
401 {
402 /* msg not handled, then try here */
403 switch(msg)
404 {
405 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
406 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_s1d15300_100x32_display_info);
407 break;
408 case U8X8_MSG_DISPLAY_INIT:
409 u8x8_d_helper_display_init(u8x8);
410 u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_100x32_init_seq);
411 break;
412 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
413 /* needs to be fixed regarding a0/c0 */
414 /*
415 if ( arg_int == 0 )
416 {
417 u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_flip0_seq);
418 u8x8->x_offset = u8x8->display_info->default_x_offset;
419 }
420 else
421 {
422 u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_flip1_seq);
423 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
424 }
425 */
426 break;
427 default:
428 return 0; /* msg unknown */
429 }
430 }
431 return 1;
432}
433
434uint8_t u8x8_d_s1d15300_100x32i(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
435{
436 /* call common procedure first and handle messages there */
437 if ( u8x8_d_s1d15300_common(u8x8, msg, arg_int, arg_ptr) == 0 )
438 {
439 /* msg not handled, then try here */
440 switch(msg)
441 {
442 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
443 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_s1d15300_100x32i_display_info);
444 break;
445 case U8X8_MSG_DISPLAY_INIT:
446 u8x8_d_helper_display_init(u8x8);
447 u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_100x32_init_seq);
448 break;
449 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
450 /* needs to be fixed regarding a0/c0 */
451 /*
452 if ( arg_int == 0 )
453 {
454 u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_flip0_seq);
455 u8x8->x_offset = u8x8->display_info->default_x_offset;
456 }
457 else
458 {
459 u8x8_cad_SendSequence(u8x8, u8x8_d_s1d15300_flip1_seq);
460 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
461 }
462 */
463 break;
464 default:
465 return 0; /* msg unknown */
466 }
467 }
468 return 1;
469}
470
471
472/*================================================*/
473
474