display.h
Go to the documentation of this file.
1#ifndef _DISPLAY_H
2#define _DISPLAY_H
3
4#include <stdint.h>
5#ifdef _AVR_LIBC_VERSION__
6#include <avr/pgmspace.h>
7#endif
8#include "check.h"
9
10/**
11 * \addtogroup Display OLED Display
12 *
13 * \brief Controls the optional 128×64 pixel monochrome OLED display
14 *
15 * The SPiCboard v3 has a TWI (two wire interface, also known as I²C),
16 * which can be used to connect an OLED display.
17 * Especially the SSD1306 monochrome OLED display fits perfectly onto the board.
18 * It has a 0.96 inch diameter with 128 horizontal and 64 vertical pixels.
19 *
20 * For the sake of simplicity the horizontal pixels are termed <i>columns</i>.
21 * The vertical pixels are divided into 8 so-called <i>pages</i>, therefore
22 * a byte can represent the contents of a <i>page segment</i> (with 8 pixels - from
23 * the <a href="https://en.wikipedia.org/wiki/Least_significant_bit">LSB</a> on
24 * top to the <a href="https://en.wikipedia.org/wiki/Most_significant_bit">MSB</a>
25 * on bottom of each page segement).
26 *
27 * \image html display_addr.png
28 *
29 * For additional details please have a look into the <a href="SSD1306.pdf">SSD1306 Datasheet</a>.
30 *
31 * In case your run into memory issues (which is quite easy with only 2 KB SRAM)
32 * you might want to have a look into the \ref DisplayFromFlash "FromFlash" function variants.
33 *
34 * \warning The display is quite sensitive to fluctuation of current.
35 * Try to avoid contact of any [semi-]conductive material (including your fingers) with the pins
36 * on the Xplained Mini Board -- especially connecting PC3 with PC4 -- or the connection to your display
37 * might stop (it stalls until you restart it, the LED on the Xplained Mini Board can indicate the error).
38 *
39 * @{
40 * \file display.h
41 * \version \$Rev: $
42 */
43
44/**
45 * \brief Activate (and setup) the OLED-display
46 *
47 * \retval 0 success
48 * \retval -1 initialization of I²C failed
49 * \retval -2 setting I²C device address failed
50 * \retval -3 writing to I²C device failed
51 * \retval -4 timeout during I²C communication
52 * \retval -5 out of bounds (addressing nonexistent page/column)
53 */
55
56/**
57 * \brief Check if a functional OLED display is present
58 *
59 * Tries to connect to the SSD1306 display (I²C device address <tt>0x78</tt>)
60 * without enabling it.
61 *
62 * \retval 0 display is available and seems to work
63 * \retval <0 display not available or not functional
64 */
66
67/**
68 * \brief Turn the OLED display off
69 *
70 * \retval 0 success
71 * \retval <0 on I²C error (\see sb_display_enable() return codes)
72 */
74
75/**
76 * \brief Draw a single page segment onto the OLED display
77 *
78 * \param pageNum page number (0-7) for vertical positioning the output
79 * \param colNum column number (0-127) for the horizontal position of the output
80 * \param content contents to be drawn on the page segment (LSB on top and MSB on bottom)
81 *
82 * \retval 0 success
83 * \retval <0 on I²C error (\see sb_display_enable() return codes)
84 */
85int8_t sb_display_draw(uint8_t pageNum, uint8_t colNum, uint8_t content);
86
87/**
88 * \brief Draw a (rectangular) bitmap onto the OLED display
89 *
90 * The result is similar to multiple calls of sb_display_draw()
91 * (although the execution of this function is way faster):
92 * \code {.c}
93 * for (uint8_t page = 0; page < pageCount; page++){
94 * for (uint8_t col = 0; col < colCount; col++){
95 * sb_display_draw(pageStart + page, colStart + col, contents[page * colCount + col]);
96 * }
97 * }
98 * \endcode
99 *
100 * \b Example:
101 *
102 * We want to draw a square with a point in its center with some spacing
103 * to the to the left top corner of the screen.
104 *
105 * The bitmap will be drawn across two pages, each with eight page segments.
106 * \image html display_square.png
107 *
108 * Hence we first initialize an array with 2*8 elements (columns 5-12 for
109 * page 0 and 1) containing the contents of each page segement (1 for a white
110 * pixel and 0 for a black/clear one) and then transfer them to the screen.
111 * \include display_square.c
112 *
113 * \param pageStart first page to set the top vertical position
114 * \param colStart first column to set the left horizontal position
115 * \param pageCount number of pages to set the bottom position
116 * (including the first page)
117 * \param colCount number of columns to define the right border
118 * (including the first column)
119 * \param contents array pointing to the bitmap (must have
120 * <tt>pageCount * colCount</tt> elements) - or \c NULL
121 * to clear the area
122 *
123 * \retval 0 success
124 * \retval <0 on I²C error (see sb_display_enable() return codes)
125 */
126int8_t sb_display_drawBitmap(uint8_t pageStart, uint8_t colStart, uint8_t pageCount, uint8_t colCount, const uint8_t * contents);
127
128/**
129 * \brief Draw the contents of a \c 8*128 item 8-bit array (8 pages with
130 * 128 columns, each filled with 8 bit) onto the OLED Display
131 *
132 * The function call is identical to
133 * \code {.c}
134 * sb_display_drawBitmap(0, 0, 8, 128, contents);
135 * \endcode
136 *
137 * In case the pointer is \c NULL, the entire screen will be cleared.
138 *
139 * \warning Make sure that the buffer points to an array with 1024 items -
140 * this is C, there is no range check!
141 *
142 * \param contents pointer to a <tt>8*128</tt> item array - or NULL
143 * to clear the screen
144 *
145 * \retval 0 success
146 * \retval <0 on I²C error (\see sb_display_enable() return codes)
147 */
148int8_t sb_display_fillScreen(const uint8_t *contents);
149
150/**
151 * \brief Print a \c \0 terminated text string on the OLED display
152 * using a 8×8 pixel font
153 *
154 * A single character will fit into one page (= eight rows) and eight columns.
155 * Therefore it is possible to print 16 characters at maximum.
156 *
157 * If the length of the string exceeds the available columns
158 * (= columns right of the start column) in the current page,
159 * the output will \b not be continued on the next line!
160 *
161 * The font was extract from the
162 * <a href="https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/lib/fonts">Linux kernel</a>
163 * and is based on <a href="https://en.wikipedia.org/wiki/Code_page_437">code page 437</a>
164 * (= <a href="https://en.wikipedia.org/wiki/Extended_ASCII">extended ASCII</a>,
165 * every possible character has a graphical string representation).
166 *
167 * Consequently, the ASCII control characters (like line break) are
168 * displayed with special symbols but don't have any functional impact.
169 *
170 * The \ref fonts "Fonts Table" contains a detailed list of the available characters
171 *
172 * \warning The font will be stored on the flash which will consume about 2300 bytes.
173 *
174 * \param pageNum page number (0-7) for vertical positioning the output
175 * \param colStart first column to set the horizontal position of the output
176 * \param str 0-terminated string
177 *
178 * \retval >=0 length of printed string (can be less than strlen(str) )
179 * \retval <0 on I²C error (\see sb_display_enable() return codes)
180 */
181int8_t sb_display_showString(uint8_t pageNum, uint8_t colStart, const char *str);
182
183/**
184 * \brief Print a \c \0 terminated text string with a (slightly) wider
185 * 8×8 pixel font onto the OLED display
186 *
187 * The character set is almost identical to the sb_display_showString() function
188 * and the space requirement is the same (up to 16 characters per line)
189 *
190 * The \ref fonts "Fonts Table" contains a detailed list of the
191 * available characters.
192 *
193 * \warning This font will consume about 2300 bytes, too.
194 *
195 * \param pageNum page number (0-7) for vertical positioning the output
196 * \param colStart first column to set the horizontal position of the output
197 * \param str 0-terminated string
198 *
199 * \retval >=0 length of printed string (can be less than strlen(str) )
200 * \retval <0 on I²C error (see sb_display_enable() return codes)
201 */
202int8_t sb_display_showStringWide(uint8_t pageNum, uint8_t colStart, const char *str);
203
204/**
205 * \brief Print a \0 terminated text string on the OLED display using
206 * a small 6×4 pixel font
207 *
208 * A single character will fit into one page (eight rows, even though it is
209 * just six pixels) and four columns, therefore it is possible to print 32
210 * characters at maximum.
211 *
212 * If the length of the string exceeds the available columns
213 * (= columns right of the start column) in the current page,
214 * the output will not be continued on the next line!
215 *
216 * The \ref fonts "Fonts Table" contains a detailed list of the
217 * available characters
218 *
219 * \warning In contrast to the other \c showString functions the character set
220 * is quite limited - it only supports printable ASCII characters (neither
221 * control characters nor the extended ASCII set).
222 * Hence, the required flash memory consumption is (with about 700 bytes) less
223 * than a third of the space requirements of the other fonts.
224 *
225 * \param pageNum page number (0-7) for vertical positioning the output
226 * \param colStart first column to set the horizontal position of the output
227 * \param str 0-terminated string
228 *
229 * \retval >=0 length of printed string (can be less than strlen(str) )
230 * \retval <0 on I²C error (\see sb_display_enable() return codes)
231 */
232int8_t sb_display_showStringSmall(uint8_t pageNum, uint8_t colStart, const char * str);
233
234/** @}*/
235
236/**
237 * \addtogroup DisplayFromFlash Display contents from Flash memory
238 *
239 * \brief Display functions enabling flash memory contents
240 *
241 * For microcontroller-based software development, memory usage is a crucial part.
242 * The SRAM on the Atmega 328PB (the processor of the Xplained Mini / SPiCboard v3)
243 * is extremly tight compared to PCs -- its 2 KB are the limiting factor for
244 * using the 128×64 pixel monochrome OLED display:
245 * Just the contents of a single screen (128×64 bits) would consume half of
246 * the available SRAM!
247 *
248 * But since most data is constant, this can be stored and read from the flash
249 * program memory (with 32 KB on this microprocessor it is sixteen times the SRAM).
250 *
251 * Due to the different address space, it is not possible to access the data in flash
252 * in the same way you access SRAM contents -- a special instruction is required to
253 * read from this memory: the \c ldm instruction (instead of \c ld).
254 *
255 * This will be done automatically by the compiler when using the
256 * <a href="https://gcc.gnu.org/onlinedocs/gcc-4.8.0/gcc/Named-Address-Spaces.html">Named-Address-Space</a>
257 * keyword \c __flash in the variable declaration.
258 *
259 * In case you have quite an old compiler not supporting this feature,
260 * you have to use the <a href="http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html">Program Space Utilities</a>
261 * from the <a href="http://www.nongnu.org/avr-libc/">AVR LibC</a>
262 * and not only tag the variables with the \c PROGMEM keywords but although use the \c pgm_read_byte function to access them.
263 *
264 * The following functions use the same parameters (besides the \c flash keyword)
265 * as their counter parts and their function name is appended by \c FromFlash
266 *
267 * @{
268 * \file display.h
269 * \version \$Rev: $
270 */
271
272 /**
273 * \brief Draw a bitmap from the flash memory onto the OLED display
274 *
275 * Almost the same function as sb_display_drawBitmap(), but the contents are
276 * read from the flash (program memory) - so no SRAM is wasted.
277 *
278 * \see sb_display_drawBitmap
279 *
280 * \param pageStart first page to set the top vertical position
281 * \param colStart first column to set the left horizontal position
282 * \param pageCount number of pages to set the bottom position
283 * \param colCount number of columns to define the right border
284 * \param contents array (<tt>pageCount * colCount</tt> elements) pointing to a bitmap
285 * stored in the flash memory (using either
286 * <a href="https://gcc.gnu.org/onlinedocs/gcc-5.4.0/gcc/Named-Address-Spaces.html">__flash</a>
287 * namespace or <a href="http://www.nongnu.org/avr-libc/user-manual/pgmspace.html">PROGMEM</a> macro)
288 *
289 * \retval 0 success
290 * \retval <0 on I²C error (see sb_display_enable() return codes)
291 */
292#ifdef __FLASH
293int8_t sb_display_drawBitmapFromFlash(uint8_t pageStart, uint8_t colStart, uint8_t pageCount, uint8_t colCount, const __flash uint8_t *contents);
294#else
295int8_t sb_display_drawBitmapFromFlash(uint8_t pageStart, uint8_t colStart, uint8_t pageCount, uint8_t colCount, const uint8_t * PROGMEM contents);
296#endif
297
298/**
299 * \brief Draw the contents of the flash to the entire OLED display screen
300 *
301 * Almost same function as sb_display_fillScreen(), but the contents are
302 * read from the flash (program memory) - so no SRAM is wasted.
303 *
304 * The function call is identical to
305 * \code {.c}
306 * sb_display_drawBitmapFromFlash(0, 0, 8, 128, contents);
307 * \endcode
308 *
309 * \param contents pointer to a \c 8*128 item array in flash memory (using either
310 * <a href="https://gcc.gnu.org/onlinedocs/gcc-5.4.0/gcc/Named-Address-Spaces.html">__flash</a>
311 * namespace or <a href="http://www.nongnu.org/avr-libc/user-manual/pgmspace.html">PROGMEM</a> macro)
312 *
313 * \retval 0 success
314 * \retval <0 on I²C error (see sb_display_enable() return codes)
315 */
316#ifdef __FLASH
317int8_t sb_display_fillScreenFromFlash(const __flash uint8_t *contents);
318#else
319int8_t sb_display_fillScreenFromFlash(const uint8_t * PROGMEM contents);
320#endif
321
322/**
323 * \brief Print a \c \0 terminated text string from flash
324 * on the OLED display using a 8×8 pixel font
325 *
326 * Almost same function as sb_display_showString(), but the string is
327 * read from the flash (program memory) - so no SRAM is wasted.
328 *
329 * The \ref fonts "Fonts Table" contains a detailed list of the available characters
330 *
331 * It is possible to define an inline flash string using the \c PSTR macro from the
332 * <a href="http://www.nongnu.org/avr-libc/user-manual/pgmspace.html">Program Space Utilities</a>:
333 * \code {.c}
334 * static const __flash str[] = "Ipsum";
335 * sb_display_showString(0, 0, "Lorem");
336 * sb_display_showStringFromFlash(1, 0, str);
337 * sb_display_showStringFromFlash(2, 0, PSTR("dolor"));
338 * \endcode
339 * This will display \a Lorem , \a Ipsum and \a dolor on the subsequent lines,
340 * but only the first string will consume SRAM during runtime.
341 * The second and third call are different ways for reading from flash memory.
342 *
343 * \warning The font will be stored on the flash which will consume about 2300 bytes
344 * (but there is no additional overhead in case you are already
345 * using the sb_display_showString() ).
346 *
347 * \param pageNum page number (0-7) for vertical positioning the output
348 * \param colStart first column to set the horizontal position of the output
349 * \param str 0-terminated string in flash memory
350 *
351 * \retval >=0 length of printed string (can be less than strlen(str) )
352 * \retval <0 on I²C error (\see sb_display_enable() return codes)
353 */
354#ifdef __FLASH
355int8_t sb_display_showStringFromFlash(uint8_t pageNum, uint8_t colStart, const __flash char *str);
356#else
357int8_t sb_display_showStringFromFlash(uint8_t pageNum, uint8_t colStart, const char * PROGMEM str);
358#endif
359
360/**
361 * \brief Print a \c \0 terminated text string from flash
362 * with a (slightly) wider 8×8 pixel font onto the OLED display
363 *
364 * Almost same function as sb_display_showStringWide(), but the string is
365 * read from the flash (program memory) - so no SRAM is wasted.
366 *
367 * The \ref fonts "Fonts Table" contains a detailed list of the
368 * available characters.
369 *
370 * \warning This font will consume about 2300 bytes, too (but no additional
371 * overhead for using sb_display_showStringWide() ).
372 *
373 * \param pageNum page number (0-7) for vertical positioning the output
374 * \param colStart first column to set the horizontal position of the output
375 * \param str 0-terminated string in flash memory
376 *
377 * \retval >=0 length of printed string (can be less than strlen(str) )
378 * \retval <0 on I²C error (see sb_display_enable() return codes)
379 */
380#ifdef __FLASH
381int8_t sb_display_showStringWideFromFlash(uint8_t pageNum, uint8_t colStart, const __flash char *str);
382#else
383int8_t sb_display_showStringWideFromFlash(uint8_t pageNum, uint8_t colStart, const char * PROGMEM str);
384#endif
385
386/**
387 * \brief Print a \0 terminated text string from flash
388 * on the OLED display using a small 6×4 pixel font
389 *
390 * Almost same function as sb_display_showStringSmall(), but the string is
391 * read from the flash (program memory) - so no SRAM is wasted.
392 *
393 * The \ref fonts "Fonts Table" contains a detailed list of the
394 * available characters
395 *
396 * \warning This font will consume about 700 bytes (but no additional
397 * overhead for using sb_display_showStringSmall() ).
398 *
399 * \param pageNum page number (0-7) for vertical positioning the output
400 * \param colStart first column to set the horizontal position of the output
401 * \param str 0-terminated string from flash
402 *
403 * \retval >=0 length of printed string (can be less than strlen(str) )
404 * \retval <0 on I²C error (\see sb_display_enable() return codes)
405 */
406#ifdef __FLASH
407int8_t sb_display_showStringSmallFromFlash(uint8_t pageNum, uint8_t colStart, const __flash char *str);
408#else
409int8_t sb_display_showStringSmallFromFlash(uint8_t pageNum, uint8_t colStart, const char * PROGMEM str);
410#endif
411
412/** @}*/
413
414#endif
415
int8_t sb_display_drawBitmapFromFlash(uint8_t pageStart, uint8_t colStart, uint8_t pageCount, uint8_t colCount, const __flash uint8_t *contents)
Draw a bitmap from the flash memory onto the OLED display.
int8_t sb_display_fillScreenFromFlash(const __flash uint8_t *contents)
Draw the contents of the flash to the entire OLED display screen.
int8_t sb_display_showStringWideFromFlash(uint8_t pageNum, uint8_t colStart, const __flash char *str)
Print a \0 terminated text string from flash with a (slightly) wider 8×8 pixel font onto the OLED dis...
int8_t sb_display_showStringFromFlash(uint8_t pageNum, uint8_t colStart, const __flash char *str)
Print a \0 terminated text string from flash on the OLED display using a 8×8 pixel font.
int8_t sb_display_showStringSmallFromFlash(uint8_t pageNum, uint8_t colStart, const __flash char *str)
Print a \0 terminated text string from flash on the OLED display using a small 6×4 pixel font.
int8_t sb_display_showStringSmall(uint8_t pageNum, uint8_t colStart, const char *str)
Print a \0 terminated text string on the OLED display using a small 6×4 pixel font.
int8_t sb_display_fillScreen(const uint8_t *contents)
Draw the contents of a 8*128 item 8-bit array (8 pages with 128 columns, each filled with 8 bit) onto...
int8_t sb_display_available()
Check if a functional OLED display is present.
int8_t sb_display_enable()
Activate (and setup) the OLED-display.
int8_t sb_display_drawBitmap(uint8_t pageStart, uint8_t colStart, uint8_t pageCount, uint8_t colCount, const uint8_t *contents)
Draw a (rectangular) bitmap onto the OLED display.
int8_t sb_display_disable()
Turn the OLED display off.
int8_t sb_display_showStringWide(uint8_t pageNum, uint8_t colStart, const char *str)
Print a \0 terminated text string with a (slightly) wider 8×8 pixel font onto the OLED display.
int8_t sb_display_showString(uint8_t pageNum, uint8_t colStart, const char *str)
Print a \0 terminated text string on the OLED display using a 8×8 pixel font.
int8_t sb_display_draw(uint8_t pageNum, uint8_t colNum, uint8_t content)
Draw a single page segment onto the OLED display.