Krolyxon
Commit 1d55752

Branches

Tags

Refs →

orion-rf.piolibdepsesp32-s3-n16r8U8g2srcclibu8x8_d_st7920.c

406 lines · 14.0 KB · C

1/*
2
3 u8x8_d_st7920.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 The ST7920 controller does not support hardware graphics flip.
36 Contrast adjustment is done by an external resistor --> no support for contrast adjustment
37
38
39*/
40#include "u8x8.h"
41
42
43
44static const uint8_t u8x8_d_st7920_init_seq[] = {
45
46 U8X8_DLY(100),
47 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
48 U8X8_DLY(10),
49
50 U8X8_C(0x038), /* 8 Bit interface (DL=1), basic instruction set (RE=0) */
51 U8X8_C(0x008), /* display on, cursor & blink off; 0x08: all off */
52 U8X8_C(0x006), /* Entry mode: Cursor move to right ,DDRAM address counter (AC) plus 1, no shift */
53 U8X8_C(0x002), /* disable scroll, enable CGRAM adress */
54 U8X8_C(0x001), /* clear RAM, needs 1.6 ms */
55 U8X8_DLY(10), /* delay 10ms */
56
57
58 U8X8_END_TRANSFER(), /* disable chip */
59 U8X8_END() /* end of sequence */
60};
61
62static const uint8_t u8x8_d_st7920_powersave0_seq[] = {
63 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
64 U8X8_C(0x038), /* 8 Bit interface (DL=1), basic instruction set (RE=0) */
65 U8X8_C(0x00c), /* display on, cursor & blink off */
66 U8X8_END_TRANSFER(), /* disable chip */
67 U8X8_END() /* end of sequence */
68};
69
70static const uint8_t u8x8_d_st7920_powersave1_seq[] = {
71 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
72 U8X8_C(0x038), /* 8 Bit interface (DL=1), basic instruction set (RE=0) */
73 U8X8_C(0x008), /* display off */
74 U8X8_C(0x034), /* 8 Bit interface (DL=1), extended instruction set (RE=1) */
75 U8X8_C(0x001), /* Standby mode */
76
77 U8X8_END_TRANSFER(), /* disable chip */
78 U8X8_END() /* end of sequence */
79};
80
81
82uint8_t u8x8_d_st7920_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
83{
84 uint8_t x, y, c, i;
85 uint8_t *ptr;
86 switch(msg)
87 {
88 /* U8X8_MSG_DISPLAY_SETUP_MEMORY is handled by the calling function */
89 /*
90 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
91 break;
92 */
93 case U8X8_MSG_DISPLAY_INIT:
94 u8x8_d_helper_display_init(u8x8);
95 u8x8_cad_SendSequence(u8x8, u8x8_d_st7920_init_seq);
96 break;
97 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
98 if ( arg_int == 0 )
99 u8x8_cad_SendSequence(u8x8, u8x8_d_st7920_powersave0_seq);
100 else
101 u8x8_cad_SendSequence(u8x8, u8x8_d_st7920_powersave1_seq);
102 break;
103 case U8X8_MSG_DISPLAY_DRAW_TILE:
104 y = (((u8x8_tile_t *)arg_ptr)->y_pos);
105 y*=8;
106 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
107 x /= 2; /* not sure whether this is a clever idea, problem is, the ST7920 can address only every second tile */
108
109 if ( y >= 32 ) /* this is the adjustment for 128x64 displays */
110 {
111 y-=32;
112 x+=8;
113 }
114
115 u8x8_cad_StartTransfer(u8x8);
116
117
118 /*
119 Tile structure is reused here for the ST7920, however u8x8 is not supported
120 tile_ptr points to data which has cnt*8 bytes (same as SSD1306 tiles)
121 Buffer is expected to have 8 lines of code fitting to the ST7920 internal memory
122 "cnt" includes the number of horizontal bytes. width is equal to cnt*8
123 Also important: Width must be a multiple of 16 (ST7920 requirement), so cnt must be even.
124
125 TODO: Consider arg_int, however arg_int is not used by u8g2
126 */
127 c = ((u8x8_tile_t *)arg_ptr)->cnt; /* number of tiles */
128 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr; /* data ptr to the tiles */
129 /* The following byte is sent to allow the ST7920 to sync up with the data */
130 /* it solves some issues with garbage data */
131 u8x8_cad_SendCmd(u8x8, 0x03e ); /* enable extended mode */
132 u8x8_cad_SendCmd(u8x8, 0x03e ); /* enable extended mode, issue 487 */
133 for( i = 0; i < 8; i++ )
134 {
135 //u8x8_cad_SendCmd(u8x8, 0x03e ); /* enable extended mode */
136 u8x8_cad_SendCmd(u8x8, 0x080 | (y+i) ); /* y pos */
137 u8x8_cad_SendCmd(u8x8, 0x080 | x ); /* set x pos */
138 c = ((u8x8_tile_t *)arg_ptr)->cnt; /* number of tiles */
139
140 //u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, 200, NULL); /* extra dely required */
141 u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes, send one line of data */
142 ptr += c;
143 //u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, 200, NULL); /* extra dely required */
144 }
145
146 u8x8_cad_EndTransfer(u8x8);
147
148 break;
149 default:
150 return 0;
151 }
152 return 1;
153}
154
155
156/*=== 128x32 === */
157/* https://github.com/olikraus/u8g2/issues/2241 */
158
159static const u8x8_display_info_t u8x8_st7920_128x32_display_info =
160{
161 /* chip_enable_level = */ 1,
162 /* chip_disable_level = */ 0,
163
164 /* post_chip_enable_wait_ns = */ 5,
165 /* pre_chip_disable_wait_ns = */ 5,
166 /* reset_pulse_width_ms = */ 1,
167 /* post_reset_wait_ms = */ 6,
168 /* sda_setup_time_ns = */ 20,
169 /* sck_pulse_width_ns = */ 140, /* datasheet ST7920 */
170 /* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
171 /* spi_mode = */ 3, /* old: sck_takeover_edge, new: active high (bit 1), rising edge (bit 0), 18 Aug 16: changed from 1 to 3 which works for 101 */
172 /* Arduino mode 3: aktive low clock, but use rising edge */
173 /* i2c_bus_clock_100kHz = */ 4,
174 /* data_setup_time_ns = */ 30,
175 /* write_pulse_width_ns = */ 40,
176 /* tile_width = */ 16,
177 /* tile_height = */ 4,
178 /* default_x_offset = */ 0,
179 /* flipmode_x_offset = */ 0,
180 /* pixel_width = */ 128,
181 /* pixel_height = */ 32
182};
183
184
185uint8_t u8x8_d_st7920_128x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
186{
187 switch(msg)
188 {
189 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
190 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7920_128x32_display_info);
191 break;
192 default:
193 return u8x8_d_st7920_common(u8x8, msg, arg_int, arg_ptr);
194 }
195 return 1;
196}
197
198
199/*=== 144x32 === */
200/* https://github.com/olikraus/u8g2/issues/209 */
201
202static const u8x8_display_info_t u8x8_st7920_144x32_display_info =
203{
204 /* chip_enable_level = */ 1,
205 /* chip_disable_level = */ 0,
206
207 /* post_chip_enable_wait_ns = */ 5,
208 /* pre_chip_disable_wait_ns = */ 5,
209 /* reset_pulse_width_ms = */ 1,
210 /* post_reset_wait_ms = */ 6,
211 /* sda_setup_time_ns = */ 20,
212 /* sck_pulse_width_ns = */ 140, /* datasheet ST7920 */
213 /* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
214 /* spi_mode = */ 3, /* old: sck_takeover_edge, new: active high (bit 1), rising edge (bit 0), 18 Aug 16: changed from 1 to 3 which works for 101 */
215 /* Arduino mode 3: aktive low clock, but use rising edge */
216 /* i2c_bus_clock_100kHz = */ 4,
217 /* data_setup_time_ns = */ 30,
218 /* write_pulse_width_ns = */ 40,
219 /* tile_width = */ 18,
220 /* tile_height = */ 4,
221 /* default_x_offset = */ 0,
222 /* flipmode_x_offset = */ 0,
223 /* pixel_width = */ 144,
224 /* pixel_height = */ 32
225};
226
227
228uint8_t u8x8_d_st7920_144x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
229{
230 switch(msg)
231 {
232 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
233 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7920_144x32_display_info);
234 break;
235 default:
236 return u8x8_d_st7920_common(u8x8, msg, arg_int, arg_ptr);
237 }
238 return 1;
239}
240
241
242/*=== 160x32 === */
243/* https://github.com/olikraus/u8g2/issues/1873, POWERTIP PG-16032LRU-BWH-H-P2 */
244
245static const u8x8_display_info_t u8x8_st7920_160x32_display_info =
246{
247 /* chip_enable_level = */ 1,
248 /* chip_disable_level = */ 0,
249
250 /* post_chip_enable_wait_ns = */ 5,
251 /* pre_chip_disable_wait_ns = */ 5,
252 /* reset_pulse_width_ms = */ 1,
253 /* post_reset_wait_ms = */ 6,
254 /* sda_setup_time_ns = */ 20,
255 /* sck_pulse_width_ns = */ 140, /* datasheet ST7920 */
256 /* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
257 /* spi_mode = */ 3, /* old: sck_takeover_edge, new: active high (bit 1), rising edge (bit 0), 18 Aug 16: changed from 1 to 3 which works for 101 */
258 /* Arduino mode 3: aktive low clock, but use rising edge */
259 /* i2c_bus_clock_100kHz = */ 4,
260 /* data_setup_time_ns = */ 30,
261 /* write_pulse_width_ns = */ 40,
262 /* tile_width = */ 20,
263 /* tile_height = */ 4,
264 /* default_x_offset = */ 0,
265 /* flipmode_x_offset = */ 0,
266 /* pixel_width = */ 160,
267 /* pixel_height = */ 32
268};
269
270uint8_t u8x8_d_st7920_160x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
271{
272 switch(msg)
273 {
274 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
275 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7920_160x32_display_info);
276 break;
277 default:
278 return u8x8_d_st7920_common(u8x8, msg, arg_int, arg_ptr);
279 }
280 return 1;
281}
282
283
284/*=== 192x32 === */
285
286static const u8x8_display_info_t u8x8_st7920_192x32_display_info =
287{
288 /* chip_enable_level = */ 1,
289 /* chip_disable_level = */ 0,
290
291 /* post_chip_enable_wait_ns = */ 5,
292 /* pre_chip_disable_wait_ns = */ 5,
293 /* reset_pulse_width_ms = */ 1,
294 /* post_reset_wait_ms = */ 6,
295 /* sda_setup_time_ns = */ 20,
296 /* sck_pulse_width_ns = */ 140, /* datasheet ST7920 */
297 /* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
298 /* spi_mode = */ 3, /* old: sck_takeover_edge, new: active high (bit 1), rising edge (bit 0), 18 Aug 16: changed from 1 to 3 which works for 101 */
299 /* Arduino mode 3: aktive low clock, but use rising edge */
300 /* i2c_bus_clock_100kHz = */ 4,
301 /* data_setup_time_ns = */ 30,
302 /* write_pulse_width_ns = */ 40,
303 /* tile_width = */ 24,
304 /* tile_height = */ 4,
305 /* default_x_offset = */ 0,
306 /* flipmode_x_offset = */ 0,
307 /* pixel_width = */ 192,
308 /* pixel_height = */ 32
309};
310
311
312uint8_t u8x8_d_st7920_192x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
313{
314 switch(msg)
315 {
316 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
317 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7920_192x32_display_info);
318 break;
319 default:
320 return u8x8_d_st7920_common(u8x8, msg, arg_int, arg_ptr);
321 }
322 return 1;
323}
324
325/*=== 128x64 === */
326
327static const u8x8_display_info_t u8x8_st7920_128x64_display_info =
328{
329 /* chip_enable_level = */ 1,
330 /* chip_disable_level = */ 0,
331
332 /* post_chip_enable_wait_ns = */ 5,
333 /* pre_chip_disable_wait_ns = */ 5,
334 /* reset_pulse_width_ms = */ 1,
335 /* post_reset_wait_ms = */ 6,
336 /* sda_setup_time_ns = */ 20,
337 /* sck_pulse_width_ns = */ 140, /* datasheet ST7920 */
338 /* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
339 /* ST7920+Due work with 1MHz but not with 2MHz, ST7920+Uno works with 2MHz */
340 /* spi_mode = */ 3, /* active high, rising edge, 18 Aug 16: changed from 1 to 3 which works for 101 */
341 /* in theory mode 3 should be correct */
342 /* i2c_bus_clock_100kHz = */ 4,
343 /* data_setup_time_ns = */ 30,
344 /* write_pulse_width_ns = */ 40,
345 /* tile_width = */ 16,
346 /* tile_height = */ 8,
347 /* default_x_offset = */ 0,
348 /* flipmode_x_offset = */ 0,
349 /* pixel_width = */ 128,
350 /* pixel_height = */ 64
351};
352
353uint8_t u8x8_d_st7920_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
354{
355 switch(msg)
356 {
357 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
358 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7920_128x64_display_info);
359 break;
360 default:
361 return u8x8_d_st7920_common(u8x8, msg, arg_int, arg_ptr);
362 }
363 return 1;
364}
365
366/*=== 256x32 === */
367/* https://github.com/olikraus/u8g2/issues/1593 */
368
369static const u8x8_display_info_t u8x8_st7920_256x32_display_info =
370{
371 /* chip_enable_level = */ 1,
372 /* chip_disable_level = */ 0,
373
374 /* post_chip_enable_wait_ns = */ 5,
375 /* pre_chip_disable_wait_ns = */ 5,
376 /* reset_pulse_width_ms = */ 1,
377 /* post_reset_wait_ms = */ 6,
378 /* sda_setup_time_ns = */ 20,
379 /* sck_pulse_width_ns = */ 140, /* datasheet ST7920 */
380 /* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
381 /* ST7920+Due work with 1MHz but not with 2MHz, ST7920+Uno works with 2MHz */
382 /* spi_mode = */ 3, /* active high, rising edge, 18 Aug 16: changed from 1 to 3 which works for 101 */
383 /* in theory mode 3 should be correct */
384 /* i2c_bus_clock_100kHz = */ 4,
385 /* data_setup_time_ns = */ 30,
386 /* write_pulse_width_ns = */ 40,
387 /* tile_width = */ 32,
388 /* tile_height = */ 4,
389 /* default_x_offset = */ 0,
390 /* flipmode_x_offset = */ 0,
391 /* pixel_width = */ 256,
392 /* pixel_height = */ 32
393};
394
395uint8_t u8x8_d_st7920_256x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
396{
397 switch(msg)
398 {
399 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
400 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7920_256x32_display_info);
401 break;
402 default:
403 return u8x8_d_st7920_common(u8x8, msg, arg_int, arg_ptr);
404 }
405 return 1;
406}