GCC Code Coverage Report


Directory: ./
File: oled/SSD1306_OLED.c
Date: 2026-10-29 08:11:58
Exec Total Coverage
Lines: 217 796 27.3%
Functions: 25 58 43.1%
Branches: 119 597 19.9%

Line Branch Exec Source
1 /*
2 * MIT License
3
4 Copyright (c) 2017 DeeplyEmbedded
5
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in all
14 copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23
24 * SSD1306_OLED.c
25 *
26 * Created on : Sep 26, 2017
27 * Author : Vinay Divakar
28 * Description : SSD1306 OLED Driver, Graphics API's.
29 * Website : www.deeplyembedded.org
30 */
31
32 /* Lib Includes */
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdint.h>
37 #include <math.h>
38 #include "I2C.h"
39 #include "SSD1306_OLED.h"
40 #include "gfxfont.h"
41
42 /* Enable or Disable DEBUG Prints */
43 //#define SSD1306_DBG
44
45 /* MACROS */
46 #define SWAP(x,y) {short temp; temp = x; x = y; y = temp;}
47 #define pgm_read_byte(addr) (*(const unsigned char *)(addr))
48 #define pgm_read_word(addr) (*(const unsigned long *)(addr))
49 #define pgm_read_dword(addr) (*(const unsigned long *)(addr))
50 #define pgm_read_pointer(addr) ((void *)pgm_read_word(addr))
51
52
53 int LED_DISPLAY_WIDTH = 128;
54 int LED_DISPLAY_HEIGHT = 64;
55 int LED_DISPLAY_TYPE = LED_DISPLAY_TYPE_SSD1306;
56
57
58 /* static Variables */
59 static unsigned char _rotation = 0,textsize = 0;
60 static short _width = 128;
61 static short _height = 64;
62 static short cursor_x = 0, cursor_y = 0, textcolor = 0, textbgcolor = 0;
63 static bool _cp437 = false, wrap = true;
64
65
66 /* static struct objects */
67 static const GFXfont *gfxFont = 0;
68
69 ✗ void setTextFont(const GFXfont *font) {
70 ✗ gfxFont = font;
71 ✗ }
72
73
74 /* Externs - I2C.c */
75 extern I2C_DeviceT I2C_DEV_2;
76
77 /* Chunk Buffer */
78 #define MAX_CHUNK_SIZE 129
79 static unsigned char chunk[MAX_CHUNK_SIZE] = {0};
80
81 // max we do is 128x128 at this point
82 #define DISPLAY_BUFF_SIZE ((128*128/2)+MAX_CHUNK_SIZE)
83
84 /* Memory buffer for displaying data on LCD */
85 static unsigned char screen[DISPLAY_BUFF_SIZE] ={0};
86
87 /* Static Functions */
88 static int transfer();
89 static void drawFastVLine(short x, short y,short h, short color);
90 static void writeFastVLine(short x, short y, short h, short color);
91 static void drawFastHLine(short x, short y,short w, short color);
92 static void writeFastHLine(short x, short y, short w, short color);
93 static short print(const char *buffer, short size);
94
95 // Standard ASCII 5x7 font
96 static const unsigned char ssd1306_font5x7[] = {
97 0x00, 0x00, 0x00, 0x00, 0x00,
98 0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
99 0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
100 0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
101 0x18, 0x3C, 0x7E, 0x3C, 0x18,
102 0x1C, 0x57, 0x7D, 0x57, 0x1C,
103 0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
104 0x00, 0x18, 0x3C, 0x18, 0x00,
105 0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
106 0x00, 0x18, 0x24, 0x18, 0x00,
107 0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
108 0x30, 0x48, 0x3A, 0x06, 0x0E,
109 0x26, 0x29, 0x79, 0x29, 0x26,
110 0x40, 0x7F, 0x05, 0x05, 0x07,
111 0x40, 0x7F, 0x05, 0x25, 0x3F,
112 0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
113 0x7F, 0x3E, 0x1C, 0x1C, 0x08,
114 0x08, 0x1C, 0x1C, 0x3E, 0x7F,
115 0x14, 0x22, 0x7F, 0x22, 0x14,
116 0x5F, 0x5F, 0x00, 0x5F, 0x5F,
117 0x06, 0x09, 0x7F, 0x01, 0x7F,
118 0x00, 0x66, 0x89, 0x95, 0x6A,
119 0x60, 0x60, 0x60, 0x60, 0x60,
120 0x94, 0xA2, 0xFF, 0xA2, 0x94,
121 0x08, 0x04, 0x7E, 0x04, 0x08,
122 0x10, 0x20, 0x7E, 0x20, 0x10,
123 0x08, 0x08, 0x2A, 0x1C, 0x08,
124 0x08, 0x1C, 0x2A, 0x08, 0x08,
125 0x1E, 0x10, 0x10, 0x10, 0x10,
126 0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
127 0x30, 0x38, 0x3E, 0x38, 0x30,
128 0x06, 0x0E, 0x3E, 0x0E, 0x06,
129 0x00, 0x00, 0x00, 0x00, 0x00,
130 0x00, 0x00, 0x5F, 0x00, 0x00,
131 0x00, 0x07, 0x00, 0x07, 0x00,
132 0x14, 0x7F, 0x14, 0x7F, 0x14,
133 0x24, 0x2A, 0x7F, 0x2A, 0x12,
134 0x23, 0x13, 0x08, 0x64, 0x62,
135 0x36, 0x49, 0x56, 0x20, 0x50,
136 0x00, 0x08, 0x07, 0x03, 0x00,
137 0x00, 0x1C, 0x22, 0x41, 0x00,
138 0x00, 0x41, 0x22, 0x1C, 0x00,
139 0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
140 0x08, 0x08, 0x3E, 0x08, 0x08,
141 0x00, 0x80, 0x70, 0x30, 0x00,
142 0x08, 0x08, 0x08, 0x08, 0x08,
143 0x00, 0x00, 0x60, 0x60, 0x00,
144 0x20, 0x10, 0x08, 0x04, 0x02,
145 0x3E, 0x51, 0x49, 0x45, 0x3E,
146 0x00, 0x42, 0x7F, 0x40, 0x00,
147 0x72, 0x49, 0x49, 0x49, 0x46,
148 0x21, 0x41, 0x49, 0x4D, 0x33,
149 0x18, 0x14, 0x12, 0x7F, 0x10,
150 0x27, 0x45, 0x45, 0x45, 0x39,
151 0x3C, 0x4A, 0x49, 0x49, 0x31,
152 0x41, 0x21, 0x11, 0x09, 0x07,
153 0x36, 0x49, 0x49, 0x49, 0x36,
154 0x46, 0x49, 0x49, 0x29, 0x1E,
155 0x00, 0x00, 0x14, 0x00, 0x00,
156 0x00, 0x40, 0x34, 0x00, 0x00,
157 0x00, 0x08, 0x14, 0x22, 0x41,
158 0x14, 0x14, 0x14, 0x14, 0x14,
159 0x00, 0x41, 0x22, 0x14, 0x08,
160 0x02, 0x01, 0x59, 0x09, 0x06,
161 0x3E, 0x41, 0x5D, 0x59, 0x4E,
162 0x7C, 0x12, 0x11, 0x12, 0x7C,
163 0x7F, 0x49, 0x49, 0x49, 0x36,
164 0x3E, 0x41, 0x41, 0x41, 0x22,
165 0x7F, 0x41, 0x41, 0x41, 0x3E,
166 0x7F, 0x49, 0x49, 0x49, 0x41,
167 0x7F, 0x09, 0x09, 0x09, 0x01,
168 0x3E, 0x41, 0x41, 0x51, 0x73,
169 0x7F, 0x08, 0x08, 0x08, 0x7F,
170 0x00, 0x41, 0x7F, 0x41, 0x00,
171 0x20, 0x40, 0x41, 0x3F, 0x01,
172 0x7F, 0x08, 0x14, 0x22, 0x41,
173 0x7F, 0x40, 0x40, 0x40, 0x40,
174 0x7F, 0x02, 0x1C, 0x02, 0x7F,
175 0x7F, 0x04, 0x08, 0x10, 0x7F,
176 0x3E, 0x41, 0x41, 0x41, 0x3E,
177 0x7F, 0x09, 0x09, 0x09, 0x06,
178 0x3E, 0x41, 0x51, 0x21, 0x5E,
179 0x7F, 0x09, 0x19, 0x29, 0x46,
180 0x26, 0x49, 0x49, 0x49, 0x32,
181 0x03, 0x01, 0x7F, 0x01, 0x03,
182 0x3F, 0x40, 0x40, 0x40, 0x3F,
183 0x1F, 0x20, 0x40, 0x20, 0x1F,
184 0x3F, 0x40, 0x38, 0x40, 0x3F,
185 0x63, 0x14, 0x08, 0x14, 0x63,
186 0x03, 0x04, 0x78, 0x04, 0x03,
187 0x61, 0x59, 0x49, 0x4D, 0x43,
188 0x00, 0x7F, 0x41, 0x41, 0x41,
189 0x02, 0x04, 0x08, 0x10, 0x20,
190 0x00, 0x41, 0x41, 0x41, 0x7F,
191 0x04, 0x02, 0x01, 0x02, 0x04,
192 0x40, 0x40, 0x40, 0x40, 0x40,
193 0x00, 0x03, 0x07, 0x08, 0x00,
194 0x20, 0x54, 0x54, 0x78, 0x40,
195 0x7F, 0x28, 0x44, 0x44, 0x38,
196 0x38, 0x44, 0x44, 0x44, 0x28,
197 0x38, 0x44, 0x44, 0x28, 0x7F,
198 0x38, 0x54, 0x54, 0x54, 0x18,
199 0x00, 0x08, 0x7E, 0x09, 0x02,
200 0x18, 0xA4, 0xA4, 0x9C, 0x78,
201 0x7F, 0x08, 0x04, 0x04, 0x78,
202 0x00, 0x44, 0x7D, 0x40, 0x00,
203 0x20, 0x40, 0x40, 0x3D, 0x00,
204 0x7F, 0x10, 0x28, 0x44, 0x00,
205 0x00, 0x41, 0x7F, 0x40, 0x00,
206 0x7C, 0x04, 0x78, 0x04, 0x78,
207 0x7C, 0x08, 0x04, 0x04, 0x78,
208 0x38, 0x44, 0x44, 0x44, 0x38,
209 0xFC, 0x18, 0x24, 0x24, 0x18,
210 0x18, 0x24, 0x24, 0x18, 0xFC,
211 0x7C, 0x08, 0x04, 0x04, 0x08,
212 0x48, 0x54, 0x54, 0x54, 0x24,
213 0x04, 0x04, 0x3F, 0x44, 0x24,
214 0x3C, 0x40, 0x40, 0x20, 0x7C,
215 0x1C, 0x20, 0x40, 0x20, 0x1C,
216 0x3C, 0x40, 0x30, 0x40, 0x3C,
217 0x44, 0x28, 0x10, 0x28, 0x44,
218 0x4C, 0x90, 0x90, 0x90, 0x7C,
219 0x44, 0x64, 0x54, 0x4C, 0x44,
220 0x00, 0x08, 0x36, 0x41, 0x00,
221 0x00, 0x00, 0x77, 0x00, 0x00,
222 0x00, 0x41, 0x36, 0x08, 0x00,
223 0x02, 0x01, 0x02, 0x04, 0x02,
224 0x3C, 0x26, 0x23, 0x26, 0x3C,
225 0x1E, 0xA1, 0xA1, 0x61, 0x12,
226 0x3A, 0x40, 0x40, 0x20, 0x7A,
227 0x38, 0x54, 0x54, 0x55, 0x59,
228 0x21, 0x55, 0x55, 0x79, 0x41,
229 0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut
230 0x21, 0x55, 0x54, 0x78, 0x40,
231 0x20, 0x54, 0x55, 0x79, 0x40,
232 0x0C, 0x1E, 0x52, 0x72, 0x12,
233 0x39, 0x55, 0x55, 0x55, 0x59,
234 0x39, 0x54, 0x54, 0x54, 0x59,
235 0x39, 0x55, 0x54, 0x54, 0x58,
236 0x00, 0x00, 0x45, 0x7C, 0x41,
237 0x00, 0x02, 0x45, 0x7D, 0x42,
238 0x00, 0x01, 0x45, 0x7C, 0x40,
239 0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut
240 0xF0, 0x28, 0x25, 0x28, 0xF0,
241 0x7C, 0x54, 0x55, 0x45, 0x00,
242 0x20, 0x54, 0x54, 0x7C, 0x54,
243 0x7C, 0x0A, 0x09, 0x7F, 0x49,
244 0x32, 0x49, 0x49, 0x49, 0x32,
245 0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut
246 0x32, 0x4A, 0x48, 0x48, 0x30,
247 0x3A, 0x41, 0x41, 0x21, 0x7A,
248 0x3A, 0x42, 0x40, 0x20, 0x78,
249 0x00, 0x9D, 0xA0, 0xA0, 0x7D,
250 0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut
251 0x3D, 0x40, 0x40, 0x40, 0x3D,
252 0x3C, 0x24, 0xFF, 0x24, 0x24,
253 0x48, 0x7E, 0x49, 0x43, 0x66,
254 0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
255 0xFF, 0x09, 0x29, 0xF6, 0x20,
256 0xC0, 0x88, 0x7E, 0x09, 0x03,
257 0x20, 0x54, 0x54, 0x79, 0x41,
258 0x00, 0x00, 0x44, 0x7D, 0x41,
259 0x30, 0x48, 0x48, 0x4A, 0x32,
260 0x38, 0x40, 0x40, 0x22, 0x7A,
261 0x00, 0x7A, 0x0A, 0x0A, 0x72,
262 0x7D, 0x0D, 0x19, 0x31, 0x7D,
263 0x26, 0x29, 0x29, 0x2F, 0x28,
264 0x26, 0x29, 0x29, 0x29, 0x26,
265 0x30, 0x48, 0x4D, 0x40, 0x20,
266 0x38, 0x08, 0x08, 0x08, 0x08,
267 0x08, 0x08, 0x08, 0x08, 0x38,
268 0x2F, 0x10, 0xC8, 0xAC, 0xBA,
269 0x2F, 0x10, 0x28, 0x34, 0xFA,
270 0x00, 0x00, 0x7B, 0x00, 0x00,
271 0x08, 0x14, 0x2A, 0x14, 0x22,
272 0x22, 0x14, 0x2A, 0x14, 0x08,
273 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code
274 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block
275 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block
276 0x00, 0x00, 0x00, 0xFF, 0x00,
277 0x10, 0x10, 0x10, 0xFF, 0x00,
278 0x14, 0x14, 0x14, 0xFF, 0x00,
279 0x10, 0x10, 0xFF, 0x00, 0xFF,
280 0x10, 0x10, 0xF0, 0x10, 0xF0,
281 0x14, 0x14, 0x14, 0xFC, 0x00,
282 0x14, 0x14, 0xF7, 0x00, 0xFF,
283 0x00, 0x00, 0xFF, 0x00, 0xFF,
284 0x14, 0x14, 0xF4, 0x04, 0xFC,
285 0x14, 0x14, 0x17, 0x10, 0x1F,
286 0x10, 0x10, 0x1F, 0x10, 0x1F,
287 0x14, 0x14, 0x14, 0x1F, 0x00,
288 0x10, 0x10, 0x10, 0xF0, 0x00,
289 0x00, 0x00, 0x00, 0x1F, 0x10,
290 0x10, 0x10, 0x10, 0x1F, 0x10,
291 0x10, 0x10, 0x10, 0xF0, 0x10,
292 0x00, 0x00, 0x00, 0xFF, 0x10,
293 0x10, 0x10, 0x10, 0x10, 0x10,
294 0x10, 0x10, 0x10, 0xFF, 0x10,
295 0x00, 0x00, 0x00, 0xFF, 0x14,
296 0x00, 0x00, 0xFF, 0x00, 0xFF,
297 0x00, 0x00, 0x1F, 0x10, 0x17,
298 0x00, 0x00, 0xFC, 0x04, 0xF4,
299 0x14, 0x14, 0x17, 0x10, 0x17,
300 0x14, 0x14, 0xF4, 0x04, 0xF4,
301 0x00, 0x00, 0xFF, 0x00, 0xF7,
302 0x14, 0x14, 0x14, 0x14, 0x14,
303 0x14, 0x14, 0xF7, 0x00, 0xF7,
304 0x14, 0x14, 0x14, 0x17, 0x14,
305 0x10, 0x10, 0x1F, 0x10, 0x1F,
306 0x14, 0x14, 0x14, 0xF4, 0x14,
307 0x10, 0x10, 0xF0, 0x10, 0xF0,
308 0x00, 0x00, 0x1F, 0x10, 0x1F,
309 0x00, 0x00, 0x00, 0x1F, 0x14,
310 0x00, 0x00, 0x00, 0xFC, 0x14,
311 0x00, 0x00, 0xF0, 0x10, 0xF0,
312 0x10, 0x10, 0xFF, 0x10, 0xFF,
313 0x14, 0x14, 0x14, 0xFF, 0x14,
314 0x10, 0x10, 0x10, 0x1F, 0x00,
315 0x00, 0x00, 0x00, 0xF0, 0x10,
316 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
317 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
318 0xFF, 0xFF, 0xFF, 0x00, 0x00,
319 0x00, 0x00, 0x00, 0xFF, 0xFF,
320 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
321 0x38, 0x44, 0x44, 0x38, 0x44,
322 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta
323 0x7E, 0x02, 0x02, 0x06, 0x06,
324 0x02, 0x7E, 0x02, 0x7E, 0x02,
325 0x63, 0x55, 0x49, 0x41, 0x63,
326 0x38, 0x44, 0x44, 0x3C, 0x04,
327 0x40, 0x7E, 0x20, 0x1E, 0x20,
328 0x06, 0x02, 0x7E, 0x02, 0x02,
329 0x99, 0xA5, 0xE7, 0xA5, 0x99,
330 0x1C, 0x2A, 0x49, 0x2A, 0x1C,
331 0x4C, 0x72, 0x01, 0x72, 0x4C,
332 0x30, 0x4A, 0x4D, 0x4D, 0x30,
333 0x30, 0x48, 0x78, 0x48, 0x30,
334 0xBC, 0x62, 0x5A, 0x46, 0x3D,
335 0x3E, 0x49, 0x49, 0x49, 0x00,
336 0x7E, 0x01, 0x01, 0x01, 0x7E,
337 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
338 0x44, 0x44, 0x5F, 0x44, 0x44,
339 0x40, 0x51, 0x4A, 0x44, 0x40,
340 0x40, 0x44, 0x4A, 0x51, 0x40,
341 0x00, 0x00, 0xFF, 0x01, 0x03,
342 0xE0, 0x80, 0xFF, 0x00, 0x00,
343 0x08, 0x08, 0x6B, 0x6B, 0x08,
344 0x36, 0x12, 0x36, 0x24, 0x36,
345 0x06, 0x0F, 0x09, 0x0F, 0x06,
346 0x00, 0x00, 0x18, 0x18, 0x00,
347 0x00, 0x00, 0x10, 0x10, 0x00,
348 0x30, 0x40, 0xFF, 0x01, 0x01,
349 0x00, 0x1F, 0x01, 0x01, 0x1E,
350 0x00, 0x19, 0x1D, 0x17, 0x12,
351 0x00, 0x3C, 0x3C, 0x3C, 0x3C,
352 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP
353 };
354
355 /****************************************************************
356 * Function Name : clearDisplay
357 * Description : Clear the display memory buffer
358 * Returns : NONE.
359 * Params : NONE.
360 ****************************************************************/
361 83 void clearDisplay()
362 {
363 83 memset(screen, 0x00, DISPLAY_BUFF_SIZE);
364 83 }
365
366 /****************************************************************
367 * Function Name : display_Init_seq
368 * Description : Performs SSD1306 OLED Initialization Sequence
369 * Returns : NONE.
370 * Params : NONE.
371 ****************************************************************/
372 12 int display_Init_seq()
373 {
374 /* Add the reset code, If needed */
375
376 /* The drawing routines clip and mirror against _width/_height, so those
377 * have to track the geometry of the panel that is actually attached.
378 * Left at the 128x64 default, a rotated 180 128x32 panel has every pixel
379 * mirrored about row 63, putting the whole image in GDDRAM pages 4-7 -
380 * which a 32 row panel never scans out, so the display just stays dark.
381 * A 128x128 SSD1327 has the opposite problem: everything below row 63
382 * gets clipped away. */
383 12 _width = LED_DISPLAY_WIDTH;
384 12 _height = LED_DISPLAY_HEIGHT;
385
386
387
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 if (LED_DISPLAY_TYPE == LED_DISPLAY_TYPE_SSD1306) {
388 /* Send display OFF command */
389
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DISPLAY_OFF) != I2C_TWO_BYTES) {
390 #ifdef SSD1306_DBG
391 printf("Display OFF Command Failed\r\n");
392 #endif
393 ✗ return 1;
394 }
395 /* Set display multiplex */
396
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_MULTIPLEX) != I2C_TWO_BYTES) {
397 #ifdef SSD1306_DBG
398 printf("Display MULT Command Failed\r\n");
399 #endif
400 ✗ return 1;
401 }
402 /* Send display MULT command parameter */
403
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_MULT_DAT) != I2C_TWO_BYTES) {
404 #ifdef SSD1306_DBG
405 printf("Display MULT Command Parameter Failed\r\n");
406 #endif
407 ✗ return 1;
408 }
409
410 /* Set display clock frequency */
411
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_DISP_CLK) != I2C_TWO_BYTES) {
412 #ifdef SSD1306_DBG
413 printf("Display CLK Command Failed\r\n");
414 #endif
415 ✗ return 1;
416 }
417
418 /* Send display CLK command parameter */
419
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DISPCLK_DIV) != I2C_TWO_BYTES) {
420 #ifdef SSD1306_DBG
421 printf("Display CLK Command Parameter Failed\r\n");
422 #endif
423 ✗ return 1;
424 }
425
426 /* Set display OFFSET */
427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_DISP_OFFSET) != I2C_TWO_BYTES) {
428 #ifdef SSD1306_DBG
429 printf("Display OFFSET Command Failed\r\n");
430 #endif
431 ✗ return 1;
432 }
433
434 /* Send display OFFSET command parameter */
435
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DISP_OFFSET_VAL) != I2C_TWO_BYTES) {
436 #ifdef SSD1306_DBG
437 printf("Display OFFSET Command Parameter Failed\r\n");
438 #endif
439 ✗ return 1;
440 }
441
442 /* Set display START LINE - Check this command if something weird happens */
443
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_DISP_START_LINE) != I2C_TWO_BYTES) {
444 #ifdef SSD1306_DBG
445 printf("Display START LINE Command Failed\r\n");
446 #endif
447 ✗ return 1;
448 }
449
450 /* Enable CHARGEPUMP*/
451
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_CONFIG_CHARGE_PUMP) != I2C_TWO_BYTES) {
452 #ifdef SSD1306_DBG
453 printf("Display CHARGEPUMP Command Failed\r\n");
454 #endif
455 ✗ return 1;
456 }
457
458 /* Send display CHARGEPUMP command parameter */
459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_CHARGE_PUMP_EN) != I2C_TWO_BYTES) {
460 #ifdef SSD1306_DBG
461 printf("Display CHARGEPUMP Command Parameter Failed\r\n");
462 #endif
463 ✗ return 1;
464 }
465
466 /* Set display MEMORYMODE */
467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_MEM_ADDR_MODE) != I2C_TWO_BYTES) {
468 #ifdef SSD1306_DBG
469 printf("Display MEMORYMODE Command Failed\r\n");
470 #endif
471 ✗ return 1;
472 }
473
474 /* Send display HORIZONTAL MEMORY ADDR MODE command parameter */
475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_HOR_MM) != I2C_TWO_BYTES) {
476 #ifdef SSD1306_DBG
477 printf("Display HORIZONTAL MEMORY ADDR MODE Command Parameter Failed\r\n");
478 #endif
479 ✗ return 1;
480 }
481
482 /* Set display SEG_REMAP */
483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SEG_REMAP) != I2C_TWO_BYTES) {
484 #ifdef SSD1306_DBG
485 printf("Display SEG_REMAP Command Failed\r\n");
486 #endif
487 ✗ return 1;
488 }
489
490 /* Set display DIR */
491
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_COMSCANDEC) != I2C_TWO_BYTES) {
492 #ifdef SSD1306_DBG
493 printf("Display DIR Command Failed\r\n");
494 #endif
495 ✗ return 1;
496 }
497
498 /* Set display COM */
499
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_COMPINS) != I2C_TWO_BYTES) {
500 #ifdef SSD1306_DBG
501 printf("Display COM Command Failed\r\n");
502 #endif
503 ✗ return 1;
504 }
505
506 /* Send display COM command parameter */
507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 int COMPINS = LED_DISPLAY_HEIGHT == 32 ? SSD1306_CONFIG_COM_PINS_32 : SSD1306_CONFIG_COM_PINS_64;
508
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, COMPINS) != I2C_TWO_BYTES) {
509 #ifdef SSD1306_DBG
510 printf("Display COM Command Parameter Failed\r\n");
511 #endif
512 ✗ return 1;
513 }
514
515 /* Set display PRECHARGE */
516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_PRECHARGE) != I2C_TWO_BYTES) {
517 #ifdef SSD1306_DBG
518 printf("Display PRECHARGE Command Failed\r\n");
519 #endif
520 ✗ return 1;
521 }
522
523 /* Send display PRECHARGE command parameter */
524
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_PRECHARGE_VAL) != I2C_TWO_BYTES) {
525 #ifdef SSD1306_DBG
526 printf("Display PRECHARGE Command Parameter Failed\r\n");
527 #endif
528 ✗ return 1;
529 }
530
531 /* Set display VCOMH */
532
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_VCOMDETECT) != I2C_TWO_BYTES) {
533 #ifdef SSD1306_DBG
534 printf("Display VCOMH Command Failed\r\n");
535 #endif
536 ✗ return 1;
537 }
538
539 /* Send display VCOMH command parameter */
540
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_VCOMH_VAL) != I2C_TWO_BYTES) {
541 #ifdef SSD1306_DBG
542 printf("Display VCOMH Command Parameter Failed\r\n");
543 #endif
544 ✗ return 1;
545 }
546
547 /* Set display ALL-ON */
548
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DISPLAYALLON_RESUME) != I2C_TWO_BYTES) {
549 #ifdef SSD1306_DBG
550 printf("Display ALL-ON Command Failed\r\n");
551 #endif
552 ✗ return 1;
553 }
554
555 /* Set display to NORMAL-DISPLAY */
556
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_NORMAL_DISPLAY) != I2C_TWO_BYTES) {
557 #ifdef SSD1306_DBG
558 printf("Display NORMAL-DISPLAY Command Failed\r\n");
559 #endif
560 ✗ return 1;
561 }
562 ✗ } else if (LED_DISPLAY_TYPE == LED_DISPLAY_TYPE_SH1106) {
563 /* Send display OFF command */
564 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DISPLAY_OFF) != I2C_TWO_BYTES) {
565 #ifdef SSD1306_DBG
566 printf("Display OFF Command Failed\r\n");
567 #endif
568 ✗ return 1;
569 }
570 /* Set display multiplex */
571 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_MULTIPLEX) != I2C_TWO_BYTES) {
572 #ifdef SSD1306_DBG
573 printf("Display MULT Command Failed\r\n");
574 #endif
575 ✗ return 1;
576 }
577 /* Send display MULT command parameter */
578 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_MULT_DAT) != I2C_TWO_BYTES) {
579 #ifdef SSD1306_DBG
580 printf("Display MULT Command Parameter Failed\r\n");
581 #endif
582 ✗ return 1;
583 }
584
585 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x02) != I2C_TWO_BYTES) { return 1; }
586 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x10) != I2C_TWO_BYTES) { return 1; }
587 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_DISP_OFFSET) != I2C_TWO_BYTES) { return 1; }
588 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) != I2C_TWO_BYTES) { return 1; }
589 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_DISP_START_LINE) != I2C_TWO_BYTES) { return 1; }
590 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xB0) != I2C_TWO_BYTES) { return 1; }
591 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SEG_REMAP) != I2C_TWO_BYTES) { return 1; }
592 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_NORMAL_DISPLAY) != I2C_TWO_BYTES) { return 1; }
593 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xad) != I2C_TWO_BYTES) { return 1; }
594 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x8b) != I2C_TWO_BYTES) { return 1; }
595 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x30) != I2C_TWO_BYTES) { return 1; }
596 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_COMSCANDEC) != I2C_TWO_BYTES) { return 1; }
597 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_DISP_CLK) != I2C_TWO_BYTES) { return 1; }
598 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x80) != I2C_TWO_BYTES) { return 1; }
599 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_PRECHARGE) != I2C_TWO_BYTES) { return 1; }
600 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x1f) != I2C_TWO_BYTES) { return 1; }
601 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_COMPINS) != I2C_TWO_BYTES) { return 1; }
602 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x12) != I2C_TWO_BYTES) { return 1; }
603 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_VCOMDETECT) != I2C_TWO_BYTES) { return 1; }
604 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x40) != I2C_TWO_BYTES) { return 1; }
605 ✗ } else if (LED_DISPLAY_TYPE == LED_DISPLAY_TYPE_SH1107) {
606 /* The SH1107 is a 128x128 1bpp controller. It is close enough to the
607 * SSD1306 to share the page based framebuffer and every drawing routine,
608 * but it differs in two ways that matter. It has no 0x21/0x22 column and
609 * page range commands - 0x21 selects vertical addressing instead - so the
610 * frame is pushed a page at a time in transfer(). And its panel supply is
611 * enabled with 0xAD 0x8A, not the SSD1306 charge pump: get that one byte
612 * wrong and the controller ACKs every command and reports itself as on
613 * while the glass stays completely dark. */
614 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DISPLAY_OFF) != I2C_TWO_BYTES) { return 1; }
615 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_DISP_CLK) != I2C_TWO_BYTES) { return 1; }
616 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x51) != I2C_TWO_BYTES) { return 1; }
617 /* 0x20 on its own selects page addressing */
618 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_MEM_ADDR_MODE) != I2C_TWO_BYTES) { return 1; }
619 /* Not SSD1306_SEG_REMAP: that is the pre-mirrored 0xA1. The flipped
620 * variant of this display is handled in software by setRotation(). */
621 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xA0) != I2C_TWO_BYTES) { return 1; }
622 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xC0) != I2C_TWO_BYTES) { return 1; }
623 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_MULTIPLEX) != I2C_TWO_BYTES) { return 1; }
624 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_MULT_DAT) != I2C_TWO_BYTES) { return 1; }
625 /* Offset 0, not the 0x60 the widely copied SH1107 init recipes use:
626 * those are written for the 128x64 boards, where 96 lines of offset
627 * are correct. On a full height 128x128 panel it rotates the frame
628 * by 32 columns and the right hand edge wraps around to the left. */
629 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_DISP_OFFSET) != I2C_TWO_BYTES) { return 1; }
630 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) != I2C_TWO_BYTES) { return 1; }
631 /* DC-DC converter on, internal */
632 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xAD) != I2C_TWO_BYTES) { return 1; }
633 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x8A) != I2C_TWO_BYTES) { return 1; }
634 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_PRECHARGE) != I2C_TWO_BYTES) { return 1; }
635 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x22) != I2C_TWO_BYTES) { return 1; }
636 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_VCOMDETECT) != I2C_TWO_BYTES) { return 1; }
637 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x35) != I2C_TWO_BYTES) { return 1; }
638 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DISPLAYALLON_RESUME) != I2C_TWO_BYTES) { return 1; }
639 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_NORMAL_DISPLAY) != I2C_TWO_BYTES) { return 1; }
640 ✗ } else if (LED_DISPLAY_TYPE == LED_DISPLAY_TYPE_SSD1327) {
641 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xae) != I2C_TWO_BYTES) { return 1; } //--turn off oled panel
642
643 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x15) != I2C_TWO_BYTES) { return 1; }; // set column address
644 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) != I2C_TWO_BYTES) { return 1; }; // start column 0
645 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x7f) != I2C_TWO_BYTES) { return 1; }; // end column 127
646
647 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x75) != I2C_TWO_BYTES) { return 1; }; // set row address
648 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) != I2C_TWO_BYTES) { return 1; }; // start row 0
649 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x7f) != I2C_TWO_BYTES) { return 1; }; // end row 127
650
651 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x81) != I2C_TWO_BYTES) { return 1; }; // set contrast control
652 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x80) != I2C_TWO_BYTES) { return 1; };
653
654 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xa0) != I2C_TWO_BYTES) { return 1; }; // gment remap
655 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x51) != I2C_TWO_BYTES) { return 1; }; //51
656
657 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xa1) != I2C_TWO_BYTES) { return 1; }; // start line
658 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) != I2C_TWO_BYTES) { return 1; };
659
660 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xa2) != I2C_TWO_BYTES) { return 1; }; // display offset
661 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) != I2C_TWO_BYTES) { return 1; };
662
663 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xa4) != I2C_TWO_BYTES) { return 1; }; // rmal display
664
665 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xa8) != I2C_TWO_BYTES) { return 1; }; // set multiplex ratio
666 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x7f) != I2C_TWO_BYTES) { return 1; };
667
668 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xb1) != I2C_TWO_BYTES) { return 1; }; // set phase leghth
669 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xf1) != I2C_TWO_BYTES) { return 1; };
670
671 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xb3) != I2C_TWO_BYTES) { return 1; }; // set dclk
672 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) != I2C_TWO_BYTES) { return 1; }; //80Hz:0xc1 90Hz:0xe1 100Hz:0x00 110Hz:0x30 120Hz:0x50 130Hz:0x70 01
673
674 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xab) != I2C_TWO_BYTES) { return 1; }; //
675 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x01) != I2C_TWO_BYTES) { return 1; }; //
676
677 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xb6) != I2C_TWO_BYTES) { return 1; }; // set phase leghth
678 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x0f) != I2C_TWO_BYTES) { return 1; };
679
680 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xbe) != I2C_TWO_BYTES) { return 1; };
681 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x0f) != I2C_TWO_BYTES) { return 1; };
682
683 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xbc) != I2C_TWO_BYTES) { return 1; };
684 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x08) != I2C_TWO_BYTES) { return 1; };
685
686 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xd5) != I2C_TWO_BYTES) { return 1; };
687 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x62) != I2C_TWO_BYTES) { return 1; };
688
689 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xfd) != I2C_TWO_BYTES) { return 1; };
690 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x12) != I2C_TWO_BYTES) { return 1; };
691
692 //----
693 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xb9) != I2C_TWO_BYTES) { return 1; };
694
695 //if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xa0) != I2C_TWO_BYTES) { return 1; }; // gment remap
696 //if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x46) != I2C_TWO_BYTES) { return 1; }; //51
697
698 //if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xaf) != I2C_TWO_BYTES) { return 1; }; //on
699 //return 0;
700 }
701
702 /* Set display CONTRAST */
703
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_CONTRAST) != I2C_TWO_BYTES) {
704 #ifdef SSD1306_DBG
705 printf("Display CONTRAST Command Failed\r\n");
706 #endif
707 ✗ return 1;
708 }
709
710 /* Send display CONTRAST command parameter */
711
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 int CONTRAST = LED_DISPLAY_TYPE == LED_DISPLAY_TYPE_SSD1306 ? SSD1306_CONTRAST_VAL : 0x80;
712
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (LED_DISPLAY_HEIGHT == 32) {
713 ✗ CONTRAST = 0x8F;
714 }
715
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, CONTRAST) != I2C_TWO_BYTES) {
716 #ifdef SSD1306_DBG
717 printf("Display CONTRAST Command Parameter Failed\r\n");
718 #endif
719 ✗ return 1;
720 }
721
722
723
724 /* Set display to DEACTIVATE_SCROLL */
725
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DEACTIVATE_SCROLL) != I2C_TWO_BYTES) {
726 #ifdef SSD1306_DBG
727 printf("Display DEACTIVATE_SCROLL Command Failed\r\n");
728 #endif
729 ✗ return 1;
730 }
731
732 /* Set display to TURN-ON */
733
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
12 if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DISPLAYON) != I2C_TWO_BYTES) {
734 #ifdef SSD1306_DBG
735 printf("Display TURN-ON Command Failed\r\n");
736 #endif
737 ✗ return 1;
738 }
739 12 return 0;
740 }
741
742 /****************************************************************
743 * Function Name : transfer
744 * Description : Transfer the frame buffer onto the display
745 * Returns : NONE.
746 * Params : NONE.
747 ****************************************************************/
748 83 int transfer()
749 {
750 /* Debugging code */
751 /*
752 int ww = (_width * _height) / 8;
753 for (int y = 0; y < ww; y++) {
754 printf("0x%02X, ", screen[y]);
755 if (y % 32 == 31) {
756 printf("\n");
757 }
758 }
759 printf("\n\n");
760 */
761
762 83 short loop_1 = 0, loop_2 = 0;
763 83 short index = 0x00;
764 83 int max = _height * _width / 8;
765
1/2
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
83 if (LED_DISPLAY_TYPE == LED_DISPLAY_TYPE_SSD1306) {
766
1/2
✓ Branch 0 taken 664 times.
✗ Branch 1 not taken.
664 for (loop_1 = 0; loop_1 < 1024; loop_1++) {
767 664 chunk[0] = 0x40;
768
2/2
✓ Branch 0 taken 84992 times.
✓ Branch 1 taken 664 times.
85656 for(loop_2 = 1; loop_2 < MAX_CHUNK_SIZE; loop_2++)
769 84992 chunk[loop_2] = screen[index++];
770
771
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 664 times.
664 if (i2c_multiple_writes(I2C_DEV_2.fd_i2c, MAX_CHUNK_SIZE, chunk) != MAX_CHUNK_SIZE) {
772 #ifdef SSD1306_DBG
773 printf("Chunk written to RAM - Failed\r\n");
774 #endif
775 ✗ return 1;
776 }
777
778 664 memset(chunk,0x00,MAX_CHUNK_SIZE);
779
2/2
✓ Branch 0 taken 83 times.
✓ Branch 1 taken 581 times.
664 if (index == max)
780 83 break;
781 }
782 ✗ } else if (LED_DISPLAY_TYPE == LED_DISPLAY_TYPE_SSD1327) {
783 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x15) != I2C_TWO_BYTES) { printf("1\n"); return 1; }
784 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0) != I2C_TWO_BYTES) { printf("2\n"); return 1; }
785 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 127) != I2C_TWO_BYTES) { printf("3\n"); return 1; }
786
787 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x75) != I2C_TWO_BYTES) { printf("4\n"); return 1; }
788 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0) != I2C_TWO_BYTES) { printf("5\n"); return 1; }
789 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 127) != I2C_TWO_BYTES) { printf("6\n"); return 1; }
790
791 ✗ int max = _height * _width / 2;
792 ✗ for (loop_1 = 0; loop_1 < 8*1024; loop_1++) {
793 ✗ memset(chunk,0x00,MAX_CHUNK_SIZE);
794 ✗ chunk[0] = 0x40;
795 ✗ for(loop_2 = 1; loop_2 < MAX_CHUNK_SIZE; ) {
796 ✗ int i = screen[index];
797 ✗ chunk[loop_2] = i;
798 ✗ index++;
799 ✗ loop_2++;
800
801 ✗ if (index == max)
802 ✗ break;
803 }
804 ✗ if (loop_2 > 1) {
805 ✗ if (i2c_multiple_writes(I2C_DEV_2.fd_i2c, loop_2, chunk) != loop_2) {
806 ✗ printf("Chunk written to RAM - Failed\r\n");
807 ✗ return 1;
808 }
809 }
810 ✗ if (index == max)
811 ✗ break;
812 }
813 } else {
814 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) != I2C_TWO_BYTES) { return 1; }
815 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x10) != I2C_TWO_BYTES) { return 1; }
816 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x40) != I2C_TWO_BYTES) { return 1; }
817
818 ✗ chunk[0] = 0x40;
819
820 /* One page is 8 rows, so a 64 row SH1106 walks 8 of them and a 128 row
821 * SH1107 walks 16. The SH1106 is a 132 column controller behind a 128
822 * column panel and its framebuffer therefore starts at column 2; the
823 * SH1107 is a true 128 columns and starts at 0. */
824 ✗ int pages = LED_DISPLAY_HEIGHT / 8;
825 ✗ unsigned char colLow = (LED_DISPLAY_TYPE == LED_DISPLAY_TYPE_SH1107) ? 0x00 : 0x02;
826 ✗ for (uint8_t k=0; k < pages; k++) {
827 //set page addressSSD_Data_Mode;
828 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xB0+k) != I2C_TWO_BYTES) {
829 ✗ return 1;
830 }
831 //set lower column address
832 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, colLow) != I2C_TWO_BYTES) {
833 ✗ return 1;
834 }
835 //set higher column address
836 ✗ if (i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x10) != I2C_TWO_BYTES) {
837 ✗ return 1;
838 }
839 ✗ for (int i = 0; i < 8; i++) {
840 ✗ for (int x = 1; x <= 16; x++) {
841 ✗ chunk[x] = screen[index++];
842 }
843 ✗ if (i2c_multiple_writes(I2C_DEV_2.fd_i2c, 17, chunk) != 17) {
844 #ifdef SSD1306_DBG
845 printf("Chunk written to RAM - Failed\r\n");
846 #endif
847 ✗ return 1;
848 }
849 }
850 }
851 }
852 83 return 0;
853 }
854
855
856 /****************************************************************
857 * Function Name : Display
858 * Description : 1. Resets the column and page addresses.
859 * 2. Displays the contents of the memory buffer.
860 * Returns : NONE.
861 * Params : NONE.
862 * Note : Each new form can be preceded by a clearDisplay.
863 ****************************************************************/
864 83 int Display()
865 {
866 /* The SSD1327 sets its own window inside transfer(). The SH1107 has to be
867 * skipped too: 0x21 is not a column range command there, it switches the
868 * controller into vertical addressing and would break the page walk. */
869
2/4
✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 83 times.
✗ Branch 3 not taken.
83 if (LED_DISPLAY_TYPE != LED_DISPLAY_TYPE_SSD1327 && LED_DISPLAY_TYPE != LED_DISPLAY_TYPE_SH1107) {
870
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if (Init_Col_PG_addrs(SSD1306_COL_START_ADDR,SSD1306_COL_END_ADDR,
871 SSD1306_PG_START_ADDR,SSD1306_PG_END_ADDR) ) {
872 ✗ return 1;
873 }
874 }
875 83 return transfer();
876 }
877
878 /****************************************************************
879 * Function Name : Init_Col_PG_addrs
880 * Description : Sets the column and page, start and
881 * end addresses.
882 * Returns : NONE.
883 * Params : @col_start_addr: Column start address
884 * @col_end_addr: Column end address
885 * @pg_start_addr: Page start address
886 * @pg_end_addr: Page end address
887 ****************************************************************/
888 83 int Init_Col_PG_addrs(unsigned char col_start_addr, unsigned char col_end_addr,
889 unsigned char pg_start_addr, unsigned char pg_end_addr)
890 {
891 /* Send COLMN address setting command */
892
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_COL_ADDR) == I2C_TWO_BYTES)
893 {
894 #ifdef SSD1306_DBG
895 printf("Display COLMN Command Passed\r\n");
896 #endif
897 }
898 else
899 {
900 #ifdef SSD1306_DBG
901 printf("Display COLMN Command Failed\r\n");
902 #endif
903 ✗ return 1;
904 }
905
906 /* Set COLMN start address */
907
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, col_start_addr) == I2C_TWO_BYTES)
908 {
909 #ifdef SSD1306_DBG
910 printf("Display COLMN Start Address param Passed\r\n");
911 #endif
912 }
913 else
914 {
915 #ifdef SSD1306_DBG
916 printf("Display COLMN Start Address param Failed\r\n");
917 #endif
918 ✗ return 1;
919 }
920
921 /* Set COLMN end address */
922
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, col_end_addr) == I2C_TWO_BYTES)
923 {
924 #ifdef SSD1306_DBG
925 printf("Display COLMN End Address param Passed\r\n");
926 #endif
927 }
928 else
929 {
930 #ifdef SSD1306_DBG
931 printf("Display COLMN End Address param Failed\r\n");
932 #endif
933 ✗ return 1;
934 }
935
936 /* Send PAGE address setting command */
937
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_PAGEADDR) == I2C_TWO_BYTES)
938 {
939 #ifdef SSD1306_DBG
940 printf("Display PAGE Command Passed\r\n");
941 #endif
942 }
943 else
944 {
945 #ifdef SSD1306_DBG
946 printf("Display PAGE Command Failed\r\n");
947 #endif
948 ✗ return 1;
949 }
950
951 /* Set PAGE start address */
952
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, pg_start_addr) == I2C_TWO_BYTES)
953 {
954 #ifdef SSD1306_DBG
955 printf("Display PAGE Start Address param Passed\r\n");
956 #endif
957 }
958 else
959 {
960 #ifdef SSD1306_DBG
961 printf("Display PAGE Start Address param Failed\r\n");
962 #endif
963 ✗ return 1;
964 }
965
966 /* Set PAGE end address */
967
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
83 if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, pg_end_addr) == I2C_TWO_BYTES)
968 {
969 #ifdef SSD1306_DBG
970 printf("Display PAGE End Address param Passed\r\n");
971 #endif
972 }
973 else
974 {
975 #ifdef SSD1306_DBG
976 printf("Display PAGE End Address param Failed\r\n");
977 #endif
978 ✗ return 1;
979 }
980 83 return 0;
981 }
982
983 /****************************************************************
984 * Function Name : setRotation
985 * Description : Set the display rotation
986 * Returns : NONE.
987 * Params : @x: Display rotation parameter
988 ****************************************************************/
989 12 void setRotation(unsigned char x)
990 {
991 12 _rotation = x & 3;
992 12 }
993
994 /****************************************************************
995 * Function Name : startscrollright
996 * Description : Activate a right handed scroll for rows start
997 * through stop
998 * Returns : NONE.
999 * Params : @start: Start location
1000 * @stop: Stop location
1001 * HINT. : the display is 16 rows tall. To scroll the whole
1002 * display, run: display.scrollright(0x00, 0x0F)
1003 ****************************************************************/
1004 ✗ int startscrollright(unsigned char start, unsigned char stop)
1005 {
1006 /* Send SCROLL horizontal right command */
1007 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_RIGHT_HORIZONTAL_SCROLL) == I2C_TWO_BYTES)
1008 {
1009 #ifdef SSD1306_DBG
1010 printf("Display HORIZONTAL SCROLL RIGHT Command Passed\r\n");
1011 #endif
1012 }
1013 else
1014 {
1015 #ifdef SSD1306_DBG
1016 printf("Display HORIZONTAL SCROLL RIGHT Command Failed\r\n");
1017 #endif
1018 ✗ return 1;
1019 }
1020
1021
1022 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES)
1023 {
1024 #ifdef SSD1306_DBG
1025 printf("HORI_SR Param_1 Passed\r\n");
1026 #endif
1027 }
1028 else
1029 {
1030 #ifdef SSD1306_DBG
1031 printf("HORI_SR Param_1 Failed\r\n");
1032 #endif
1033 ✗ return 1;
1034 }
1035
1036 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, start) == I2C_TWO_BYTES)
1037 {
1038 #ifdef SSD1306_DBG
1039 printf("HORI_SR Param_2 Passed\r\n");
1040 #endif
1041 }
1042 else
1043 {
1044 #ifdef SSD1306_DBG
1045 printf("HORI_SR Param_2 Passed\r\n");
1046 #endif
1047 ✗ return 1;
1048 }
1049
1050 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES)
1051 {
1052 #ifdef SSD1306_DBG
1053 printf("HORI_SR Param_3 Passed\r\n");
1054 #endif
1055 }
1056 else
1057 {
1058 #ifdef SSD1306_DBG
1059 printf("HORI_SR Param_3 Failed\r\n");
1060 #endif
1061 ✗ return 1;
1062 }
1063
1064 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, stop) == I2C_TWO_BYTES)
1065 {
1066 #ifdef SSD1306_DBG
1067 printf("HORI_SR Param_4 Passed\r\n");
1068 #endif
1069 }
1070 else
1071 {
1072 #ifdef SSD1306_DBG
1073 printf("HORI_SR Param_4 Passed\r\n");
1074 #endif
1075 ✗ return 1;
1076 }
1077
1078 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES)
1079 {
1080 #ifdef SSD1306_DBG
1081 printf("HORI_SR Param_5 Passed\r\n");
1082 #endif
1083 }
1084 else
1085 {
1086 #ifdef SSD1306_DBG
1087 printf("HORI_SR Param_5 Failed\r\n");
1088 #endif
1089 ✗ return 1;
1090 }
1091
1092 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xFF) == I2C_TWO_BYTES)
1093 {
1094 #ifdef SSD1306_DBG
1095 printf("HORI_SR Param_6 Passed\r\n");
1096 #endif
1097 }
1098 else
1099 {
1100 #ifdef SSD1306_DBG
1101 printf("HORI_SR Param_6 Passed\r\n");
1102 #endif
1103 ✗ return 1;
1104 }
1105 /* Send SCROLL Activate command */
1106 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_ACTIVATE_SCROLL) == I2C_TWO_BYTES)
1107 {
1108 #ifdef SSD1306_DBG
1109 printf("SCROLL Activate Command Passed\r\n");
1110 #endif
1111 }
1112 else
1113 {
1114 #ifdef SSD1306_DBG
1115 printf("SCROLL Activate Command Failed\r\n");
1116 #endif
1117 ✗ return 1;
1118 }
1119 ✗ return 0;
1120 }
1121
1122 /****************************************************************
1123 * Function Name : startscrollleft
1124 * Description : Activate a left handed scroll for rows start
1125 * through stop
1126 * Returns : NONE.
1127 * Params : @start: Start location
1128 * @stop: Stop location
1129 * HINT. : the display is 16 rows tall. To scroll the whole
1130 * display, run: display.scrollright(0x00, 0x0F)
1131 ****************************************************************/
1132 ✗ int startscrollleft(unsigned char start, unsigned char stop)
1133 {
1134 /* Send SCROLL horizontal left command */
1135 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_LEFT_HORIZONTAL_SCROLL) == I2C_TWO_BYTES)
1136 {
1137 #ifdef SSD1306_DBG
1138 printf("Display HORIZONTAL SCROLL LEFT Command Passed\r\n");
1139 #endif
1140 }
1141 else
1142 {
1143 #ifdef SSD1306_DBG
1144 printf("Display HORIZONTAL SCROLL LEFT Command Failed\r\n");
1145 #endif
1146 ✗ return 1;
1147 }
1148
1149
1150 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES)
1151 {
1152 #ifdef SSD1306_DBG
1153 printf("HORI_SR Param_1 Passed\r\n");
1154 #endif
1155 }
1156 else
1157 {
1158 #ifdef SSD1306_DBG
1159 printf("HORI_SR Param_1 Failed\r\n");
1160 #endif
1161 ✗ return 1;
1162 }
1163
1164 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, start) == I2C_TWO_BYTES)
1165 {
1166 #ifdef SSD1306_DBG
1167 printf("HORI_SR Param_2 Passed\r\n");
1168 #endif
1169 }
1170 else
1171 {
1172 #ifdef SSD1306_DBG
1173 printf("HORI_SR Param_2 Passed\r\n");
1174 #endif
1175 ✗ return 1;
1176 }
1177
1178 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES)
1179 {
1180 #ifdef SSD1306_DBG
1181 printf("HORI_SR Param_3 Passed\r\n");
1182 #endif
1183 }
1184 else
1185 {
1186 #ifdef SSD1306_DBG
1187 printf("HORI_SR Param_3 Failed\r\n");
1188 #endif
1189 ✗ return 1;
1190 }
1191
1192 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, stop) == I2C_TWO_BYTES)
1193 {
1194 #ifdef SSD1306_DBG
1195 printf("HORI_SR Param_4 Passed\r\n");
1196 #endif
1197 }
1198 else
1199 {
1200 #ifdef SSD1306_DBG
1201 printf("HORI_SR Param_4 Passed\r\n");
1202 #endif
1203 ✗ return 1;
1204 }
1205
1206 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES)
1207 {
1208 #ifdef SSD1306_DBG
1209 printf("HORI_SR Param_5 Passed\r\n");
1210 #endif
1211 }
1212 else
1213 {
1214 #ifdef SSD1306_DBG
1215 printf("HORI_SR Param_5 Failed\r\n");
1216 #endif
1217 ✗ return 1;
1218 }
1219
1220 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0xFF) == I2C_TWO_BYTES)
1221 {
1222 #ifdef SSD1306_DBG
1223 printf("HORI_SR Param_6 Passed\r\n");
1224 #endif
1225 }
1226 else
1227 {
1228 #ifdef SSD1306_DBG
1229 printf("HORI_SR Param_6 Passed\r\n");
1230 #endif
1231 ✗ return 1;
1232 }
1233 /* Send SCROLL Activate command */
1234 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_ACTIVATE_SCROLL) == I2C_TWO_BYTES)
1235 {
1236 #ifdef SSD1306_DBG
1237 printf("SCROLL Activate Command Passed\r\n");
1238 #endif
1239 }
1240 else
1241 {
1242 #ifdef SSD1306_DBG
1243 printf("SCROLL Activate Command Failed\r\n");
1244 #endif
1245 ✗ return 1;
1246 }
1247 ✗ return 0;
1248 }
1249
1250 /****************************************************************
1251 * Function Name : startscrolldiagright
1252 * Description : Activate a diagonal scroll for rows start
1253 * through stop
1254 * Returns : NONE.
1255 * Params : @start: Start location
1256 * @stop: Stop location
1257 * HINT. : the display is 16 rows tall. To scroll the whole
1258 * display, run: display.scrollright(0x00, 0x0F)
1259 ****************************************************************/
1260 ✗ int startscrolldiagright(unsigned char start, unsigned char stop)
1261 {
1262 /* Send SCROLL diagonal right command */
1263 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_VERTICAL_SCROLL_AREA) == I2C_TWO_BYTES)
1264 {
1265 #ifdef SSD1306_DBG
1266 printf("Display DIAGONAL SCROLL RIGHT Command Passed\r\n");
1267 #endif
1268 }
1269 else
1270 {
1271 #ifdef SSD1306_DBG
1272 printf("Display DIAGONAL SCROLL RIGHT Command Failed\r\n");
1273 #endif
1274 ✗ return 1;
1275 }
1276
1277
1278 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES)
1279 {
1280 #ifdef SSD1306_DBG
1281 printf("DIAG_SR Param_1 Passed\r\n");
1282 #endif
1283 }
1284 else
1285 {
1286 #ifdef SSD1306_DBG
1287 printf("DIAG_SR Param_1 Failed\r\n");
1288 #endif
1289 ✗ return 1;
1290 }
1291
1292 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, LED_DISPLAY_HEIGHT) == I2C_TWO_BYTES)
1293 {
1294 #ifdef SSD1306_DBG
1295 printf("DIAG_SR Param_2 Passed\r\n");
1296 #endif
1297 }
1298 else
1299 {
1300 #ifdef SSD1306_DBG
1301 printf("DIAG_SR Param_2 Failed\r\n");
1302 #endif
1303 ✗ return 1;
1304 }
1305
1306 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_VERTICAL_AND_RIGHT_HORIZONTAL_SCROLL) == I2C_TWO_BYTES)
1307 {
1308 #ifdef SSD1306_DBG
1309 printf("Cmd Passed\r\n");
1310 #endif
1311 }
1312 else
1313 {
1314 #ifdef SSD1306_DBG
1315 printf("Cmd Failed\r\n");
1316 #endif
1317 ✗ return 1;
1318 }
1319
1320 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES)
1321 {
1322 #ifdef SSD1306_DBG
1323 printf("DIAG_SR Param_3 Passed\r\n");
1324 #endif
1325 }
1326 else
1327 {
1328 #ifdef SSD1306_DBG
1329 printf("DIAG_SR Param_3 Failed\r\n");
1330 #endif
1331 ✗ return 1;
1332 }
1333
1334 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, start) == I2C_TWO_BYTES)
1335 {
1336 #ifdef SSD1306_DBG
1337 printf("DIAG_SR Param_4 Passed\r\n");
1338 #endif
1339 }
1340 else
1341 {
1342 #ifdef SSD1306_DBG
1343 printf("DIAG_SR Param_4 Failed\r\n");
1344 #endif
1345 ✗ return 1;
1346 }
1347
1348 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES)
1349 {
1350 #ifdef SSD1306_DBG
1351 printf("DIAG_SR Param_5 Passed\r\n");
1352 #endif
1353 }
1354 else
1355 {
1356 #ifdef SSD1306_DBG
1357 printf("DIAG_SR Param_5 Failed\r\n");
1358 #endif
1359 ✗ return 1;
1360 }
1361
1362 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, stop) == I2C_TWO_BYTES)
1363 {
1364 #ifdef SSD1306_DBG
1365 printf("DIAG_SR Param_6 Passed\r\n");
1366 #endif
1367 }
1368 else
1369 {
1370 #ifdef SSD1306_DBG
1371 printf("DIAG_SR Param_6 Failed\r\n");
1372 #endif
1373 ✗ return 1;
1374 }
1375
1376 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x01) == I2C_TWO_BYTES)
1377 {
1378 #ifdef SSD1306_DBG
1379 printf("DIAG_SR Param_5 Passed\r\n");
1380 #endif
1381 }
1382 else
1383 {
1384 #ifdef SSD1306_DBG
1385 printf("DIAG_SR Param_5 Failed\r\n");
1386 #endif
1387 ✗ return 1;
1388 }
1389
1390 /* Send SCROLL Activate command */
1391 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_ACTIVATE_SCROLL) == I2C_TWO_BYTES)
1392 {
1393 #ifdef SSD1306_DBG
1394 printf("SCROLL Activate Command Passed\r\n");
1395 #endif
1396 }
1397 else
1398 {
1399 #ifdef SSD1306_DBG
1400 printf("SCROLL Activate Command Failed\r\n");
1401 #endif
1402 ✗ return 1;
1403 }
1404 ✗ return 0;
1405 }
1406
1407 /****************************************************************
1408 * Function Name : startscrolldiagleft
1409 * Description : Activate a diagonal scroll for rows start
1410 * through stop
1411 * Returns : NONE.
1412 * Params : @start: Start location
1413 * @stop: Stop location
1414 * HINT. : the display is 16 rows tall. To scroll the whole
1415 * display, run: display.scrollright(0x00, 0x0F)
1416 ****************************************************************/
1417 ✗ int startscrolldiagleft(unsigned char start, unsigned char stop)
1418 {
1419 /* Send SCROLL diagonal right command */
1420 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_SET_VERTICAL_SCROLL_AREA) == I2C_TWO_BYTES)
1421 {
1422 #ifdef SSD1306_DBG
1423 printf("Display DIAGONAL SCROLL RIGHT Command Passed\r\n");
1424 #endif
1425 }
1426 else
1427 {
1428 #ifdef SSD1306_DBG
1429 printf("Display DIAGONAL SCROLL RIGHT Command Failed\r\n");
1430 #endif
1431 ✗ return 1;
1432 }
1433
1434
1435 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES)
1436 {
1437 #ifdef SSD1306_DBG
1438 printf("DIAG_SR Param_1 Passed\r\n");
1439 #endif
1440 }
1441 else
1442 {
1443 #ifdef SSD1306_DBG
1444 printf("DIAG_SR Param_1 Failed\r\n");
1445 #endif
1446 ✗ return 1;
1447 }
1448
1449 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, LED_DISPLAY_HEIGHT) == I2C_TWO_BYTES)
1450 {
1451 #ifdef SSD1306_DBG
1452 printf("DIAG_SR Param_2 Passed\r\n");
1453 #endif
1454 }
1455 else
1456 {
1457 #ifdef SSD1306_DBG
1458 printf("DIAG_SR Param_2 Failed\r\n");
1459 #endif
1460 ✗ return 1;
1461 }
1462
1463 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_VERTICAL_AND_LEFT_HORIZONTAL_SCROLL) == I2C_TWO_BYTES)
1464 {
1465 #ifdef SSD1306_DBG
1466 printf("Cmd Passed\r\n");
1467 #endif
1468 }
1469 else
1470 {
1471 #ifdef SSD1306_DBG
1472 printf("Cmd Failed\r\n");
1473 #endif
1474 ✗ return 1;
1475 }
1476
1477 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES)
1478 {
1479 #ifdef SSD1306_DBG
1480 printf("DIAG_SR Param_3 Passed\r\n");
1481 #endif
1482 }
1483 else
1484 {
1485 #ifdef SSD1306_DBG
1486 printf("DIAG_SR Param_3 Failed\r\n");
1487 #endif
1488 ✗ return 1;
1489 }
1490
1491 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, start) == I2C_TWO_BYTES)
1492 {
1493 #ifdef SSD1306_DBG
1494 printf("DIAG_SR Param_4 Passed\r\n");
1495 #endif
1496 }
1497 else
1498 {
1499 #ifdef SSD1306_DBG
1500 printf("DIAG_SR Param_4 Failed\r\n");
1501 #endif
1502 ✗ return 1;
1503 }
1504
1505 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x00) == I2C_TWO_BYTES)
1506 {
1507 #ifdef SSD1306_DBG
1508 printf("DIAG_SR Param_5 Passed\r\n");
1509 #endif
1510 }
1511 else
1512 {
1513 #ifdef SSD1306_DBG
1514 printf("DIAG_SR Param_5 Failed\r\n");
1515 #endif
1516 ✗ return 1;
1517 }
1518
1519 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, stop) == I2C_TWO_BYTES)
1520 {
1521 #ifdef SSD1306_DBG
1522 printf("DIAG_SR Param_6 Passed\r\n");
1523 #endif
1524 }
1525 else
1526 {
1527 #ifdef SSD1306_DBG
1528 printf("DIAG_SR Param_6 Failed\r\n");
1529 #endif
1530 ✗ return 1;
1531 }
1532
1533 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, 0x01) == I2C_TWO_BYTES)
1534 {
1535 #ifdef SSD1306_DBG
1536 printf("DIAG_SR Param_5 Passed\r\n");
1537 #endif
1538 }
1539 else
1540 {
1541 #ifdef SSD1306_DBG
1542 printf("DIAG_SR Param_5 Failed\r\n");
1543 #endif
1544 ✗ return 1;
1545 }
1546
1547 /* Send SCROLL Activate command */
1548 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_ACTIVATE_SCROLL) == I2C_TWO_BYTES)
1549 {
1550 #ifdef SSD1306_DBG
1551 printf("SCROLL Activate Command Passed\r\n");
1552 #endif
1553 }
1554 else
1555 {
1556 #ifdef SSD1306_DBG
1557 printf("SCROLL Activate Command Failed\r\n");
1558 #endif
1559 ✗ return 1;
1560 }
1561 ✗ return 0;
1562 }
1563
1564 /****************************************************************
1565 * Function Name : stopscroll
1566 * Description : Stop scrolling
1567 * Returns : NONE.
1568 * Params : NONE.
1569 ****************************************************************/
1570 ✗ int stopscroll()
1571 {
1572 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_DEACTIVATE_SCROLL) == I2C_TWO_BYTES)
1573 {
1574 #ifdef SSD1306_DBG
1575 printf("De-activate SCROLL Command Passed\r\n");
1576 #endif
1577 }
1578 else
1579 {
1580 #ifdef SSD1306_DBG
1581 printf("De-activate SCROLL Command Passed Failed\r\n");
1582 #endif
1583 ✗ return 1;
1584 }
1585 ✗ return 0;
1586 }
1587
1588 /****************************************************************
1589 * Function Name : invertDisplay
1590 * Description : Invert or Normalize the display
1591 * Returns : NONE.
1592 * Params : @i: 0x00 to Normal and 0x01 for Inverting
1593 ****************************************************************/
1594 ✗ int invertDisplay(unsigned char i)
1595 {
1596 ✗ if (i)
1597 {
1598 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_INVERTDISPLAY) == I2C_TWO_BYTES)
1599 {
1600 ✗ printf("Display Inverted - Passed\r\n");
1601 }
1602 else
1603 {
1604 ✗ printf("Display Inverted - Failed\r\n");
1605 ✗ return 1;
1606 }
1607 }
1608 else
1609 {
1610 ✗ if(i2c_write_register(I2C_DEV_2.fd_i2c, SSD1306_CNTRL_CMD, SSD1306_NORMAL_DISPLAY) == I2C_TWO_BYTES)
1611 {
1612 ✗ printf("Display Normal - Passed\r\n");
1613 }
1614 else
1615 {
1616 ✗ printf("Display Normal - Failed\r\n");
1617 ✗ return 1;
1618 }
1619 }
1620 ✗ return 0;
1621 }
1622
1623 /****************************************************************
1624 * Function Name : drawPixel
1625 * Description : Draw a pixel
1626 * Returns : -1 on error and 0 on success
1627 * Params : @x: X - Co-ordinate
1628 * @y: Y - Co-ordinate
1629 * @color: Color
1630 ****************************************************************/
1631 90258 signed char drawPixel(short x, short y, short color)
1632 {
1633 /* Return if co-ordinates are out of display dimension's range */
1634
4/8
✓ Branch 0 taken 90258 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 90258 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 90258 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 90258 times.
90258 if ((x < 0) || (x >= _width) || (y < 0) || (y >= _height))
1635 ✗ return -1;
1636
1/3
✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 90258 times.
90258 switch(_rotation)
1637 {
1638 ✗ case 1:
1639 ✗ x = _width - x - 1;
1640 ✗ break;
1641 ✗ case 2:
1642 ✗ x = _width - x - 1;
1643 ✗ y = _height - y - 1;
1644 ✗ break;
1645 }
1646 /* x is the column */
1647
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 90258 times.
90258 if (LED_DISPLAY_TYPE == LED_DISPLAY_TYPE_SSD1327) {
1648 ✗ int idx = y * LED_DISPLAY_WIDTH/2 + x / 2;
1649 ✗ uint8_t val = 0xF0;
1650 ✗ if (x % 2) {
1651 ✗ val = 0x0F;
1652 }
1653 ✗ switch(color) {
1654 ✗ case WHITE: screen[idx] |= val; break;
1655 ✗ case BLACK: screen[idx] &= ~val; break;
1656 ✗ case INVERSE: screen[idx] ^= val; break;
1657 }
1658 } else {
1659
2/4
✓ Branch 0 taken 88460 times.
✓ Branch 1 taken 1798 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
90258 switch(color) {
1660 88460 case WHITE: screen[x+ (y/8)*LED_DISPLAY_WIDTH] |= (1 << (y&7)); break;
1661 1798 case BLACK: screen[x+ (y/8)*LED_DISPLAY_WIDTH] &= ~(1 << (y&7)); break;
1662 ✗ case INVERSE: screen[x+ (y/8)*LED_DISPLAY_WIDTH] ^= (1 << (y&7)); break;
1663 }
1664 }
1665 90258 return 0;
1666 }
1667
1668 /****************************************************************
1669 * Function Name : writeLine
1670 * Description : Bresenham's algorithm
1671 * Returns : NONE
1672 * Params : @x0: X0 Co-ordinate
1673 * @y0: Y0 Co-ordinate
1674 * @x1: X1 Co-ordinate
1675 * @y1: Y1 Co-ordinate
1676 * @color: Pixel color
1677 ****************************************************************/
1678 1809 void writeLine(short x0, short y0, short x1, short y1, short color)
1679 {
1680 1809 short steep = 0, dx = 0, dy = 0, err = 0, ystep = 0;
1681 1809 steep = abs(y1 - y0) > abs(x1 - x0);
1682
2/2
✓ Branch 0 taken 1680 times.
✓ Branch 1 taken 129 times.
1809 if (steep)
1683 {
1684 1680 SWAP(x0, y0);
1685 1680 SWAP(x1, y1);
1686 }
1687
1688
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1809 times.
1809 if (x0 > x1)
1689 {
1690 ✗ SWAP(x0, x1);
1691 ✗ SWAP(y0, y1);
1692 }
1693 1809 dx = x1 - x0;
1694 1809 dy = abs(y1 - y0);
1695
1696 1809 err = dx / 2;
1697
1698
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1809 times.
1809 if (y0 < y1)
1699 {
1700 ✗ ystep = 1;
1701 } else
1702 {
1703 1809 ystep = -1;
1704 }
1705
1706
2/2
✓ Branch 0 taken 23057 times.
✓ Branch 1 taken 1809 times.
24866 for (; x0<=x1; x0++)
1707 {
1708
2/2
✓ Branch 0 taken 14224 times.
✓ Branch 1 taken 8833 times.
23057 if (steep)
1709 {
1710 14224 drawPixel(y0, x0, color);
1711 } else
1712 {
1713 8833 drawPixel(x0, y0, color);
1714 }
1715 23057 err -= dy;
1716
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 23057 times.
23057 if (err < 0)
1717 {
1718 ✗ y0 += ystep;
1719 ✗ err += dx;
1720 }
1721 }
1722 1809 }
1723
1724 /* (x,y) is topmost point; if unsure, calling function
1725 should sort endpoints or call writeLine() instead */
1726 1680 void drawFastVLine(short x, short y,short h, short color)
1727 {
1728 //startWrite();
1729 1680 writeLine(x, y, x, y+h-1, color);
1730 //endWrite();
1731 1680 }
1732
1733 /* (x,y) is topmost point; if unsure, calling function
1734 should sort endpoints or call writeLine() instead */
1735 1680 void writeFastVLine(short x, short y, short h, short color)
1736 {
1737 1680 drawFastVLine(x, y, h, color);
1738 1680 }
1739
1740 /* (x,y) is leftmost point; if unsure, calling function
1741 should sort endpoints or call writeLine() instead */
1742 129 void drawFastHLine(short x, short y,short w, short color)
1743 {
1744 //startWrite();
1745 129 writeLine(x, y, x+w-1, y, color);
1746 //endWrite();
1747 129 }
1748
1749 // (x,y) is leftmost point; if unsure, calling function
1750 // should sort endpoints or call writeLine() instead
1751 77 void writeFastHLine(short x, short y, short w, short color)
1752 {
1753 77 drawFastHLine(x, y, w, color);
1754 77 }
1755
1756 /****************************************************************
1757 * Function Name : drawCircleHelper
1758 * Description : Draw a....
1759 * Returns : NONE
1760 * Params : @x: X Co-ordinate
1761 * @y: Y Co-ordinate
1762 * @w: Width
1763 * @h: height
1764 * @r: Corner radius
1765 * @color: Pixel color
1766 ****************************************************************/
1767 ✗ void drawCircleHelper( short x0, short y0, short r, unsigned char cornername, short color)
1768 {
1769 ✗ short f = 1 - r;
1770 ✗ short ddF_x = 1;
1771 ✗ short ddF_y = -2 * r;
1772 ✗ short x = 0;
1773 ✗ short y = r;
1774
1775 ✗ while (x<y)
1776 {
1777 ✗ if (f >= 0)
1778 {
1779 ✗ y--;
1780 ✗ ddF_y += 2;
1781 ✗ f += ddF_y;
1782 }
1783 ✗ x++;
1784 ✗ ddF_x += 2;
1785 ✗ f += ddF_x;
1786 ✗ if (cornername & 0x4)
1787 {
1788 ✗ drawPixel(x0 + x, y0 + y, color);
1789 ✗ drawPixel(x0 + y, y0 + x, color);
1790 }
1791 ✗ if (cornername & 0x2)
1792 {
1793 ✗ drawPixel(x0 + x, y0 - y, color);
1794 ✗ drawPixel(x0 + y, y0 - x, color);
1795 }
1796 ✗ if (cornername & 0x8)
1797 {
1798 ✗ drawPixel(x0 - y, y0 + x, color);
1799 ✗ drawPixel(x0 - x, y0 + y, color);
1800 }
1801 ✗ if (cornername & 0x1)
1802 {
1803 ✗ drawPixel(x0 - y, y0 - x, color);
1804 ✗ drawPixel(x0 - x, y0 - y, color);
1805 }
1806 }
1807 ✗ }
1808
1809 /****************************************************************
1810 * Function Name : drawLine
1811 * Description : Draw line between two points
1812 * Returns : NONE
1813 * Params : @x0: X0 Starting X Co-ordinate
1814 * @y0: Y0 Starting Y Co-ordinate
1815 * @x1: X1 Ending X Co-ordinate
1816 * @y1: Y1 Ending Y Co-ordinate
1817 * @color: Pixel color
1818 ****************************************************************/
1819 52 void drawLine(short x0, short y0, short x1, short y1, short color)
1820 {
1821
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if(x0 == x1)
1822 {
1823 ✗ if(y0 > y1)
1824 ✗ SWAP(y0, y1);
1825 ✗ drawFastVLine(x0, y0, y1 - y0 + 1, color);
1826 }
1827
1/2
✓ Branch 0 taken 52 times.
✗ Branch 1 not taken.
52 else if(y0 == y1)
1828 {
1829
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 52 times.
52 if(x0 > x1) SWAP(x0, x1);
1830 52 drawFastHLine(x0, y0, x1 - x0 + 1, color);
1831 }
1832 else
1833 {
1834 //startWrite();
1835 ✗ writeLine(x0, y0, x1, y1, color);
1836 //endWrite();
1837 }
1838 52 }
1839
1840 /****************************************************************
1841 * Function Name : drawRect
1842 * Description : Draw a rectangle
1843 * Returns : NONE
1844 * Params : @x: Corner X Co-ordinate
1845 * @y: Corner Y Co-ordinate
1846 * @w: Width in pixels
1847 * @h: Height in pixels
1848 * @color: Pixel color
1849 ****************************************************************/
1850 7 void drawRect(short x, short y, short w, short h, short color)
1851 {
1852 //startWrite();
1853 7 writeFastHLine(x, y, w, color);
1854 7 writeFastHLine(x, y+h-1, w, color);
1855 7 writeFastVLine(x, y, h, color);
1856 7 writeFastVLine(x+w-1, y, h, color);
1857 //endWrite();
1858 7 }
1859
1860 /****************************************************************
1861 * Function Name : fillRect
1862 * Description : Fill the rectangle
1863 * Returns : NONE
1864 * Params : @x: Starting X Co-ordinate
1865 * @y: Starting Y Co-ordinate
1866 * @w: Width in pixels
1867 * @h: Height in pixels
1868 * @color: Pixel color
1869 ****************************************************************/
1870 14 void fillRect(short x, short y, short w, short h, short color)
1871 {
1872 14 short i = 0;
1873 //startWrite();
1874
2/2
✓ Branch 0 taken 1666 times.
✓ Branch 1 taken 14 times.
1680 for (i=x; i<x+w; i++)
1875 {
1876 1666 writeFastVLine(i, y, h, color);
1877 }
1878 //endWrite();
1879 14 }
1880
1881 /****************************************************************
1882 * Function Name : drawCircle
1883 * Description : Draw a circle
1884 * Returns : NONE
1885 * Params : @x: Center X Co-ordinate
1886 * @y: Center Y Co-ordinate
1887 * @r: Radius in pixels
1888 * @color: Pixel color
1889 ****************************************************************/
1890 ✗ void drawCircle(short x0, short y0, short r, short color)
1891 {
1892 ✗ short f = 1 - r;
1893 ✗ short ddF_x = 1;
1894 ✗ short ddF_y = -2 * r;
1895 ✗ short x = 0;
1896 ✗ short y = r;
1897
1898 //startWrite();
1899 ✗ drawPixel(x0 , y0+r, color);
1900 ✗ drawPixel(x0 , y0-r, color);
1901 ✗ drawPixel(x0+r, y0 , color);
1902 ✗ drawPixel(x0-r, y0 , color);
1903
1904 ✗ while (x<y)
1905 {
1906 ✗ if (f >= 0)
1907 {
1908 ✗ y--;
1909 ✗ ddF_y += 2;
1910 ✗ f += ddF_y;
1911 }
1912 ✗ x++;
1913 ✗ ddF_x += 2;
1914 ✗ f += ddF_x;
1915
1916 ✗ drawPixel(x0 + x, y0 + y, color);
1917 ✗ drawPixel(x0 - x, y0 + y, color);
1918 ✗ drawPixel(x0 + x, y0 - y, color);
1919 ✗ drawPixel(x0 - x, y0 - y, color);
1920 ✗ drawPixel(x0 + y, y0 + x, color);
1921 ✗ drawPixel(x0 - y, y0 + x, color);
1922 ✗ drawPixel(x0 + y, y0 - x, color);
1923 ✗ drawPixel(x0 - y, y0 - x, color);
1924 }
1925 //endWrite();
1926 ✗ }
1927
1928 /****************************************************************
1929 * Function Name : fillCircleHelper
1930 * Description : Used to do circles and roundrects
1931 * Returns : NONE
1932 * Params : @x: Center X Co-ordinate
1933 * @y: Center Y Co-ordinate
1934 * @r: Radius in pixels
1935 * @cornername: Corner radius in pixels
1936 * @color: Pixel color
1937 ****************************************************************/
1938 ✗ void fillCircleHelper(short x0, short y0, short r, unsigned char cornername, short delta, short color)
1939 {
1940
1941 ✗ short f = 1 - r;
1942 ✗ short ddF_x = 1;
1943 ✗ short ddF_y = -2 * r;
1944 ✗ short x = 0;
1945 ✗ short y = r;
1946
1947 ✗ while (x<y)
1948 {
1949 ✗ if (f >= 0)
1950 {
1951 ✗ y--;
1952 ✗ ddF_y += 2;
1953 ✗ f += ddF_y;
1954 }
1955 ✗ x++;
1956 ✗ ddF_x += 2;
1957 ✗ f += ddF_x;
1958
1959 ✗ if (cornername & 0x1)
1960 {
1961 ✗ writeFastVLine(x0+x, y0-y, 2*y+1+delta, color);
1962 ✗ writeFastVLine(x0+y, y0-x, 2*x+1+delta, color);
1963 }
1964 ✗ if (cornername & 0x2)
1965 {
1966 ✗ writeFastVLine(x0-x, y0-y, 2*y+1+delta, color);
1967 ✗ writeFastVLine(x0-y, y0-x, 2*x+1+delta, color);
1968 }
1969 }
1970 ✗ }
1971
1972 /****************************************************************
1973 * Function Name : fillCircle
1974 * Description : Fill the circle
1975 * Returns : NONE
1976 * Params : @x0: Center X Co-ordinate
1977 * @y0: Center Y Co-ordinate
1978 * @r: Radius in pixels
1979 * @color: Pixel color
1980 ****************************************************************/
1981 ✗ void fillCircle(short x0, short y0, short r, short color)
1982 {
1983 //startWrite();
1984 ✗ writeFastVLine(x0, y0-r, 2*r+1, color);
1985 ✗ fillCircleHelper(x0, y0, r, 3, 0, color);
1986 //endWrite();
1987 ✗ }
1988
1989 /****************************************************************
1990 * Function Name : drawTriangle
1991 * Description : Draw a triangle
1992 * Returns : NONE
1993 * Params : @x0: Corner-1 X Co-ordinate
1994 * @y0: Corner-1 Y Co-ordinate
1995 * @x1: Corner-2 X Co-ordinate
1996 * @y1: Corner-2 Y Co-ordinate
1997 * @x2: Corner-3 X Co-ordinate
1998 * @y2: Corner-3 Y Co-ordinate
1999 * @color: Pixel color
2000 ****************************************************************/
2001 ✗ void drawTriangle(short x0, short y0, short x1, short y1, short x2, short y2, short color)
2002 {
2003 ✗ drawLine(x0, y0, x1, y1, color);
2004 ✗ drawLine(x1, y1, x2, y2, color);
2005 ✗ drawLine(x2, y2, x0, y0, color);
2006 ✗ }
2007
2008 /****************************************************************
2009 * Function Name : fillTriangle
2010 * Description : Fill a triangle
2011 * Returns : NONE
2012 * Params : @x0: Corner-1 X Co-ordinate
2013 * @y0: Corner-1 Y Co-ordinate
2014 * @x1: Corner-2 X Co-ordinate
2015 * @y1: Corner-2 Y Co-ordinate
2016 * @x2: Corner-3 X Co-ordinate
2017 * @y2: Corner-3 Y Co-ordinate
2018 * @color: Pixel color
2019 ****************************************************************/
2020 7 void fillTriangle(short x0, short y0, short x1, short y1, short x2, short y2, short color)
2021 {
2022 short a, b, y, last, dx01, dy01, dx02, dy02, dx12, dy12;
2023 int sa, sb;
2024
2025 // Sort coordinates by Y order (y2 >= y1 >= y0)
2026
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (y0 > y1)
2027 {
2028 ✗ SWAP(y0, y1);
2029 ✗ SWAP(x0, x1);
2030 }
2031
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (y1 > y2)
2032 {
2033 ✗ SWAP(y2, y1);
2034 ✗ SWAP(x2, x1);
2035 }
2036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if (y0 > y1)
2037 {
2038 ✗ SWAP(y0, y1);
2039 ✗ SWAP(x0, x1);
2040 }
2041
2042 //startWrite();
2043
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if(y0 == y2)
2044 { // Handle awkward all-on-same-line case as its own thing
2045 ✗ a = b = x0;
2046 ✗ if(x1 < a)
2047 ✗ a = x1;
2048 ✗ else if(x1 > b)
2049 ✗ b = x1;
2050 ✗ if(x2 < a)
2051 ✗ a = x2;
2052 ✗ else if(x2 > b)
2053 ✗ b = x2;
2054 ✗ writeFastHLine(a, y0, b-a+1, color);
2055 // endWrite();
2056 ✗ return;
2057 }
2058
2059 7 dx01 = x1 - x0;
2060 7 dy01 = y1 - y0;
2061 7 dx02 = x2 - x0;
2062 7 dy02 = y2 - y0;
2063 7 dx12 = x2 - x1;
2064 7 dy12 = y2 - y1;
2065 7 sa = 0;
2066 7 sb = 0;
2067
2068 // For upper part of triangle, find scanline crossings for segments
2069 // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1
2070 // is included here (and second loop will be skipped, avoiding a /0
2071 // error there), otherwise scanline y1 is skipped here and handled
2072 // in the second loop...which also avoids a /0 error here if y0=y1
2073 // (flat-topped triangle).
2074
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if(y1 == y2)
2075 ✗ last = y1; // Include y1 scanline
2076 else
2077 7 last = y1-1; // Skip it
2078
2079
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 for(y=y0; y<=last; y++)
2080 {
2081 ✗ a = x0 + sa / dy01;
2082 ✗ b = x0 + sb / dy02;
2083 ✗ sa += dx01;
2084 ✗ sb += dx02;
2085 /* longhand:
2086 a = x0 + (x1 - x0) * (y - y0) / (y1 - y0);
2087 b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
2088 */
2089 ✗ if(a > b)
2090 ✗ SWAP(a,b);
2091 ✗ writeFastHLine(a, y, b-a+1, color);
2092 }
2093
2094 // For lower part of triangle, find scanline crossings for segments
2095 // 0-2 and 1-2. This loop is skipped if y1=y2.
2096 7 sa = dx12 * (y - y1);
2097 7 sb = dx02 * (y - y0);
2098
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 7 times.
70 for(; y<=y2; y++)
2099 {
2100 63 a = x1 + sa / dy12;
2101 63 b = x0 + sb / dy02;
2102 63 sa += dx12;
2103 63 sb += dx02;
2104 /* longhand:
2105 a = x1 + (x2 - x1) * (y - y1) / (y2 - y1);
2106 b = x0 + (x2 - x0) * (y - y0) / (y2 - y0);
2107 */
2108
2/2
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 7 times.
63 if(a > b)
2109 56 SWAP(a,b);
2110 63 writeFastHLine(a, y, b-a+1, color);
2111 }
2112 //endWrite();
2113 }
2114
2115 /****************************************************************
2116 * Function Name : drawRoundRect
2117 * Description : Draw a rounded rectangle
2118 * Returns : NONE
2119 * Params : @x: X Co-ordinate
2120 * @y: Y Co-ordinate
2121 * @w: Width
2122 * @h: height
2123 * @r: Corner radius
2124 * @color: Pixel color
2125 ****************************************************************/
2126 ✗ void drawRoundRect(short x, short y, short w, short h, short r, short color)
2127 {
2128 // smarter version
2129 //startWrite();
2130 ✗ writeFastHLine(x+r , y , w-2*r, color); // Top
2131 ✗ writeFastHLine(x+r , y+h-1, w-2*r, color); // Bottom
2132 ✗ writeFastVLine(x , y+r , h-2*r, color); // Left
2133 ✗ writeFastVLine(x+w-1, y+r , h-2*r, color); // Right
2134 // draw four corners
2135 ✗ drawCircleHelper(x+r , y+r , r, 1, color);
2136 ✗ drawCircleHelper(x+w-r-1, y+r , r, 2, color);
2137 ✗ drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color);
2138 ✗ drawCircleHelper(x+r , y+h-r-1, r, 8, color);
2139 //endWrite();
2140 ✗ }
2141
2142 /****************************************************************
2143 * Function Name : fillRoundRect
2144 * Description : Fill a rounded rectangle
2145 * Returns : NONE
2146 * Params : @x: X Co-ordinate
2147 * @y: Y Co-ordinate
2148 * @w: Width
2149 * @h: height
2150 * @r: Corner radius
2151 * @color: Pixel color
2152 ****************************************************************/
2153 ✗ void fillRoundRect(short x, short y, short w, short h, short r, short color)
2154 {
2155 // smarter version
2156 //startWrite();
2157 ✗ fillRect(x+r, y, w-2*r, h, color);
2158
2159 // draw four corners
2160 ✗ fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color);
2161 ✗ fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color);
2162 //endWrite();
2163 ✗ }
2164
2165 /*----------------------------------------------------------------------------
2166 * BITMAP API's
2167 ----------------------------------------------------------------------------*/
2168
2169 /****************************************************************
2170 * Function Name : drawBitmap
2171 * Description : Draw a bitmap
2172 * Returns : NONE
2173 * Params : @x: X Co-ordinate
2174 * @y: Y Co-ordinate
2175 * @bitmap: bitmap to display
2176 * @w: Width
2177 * @h: height
2178 * @color: Pixel color
2179 ****************************************************************/
2180 56 void drawBitmap(short x, short y, const unsigned char bitmap[], short w, short h, short color)
2181 {
2182 56 short byteWidth = 0, j = 0, i = 0;
2183 56 unsigned char byte = 0;
2184 56 byteWidth = (w + 7) / 8; // Bitmap scanline pad = whole byte
2185
2186
2/2
✓ Branch 0 taken 2160 times.
✓ Branch 1 taken 56 times.
2216 for(j=0; j<h; j++, y++)
2187 {
2188
2/2
✓ Branch 0 taken 244080 times.
✓ Branch 1 taken 2160 times.
246240 for(i=0; i<w; i++)
2189 {
2190
2/2
✓ Branch 0 taken 211680 times.
✓ Branch 1 taken 32400 times.
244080 if(i & 7)
2191 211680 byte <<= 1;
2192 else
2193 32400 byte = pgm_read_byte(&bitmap[j * byteWidth + i / 8]);
2194
2/2
✓ Branch 0 taken 46764 times.
✓ Branch 1 taken 197316 times.
244080 if(byte & 0x80)
2195 46764 drawPixel(x+i, y, color);
2196 }
2197 }
2198 56 }
2199
2200 /*----------------------------------------------------------------------------
2201 * TEXT AND CHARACTER HANDLING API's
2202 ----------------------------------------------------------------------------*/
2203
2204 /****************************************************************
2205 * Function Name : setCursor
2206 * Description : Sets the cursor on f(x,y)
2207 * Returns : NONE.
2208 * Params : @x - X-Cordinate
2209 * @y - Y-Cordinate
2210 ****************************************************************/
2211 158 void setCursor(short x, short y)
2212 {
2213 158 cursor_x = x;
2214 158 cursor_y = y;
2215 158 }
2216
2217 /****************************************************************
2218 * Function Name : getCursorX
2219 * Description : Get cursor at X- Cordinate
2220 * Returns : x cordinate value.
2221 ****************************************************************/
2222 ✗ short getCursorX()
2223 {
2224 ✗ return cursor_x;
2225 }
2226
2227 /****************************************************************
2228 * Function Name : getCursorY
2229 * Description : Get cursor at Y- Cordinate
2230 * Returns : y cordinate value.
2231 ****************************************************************/
2232 ✗ short getCursorY()
2233 {
2234 ✗ return cursor_y;
2235 }
2236
2237 /****************************************************************
2238 * Function Name : setTextSize
2239 * Description : Set text size
2240 * Returns : @s - font size
2241 ****************************************************************/
2242 12 void setTextSize(unsigned char s)
2243 {
2244
1/2
✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
12 textsize = (s > 0) ? s : 1;
2245 12 }
2246
2247 /****************************************************************
2248 * Function Name : setTextColor
2249 * Description : Set text color
2250 * Returns : @c - Color
2251 ****************************************************************/
2252 158 void setTextColor(short c)
2253 {
2254 // For 'transparent' background, we'll set the bg
2255 // to the same as fg instead of using a flag
2256 158 textcolor = textbgcolor = c;
2257 158 }
2258
2259 /****************************************************************
2260 * Function Name : setTextWrap
2261 * Description : Wraps the text
2262 * Returns : @w - enable or disbale wrap
2263 ****************************************************************/
2264 ✗ void setTextWrap(bool w)
2265 {
2266 ✗ wrap = w;
2267 ✗ }
2268
2269 /****************************************************************
2270 * Function Name : getRotation
2271 * Description : Get the rotation value
2272 * Returns : NONE.
2273 ****************************************************************/
2274 ✗ unsigned char getRotation()
2275 {
2276 ✗ return _rotation;
2277 }
2278
2279 7 short getTextWidth(const char *strPtr) {
2280 7 short maxW = 0;
2281 7 short w = 0;
2282 7 const char *p = strPtr;
2283
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 7 times.
70 while (*p) {
2284
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 63 times.
63 if (*p == '\n') {
2285 ✗ if (maxW < w) {
2286 ✗ maxW = w;
2287 }
2288 ✗ w = 0;
2289
1/2
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
63 } else if (*p != '\r') {
2290
1/2
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
63 if (!gfxFont) {
2291
2/4
✓ Branch 0 taken 63 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 63 times.
63 if(!_cp437 && (*p >= 176))
2292 ✗ p++;
2293 63 w += 5 * textsize;
2294 } else {
2295 ✗ unsigned char c = *p;
2296 ✗ c -= (unsigned char)pgm_read_byte(&gfxFont->first);
2297 ✗ GFXglyphPtr glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]);
2298 ✗ w += glyph->xAdvance;
2299 }
2300 }
2301 63 p++;
2302 }
2303
1/2
✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
7 if (maxW < w) {
2304 7 maxW = w;
2305 }
2306 7 return maxW;
2307 }
2308
2309
2310 /****************************************************************
2311 * Function Name : drawBitmap
2312 * Description : Draw a character
2313 * Returns : NONE
2314 * Params : @x: X Co-ordinate
2315 * @y: Y Co-ordinate
2316 * @c: Character
2317 * @size: Scaling factor
2318 * @bg: Background color
2319 * @color: Pixel color
2320 ****************************************************************/
2321 1880 void drawChar(short x, short y, unsigned char c, short color, short bg, unsigned char size)
2322 {
2323 1880 unsigned char line = 0, *bitmap = NULL, w = 0, h = 0, xx = 0, yy = 0, bits = 0, bit = 0;
2324 1880 int8_t i = 0, j = 0, xo = 0, yo = 0;
2325 1880 short bo = 0, xo16 = 0, yo16 = 0;
2326 GFXglyphPtr glyph;
2327
1/2
✓ Branch 0 taken 1880 times.
✗ Branch 1 not taken.
1880 if(!gfxFont)
2328 {
2329 // 'Classic' built-in font
2330
4/8
✓ Branch 0 taken 1880 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1880 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1880 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 1880 times.
1880 if((x >= _width) || (y >= _height) || ((x + 6 * size - 1) < 0) || ((y + 8 * size - 1) < 0))
2331 ✗ return;
2332
2333 // Handle 'classic' charset behavior
2334
2/4
✓ Branch 0 taken 1880 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1880 times.
1880 if(!_cp437 && (c >= 176))
2335 ✗ c++;
2336
2337 // Char bitmap = 5 columns
2338
2/2
✓ Branch 0 taken 9400 times.
✓ Branch 1 taken 1880 times.
11280 for(i=0; i<5; i++ )
2339 {
2340 9400 line = pgm_read_byte(&ssd1306_font5x7[c * 5 + i]);
2341
2/2
✓ Branch 0 taken 75200 times.
✓ Branch 1 taken 9400 times.
84600 for(j=0; j<8; j++, line >>= 1)
2342 {
2343
2/2
✓ Branch 0 taken 20437 times.
✓ Branch 1 taken 54763 times.
75200 if(line & 1)
2344 {
2345
1/2
✓ Branch 0 taken 20437 times.
✗ Branch 1 not taken.
20437 if(size == 1)
2346 20437 drawPixel(x+i, y+j, color);
2347 else
2348 ✗ fillRect(x+i*size, y+j*size, size, size, color);
2349 }
2350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 54763 times.
54763 else if(bg != color)
2351 {
2352 ✗ if(size == 1)
2353 ✗ drawPixel(x+i, y+j, bg);
2354 else
2355 ✗ fillRect(x+i*size, y+j*size, size, size, bg);
2356 }
2357 }
2358 }
2359
2360 // If opaque, draw vertical line for last column
2361
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1880 times.
1880 if(bg != color)
2362 {
2363 ✗ if(size == 1)
2364 ✗ writeFastVLine(x+5, y, 8, bg);
2365 else
2366 ✗ fillRect(x+5*size, y, size, 8*size, bg);
2367 }
2368
2369 }
2370 // Custom font
2371 else
2372 {
2373 // Character is assumed previously filtered by write() to eliminate
2374 // newlines, returns, non-printable characters, etc. Calling
2375 // drawChar() directly with 'bad' characters of font may cause mayhem!
2376 ✗ unsigned char cOrig = c;
2377 ✗ c -= (unsigned char)pgm_read_byte(&gfxFont->first);
2378 ✗ glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]);
2379 ✗ bitmap = (unsigned char *)pgm_read_pointer(&gfxFont->bitmap);
2380 ✗ bo = pgm_read_word(&glyph->bitmapOffset);
2381 ✗ w = pgm_read_byte(&glyph->width);
2382 ✗ h = pgm_read_byte(&glyph->height);
2383 ✗ xo = pgm_read_byte(&glyph->xOffset);
2384 ✗ yo = pgm_read_byte(&glyph->yOffset);
2385
2386 ✗ y += gfxFont->yMaxAscent;
2387
2388 ✗ if(size > 1)
2389 {
2390 ✗ xo16 = xo;
2391 ✗ yo16 = yo;
2392 }
2393
2394 // Todo: Add character clipping here
2395
2396 // NOTE: THERE IS NO 'BACKGROUND' COLOR OPTION ON CUSTOM FONTS.
2397 // THIS IS ON PURPOSE AND BY DESIGN. The background color feature
2398 // has typically been used with the 'classic' font to overwrite old
2399 // screen contents with new data. This ONLY works because the
2400 // characters are a uniform size; it's not a sensible thing to do with
2401 // proportionally-spaced fonts with glyphs of varying sizes (and that
2402 // may overlap). To replace previously-drawn text when using a custom
2403 // font, use the getTextBounds() function to determine the smallest
2404 // rectangle encompassing a string, erase the area with fillRect(),
2405 // then draw new text. This WILL unfortunately 'blink' the text, but
2406 // is unavoidable. Drawing 'background' pixels will NOT fix this,
2407 // only creates a new set of problems. Have an idea to work around
2408 // this (a canvas object type for MCUs that can afford the RAM and
2409 // displays supporting setAddrWindow() and pushColors()), but haven't
2410 // implemented this yet.
2411 ✗ for(yy=0; yy<h; yy++)
2412 {
2413 ✗ for(xx=0; xx<w; xx++)
2414 {
2415 ✗ if(!(bit++ & 7))
2416 {
2417 ✗ bits = pgm_read_byte(&bitmap[bo++]);
2418 }
2419 ✗ if(bits & 0x80)
2420 {
2421 ✗ if(size == 1)
2422 {
2423 ✗ drawPixel(x+xo+xx, y+yo+yy, color);
2424 }
2425 else
2426 {
2427 ✗ fillRect(x+(xo16+xx)*size, y+(yo16+yy)*size,size, size, color);
2428 }
2429 }
2430 ✗ bits <<= 1;
2431 }
2432 }
2433 } // End classic vs custom font
2434 }
2435
2436 /****************************************************************
2437 * Function Name : write
2438 * Description : Base function for text and character handling
2439 * Returns : 1
2440 * Params : @c: Character
2441 ****************************************************************/
2442 1880 short oled_write(unsigned char c)
2443 {
2444 1880 unsigned char first = 0, w = 0, h = 0;
2445 1880 short xo = 0;
2446 GFXglyphPtr glyph;
2447
1/2
✓ Branch 0 taken 1880 times.
✗ Branch 1 not taken.
1880 if(!gfxFont)
2448 {
2449 // 'Classic' built-in font
2450
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1880 times.
1880 if(c == '\n')
2451 {
2452 // Newline?
2453 ✗ cursor_x = 0; // Reset x to zero,
2454 ✗ cursor_y += textsize * 8; // advance y one line
2455 }
2456
1/2
✓ Branch 0 taken 1880 times.
✗ Branch 1 not taken.
1880 else if(c != '\r')
2457 {
2458 // Ignore carriage returns
2459
2/4
✓ Branch 0 taken 1880 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1880 times.
1880 if(wrap && ((cursor_x + textsize * 6) > _width))
2460 {
2461 // Off right?
2462 ✗ cursor_x = 0; // Reset x to zero,
2463 ✗ cursor_y += textsize * 8; // advance y one line
2464 }
2465 1880 drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize);
2466 1880 cursor_x += textsize * 6; // Advance x one char
2467 }
2468
2469 }
2470 else
2471 {
2472 // Custom font
2473 ✗ if(c == '\n')
2474 {
2475 ✗ cursor_x = 0;
2476 ✗ cursor_y += (short)textsize *(unsigned char)pgm_read_byte(&gfxFont->yAdvance);
2477 }
2478 ✗ else if(c != '\r')
2479 {
2480 ✗ first = pgm_read_byte(&gfxFont->first);
2481 ✗ if((c >= first) && (c <= (unsigned char)pgm_read_byte(&gfxFont->last)))
2482 {
2483 ✗ glyph = &(((GFXglyphPtr)pgm_read_pointer(&gfxFont->glyph))[c - first]);
2484 ✗ w = pgm_read_byte(&glyph->width);
2485 ✗ h = pgm_read_byte(&glyph->height);
2486 ✗ if((w > 0) && (h > 0))
2487 {
2488 // Is there an associated bitmap?
2489 ✗ xo = (char)pgm_read_byte(&glyph->xOffset); // sic
2490 ✗ if(wrap && ((cursor_x + textsize * (xo + w)) > _width))
2491 {
2492 ✗ cursor_x = 0;
2493 ✗ cursor_y += (short)textsize *(unsigned char)pgm_read_byte(&gfxFont->yAdvance);
2494 }
2495 ✗ drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize);
2496 }
2497 ✗ cursor_x += (unsigned char)pgm_read_byte(&glyph->xAdvance) * (short)textsize;
2498 }
2499 }
2500 }
2501 1880 return 1;
2502 }
2503
2504 /****************************************************************
2505 * Function Name : print
2506 * Description : Base function for printing strings
2507 * Returns : No. of characters printed
2508 * Params : @buffer: Ptr to buffer containing the string
2509 * @size: Length of the string.
2510 ****************************************************************/
2511 158 short print(const char *buffer, short size)
2512 {
2513 158 short n = 0;
2514
2/2
✓ Branch 0 taken 1880 times.
✓ Branch 1 taken 158 times.
2038 while(size--)
2515 {
2516
1/2
✓ Branch 0 taken 1880 times.
✗ Branch 1 not taken.
1880 if(oled_write(*buffer++))
2517 1880 n++;
2518 else
2519 ✗ break;
2520 }
2521 158 return (n);
2522 }
2523
2524 /****************************************************************
2525 * Function Name : print_str
2526 * Description : Print strings
2527 * Returns : No. of characters printed
2528 * Params : @strPtr: Ptr to buffer containing the string
2529 ****************************************************************/
2530 158 short print_str(const char *strPtr)
2531 {
2532 158 return print(strPtr, strlen(strPtr));
2533 }
2534
2535 /****************************************************************
2536 * Function Name : println
2537 * Description : Move to next line
2538 * Returns : No. of characters printed
2539 * Params : NONE.
2540 ****************************************************************/
2541 ✗ short println()
2542 {
2543 ✗ return print_str("\r\n");
2544 }
2545
2546 /****************************************************************
2547 * Function Name : print_strln
2548 * Description : Print strings and move to next line
2549 * Returns : No. of characters printed
2550 * Params : @strPtr: Ptr to buffer containing the string
2551 ****************************************************************/
2552 ✗ short print_strln(const char *strPtr)
2553 {
2554 ✗ short n = 0;
2555 ✗ n = print(strPtr, strlen(strPtr));
2556 ✗ n += print_str("\r\n");
2557 ✗ return (n);
2558 }
2559
2560 /*----------------------------------------------------------------------------
2561 * NUMBERS HANDLING API's
2562 ----------------------------------------------------------------------------*/
2563
2564 /****************************************************************
2565 * Function Name : printNumber
2566 * Description : Base function to print unsigned numbers
2567 * Returns : No. of characters printed
2568 * Params : @n: Number
2569 * @base: Base e.g. HEX, BIN...
2570 ****************************************************************/
2571 ✗ short printNumber(unsigned long n, unsigned char base)
2572 {
2573 ✗ unsigned long m = 0;
2574 ✗ char c = 0;
2575 char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
2576 ✗ char *str = &buf[sizeof(buf) - 1];
2577
2578 ✗ *str = '\0';
2579
2580 // prevent crash if called with base == 1
2581 ✗ if(base < 2)
2582 ✗ base = 10;
2583 do
2584 {
2585 ✗ m = n;
2586 ✗ n /= base;
2587 ✗ c = m - base * n;
2588 ✗ *--str = c < 10 ? c + '0' : c + 'A' - 10;
2589 }
2590 ✗ while(n);
2591 //return oled_write((unsigned char)str);
2592 ✗ return print_str(str);
2593 }
2594
2595 /****************************************************************
2596 * Function Name : printNumber_UL
2597 * Description : Print unsigned long data types
2598 * Returns : No. of characters printed
2599 * Params : @n: Number
2600 * @base: Base e.g. HEX, BIN...
2601 ****************************************************************/
2602 ✗ short printNumber_UL(unsigned long n, int base)
2603 {
2604 ✗ if(base == 0)
2605 ✗ return oled_write(n);
2606 else
2607 ✗ return printNumber(n, base);
2608 }
2609
2610 /****************************************************************
2611 * Function Name : printNumber_UL_ln
2612 * Description : Print unsigned long & advance to next line
2613 * Returns : No. of characters printed
2614 * Params : @n: Number
2615 * @base: Base e.g. HEX, BIN...
2616 ****************************************************************/
2617 ✗ short printNumber_UL_ln(unsigned long num, int base)
2618 {
2619 ✗ short n = 0;
2620 ✗ n = printNumber(num, base);
2621 ✗ n += println();
2622 ✗ return (n);
2623 }
2624
2625 /****************************************************************
2626 * Function Name : printNumber_UI
2627 * Description : Print unsigned int data types
2628 * Returns : No. of characters printed
2629 * Params : @n: Number
2630 * @base: Base e.g. HEX, BIN...
2631 ****************************************************************/
2632 ✗ short printNumber_UI(unsigned int n, int base)
2633 {
2634 ✗ return printNumber((unsigned long) n, base);
2635 }
2636
2637 /****************************************************************
2638 * Function Name : printNumber_UI_ln
2639 * Description : Print unsigned int & advance to next line
2640 * Returns : No. of characters printed
2641 * Params : @n: Number
2642 * @base: Base e.g. HEX, BIN...
2643 ****************************************************************/
2644 ✗ short printNumber_UI_ln(unsigned int n, int base)
2645 {
2646 ✗ short a = 0;
2647 ✗ a = printNumber((unsigned long) n, base);
2648 ✗ a += println();
2649 ✗ return (a);
2650 }
2651
2652 /****************************************************************
2653 * Function Name : printNumber_UC
2654 * Description : Print unsigned char data types
2655 * Returns : No. of characters printed
2656 * Params : @n: Number
2657 * @base: Base e.g. HEX, BIN...
2658 ****************************************************************/
2659 ✗ short printNumber_UC(unsigned char b, int base)
2660 {
2661 ✗ return printNumber((unsigned long) b, base);
2662 }
2663
2664 /****************************************************************
2665 * Function Name : printNumber_UC_ln
2666 * Description : Print unsigned char & advance to next line
2667 * Returns : No. of characters printed
2668 * Params : @n: Number
2669 * @base: Base e.g. HEX, BIN...
2670 ****************************************************************/
2671 ✗ short printNumber_UC_ln(unsigned char b, int base)
2672 {
2673 ✗ short n = 0;
2674 ✗ n = printNumber((unsigned long) b, base);
2675 ✗ n += println();
2676 ✗ return (n);
2677 }
2678
2679 /****************************************************************
2680 * Function Name : printNumber_L
2681 * Description : Print Long data types
2682 * Returns : No. of characters printed
2683 * Params : @n: Number
2684 * @base: Base e.g. HEX, BIN...
2685 ****************************************************************/
2686 ✗ short printNumber_L(long n, int base)
2687 {
2688 ✗ int t = 0;
2689 ✗ if(base == 0)
2690 {
2691 ✗ return oled_write(n);
2692 }
2693 ✗ else if(base == 10)
2694 {
2695 ✗ if(n < 0)
2696 {
2697 ✗ t = oled_write('-');
2698 ✗ n = -n;
2699 ✗ return printNumber(n, 10) + t;
2700 }
2701 ✗ return printNumber(n, 10);
2702 }
2703 else
2704 {
2705 ✗ return printNumber(n, base);
2706 }
2707 }
2708
2709 /****************************************************************
2710 * Function Name : printNumber_UC_ln
2711 * Description : Print long & advance to next line
2712 * Returns : No. of characters printed
2713 * Params : @n: Number
2714 * @base: Base e.g. HEX, BIN...
2715 ****************************************************************/
2716 ✗ short printNumber_L_ln(long num, int base)
2717 {
2718 ✗ short n = 0;
2719 ✗ n = printNumber_L(num, base);
2720 ✗ n += println();
2721 ✗ return n;
2722 }
2723
2724 /****************************************************************
2725 * Function Name : printNumber_I
2726 * Description : Print int data types
2727 * Returns : No. of characters printed
2728 * Params : @n: Number
2729 * @base: Base e.g. HEX, BIN...
2730 ****************************************************************/
2731 ✗ short printNumber_I(int n, int base)
2732 {
2733 ✗ return printNumber_L((long) n, base);
2734 }
2735
2736 /****************************************************************
2737 * Function Name : printNumber_I_ln
2738 * Description : Print int & advance to next line
2739 * Returns : No. of characters printed
2740 * Params : @n: Number
2741 * @base: Base e.g. HEX, BIN...
2742 ****************************************************************/
2743 ✗ short printNumber_I_ln(int n, int base)
2744 {
2745 ✗ short a = 0;
2746 ✗ a = printNumber_L((long) n, base);
2747 ✗ a += println();
2748 ✗ return a;
2749 }
2750
2751 /****************************************************************
2752 * Function Name : printFloat
2753 * Description : Print floating Pt. No's.
2754 * Returns : No. of characters printed
2755 * Params : @n: Number
2756 * @digits: Resolution
2757 ****************************************************************/
2758 ✗ short printFloat(double number, unsigned char digits)
2759 {
2760 ✗ unsigned char i = 0;
2761 ✗ short n = 0;
2762 ✗ unsigned long int_part = 0;
2763 ✗ double remainder = 0.0;
2764 ✗ int toPrint = 0;
2765
2766 // Round correctly so that print(1.999, 2) prints as "2.00"
2767 ✗ double rounding = 0.5;
2768
2769 ✗ if(isnan(number))
2770 ✗ return print_str("nan");
2771 ✗ if(isinf(number))
2772 ✗ return print_str("inf");
2773 ✗ if(number > 4294967040.0)
2774 ✗ return print_str("ovf"); // constant determined empirically
2775 ✗ if(number < -4294967040.0)
2776 ✗ return print_str("ovf"); // constant determined empirically
2777
2778 // Handle negative numbers
2779 ✗ if(number < 0.0)
2780 {
2781 ✗ n += oled_write('-');
2782 ✗ number = -number;
2783 }
2784
2785
2786 ✗ for(i = 0; i < digits; ++i)
2787 ✗ rounding /= 10.0;
2788
2789 ✗ number += rounding;
2790
2791 // Extract the integer part of the number and print it
2792 ✗ int_part = (unsigned long) number;
2793 ✗ remainder = number - (double) int_part;
2794 ✗ n += printNumber_UL(int_part,DEC);
2795
2796 // Print the decimal point, but only if there are digits beyond
2797 ✗ if(digits > 0)
2798 {
2799 ✗ n += print_str(".");
2800 }
2801
2802 // Extract digits from the remainder one at a time
2803 ✗ while(digits-- > 0)
2804 {
2805 ✗ remainder *= 10.0;
2806 ✗ toPrint = (int)remainder;
2807 ✗ n += printNumber_I(toPrint,DEC);
2808 ✗ remainder -= toPrint;
2809 }
2810 ✗ return n;
2811 }
2812
2813 /****************************************************************
2814 * Function Name : printFloat_ln
2815 * Description : Print floating Pt. No and advance to next line
2816 * Returns : No. of characters printed
2817 * Params : @n: Number
2818 * @digits: Resolution
2819 ****************************************************************/
2820 ✗ short printFloat_ln(double num, int digits)
2821 {
2822 ✗ short n = 0;
2823 ✗ n = printFloat(num, digits);
2824 ✗ n += println();
2825 ✗ return n;
2826 }
2827