components/u8g2/csrc/u8x8_d_ssd1305.c

changeset 0
88d965579617
equal deleted inserted replaced
-1:000000000000 0:88d965579617
1 /*
2
3 u8x8_d_ssd1305.c
4
5 Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
6
7 Copyright (c) 2017, 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
36
37 #include "u8x8.h"
38
39
40
41
42 static const uint8_t u8x8_d_ssd1305_powersave0_seq[] = {
43 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
44 U8X8_C(0x0af), /* display on */
45 U8X8_END_TRANSFER(), /* disable chip */
46 U8X8_END() /* end of sequence */
47 };
48
49 static const uint8_t u8x8_d_ssd1305_powersave1_seq[] = {
50 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
51 U8X8_C(0x0ae), /* display off */
52 U8X8_END_TRANSFER(), /* disable chip */
53 U8X8_END() /* end of sequence */
54 };
55
56 static const uint8_t u8x8_d_ssd1305_128x32_flip0_seq[] = {
57 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
58 U8X8_CA(0x0d3, 32), /* display offset to 32 */
59 U8X8_C(0x0a1), /* segment remap a0/a1*/
60 U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
61 U8X8_END_TRANSFER(), /* disable chip */
62 U8X8_END() /* end of sequence */
63 };
64
65 static const uint8_t u8x8_d_ssd1305_128x32_flip1_seq[] = {
66 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
67 U8X8_CA(0x0d3, 0), /* display offset to */
68 U8X8_C(0x0a0), /* segment remap a0/a1*/
69 U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
70 U8X8_END_TRANSFER(), /* disable chip */
71 U8X8_END() /* end of sequence */
72 };
73
74
75
76 static uint8_t u8x8_d_ssd1305_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
77 {
78 uint8_t x, c;
79 uint8_t *ptr;
80 switch(msg)
81 {
82 case U8X8_MSG_DISPLAY_DRAW_TILE:
83 u8x8_cad_StartTransfer(u8x8);
84 x = ((u8x8_tile_t *)arg_ptr)->x_pos;
85 x *= 8;
86 x += u8x8->x_offset;
87
88 u8x8_cad_SendCmd(u8x8, 0x040 ); /* set line offset to 0 */
89
90 u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
91 u8x8_cad_SendArg(u8x8, 0x000 | ((x&15)));
92 u8x8_cad_SendArg(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos) );
93
94
95 do
96 {
97 c = ((u8x8_tile_t *)arg_ptr)->cnt;
98 ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
99 u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
100 /*
101 do
102 {
103 u8x8_cad_SendData(u8x8, 8, ptr);
104 ptr += 8;
105 c--;
106 } while( c > 0 );
107 */
108 arg_int--;
109 } while( arg_int > 0 );
110
111 u8x8_cad_EndTransfer(u8x8);
112 break;
113 case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
114 if ( arg_int == 0 )
115 u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_powersave0_seq);
116 else
117 u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_powersave1_seq);
118 break;
119 #ifdef U8X8_WITH_SET_CONTRAST
120 case U8X8_MSG_DISPLAY_SET_CONTRAST:
121 u8x8_cad_StartTransfer(u8x8);
122 u8x8_cad_SendCmd(u8x8, 0x081 );
123 u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1305 has range from 0 to 255 */
124 u8x8_cad_EndTransfer(u8x8);
125 break;
126 #endif
127 default:
128 return 0;
129 }
130 return 1;
131 }
132
133 /* timing from SSD1306 */
134 static const u8x8_display_info_t u8x8_ssd1305_128x32_noname_display_info =
135 {
136 /* chip_enable_level = */ 0,
137 /* chip_disable_level = */ 1,
138
139 /* post_chip_enable_wait_ns = */ 20,
140 /* pre_chip_disable_wait_ns = */ 10,
141 /* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
142 /* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
143 /* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
144 /* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
145 /* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
146 /* spi_mode = */ 0, /* active high, rising edge */
147 /* i2c_bus_clock_100kHz = */ 4,
148 /* data_setup_time_ns = */ 40,
149 /* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
150 /* tile_width = */ 16,
151 /* tile_hight = */ 4,
152 /* default_x_offset = */ 2,
153 /* flipmode_x_offset = */ 2,
154 /* pixel_width = */ 128,
155 /* pixel_height = */ 32
156 };
157
158
159 static const uint8_t u8x8_d_ssd1305_128x32_noname_init_seq[] = {
160
161 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
162
163
164 U8X8_C(0x0ae), /* display off */
165 U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
166 U8X8_CA(0x0a8, 0x03f), /* multiplex ratio */
167 U8X8_CA(0x0d3, 32), /* display offset to 32 */
168 U8X8_C(0x040), /* set display start line to 0 */
169 U8X8_CA(0x020, 0x000), /* page addressing mode */
170
171 U8X8_C(0x0a1), /* segment remap a0/a1*/
172 U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
173 // Flipmode
174 // U8X8_C(0x0a0), /* segment remap a0/a1*/
175 // U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
176
177 U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
178
179 U8X8_CA(0x081, 0x0cf), /* [2] set contrast control */
180 U8X8_CA(0x0d9, 0x0f1), /* [2] pre-charge period 0x022/f1*/
181 U8X8_CA(0x0db, 0x040), /* vcomh deselect level */
182 // if vcomh is 0, then this will give the biggest range for contrast control issue #98
183 // restored the old values for the noname constructor, because vcomh=0 will not work for all OLEDs, #116
184
185 U8X8_C(0x02e), /* Deactivate scroll */
186 U8X8_C(0x0a4), /* output ram to display */
187 U8X8_C(0x0a6), /* none inverted normal display mode */
188
189 U8X8_END_TRANSFER(), /* disable chip */
190 U8X8_END() /* end of sequence */
191 };
192
193
194 uint8_t u8x8_d_ssd1305_128x32_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
195 {
196
197 if ( u8x8_d_ssd1305_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
198 return 1;
199
200 switch(msg)
201 {
202 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
203 if ( arg_int == 0 )
204 {
205 u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_flip0_seq);
206 u8x8->x_offset = u8x8->display_info->default_x_offset;
207 }
208 else
209 {
210 u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_flip1_seq);
211 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
212 }
213 break;
214 case U8X8_MSG_DISPLAY_INIT:
215 u8x8_d_helper_display_init(u8x8);
216 u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_noname_init_seq);
217 break;
218 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
219 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1305_128x32_noname_display_info);
220 break;
221 default:
222 return 0;
223 }
224 return 1;
225 }
226
227 /*================================================*/
228 /* adafruit 128x32 SSD1305 OLED, https://www.adafruit.com/product/2675 */
229 /* issue 724 */
230
231 /* timing from SSD1306 */
232 static const u8x8_display_info_t u8x8_ssd1305_128x32_adafruit_display_info =
233 {
234 /* chip_enable_level = */ 0,
235 /* chip_disable_level = */ 1,
236
237 /* post_chip_enable_wait_ns = */ 20,
238 /* pre_chip_disable_wait_ns = */ 10,
239 /* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
240 /* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
241 /* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
242 /* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
243 /* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
244 /* spi_mode = */ 0, /* active high, rising edge */
245 /* i2c_bus_clock_100kHz = */ 4,
246 /* data_setup_time_ns = */ 40,
247 /* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
248 /* tile_width = */ 16,
249 /* tile_hight = */ 4,
250 /* default_x_offset = */ 4,
251 /* flipmode_x_offset = */ 0,
252 /* pixel_width = */ 128,
253 /* pixel_height = */ 32
254 };
255
256
257 uint8_t u8x8_d_ssd1305_128x32_adafruit(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
258 {
259
260 if ( u8x8_d_ssd1305_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
261 return 1;
262
263 switch(msg)
264 {
265 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
266 if ( arg_int == 0 )
267 {
268 u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_flip0_seq);
269 u8x8->x_offset = u8x8->display_info->default_x_offset;
270 }
271 else
272 {
273 u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_flip1_seq);
274 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
275 }
276 break;
277 case U8X8_MSG_DISPLAY_INIT:
278 u8x8_d_helper_display_init(u8x8);
279 u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_noname_init_seq);
280 break;
281 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
282 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1305_128x32_adafruit_display_info);
283 break;
284 default:
285 return 0;
286 }
287 return 1;
288 }
289
290
291
292
293 /*================================================*/
294 /* adafruit SSD1305 OLED */
295
296 /* timing from SSD1306 */
297 static const u8x8_display_info_t u8x8_ssd1305_128x64_adafruit_display_info =
298 {
299 /* chip_enable_level = */ 0,
300 /* chip_disable_level = */ 1,
301
302 /* post_chip_enable_wait_ns = */ 20,
303 /* pre_chip_disable_wait_ns = */ 10,
304 /* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
305 /* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
306 /* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
307 /* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
308 /* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
309 /* spi_mode = */ 0, /* active high, rising edge */
310 /* i2c_bus_clock_100kHz = */ 4,
311 /* data_setup_time_ns = */ 40,
312 /* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
313 /* tile_width = */ 16,
314 /* tile_hight = */ 8,
315 /* default_x_offset = */ 2,
316 /* flipmode_x_offset = */ 2,
317 /* pixel_width = */ 128,
318 /* pixel_height = */ 64
319 };
320
321
322 static const uint8_t u8x8_d_ssd1305_128x64_adafruit_init_seq[] = {
323
324 U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
325
326
327 U8X8_C(0x0ae), /* display off */
328 U8X8_CA(0x0d5, 0x0f0), /* clock divide ratio (0x00=1) and oscillator frequency */
329 U8X8_CA(0x0a8, 0x03f), /* multiplex ratio */
330 U8X8_CA(0x0d3, 0x040), /* display offset to 32 */
331 U8X8_C(0x040), /* set display start line to 0 */
332 U8X8_CA(0x020, 0x000), /* page addressing mode */
333
334 U8X8_C(0x0a1), /* segment remap a0/a1*/
335 U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
336 // Flipmode
337 // U8X8_C(0x0a0), /* segment remap a0/a1*/
338 // U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
339
340 U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
341
342 U8X8_CA(0x081, 0x032), /* [2] set contrast control */
343 U8X8_CA(0x082, 0x080), /* set area brightness (reset=0x080) */
344 U8X8_CA(0x0d9, 0x0f1), /* [2] pre-charge period 0x022/f1*/
345 U8X8_CA(0x0db, 0x040), /* vcomh deselect level */
346 // if vcomh is 0, then this will give the biggest range for contrast control issue #98
347 // restored the old values for the noname constructor, because vcomh=0 will not work for all OLEDs, #116
348
349 U8X8_C(0x02e), /* Deactivate scroll */
350 U8X8_C(0x0a4), /* output ram to display */
351 U8X8_C(0x0a6), /* none inverted normal display mode */
352
353 U8X8_END_TRANSFER(), /* disable chip */
354 U8X8_END() /* end of sequence */
355 };
356
357
358 uint8_t u8x8_d_ssd1305_128x64_adafruit(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
359 {
360
361 if ( u8x8_d_ssd1305_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
362 return 1;
363
364 switch(msg)
365 {
366 case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
367 if ( arg_int == 0 )
368 {
369 u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_flip0_seq);
370 u8x8->x_offset = u8x8->display_info->default_x_offset;
371 }
372 else
373 {
374 u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_flip1_seq);
375 u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
376 }
377 break;
378 case U8X8_MSG_DISPLAY_INIT:
379 u8x8_d_helper_display_init(u8x8);
380 u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x64_adafruit_init_seq);
381 break;
382 case U8X8_MSG_DISPLAY_SETUP_MEMORY:
383 u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1305_128x64_adafruit_display_info);
384 break;
385 default:
386 return 0;
387 }
388 return 1;
389 }

mercurial