SSD1306 I2C Display Driver  1.2.2
This library is developed to control SSD1306 I2C 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 "intf/ssd1306_interface.h"
23 #include "lcd/lcd_common.h"
24 #include "i2c/ssd1306_i2c.h"
25 #include "spi/ssd1306_spi.h"
26 #include "intf/ssd1306_commands.h"
27 
31 static uint8_t s_invertByte = 0x00000000;
32 const uint8_t *s_font6x8 = ssd1306xled_font6x8;
33 
35 {
36  return s_displayHeight;
37 }
38 
40 {
41  return s_displayWidth;
42 }
43 
44 void ssd1306_setRamBlock(uint8_t x, uint8_t y, uint8_t w)
45 {
47  {
49  ssd1306_sendByte(SSD1306_COLUMNADDR);
51  ssd1306_sendByte(x + w - 1);
52  ssd1306_sendByte(0xb0+y);
53  ssd1306_sendByte((x>>4) | 0x10);
54  ssd1306_sendByte(x&0x0f);
56  }
57  else if ( g_lcd_type == LCD_TYPE_PCD8544 )
58  {
60  if (w == 1) ssd1306_sendByte( 0x22 ); else ssd1306_sendByte( 0x20 );
61  ssd1306_sendByte(0x80 | x);
62  ssd1306_sendByte(0x40 | y);
64  }
65 }
66 
67 void ssd1306_setPos(uint8_t x, uint8_t y)
68 {
70  {
72  ssd1306_sendByte(0xb0+y);
73  ssd1306_sendByte((x>>4) | 0x10);
74  ssd1306_sendByte(x&0x0f);
76  }
77  else if ( g_lcd_type == LCD_TYPE_PCD8544 )
78  {
80  ssd1306_sendByte(0x80 | x);
81  ssd1306_sendByte(0x40 | y);
83  }
84 }
85 
86 void ssd1306_sendData(uint8_t data)
87 {
89  ssd1306_sendByte( data );
91 }
92 
93 void ssd1306_fillScreen(uint8_t fill_Data)
94 {
95  fill_Data ^= s_invertByte;
96  ssd1306_setRamBlock(0, 0, s_displayWidth);
98  for(uint8_t m=0; m<(s_displayHeight >> 3); m++)
99  {
100  for(uint8_t n=0; n<s_displayWidth; n++)
101  {
102  ssd1306_sendByte(fill_Data);
103  }
104  }
106 }
107 
109 {
110  ssd1306_setRamBlock(0, 0, s_displayWidth);
112  for(uint8_t m=0; m<(s_displayHeight >> 3); m++)
113  {
114  for(uint8_t n=0; n<s_displayWidth; n++)
115  {
116  ssd1306_sendByte( s_invertByte );
117  }
118  }
120 }
121 
122 
124 {
125  ssd1306_sendCommand(SSD1306_DISPLAYOFF);
126 }
127 
128 
130 {
131  ssd1306_sendCommand(SSD1306_DISPLAYON);
132 }
133 
134 void ssd1306_charF6x8(uint8_t x, uint8_t y, const char ch[], EFontStyle style)
135 {
136  uint8_t i, j=0;
137  ssd1306_setRamBlock(0, 0, s_displayWidth);
138  ssd1306_setPos(x,y);
140  while(ch[j] != '\0')
141  {
142  uint8_t c = ch[j] - 32;
143  if(x>s_displayWidth-2)
144  {
145  x=0;
146  y++;
147  }
148  uint8_t ldata = 0;
149  for(i=0;i<6;i++)
150  {
151  uint8_t data;
152  if ( style == STYLE_NORMAL )
153  {
154  data = pgm_read_byte(&s_font6x8[c*6+i]);
155  }
156  else if ( style == STYLE_BOLD )
157  {
158  uint8_t temp = pgm_read_byte(&s_font6x8[c*6+i]);
159  data = temp | ldata;
160  ldata = temp;
161  }
162  else
163  {
164  uint8_t temp = pgm_read_byte(&s_font6x8[c*6+i + 1]);
165  data = (temp & 0xF0) | ldata;
166  ldata = (temp & 0x0F);
167  }
168  ssd1306_sendByte(data^s_invertByte);
169  }
170  x += 6;
171  j++;
172  }
174 }
175 
176 void ssd1306_setFont6x8(const uint8_t * progmemFont)
177 {
178  s_font6x8 = progmemFont;
179 }
180 
181 void ssd1306_putPixel(uint8_t x, uint8_t y)
182 {
183  ssd1306_setRamBlock(0, y >> 3, s_displayWidth);
184  ssd1306_setPos(x,y >> 3);
186  ssd1306_sendByte((1 << (y & 0x07))^s_invertByte);
188 }
189 
190 void ssd1306_putPixels(uint8_t x, uint8_t y, uint8_t pixels)
191 {
192  ssd1306_setRamBlock(0, 0, s_displayWidth);
193  ssd1306_setPos(x,y);
195  ssd1306_sendByte(pixels^s_invertByte);
197 }
198 
199 void ssd1306_drawHLine(uint8_t x1, uint8_t y1, uint8_t x2)
200 {
201  ssd1306_setRamBlock(x1, y1 >> 3, x2 - x1 + 1);
203  for (uint8_t x = x1; x <= x2; x++)
204  {
205  ssd1306_sendByte((1 << (y1 & 0x07))^s_invertByte);
206  }
208 }
209 
210 void ssd1306_drawVLine(uint8_t x1, uint8_t y1, uint8_t y2)
211 {
212  ssd1306_setRamBlock(x1, y1 >> 3, 1);
214  ssd1306_sendByte( (0xFF << (y1 & 0x07))^s_invertByte );
215  for ( uint8_t y = ((y1 >> 3) + 1); y <= ((y2 >> 3) - 1); y++)
216  {
217  ssd1306_sendByte( 0xFF^s_invertByte );
218  }
219  ssd1306_sendByte( (0xFF >> (0x07 - (y2 & 0x07)))^s_invertByte );
221 }
222 
223 void ssd1306_drawRect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
224 {
225  ssd1306_drawHLine(x1+1, y1, x2-1);
226  ssd1306_drawHLine(x1+1, y2, x2-1);
227  ssd1306_drawVLine(x1, y1, y2);
228  ssd1306_drawVLine(x2, y1, y2);
229 }
230 
231 void ssd1306_drawBuffer(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
232 {
233  uint8_t i, j;
234  ssd1306_setRamBlock(x, y, w);
236  for(j=0; j<(h >> 3); j++)
237  {
238  if ( g_lcd_type == LCD_TYPE_PCD8544 )
239  {
241  ssd1306_setPos(x, y+j);
243  }
244  for(i=0;i<w;i++)
245  {
246  ssd1306_sendByte(s_invertByte^*buf++);
247  }
248  }
250 }
251 
252 void ssd1306_drawBitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
253 {
254  uint8_t i, j;
255  ssd1306_setRamBlock(x, y, w);
257  for(j=0; j<(h >> 3); j++)
258  {
259  if ( g_lcd_type == LCD_TYPE_PCD8544 )
260  {
262  ssd1306_setPos(x, y+j);
264  }
265  for(i=w;i>0;i--)
266  {
267  ssd1306_sendByte(s_invertByte^pgm_read_byte(buf++));
268  }
269  }
271 }
272 
273 
274 void ssd1306_clearBlock(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
275 {
276  uint8_t i, j;
277  ssd1306_setRamBlock(x, y, w);
279  for(j=0; j<(h >> 3); j++)
280  {
281  if ( g_lcd_type == LCD_TYPE_PCD8544 )
282  {
284  ssd1306_setPos(x, y+j);
286  }
287  for(i=w;i>0;i--)
288  {
289  ssd1306_sendByte(s_invertByte);
290  }
291  }
293 }
294 
295 
296 void ssd1306_drawSpriteEx(uint8_t x, uint8_t y, uint8_t w, const uint8_t *sprite)
297 {
298  uint8_t i;
299  ssd1306_setPos(x,y);
301  for(i=0;i<w;i++)
302  {
303  ssd1306_sendByte(s_invertByte^pgm_read_byte(&sprite[i]));
304  }
306 }
307 
308 
310 {
311  uint8_t posy = sprite->y >> 3;
312  uint8_t offsety = sprite->y & 0x7;
313  if (posy < (s_displayHeight >> 3))
314  {
315  ssd1306_setPos(sprite->x, posy);
317  for (uint8_t i=0; i < sprite->w; i++)
318  {
319  ssd1306_sendByte( s_invertByte^(pgm_read_byte( &sprite->data[i] ) << offsety) );
320  }
322  }
323  if (offsety && (posy + 1 < (s_displayHeight >> 3)))
324  {
325  ssd1306_setPos(sprite->x, posy + 1);
327  for (uint8_t i=0; i < sprite->w; i++)
328  {
329  ssd1306_sendByte( s_invertByte^(pgm_read_byte( &sprite->data[i] ) >> (8 - offsety)) );
330  }
331  }
333  sprite->lx = sprite->x;
334  sprite->ly = sprite->y;
335 }
336 
337 
339 {
340  uint8_t posy = sprite->y >> 3;
341  uint8_t offsety = sprite->y & 0x7;
342  ssd1306_setPos(sprite->x, posy);
344  for (uint8_t i=0; i < sprite->w; i++)
345  {
346  ssd1306_sendByte( s_invertByte );
347  }
349  if (offsety)
350  {
351  ssd1306_setPos(sprite->x, posy + 1);
353  for (uint8_t i=0; i < sprite->w; i++)
354  {
355  ssd1306_sendByte( s_invertByte );
356  }
357  }
359 }
360 
361 
363 {
364  uint8_t y1 = sprite->ly >> 3;
365  uint8_t y2 = (sprite->ly + 7) >> 3;
366  if (sprite->ly < sprite->y)
367  y2 = min(y2, (uint8_t)((sprite->y >> 3) - 1));
368  else
369  y1 = max(y1, (sprite->ly + 7) >> 3);
370  for(uint8_t y = y1; y <= y2; y++)
371  {
372  ssd1306_setPos(sprite->lx, y);
374  for(uint8_t x = sprite->lx; x < sprite->lx + sprite->w; x++)
375  {
376  ssd1306_sendByte( s_invertByte );
377  }
379  }
380  if (sprite->lx != sprite->x)
381  {
382  uint8_t x1 = sprite->lx;
383  uint8_t x2 = sprite->lx + sprite->w - 1;
384  if (sprite->x < sprite->lx)
385  x1 = max(x1, sprite->x + sprite->w);
386  else
387  x2 = min((uint8_t)(sprite->x - 1), x2);
388  for(uint8_t y = sprite->ly >> 3; y <= (sprite->ly + 7) >> 3; y++)
389  {
390  ssd1306_setPos(x1, y);
392  for(uint8_t x = x1; x <= x2; x++)
393  {
394  ssd1306_sendByte( s_invertByte );
395  }
397  }
398  }
399 }
400 
401 SPRITE ssd1306_createSprite(uint8_t x, uint8_t y, uint8_t w, const uint8_t *data)
402 {
403  return {x,y,w,x,y,data,nullptr};
404 }
405 
406 void ssd1306_replaceSprite(SPRITE *sprite, const uint8_t *data)
407 {
408  sprite->data = data;
409 }
410 
412 {
413  ssd1306_sendCommand(SSD1306_INVERTDISPLAY);
414 }
415 
417 {
418  ssd1306_sendCommand(SSD1306_NORMALDISPLAY);
419 }
420 
422 {
423  s_invertByte = 0xFF;
424 }
425 
427 {
428  s_invertByte = 0x00;
429 }
void ssd1306_charF6x8(uint8_t x, uint8_t y, const char ch[], EFontStyle style)
Definition: ssd1306.cpp:134
void ssd1306_drawBitmap(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
Definition: ssd1306.cpp:252
void ssd1306_negativeMode()
Definition: ssd1306.cpp:421
const uint8_t * data
Pointer to PROGMEM data, representing sprite image.
void ssd1306_displayOff()
Definition: ssd1306.cpp:123
uint8_t ssd1306_displayHeight()
Definition: ssd1306.cpp:34
void(* ssd1306_endTransmission)()
void ssd1306_replaceSprite(SPRITE *sprite, const uint8_t *data)
Definition: ssd1306.cpp:406
void ssd1306_drawHLine(uint8_t x1, uint8_t y1, uint8_t x2)
Definition: ssd1306.cpp:199
void(* ssd1306_sendByte)(uint8_t data)
void ssd1306_setFont6x8(const uint8_t *progmemFont)
Definition: ssd1306.cpp:176
void ssd1306_displayOn()
Definition: ssd1306.cpp:129
void ssd1306_drawVLine(uint8_t x1, uint8_t y1, uint8_t y2)
Definition: ssd1306.cpp:210
void ssd1306_sendCommand(uint8_t command)
void ssd1306_positiveMode()
Definition: ssd1306.cpp:426
void ssd1306_putPixels(uint8_t x, uint8_t y, uint8_t pixels)
Definition: ssd1306.cpp:190
void(* ssd1306_dataStart)()
SPRITE ssd1306_createSprite(uint8_t x, uint8_t y, uint8_t w, const uint8_t *data)
Definition: ssd1306.cpp:401
void ssd1306_drawSpriteEx(uint8_t x, uint8_t y, uint8_t w, const uint8_t *sprite)
Definition: ssd1306.cpp:296
void ssd1306_fillScreen(uint8_t fill_Data)
Definition: ssd1306.cpp:93
void ssd1306_drawRect(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
Definition: ssd1306.cpp:223
void ssd1306_clearScreen()
Definition: ssd1306.cpp:108
uint8_t y
draw position Y on the screen
void ssd1306_clearBlock(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
Definition: ssd1306.cpp:274
void ssd1306_invertMode()
Definition: ssd1306.cpp:411
uint8_t x
draw position X on the screen
uint8_t ssd1306_displayWidth()
Definition: ssd1306.cpp:39
void ssd1306_drawSprite(SPRITE *sprite)
Definition: ssd1306.cpp:309
void ssd1306_eraseTrace(SPRITE *sprite)
Definition: ssd1306.cpp:362
void ssd1306_drawBuffer(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t *buf)
Definition: ssd1306.cpp:231
void ssd1306_eraseSprite(SPRITE *sprite)
Definition: ssd1306.cpp:338
uint8_t g_lcd_type
Definition: ssd1306.cpp:30
uint8_t s_displayHeight
Definition: ssd1306.cpp:28
void ssd1306_sendData(uint8_t data)
Definition: ssd1306.cpp:86
void ssd1306_setPos(uint8_t x, uint8_t y)
Definition: ssd1306.cpp:67
void ssd1306_normalMode()
Definition: ssd1306.cpp:416
uint8_t w
sprite width
void ssd1306_putPixel(uint8_t x, uint8_t y)
Definition: ssd1306.cpp:181
uint8_t lx
last draw position X on the screen
void(* ssd1306_commandStart)()
EFontStyle
uint8_t s_displayWidth
Definition: ssd1306.cpp:29
uint8_t ly
last draw position Y on the screen