Krolyxon
Commit 1d55752

Branches

Tags

Refs →

orion-rf.piolibdepsesp32-s3-n16r8U8g2srcclibu8x8_d_gu800.c

296 lines · 10.1 KB · C

1/*
2
3 u8x8_d_gu800.c
4
5 Support for GU800 series of VFD displays
6 https://www.noritake-elec.com/products/vfd-display-module/dot-matrix-graphic-display/gu-800-series
7
8 Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
9
10 Copyright (c) 2021, olikraus@gmail.com
11 All rights reserved.
12
13 Redistribution and use in source and binary forms, with or without modification,
14 are permitted provided that the following conditions are met:
15
16 * Redistributions of source code must retain the above copyright notice, this list
17 of conditions and the following disclaimer.
18
19 * Redistributions in binary form must reproduce the above copyright notice, this
20 list of conditions and the following disclaimer in the documentation and/or other
21 materials provided with the distribution.
22
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
24 CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
28 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
33 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
35 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36
37
38
39 u8x8_gu800_cad_110
40
41 WARNING: DO NOT USE THIS FILE AS TEMPLATE:
42
43 This code requires a special cad callback which includes the start
44 and end transfer code. As a consequence this code does not include any
45 start / end transfer calls.
46
47*/
48#include "u8x8.h"
49
50
51
52
53static const uint8_t u8x8_d_gu800_128x64_powersave0_seq[] = {
54 U8X8_CA(0x024, 0x040), /* Byte 1: Layer 0010xx00, Byte 2: 0x40 (graphics on, normal mode, no or/xor) */
55 U8X8_END() /* end of sequence */
56};
57
58static const uint8_t u8x8_d_gu800_128x64_powersave1_seq[] = {
59 U8X8_CA(0x020, 0x040), /* Byte 1: Layer 0010xx00, Byte 2: 0x40 (graphics on, normal mode, no or/xor) */
60 U8X8_END() /* end of sequence */
61};
62
63/* hardware flip is not supported by GU800 */
64#ifdef NOT_SUPPORTED
65static const uint8_t u8x8_d_gu800_128x64_flip0_seq[] = {
66 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
67 U8X8_END_TRANSFER(), /* disable chip */
68 U8X8_END() /* end of sequence */
69};
70
71static const uint8_t u8x8_d_gu800_128x64_flip1_seq[] = {
72 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
73 U8X8_END_TRANSFER(), /* disable chip */
74 U8X8_END() /* end of sequence */
75};
76#endif
77
78uint8_t u8x8_d_gu800_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_SET_POWER_SAVE:
85 if ( arg_int == 0 )
86 u8x8_cad_SendSequence(u8x8, u8x8_d_gu800_128x64_powersave0_seq);
87 else
88 u8x8_cad_SendSequence(u8x8, u8x8_d_gu800_128x64_powersave1_seq);
89 break;
90#ifdef NOT_SUPPORTED
91 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
92 if ( arg_int == 0 )
93 {
94 u8x8_cad_SendSequence(u8x8, u8x8_d_gu800_128x64_flip0_seq);
95 u8x8->x_offset = u8x8->display_info->default_x_offset;
96 }
97 else
98 {
99 u8x8_cad_SendSequence(u8x8, u8x8_d_gu800_128x64_flip1_seq);
100 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
101 }
102 break;
103#endif
104#ifdef U8X8_WITH_SET_CONTRAST
105 case U8X8_MSG_DISPLAY_SET_CONTRAST:
106 u8x8_cad_SendCmd(u8x8, 0x4f - ((arg_int >> 4)&0x0f) ); /* GU800 has range from 0..15, max brightness is 0x040 */
107 break;
108#endif
109 case U8X8_MSG_DISPLAY_DRAW_TILE:
110
111 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
112 x *= 8;
113 x += u8x8->x_offset;
114 u8x8_cad_SendCmd(u8x8, 0x064 );
115 u8x8_cad_SendArg(u8x8, x );
116 u8x8_cad_SendCmd(u8x8, 0x060 );
117 u8x8_cad_SendArg(u8x8, (((u8x8_tile_t *)arg_ptr)->y_pos) );
118
119 do
120 {
121 c = ((u8x8_tile_t *)arg_ptr)->cnt;
122 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
123 /* SendData can not handle more than 255 bytes, treat c > 31 correctly */
124 if ( c > 31 )
125 {
126 u8x8_cad_SendData(u8x8, 248, ptr); /* 31*8=248 */
127 ptr+=248;
128 c -= 31;
129 }
130 u8x8_cad_SendData(u8x8, c*8, ptr);
131 arg_int--;
132 } while( arg_int > 0 );
133 break;
134 default:
135 return 0;
136 }
137 return 1;
138}
139
140/*=================================================*/
141
142static const uint8_t u8x8_d_gu800_128x64_init_seq[] = {
143
144 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
145
146 U8X8_C(0x05f), /* clear all RAM, clear address counters */
147 U8X8_DLY(1), /* delay for 1 ms (see datasheet) */
148
149 /* configure all area as graphics RAM */
150 U8X8_CA(0x62,0), U8X8_D1(0xff),
151 U8X8_CA(0x62,1), U8X8_D1(0xff),
152 U8X8_CA(0x62,2), U8X8_D1(0xff),
153 U8X8_CA(0x62,3), U8X8_D1(0xff),
154 U8X8_CA(0x62,4), U8X8_D1(0xff),
155 U8X8_CA(0x62,5), U8X8_D1(0xff),
156 U8X8_CA(0x62,6), U8X8_D1(0xff),
157 U8X8_CA(0x62,7), U8X8_D1(0xff),
158
159 U8X8_CA(0x70, 0), /* horizontal shift */
160 U8X8_C(0xb0), /* vertical shift */
161 U8X8_C(0x40), /* min (0x04f) / max (0x040) brightness */
162 U8X8_C(0x84), /* x increment */
163
164 // U8X8_CA(0x024, 0x040) /* display on */
165
166 U8X8_END_TRANSFER(), /* disable chip */
167 U8X8_END() /* end of sequence */
168};
169
170
171static const u8x8_display_info_t u8x8_d_gu800_128x64_display_info =
172{
173 /* chip_enable_level = */ 0, /* GU800: CSS signal */
174 /* chip_disable_level = */ 1, /* GU800: CSS signal */
175
176 /* post_chip_enable_wait_ns = */ 40,
177 /* pre_chip_disable_wait_ns = */ 150,
178 /* reset_pulse_width_ms = */ 2, /* GU800: Unspecified in datasheet */
179 /* post_reset_wait_ms = */ 2, /* GU800: Min 1.5ms per datasheet */
180 /* sda_setup_time_ns = */ 40, /* GU800: 40ns according to the timing diagram */
181 /* sck_pulse_width_ns = */ 80, /* GU800: Min 80ns per datasheet */
182 /* sck_clock_hz = */ 4000000UL,
183 /* spi_mode = */ 2, /* active high, rising edge */
184 /* i2c_bus_clock_100kHz = */ 4, /* GU800: Not used */
185 /* data_setup_time_ns = */ 40, /* GU800: Min 40ns per datasheet */
186 /* write_pulse_width_ns = */ 150, /* GU800: Min 150ns per datasheet */
187 /* tile_width = */ 16, /* width of 16*8=128 pixel */
188 /* tile_height = */ 8,
189 /* default_x_offset = */ 0,
190 /* flipmode_x_offset = */ 0,
191 /* pixel_width = */ 128,
192 /* pixel_height = */ 64
193};
194
195
196uint8_t u8x8_d_gu800_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
197{
198
199 if ( u8x8_d_gu800_common(u8x8, msg, arg_int, arg_ptr) )
200 return 1;
201
202 switch(msg)
203 {
204 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
205 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_d_gu800_128x64_display_info);
206 break;
207 case U8X8_MSG_DISPLAY_INIT:
208 u8x8_d_helper_display_init(u8x8);
209 u8x8_cad_SendSequence(u8x8, u8x8_d_gu800_128x64_init_seq);
210 break;
211 default:
212 return 0;
213 }
214 return 1;
215}
216
217/*=================================================*/
218/* https://github.com/olikraus/u8g2/issues/1970 */
219
220static const uint8_t u8x8_d_gu800_160x16_init_seq[] = {
221
222 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
223
224 U8X8_C(0x05f), /* clear all RAM, clear address counters */
225 U8X8_DLY(1), /* delay for 1 ms (see datasheet) */
226
227 /* configure all area as graphics RAM */
228 U8X8_CA(0x62,0), U8X8_D1(0xff),
229 U8X8_CA(0x62,1), U8X8_D1(0xff),
230 U8X8_CA(0x62,2), U8X8_D1(0xff),
231 U8X8_CA(0x62,3), U8X8_D1(0xff),
232 U8X8_CA(0x62,4), U8X8_D1(0xff),
233 U8X8_CA(0x62,5), U8X8_D1(0xff),
234 U8X8_CA(0x62,6), U8X8_D1(0xff),
235 U8X8_CA(0x62,7), U8X8_D1(0xff),
236
237 U8X8_CA(0x70, 0), /* horizontal shift */
238 U8X8_C(0xb0), /* vertical shift */
239 U8X8_C(0x40), /* min (0x04f) / max (0x040) brightness */
240 U8X8_C(0x84), /* x increment */
241
242 // U8X8_CA(0x024, 0x040) /* display on */
243
244 U8X8_END_TRANSFER(), /* disable chip */
245 U8X8_END() /* end of sequence */
246};
247
248
249static const u8x8_display_info_t u8x8_d_gu800_160x16_display_info =
250{
251 /* chip_enable_level = */ 0, /* GU800: CSS signal */
252 /* chip_disable_level = */ 1, /* GU800: CSS signal */
253
254 /* post_chip_enable_wait_ns = */ 40,
255 /* pre_chip_disable_wait_ns = */ 150,
256 /* reset_pulse_width_ms = */ 2, /* GU800: Unspecified in datasheet */
257 /* post_reset_wait_ms = */ 2, /* GU800: Min 1.5ms per datasheet */
258 /* sda_setup_time_ns = */ 40, /* GU800: 40ns according to the timing diagram */
259 /* sck_pulse_width_ns = */ 80, /* GU800: Min 80ns per datasheet */
260 /* sck_clock_hz = */ 4000000UL,
261 /* spi_mode = */ 3, /* active high, rising edge, ISSUE 1970 */
262 /* i2c_bus_clock_100kHz = */ 4, /* GU800: Not used */
263 /* data_setup_time_ns = */ 40, /* GU800: Min 40ns per datasheet */
264 /* write_pulse_width_ns = */ 150, /* GU800: Min 150ns per datasheet */
265 /* tile_width = */ 20, /* width of 8*20=160 pixel */
266 /* tile_height = */ 2,
267 /* default_x_offset = */ 0,
268 /* flipmode_x_offset = */ 0,
269 /* pixel_width = */ 160,
270 /* pixel_height = */ 16
271};
272
273
274uint8_t u8x8_d_gu800_160x16(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
275{
276
277 if ( u8x8_d_gu800_common(u8x8, msg, arg_int, arg_ptr) )
278 return 1;
279
280 switch(msg)
281 {
282 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
283 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_d_gu800_160x16_display_info);
284 break;
285 case U8X8_MSG_DISPLAY_INIT:
286 u8x8_d_helper_display_init(u8x8);
287 u8x8_cad_SendSequence(u8x8, u8x8_d_gu800_160x16_init_seq);
288 break;
289 default:
290 return 0;
291 }
292 return 1;
293}
294
295/*=================================================*/
296