Friedrich-Alexander-Universität Erlangen-Nürnberg  /   Technische Fakultät  /   Department Informatik

 

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  */
54 int8_t sb_display_enable();
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  */
65 int8_t sb_display_available();
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  */
73 int8_t sb_display_disable();
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  */
85 int8_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  */
126 int8_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  */
148 int8_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  */
181 int8_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  */
202 int8_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  */
232 int8_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
293 int8_t sb_display_drawBitmapFromFlash(uint8_t pageStart, uint8_t colStart, uint8_t pageCount, uint8_t colCount, const __flash uint8_t *contents);
294 #else
295 int8_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
317 int8_t sb_display_fillScreenFromFlash(const __flash uint8_t *contents);
318 #else
319 int8_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
355 int8_t sb_display_showStringFromFlash(uint8_t pageNum, uint8_t colStart, const __flash char *str);
356 #else
357 int8_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
381 int8_t sb_display_showStringWideFromFlash(uint8_t pageNum, uint8_t colStart, const __flash char *str);
382 #else
383 int8_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
407 int8_t sb_display_showStringSmallFromFlash(uint8_t pageNum, uint8_t colStart, const __flash char *str);
408 #else
409 int8_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_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_available()
Check if a functional OLED display is present.
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_enable()
Activate (and setup) the OLED-display.
int8_t sb_display_disable()
Turn the OLED display off.
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_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_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_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_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_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_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_draw(uint8_t pageNum, uint8_t colNum, uint8_t content)
Draw a single page segment onto the OLED display.