SSD1306 OLED display driver  1.3.3
This library is developed to control SSD1306 i2c/spi OLED display
ssd1306.cpp
1 /*
2  Copyright (C) 2016-2017 Alexey Dynda
3 
4  This file is part of SSD1306 library.
5 
6  This program is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "font6x8.h"
21 #include "ssd1306.h"
22 #include "lcd/lcd_common.h"
23 #include "i2c/ssd1306_i2c.h"
24 #include "spi/ssd1306_spi.h"
25 #include "intf/ssd1306_interface.h"
26 
27 // TODO: remove
28 #include "lcd/ssd1306_commands.h"
29 
33 static uint8_t s_invertByte = 0x00000000;
34 const uint8_t *s_font6x8 = ssd1306xled_font6x8;
35 
37 {
38  return s_displayHeight;
39 }
40 
42 {
43  return s_displayWidth;
44 }
45 
46 void ssd1306_fillScreen(uint8_t fill_Data)
47 {
48  fill_Data ^= s_invertByte;
49  ssd1306_setRamBlock(0, 0, 0);
51  for(uint8_t m=(s_displayHeight >> 3); m>0; m--)
52  {
53  for(uint8_t n=s_displayWidth; n>0; n--)
54  {
55  ssd1306_sendByte(fill_Data);
56  }
58  }
60 }
61 
63 {
64  ssd1306_setRamBlock(0, 0, 0);
66  for(uint8_t m=(s_displayHeight >> 3); m>0; m--)
67  {
68  for(uint8_t n=s_displayWidth; n>0; n--)
69  {
70  ssd1306_sendByte( s_invertByte );
71  }
73  }
75 }
76 
77 
79 {
80  ssd1306_sendCommand(SSD1306_DISPLAYOFF);
81 }
82 
83 
85 {
86  ssd1306_sendCommand(SSD1306_DISPLAYON);
87 }
88 
89 uint8_t ssd1306_charF6x8(uint8_t x, uint8_t y, const char ch[], EFontStyle style)
90 {
91  uint8_t i, j=0;
94  while(ch[j] != '\0')
95  {
96  uint8_t c = ch[j] - 32;
97  if(x>s_displayWidth-2)
98  {
99  x=0;
100  y++;
101  }
102  uint8_t ldata = 0;
103  for(i=0;i<6;i++)
104  {
105  uint8_t data;
106  if ( style == STYLE_NORMAL )
107  {
108  data = pgm_read_byte(&s_font6x8[c*6+i]);
109  }
110  else if ( style == STYLE_BOLD )
111  {
112  uint8_t temp = pgm_read_byte(&s_font6x8[c*6+i]);
113  data = temp | ldata;
114  ldata = temp;
115  }
116  else
117  {
118  uint8_t temp = pgm_read_byte(&s_font6x8[c*6+i + 1]);
119  data = (temp & 0xF0) | ldata;
120  ldata = (temp & 0x0F);
121  }
122  ssd1306_sendByte(data^s_invertByte);
123  }
124  x += 6;
125  j++;
126  }
128  return j;
129 }
130 
131 uint8_t ssd1306_charF12x16(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style)
132 {
133  uint8_t i, j=0;
134  uint8_t text_index = 0;
135  uint8_t odd = 0;
136  uint8_t x = xpos;
137  ssd1306_setRamBlock(xpos, y, s_displayWidth - xpos);
139  for(;;)
140  {
141  if( (x > s_displayWidth-12) || (ch[j] == '\0') )
142  {
143  x = xpos;
144  y++;
145  if (y >= (s_displayHeight >> 3))
146  {
147  break;
148  }
149  if (odd)
150  {
151  text_index = j;
152  if (ch[j] == '\0')
153  {
154  break;
155  }
156  }
157  else
158  {
159  j = text_index;
160  }
161  odd = !odd;
163  ssd1306_setRamBlock(xpos, y, s_displayWidth - xpos);
165  }
166  uint8_t c = ch[j] - 32;
167  uint8_t ldata = 0;
168  for(i=0;i<6;i++)
169  {
170  uint8_t data;
171  if ( style == STYLE_NORMAL )
172  {
173  data = pgm_read_byte(&s_font6x8[c*6+i]);
174  }
175  else if ( style == STYLE_BOLD )
176  {
177  uint8_t temp = pgm_read_byte(&s_font6x8[c*6+i]);
178  data = temp | ldata;
179  ldata = temp;
180  }
181  else
182  {
183  uint8_t temp = pgm_read_byte(&s_font6x8[c*6+i + 1]);
184  data = (temp & 0xF0) | ldata;
185  ldata = (temp & 0x0F);
186  }
187  if (odd) data >>= 4;
188  data = ((data & 0x01) ? 0x03: 0x00) |
189  ((data & 0x02) ? 0x0C: 0x00) |
190  ((data & 0x04) ? 0x30: 0x00) |
191  ((data & 0x08) ? 0xC0: 0x00);
192  ssd1306_sendByte(data^s_invertByte);
193  ssd1306_sendByte(data^s_invertByte);
194  }
195  x += 12;
196  j++;
197  }
199  return j;
200 }
201 
202 uint8_t ssd1306_charF6x8_eol(uint8_t left,
203  uint8_t y,
204  const char ch[],
205  EFontStyle style,
206  uint8_t right)
207 {
208  uint8_t len = ssd1306_charF6x8(left, y, ch, style);
209  uint8_t text_end_pos = len * 6 + left;
210  if (text_end_pos <= right)
211  {
212  ssd1306_clearBlock(text_end_pos, y, right - text_end_pos + 1, 8);
213  }
214  return len;
215 }
216 
217 void ssd1306_setFont6x8(const uint8_t * progmemFont)
218 {
219  s_font6x8 = progmemFont;
220 }
221 
222 void ssd1306_putPixel(uint8_t x, uint8_t y)
223 {
224  ssd1306_setRamBlock(x, y >> 3, 1);
226  ssd1306_sendByte((1 << (y & 0x07))^s_invertByte);
228 }
229 
230 void ssd1306_putPixels(uint8_t x, uint8_t y, uint8_t pixels)
231 {
232  ssd1306_setRamBlock(x, y >> 3, 1);
234  ssd1306_sendByte(pixels^s_invertByte);
236 }
237 
238 void ssd1306_drawHLine(uint8_t x1, uint8_t y1, uint8_t x2)
239 {
240  ssd1306_setRamBlock(x1, y1 >> 3, x2 - x1 + 1);
242  for (uint8_t x = x1; x <= x2; x++)
243  {
244  ssd1306_sendByte((1 << (y1 & 0x07))^s_invertByte);
245  }
247 }
248 
249 void ssd1306_drawVLine(uint8_t x1, uint8_t y1, uint8_t y2)
250 {
251  if ((y1 >> 3) == (y2 >> 3)) {
252  uint8_t b = ((0xFF >> (7-(y2-y1))) << (y1 & 0x07))^s_invertByte;
253  ssd1306_putPixels(x1, y1, b);
254  return;
255  }
256  ssd1306_setRamBlock(x1, y1 >> 3, 1);
258  ssd1306_sendByte( (0xFF << (y1 & 0x07))^s_invertByte );
259  uint8_t y;
260  for ( y = ((y1 >> 3) + 1); y <= ((y2 >> 3) - 1); y++)
261  {
263  ssd1306_sendByte( 0xFF^s_invertByte );
264  }
266  ssd1306_sendByte( (0xFF >> (0x07 - (y2 & 0x07)))^s_invertByte );
268 }
269 
270 void ssd1306_drawRect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
271 {
272  ssd1306_drawHLine(x1+1, y1, x2-1);
273  ssd1306_drawHLine(x1+1, y2, x2-1);
274  ssd1306_drawVLine(x1, y1, y2);
275  ssd1306_drawVLine(x2, y1, y2);
276 }
277 
278 void ssd1306_drawBuffer(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
279 {
280  uint8_t i, j;
281  ssd1306_setRamBlock(x, y, w);
283  for(j=0; j<(h >> 3); j++)
284  {
285  for(i=0;i<w;i++)
286  {
287  ssd1306_sendByte(s_invertByte^*buf++);
288  }
290  }
292 }
293 
294 void ssd1306_drawBitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
295 {
296  uint8_t i, j;
297  ssd1306_setRamBlock(x, y, w);
299  for(j=0; j<(h >> 3); j++)
300  {
301  for(i=w;i>0;i--)
302  {
303  ssd1306_sendByte(s_invertByte^pgm_read_byte(buf++));
304  }
306  }
308 }
309 
310 
311 void ssd1306_clearBlock(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
312 {
313  uint8_t i, j;
314  ssd1306_setRamBlock(x, y, w);
316  for(j=0; j<(h >> 3); j++)
317  {
318  for(i=w;i>0;i--)
319  {
320  ssd1306_sendByte(s_invertByte);
321  }
323  }
325 }
326 
327 
328 void ssd1306_drawSpriteEx(uint8_t x, uint8_t y, uint8_t w, const uint8_t *sprite)
329 {
330  uint8_t i;
331  ssd1306_setRamBlock(x,y,w);
333  for(i=0;i<w;i++)
334  {
335  ssd1306_sendByte(s_invertByte^pgm_read_byte(&sprite[i]));
336  }
338 }
339 
340 
342 {
343  uint8_t offsety = sprite->y & 0x7;
344  if (sprite->y < s_displayHeight)
345  {
346  ssd1306_setRamBlock(sprite->x, sprite->y >> 3, sprite->w);
348  for (uint8_t i=0; i < sprite->w; i++)
349  {
350  ssd1306_sendByte( s_invertByte^(pgm_read_byte( &sprite->data[i] ) << offsety) );
351  }
353  }
354  if (offsety && (sprite->y + 8 < s_displayHeight))
355  {
356  ssd1306_setRamBlock(sprite->x, (sprite->y >> 3) + 1, sprite->w);
358  for (uint8_t i=0; i < sprite->w; i++)
359  {
360  ssd1306_sendByte( s_invertByte^(pgm_read_byte( &sprite->data[i] ) >> (8 - offsety)) );
361  }
362  }
364  sprite->lx = sprite->x;
365  sprite->ly = sprite->y;
366 }
367 
368 
370 {
371  uint8_t posy = sprite->y >> 3;
372  uint8_t offsety = sprite->y & 0x7;
373  ssd1306_setRamBlock(sprite->x, posy, sprite->w);
375  for (uint8_t i=0; i < sprite->w; i++)
376  {
377  ssd1306_sendByte( s_invertByte );
378  }
380  if (offsety)
381  {
382  ssd1306_setRamBlock(sprite->x, posy + 1, sprite->w);
384  for (uint8_t i=0; i < sprite->w; i++)
385  {
386  ssd1306_sendByte( s_invertByte );
387  }
388  }
390 }
391 
392 
394 {
395  uint8_t y1 = sprite->ly >> 3;
396  uint8_t y2 = (sprite->ly + 7) >> 3;
397  if (sprite->ly < sprite->y)
398  y2 = min(y2, (uint8_t)((sprite->y >> 3) - 1));
399  else
400  y1 = max(y1, (sprite->ly + 7) >> 3);
401  for(uint8_t y = y1; y <= y2; y++)
402  {
403  ssd1306_setRamBlock(sprite->lx, y, sprite->w);
405  for(uint8_t x = sprite->lx; x < sprite->lx + sprite->w; x++)
406  {
407  ssd1306_sendByte( s_invertByte );
408  }
410  }
411  if (sprite->lx != sprite->x)
412  {
413  uint8_t x1 = sprite->lx;
414  uint8_t x2 = sprite->lx + sprite->w - 1;
415  if (sprite->x < sprite->lx)
416  x1 = max(x1, sprite->x + sprite->w);
417  else
418  x2 = min((uint8_t)(sprite->x - 1), x2);
419  for(uint8_t y = sprite->ly >> 3; y <= (sprite->ly + 7) >> 3; y++)
420  {
421  ssd1306_setRamBlock(x1, y, x2 - x1 +1 );
423  for(uint8_t x = x1; x <= x2; x++)
424  {
425  ssd1306_sendByte( s_invertByte );
426  }
428  }
429  }
430 }
431 
432 SPRITE ssd1306_createSprite(uint8_t x, uint8_t y, uint8_t w, const uint8_t *data)
433 {
434  return {x,y,w,x,y,data,nullptr};
435 }
436 
437 void ssd1306_replaceSprite(SPRITE *sprite, const uint8_t *data)
438 {
439  sprite->data = data;
440 }
441 
443 {
444  ssd1306_sendCommand(SSD1306_INVERTDISPLAY);
445 }
446 
448 {
449  ssd1306_sendCommand(SSD1306_NORMALDISPLAY);
450 }
451 
453 {
454  s_invertByte = 0xFF;
455 }
456 
458 {
459  s_invertByte = 0x00;
460 }
void ssd1306_drawBitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
Definition: ssd1306.cpp:294
void ssd1306_negativeMode()
Definition: ssd1306.cpp:452
const uint8_t * data
Pointer to PROGMEM data, representing sprite image.
void(* ssd1306_sendByte)(uint8_t data)
void ssd1306_displayOff()
Definition: ssd1306.cpp:78
void(* ssd1306_dataStart)()
void(* ssd1306_endTransmission)()
uint8_t ssd1306_displayHeight()
Definition: ssd1306.cpp:36
void ssd1306_replaceSprite(SPRITE *sprite, const uint8_t *data)
Definition: ssd1306.cpp:437
void ssd1306_drawHLine(uint8_t x1, uint8_t y1, uint8_t x2)
Definition: ssd1306.cpp:238
void(* ssd1306_nextRamPage)()
void ssd1306_setFont6x8(const uint8_t *progmemFont)
Definition: ssd1306.cpp:217
uint8_t ssd1306_charF6x8_eol(uint8_t left, uint8_t y, const char ch[], EFontStyle style, uint8_t right)
Definition: ssd1306.cpp:202
void ssd1306_displayOn()
Definition: ssd1306.cpp:84
void ssd1306_drawVLine(uint8_t x1, uint8_t y1, uint8_t y2)
Definition: ssd1306.cpp:249
void ssd1306_positiveMode()
Definition: ssd1306.cpp:457
void ssd1306_putPixels(uint8_t x, uint8_t y, uint8_t pixels)
Definition: ssd1306.cpp:230
SPRITE ssd1306_createSprite(uint8_t x, uint8_t y, uint8_t w, const uint8_t *data)
Definition: ssd1306.cpp:432
void ssd1306_drawSpriteEx(uint8_t x, uint8_t y, uint8_t w, const uint8_t *sprite)
Definition: ssd1306.cpp:328
void ssd1306_sendCommand(uint8_t command)
void ssd1306_fillScreen(uint8_t fill_Data)
Definition: ssd1306.cpp:46
void ssd1306_drawRect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
Definition: ssd1306.cpp:270
void ssd1306_clearScreen()
Definition: ssd1306.cpp:62
uint8_t y
draw position Y on the screen
uint8_t ssd1306_charF12x16(uint8_t xpos, uint8_t y, const char ch[], EFontStyle style)
Definition: ssd1306.cpp:131
uint8_t ssd1306_charF6x8(uint8_t x, uint8_t y, const char ch[], EFontStyle style)
Definition: ssd1306.cpp:89
void ssd1306_clearBlock(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
Definition: ssd1306.cpp:311
void ssd1306_invertMode()
Definition: ssd1306.cpp:442
uint8_t x
draw position X on the screen
uint8_t ssd1306_displayWidth()
Definition: ssd1306.cpp:41
void ssd1306_drawSprite(SPRITE *sprite)
Definition: ssd1306.cpp:341
void ssd1306_eraseTrace(SPRITE *sprite)
Definition: ssd1306.cpp:393
void ssd1306_drawBuffer(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
Definition: ssd1306.cpp:278
void ssd1306_eraseSprite(SPRITE *sprite)
Definition: ssd1306.cpp:369
uint8_t g_lcd_type
Definition: ssd1306.cpp:32
uint8_t s_displayHeight
Definition: ssd1306.cpp:30
void ssd1306_normalMode()
Definition: ssd1306.cpp:447
uint8_t w
sprite width
void(* ssd1306_setRamBlock)(uint8_t x, uint8_t y, uint8_t w)
void ssd1306_putPixel(uint8_t x, uint8_t y)
Definition: ssd1306.cpp:222
uint8_t lx
last draw position X on the screen
EFontStyle
uint8_t s_displayWidth
Definition: ssd1306.cpp:31
uint8_t ly
last draw position Y on the screen