Krolyxon
Commit 3120783

Branches

Tags

Refs →

orion-rf.piolibdepsesp32-s3-n16r8U8g2srcclibu8x8_d_st7528.c

461 lines · 14.3 KB · C

1/*
2
3 u8x8_d_st7528.c
4
5 Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
6
7 Copyright (c) 2019, 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 ST7528: 16 Graylevel Controller
35 https://github.com/olikraus/u8g2/issues/986
36 I2C Address: 0x03f (0x7e)
37
38
39 ERC16004
40 https://www.buydisplay.com/default/2-inch-lcd-160x64-graphic-module-serial-spi-display-st7528-black-on-white
41
42*/
43
44
45#include "u8x8.h"
46
47
48static const uint8_t u8x8_d_st7528_powersave0_seq[] = {
49 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
50 U8X8_CA(0x038, 0x074), /* ext mode 0*/
51 U8X8_C(0x0af), /* display on */
52 U8X8_END_TRANSFER(), /* disable chip */
53 U8X8_END() /* end of sequence */
54};
55
56static const uint8_t u8x8_d_st7528_powersave1_seq[] = {
57 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
58 U8X8_CA(0x038, 0x074), /* ext mode 0*/
59 U8X8_C(0x0ae), /* display off */
60 U8X8_END_TRANSFER(), /* disable chip */
61 U8X8_END() /* end of sequence */
62};
63
64static const uint8_t u8x8_d_st7528_flip0_seq[] = {
65 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
66 U8X8_C(0x0a0), /* ADC */
67 U8X8_C(0x0c8), /* SHL */
68 U8X8_END_TRANSFER(), /* disable chip */
69 U8X8_END() /* end of sequence */
70};
71
72static const uint8_t u8x8_d_st7528_flip1_seq[] = {
73 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
74 U8X8_C(0x0a1), /* ADC */
75 U8X8_C(0x0c0), /* SHL */
76 U8X8_END_TRANSFER(), /* disable chip */
77 U8X8_END() /* end of sequence */
78};
79
80
81/*
82 input:
83 one tile (8 Bytes)
84 output:
85 Tile for st7528 (32 Bytes)
86*/
87
88static uint8_t u8x8_st7528_8to32_dest_buf[32];
89
90static uint8_t *u8x8_st7528_8to32(U8X8_UNUSED u8x8_t *u8x8, uint8_t *ptr)
91{
92 uint8_t j;
93 uint8_t *dest;
94
95 dest = u8x8_st7528_8to32_dest_buf;
96 for( j = 0; j < 8; j++ )
97 {
98 *dest++ =*ptr;
99 *dest++ =*ptr;
100 *dest++ =*ptr;
101 *dest++ =*ptr;
102 ptr++;
103 }
104 return u8x8_st7528_8to32_dest_buf;
105}
106
107
108
109static uint8_t u8x8_d_st7528_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
110{
111 uint8_t x;
112 uint8_t y, c;
113 uint8_t *ptr;
114 switch(msg)
115 {
116 /* handled by the calling function
117 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
118 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7528_display_info);
119 break;
120 case U8X8_MSG_DISPLAY_INIT:
121 u8x8_d_helper_display_init(u8x8);
122 u8x8_cad_SendSequence(u8x8, u8x8_d_st7528_nhd_c160100_init_seq);
123 */
124 break;
125 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
126 if ( arg_int == 0 )
127 u8x8_cad_SendSequence(u8x8, u8x8_d_st7528_powersave0_seq);
128 else
129 u8x8_cad_SendSequence(u8x8, u8x8_d_st7528_powersave1_seq);
130 break;
131 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
132 if ( arg_int == 0 )
133 {
134 u8x8_cad_SendSequence(u8x8, u8x8_d_st7528_flip0_seq);
135 u8x8->x_offset = u8x8->display_info->default_x_offset;
136 }
137 else
138 {
139 u8x8_cad_SendSequence(u8x8, u8x8_d_st7528_flip1_seq);
140 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
141 }
142 break;
143#ifdef U8X8_WITH_SET_CONTRAST
144 case U8X8_MSG_DISPLAY_SET_CONTRAST:
145 u8x8_cad_StartTransfer(u8x8);
146 u8x8_cad_SendCmd(u8x8, 0x081 );
147 u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1326 has range from 0 to 255 */
148 u8x8_cad_EndTransfer(u8x8);
149 break;
150#endif
151 case U8X8_MSG_DISPLAY_DRAW_TILE:
152 u8x8_cad_StartTransfer(u8x8);
153 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
154 x *= 8; // not clear
155
156 y = (((u8x8_tile_t *)arg_ptr)->y_pos);
157
158
159
160 do
161 {
162 c = ((u8x8_tile_t *)arg_ptr)->cnt;
163 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
164
165 do
166 {
167 u8x8_cad_SendCmd(u8x8, 0xb0 | y ); /* set page address */
168 u8x8_cad_SendCmd(u8x8, 0x10| (x>>4) ); /* set col msb*/
169 u8x8_cad_SendCmd(u8x8, 0x00| (x&15) ); /* set col lsb*/
170
171 u8x8_cad_SendData(u8x8, 32, u8x8_st7528_8to32(u8x8, ptr));
172
173 ptr += 8;
174 x += 8;
175 c--;
176 } while( c > 0 );
177 arg_int--;
178 } while( arg_int > 0 );
179
180 u8x8_cad_EndTransfer(u8x8);
181 break;
182 default:
183 return 0;
184 }
185 return 1;
186}
187
188
189static void u8x8_d_st7528_graylevel_init(u8x8_t *u8x8, uint8_t mode0)
190{
191 uint8_t i;
192
193 u8x8_cad_StartTransfer(u8x8);
194 u8x8_cad_SendCmd(u8x8, 0x38 );
195 u8x8_cad_SendArg(u8x8, mode0+1 );
196 for( i = 0; i < 64; i++ )
197 {
198 u8x8_cad_SendCmd(u8x8, i+0x080 );
199 u8x8_cad_SendArg(u8x8, i & 0xfc);
200 }
201 u8x8_cad_SendCmd(u8x8, 0x38 );
202 u8x8_cad_SendArg(u8x8, mode0 );
203 u8x8_cad_EndTransfer(u8x8);
204}
205
206/*===============================================================*/
207/* NHD C160100 */
208static const uint8_t u8x8_d_st7528_nhd_c160100_init_seq[] = {
209
210 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
211
212
213/*
214 I2C_out(0x48);//partial display duty ratio
215 I2C_out(0x64);// 1/100 duty
216 I2C_out(0xA0);//ADC select
217 I2C_out(0xC8);//SHL select
218 I2C_out(0x44);//initial Com0 register
219 I2C_out(0x00);//scan from Com0
220 I2C_out(0xAB);//OSC on
221 I2C_out(0x26);//
222 I2C_out(0x81); //set electronic volume
223 I2C_out(0x15);//vopcode=0x1C
224 I2C_out(0x56);//set 1/11 bias
225 I2C_out(0x64);//3x
226 delay(2);
227 I2C_out(0x2C);//
228 I2C_out(0x66);//5x
229 delay(2);
230 I2C_out(0x2E);//
231 delay(2);
232 I2C_out(0x2F);//power control
233 I2C_out(0xF3);//bias save circuit
234 I2C_out(0x00);//
235 I2C_out(0x96);//frc and pwm
236 I2C_out(0x38);//external mode
237 I2C_out(0x75);//
238 I2C_out(0x97);//3frc, 45 pwm THIS IS A MODE0 CMD, IT IS USELESS HERE
239 I2C_out(0x80);//start 16-level grayscale settings
240*/
241 U8X8_CA(0x038, 0x064), /* ext mode 0*/
242 U8X8_CA(0x048, 0x064), /* partial display duty ratio, 1/100 duty*/
243 U8X8_C(0x0a0), /* ADC */
244 U8X8_C(0x0c8), /* SHL */
245 U8X8_CA(0x044, 0x000), /* initial Com0 */
246 U8X8_CA(0x040, 0x000), /* y shift, issue https://github.com/olikraus/u8g2/issues/1828 */
247 U8X8_C(0x0ab), /* start oscillator */
248 U8X8_C(0x026), /* Select the internal resistance ratio of the regulator resistor */
249 U8X8_CA(0x081, 0x015), /* volumn */
250 U8X8_C(0x056), /* LCD Bias */
251 U8X8_C(0x064), /* DC DC step up */
252 U8X8_DLY(2),
253 U8X8_C(0x02c), /* Power Control */
254 U8X8_C(0x066), /* DC DC step up */
255 U8X8_DLY(2),
256 U8X8_C(0x02e), /* Power Control */
257 U8X8_DLY(2),
258 U8X8_C(0x02f), /* Power Control */
259 U8X8_CA(0x0f3, 0x000), /* bias power save */
260 U8X8_C(0x096), /* frc and pwm */
261
262 U8X8_END_TRANSFER(), /* disable chip */
263 U8X8_END() /* end of sequence */
264};
265
266static const u8x8_display_info_t u8x8_st7528_160x100_display_info =
267{
268 /* chip_enable_level = */ 0,
269 /* chip_disable_level = */ 1,
270
271 /* post_chip_enable_wait_ns = */ 20,
272 /* pre_chip_disable_wait_ns = */ 20,
273 /* reset_pulse_width_ms = */ 5,
274 /* post_reset_wait_ms = */ 5, /**/
275 /* sda_setup_time_ns = */ 20, /* st7528 */
276 /* sck_pulse_width_ns = */ 25, /* st7528 */
277 /* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
278 /* st7528 actually allows 20MHz according to the datasheet */
279 /* spi_mode = */ 0, /* active high, rising edge */
280 /* i2c_bus_clock_100kHz = */ 4,
281 /* data_setup_time_ns = */ 40,
282 /* write_pulse_width_ns = */ 80, /* st7528 */
283 /* tile_width = */ 20,
284 /* tile_height = */ 13,
285 /* default_x_offset = */ 0, /* x_offset is used as y offset for the ssd1326 */
286 /* flipmode_x_offset = */ 0, /* x_offset is used as y offset for the ssd1326 */
287 /* pixel_width = */ 160,
288 /* pixel_height = */ 100
289};
290
291uint8_t u8x8_d_st7528_nhd_c160100(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
292{
293 if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
294 {
295 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7528_160x100_display_info);
296 return 1;
297 }
298 if ( msg == U8X8_MSG_DISPLAY_INIT )
299 {
300 u8x8_d_helper_display_init(u8x8);
301 u8x8_cad_SendSequence(u8x8, u8x8_d_st7528_nhd_c160100_init_seq);
302 u8x8_d_st7528_graylevel_init(u8x8, 0x074);
303 return 1;
304 }
305 return u8x8_d_st7528_generic(u8x8, msg, arg_int, arg_ptr);
306}
307
308/*===============================================================*/
309/* ERC16064, https://www.buydisplay.com/2-inch-lcd-160x64-graphic-module-serial-spi-display-st7528-black-on-white */
310
311/*
312
313#define ModeSet 0x38
314#define ModeSetP1 0x64 //EXT=0
315#define ModeSetP2 0x65 //EXT=1
316
317#define Display_on 0xaf
318#define Display_off 0xae
319
320#define Regulator 0x26
321#define Contrast_level 0x81
322#define PowerControll_on1 0x2c
323#define PowerControll_on2 0x2e
324#define PowerControll_on3 0x2f
325
326#define LcdBias_9 0x54
327#define InterOsc_on 0xab
328#define EntireDisp_on 0xa5
329#define EntireDisp_off 0xa4
330#define BoostLevel_5 0x66
331#define Duty_set 0x48
332#define Duty_setP 0x40
333#define Start_columnlsb 0x00
334#define Start_columnmsb 0x10
335#define Start_page 0xb0
336#define StartLine_set 0x40
337//#define StartLine_setP 0x00
338#define Set_Initial_COM0 0x44
339#define Set_Initial_COM0P 0x12
340
341
342#define Entire_Displa_ON 0xA5
343#define Entire_Displa_OFF 0xA4
344
345#define FrcPwm_set 0x92
346#define NLineInversion_on 0x4c
347#define NLineInversion_onP 0x1f
348#define NLineInversion_off 0xe4
349#define ReverseDisp_on 0xa7
350#define ReverseDisp_off 0xa6
351#define AdcSelect 0xa0
352#define ComScanDirection 0xc8
353
354 Write_command(ModeSet); 0x38, 0x64
355 Write_command(ModeSetP1);
356 Write_command(InterOsc_on); 0xab
357 Write_command(Set_Initial_COM0); 0x44, 0x12
358 Write_command(Set_Initial_COM0P);
359
360 Write_command(AdcSelect); 0xa0
361 Write_command(ComScanDirection); 0xc8
362 Write_command(BoostLevel_5); 0x66
363 Delay(1000);
364 Write_command(LcdBias_9); 0x54
365 Write_command(Duty_set); 0x48, 0x40
366 Write_command(Duty_setP);
367 Write_command(Regulator); 0x26
368 Write_command(Contrast_level); 0x81, 0x0b
369 Write_command(Contrast_levelP);
370 Write_command(PowerControll_on1); 0x2c
371 Delay(10000);
372 Write_command(PowerControll_on2); 0x2e
373 Delay(1000);
374 Write_command(PowerControll_on3); 0x2f
375 Delay(1000);
376 Write_command(FrcPwm_set); 0x92
377
378 Write_command(ModeSet);
379 Write_command(ModeSetP2);
380 for(i=0;i<64;i++)
381 {
382 Write_command(0x80+i);
383 Write_command(Gray_Parameters[i]);
384 }
385 Write_command(ModeSet);
386 Write_command(ModeSetP1);
387*/
388
389static const uint8_t u8x8_d_st7528_erc16064_init_seq[] = {
390 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
391 U8X8_CA(0x038, 0x064), /* ext mode 0*/
392 U8X8_C(0x0ab), /* start oscillator */
393 U8X8_CA(0x044, 0x012), /* initial Com0 */
394 U8X8_C(0x0a0), /* ADC */
395 U8X8_C(0x0c8), /* SHL */
396 U8X8_C(0x066), /* boost level, ERC16064: 0x066 */
397 U8X8_DLY(1),
398 U8X8_C(0x054), /* LCD Bias, ERC16064: 0x054 */
399 U8X8_CA(0x048, 0x040), /* partial display duty ratio */
400 U8X8_C(0x026), /* Select the internal resistance ratio of the regulator resistor */
401 U8X8_CA(0x081, 0x00b), /* contrast, ERC16064: 0x00b */
402
403 U8X8_C(0x02c), /* Power Control */
404 U8X8_DLY(2),
405 U8X8_C(0x02e), /* Power Control */
406 U8X8_DLY(2),
407 U8X8_C(0x02f), /* Power Control */
408 U8X8_DLY(2),
409 U8X8_C(0x092), /* frc and pwm, ERC160624: 0x092 */
410
411
412
413 U8X8_END_TRANSFER(), /* disable chip */
414 U8X8_END() /* end of sequence */
415};
416
417
418static const u8x8_display_info_t u8x8_st7528_erc16064_display_info =
419{
420 /* chip_enable_level = */ 0,
421 /* chip_disable_level = */ 1,
422
423 /* post_chip_enable_wait_ns = */ 20,
424 /* pre_chip_disable_wait_ns = */ 20,
425 /* reset_pulse_width_ms = */ 5,
426 /* post_reset_wait_ms = */ 5, /**/
427 /* sda_setup_time_ns = */ 20, /* st7528 */
428 /* sck_pulse_width_ns = */ 25, /* st7528 */
429 /* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
430 /* st7528 actually allows 20MHz according to the datasheet */
431 /* spi_mode = */ 0, /* active high, rising edge */
432 /* i2c_bus_clock_100kHz = */ 4,
433 /* data_setup_time_ns = */ 40,
434 /* write_pulse_width_ns = */ 80, /* st7528 */
435 /* tile_width = */ 20,
436 /* tile_height = */ 8,
437 /* default_x_offset = */ 0, /* x_offset is used as y offset for the ssd1326 */
438 /* flipmode_x_offset = */ 0, /* x_offset is used as y offset for the ssd1326 */
439 /* pixel_width = */ 160,
440 /* pixel_height = */ 64
441};
442
443
444uint8_t u8x8_d_st7528_erc16064(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
445{
446 if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
447 {
448 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7528_erc16064_display_info);
449 return 1;
450 }
451 if ( msg == U8X8_MSG_DISPLAY_INIT )
452 {
453 u8x8_d_helper_display_init(u8x8);
454 u8x8_cad_SendSequence(u8x8, u8x8_d_st7528_erc16064_init_seq);
455 u8x8_d_st7528_graylevel_init(u8x8, 0x064);
456 return 1;
457 }
458 return u8x8_d_st7528_generic(u8x8, msg, arg_int, arg_ptr);
459}
460
461