SSD1306 OLED display driver  1.7.1
This library is developed to control SSD1306/SSD1331/SSD1351/IL9163/PCD8554 RGB i2c/spi LED displays
ssd1331_api.c
1 /*
2  MIT License
3 
4  Copyright (c) 2018, Alexey Dynda
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 
25 #include "ssd1306.h"
26 #include "ssd1331_api.h"
27 #include "intf/ssd1306_interface.h"
28 #include "intf/spi/ssd1306_spi.h"
29 #include "ssd1306_hal/io.h"
30 
31 #include "lcd/ssd1331_commands.h"
32 #include "lcd/lcd_common.h"
33 
34 extern uint16_t ssd1306_color;
35 extern uint8_t s_ssd1306_invertByte;
36 extern lcduint_t ssd1306_cursorX;
37 extern lcduint_t ssd1306_cursorY;
39 
40 void ssd1331_setColor(uint16_t color)
41 {
42  ssd1306_color = color;
43 }
44 
45 void ssd1331_setRgbColor(uint8_t r, uint8_t g, uint8_t b)
46 {
47  ssd1306_color = RGB_COLOR8(r,g,b);
48 }
49 
50 void ssd1331_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t color)
51 {
54  ssd1306_intf.send(SSD1331_DRAWLINE);
55  ssd1306_intf.send(x1);
56  ssd1306_intf.send(y1);
57  ssd1306_intf.send(x2);
58  ssd1306_intf.send(y2);
59  ssd1306_intf.send( (color & 0x03) << 4 );
60  ssd1306_intf.send( (color & 0x1C) << 2 );
61  ssd1306_intf.send( (color & 0xE0) >> 2 );
63 }
64 
65 void ssd1331_copyBlock(uint8_t left, uint8_t top, uint8_t right, uint8_t bottom, uint8_t newLeft, uint8_t newTop)
66 {
69  ssd1306_intf.send(0x23);
70  ssd1306_intf.send(left);
71  ssd1306_intf.send(top);
72  ssd1306_intf.send(right);
73  ssd1306_intf.send(bottom);
74  ssd1306_intf.send(newLeft);
75  ssd1306_intf.send(newTop);
77 }
78 
79 void ssd1331_drawMonoBuffer8(lcdint_t xpos, lcdint_t ypos, lcduint_t w, lcduint_t h, const uint8_t *bitmap)
80 {
81  uint8_t bit = 1;
82  uint8_t blackColor = s_ssd1306_invertByte ? ssd1306_color : 0x00;
83  uint8_t color = s_ssd1306_invertByte ? 0x00 : ssd1306_color;
84  ssd1306_lcd.set_block(xpos, ypos, w);
85  while (h--)
86  {
87  uint8_t wx = w;
88  while (wx--)
89  {
90  uint8_t data = *bitmap;
91  if ( data & bit )
92  ssd1306_lcd.send_pixels8( color );
93  else
94  ssd1306_lcd.send_pixels8( blackColor );
95  bitmap++;
96  }
97  bit <<= 1;
98  if (bit == 0)
99  {
100  bit = 1;
101  }
102  else
103  {
104  bitmap -= w;
105  }
106  }
107  ssd1306_intf.stop();
108 }
109 
110 void ssd1331_drawBufferFast8(lcdint_t x, lcdint_t y, lcduint_t w, lcduint_t h, const uint8_t *data)
111 {
112  uint16_t count = w * h;
113  ssd1306_lcd.set_block(x, y, w);
114  while (count--)
115  {
116  ssd1306_lcd.send_pixels8( *data );
117  data++;
118  }
119  ssd1306_intf.stop();
120 }
121 
122 void ssd1331_drawBufferFast16(lcdint_t x, lcdint_t y, lcduint_t w, lcduint_t h, const uint8_t *data)
123 {
124  uint16_t count = (w * h) << 1;
125  ssd1306_lcd.set_block(x, y, w);
126  while (count--)
127  {
128  ssd1306_intf.send( *data );
129  data++;
130  }
131  ssd1306_intf.stop();
132 }
133 
134 void ssd1331_fillScreen8(uint8_t fill_Data)
135 {
136  ssd1306_lcd.set_block(0, 0, 0);
137  uint16_t count = ssd1306_lcd.width * ssd1306_lcd.height;
138  while (count--)
139  {
140  ssd1306_lcd.send_pixels8( fill_Data );
141  }
142  ssd1306_intf.stop();
143 }
144 
146 {
147  ssd1331_fillScreen8( 0x00 );
148 }
149 
150 void ssd1331_putPixel8(lcdint_t x, lcdint_t y)
151 {
152  ssd1306_lcd.set_block(x, y, 0);
153  ssd1306_lcd.send_pixels8( ssd1306_color );
154  ssd1306_intf.stop();
155 }
156 
157 void ssd1331_drawVLine8(lcdint_t x1, lcdint_t y1, lcdint_t y2)
158 {
159  ssd1306_lcd.set_block(x1, y1, 1);
160  while (y1<=y2)
161  {
162  ssd1306_lcd.send_pixels8( ssd1306_color );
163  y1++;
164  }
165  ssd1306_intf.stop();
166 }
167 
168 void ssd1331_drawHLine8(lcdint_t x1, lcdint_t y1, lcdint_t x2)
169 {
170  ssd1306_lcd.set_block(x1, y1, 0);
171  while (x1 < x2)
172  {
173  ssd1306_lcd.send_pixels8( ssd1306_color );
174  x1++;
175  }
176  ssd1306_intf.stop();
177 }
178 
179 void ssd1331_drawLine8(lcdint_t x1, lcdint_t y1, lcdint_t x2, lcdint_t y2)
180 {
181  lcduint_t dx = x1 > x2 ? (x1 - x2): (x2 - x1);
182  lcduint_t dy = y1 > y2 ? (y1 - y2): (y2 - y1);
183  lcduint_t err = 0;
184  if (dy > dx)
185  {
186  if (y1 > y2)
187  {
188  ssd1306_swap_data(x1, x2, lcdint_t);
189  ssd1306_swap_data(y1, y2, lcdint_t);
190  }
191  for(; y1<=y2; y1++)
192  {
193  err += dx;
194  if (err >= dy)
195  {
196  err -= dy;
197  x1 < x2 ? x1++: x1--;
198  }
199  ssd1331_putPixel8( x1, y1 );
200  }
201  }
202  else
203  {
204  if (x1 > x2)
205  {
206  ssd1306_swap_data(x1, x2, lcdint_t);
207  ssd1306_swap_data(y1, y2, lcdint_t);
208  }
209  for(; x1<=x2; x1++)
210  {
211  err += dy;
212  if (err >= dx)
213  {
214  err -= dx;
215  if (y1 < y2) y1++; else y1--;
216  }
217  ssd1331_putPixel8( x1, y1 );
218  }
219  }
220 }
221 
222 void ssd1331_drawRect8(lcdint_t x1, lcdint_t y1, lcdint_t x2, lcdint_t y2)
223 {
224  ssd1331_drawHLine8(x1,y1,x2);
225  ssd1331_drawHLine8(x1,y2,x2);
226  ssd1331_drawVLine8(x1,y1,y2);
227  ssd1331_drawVLine8(x2,y1,y2);
228 }
229 
230 void ssd1331_fillRect8(lcdint_t x1, lcdint_t y1, lcdint_t x2, lcdint_t y2)
231 {
232  if (y1 > y2)
233  {
234  ssd1306_swap_data(y1, y2, lcdint_t);
235  }
236  if (x1 > x2)
237  {
238  ssd1306_swap_data(x1, x2, lcdint_t);
239  }
240  ssd1306_lcd.set_block(x1, y1, x2 - x1 + 1);
241  uint16_t count = (x2 - x1 + 1) * (y2 - y1 + 1);
242  while (count--)
243  {
244  ssd1306_lcd.send_pixels8( ssd1306_color );
245  }
246  ssd1306_intf.stop();
247 }
248 
249 void ssd1331_drawMonoBitmap8(lcdint_t xpos, lcdint_t ypos, lcduint_t w, lcduint_t h, const uint8_t *bitmap)
250 {
251  uint8_t bit = 1;
252  uint8_t blackColor = s_ssd1306_invertByte ? ssd1306_color : 0x00;
253  uint8_t color = s_ssd1306_invertByte ? 0x00 : ssd1306_color;
254  ssd1306_lcd.set_block(xpos, ypos, w);
255  while (h--)
256  {
257  uint8_t wx = w;
258  while (wx--)
259  {
260  uint8_t data = pgm_read_byte( bitmap );
261  if ( data & bit )
262  ssd1306_lcd.send_pixels8( color );
263  else
264  ssd1306_lcd.send_pixels8( blackColor );
265  bitmap++;
266  }
267  bit <<= 1;
268  if (bit == 0)
269  {
270  bit = 1;
271  }
272  else
273  {
274  bitmap -= w;
275  }
276  }
277  ssd1306_intf.stop();
278 }
279 
280 void ssd1331_drawBitmap8(lcdint_t xpos, lcdint_t ypos, lcduint_t w, lcduint_t h, const uint8_t *bitmap)
281 {
282  ssd1306_lcd.set_block(xpos, ypos, w);
283  uint16_t count = (w) * (h);
284  while (count--)
285  {
286  ssd1306_lcd.send_pixels8( pgm_read_byte( bitmap ) );
287  bitmap++;
288  }
289  ssd1306_intf.stop();
290 }
291 
292 void ssd1331_clearBlock8(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
293 {
294  ssd1306_lcd.set_block(x, y, w);
295  uint16_t count = w * h;
296  while (count--)
297  {
298  ssd1306_lcd.send_pixels8( 0x00 );
299  }
300  ssd1306_intf.stop();
301 }
302 
303 void ssd1331_setCursor8(lcduint_t x, lcduint_t y)
304 {
305  ssd1306_cursorX = x;
306  ssd1306_cursorY = y;
307 }
308 
309 void ssd1331_printChar8(uint8_t c)
310 {
311  c -= s_fixedFont.ascii_offset;
312  ssd1331_drawMonoBitmap8(ssd1306_cursorX,
313  ssd1306_cursorY,
314  s_fixedFont.width,
315  s_fixedFont.height,
316  &s_fixedFont.data[ c * s_fixedFont.pages * s_fixedFont.width ] );
317 }
318 
319 size_t ssd1331_write8(uint8_t ch)
320 {
321  if (ch == '\r')
322  {
323  ssd1306_cursorX = 0;
324  return 0;
325  }
326  else if ( (ssd1306_cursorX > ssd1306_lcd.width - s_fixedFont.width) || (ch == '\n') )
327  {
328  ssd1306_cursorX = 0;
329  ssd1306_cursorY += s_fixedFont.height;
330  if ( ssd1306_cursorY > ssd1306_lcd.height - s_fixedFont.height )
331  {
332  ssd1306_cursorY = 0;
333  }
334  ssd1331_clearBlock8(0, ssd1306_cursorY, ssd1306_lcd.width, s_fixedFont.height);
335  if (ch == '\n')
336  {
337  return 0;
338  }
339  }
340  ch -= s_fixedFont.ascii_offset;
341  ssd1331_drawMonoBitmap8( ssd1306_cursorX,
342  ssd1306_cursorY,
343  s_fixedFont.width,
344  s_fixedFont.height,
345  &s_fixedFont.data[ ch * s_fixedFont.pages * s_fixedFont.width ] );
346  ssd1306_cursorX += s_fixedFont.width;
347  return 1;
348 }
349 
350 size_t ssd1331_print8(const char ch[])
351 {
352  size_t n = 0;
353  while (*ch)
354  {
355  n += ssd1331_write8(*ch);
356  ch++;
357  }
358  return n;
359 }
360 
361 uint8_t ssd1331_printFixed8(lcdint_t x, lcdint_t y, const char *ch, EFontStyle style)
362 {
363  ssd1306_cursorX = x;
364  ssd1306_cursorY = y;
365  return ssd1331_print8(ch);
366 }
367 
368 
void ssd1331_setCursor8(lcduint_t x, lcduint_t y)
Definition: ssd1331_api.c:303
void ssd1331_drawBufferFast16(lcdint_t x, lcdint_t y, lcduint_t w, lcduint_t h, const uint8_t *data)
Definition: ssd1331_api.c:122
void ssd1331_drawLine8(lcdint_t x1, lcdint_t y1, lcdint_t x2, lcdint_t y2)
Definition: ssd1331_api.c:179
void(* send)(uint8_t data)
void ssd1331_fillRect8(lcdint_t x1, lcdint_t y1, lcdint_t x2, lcdint_t y2)
Definition: ssd1331_api.c:230
void ssd1331_setRgbColor(uint8_t r, uint8_t g, uint8_t b)
Sets default color.
Definition: ssd1331_api.c:45
void ssd1331_clearScreen8(void)
Definition: ssd1331_api.c:145
#define RGB_COLOR8(r, g, b)
void(* set_block)(lcduint_t x, lcduint_t y, lcduint_t w)
Sets block in RAM of lcd display controller to write data to.
Definition: lcd_common.h:114
SFixedFontInfo s_fixedFont
Definition: tiler.h:39
void ssd1331_drawHLine8(lcdint_t x1, lcdint_t y1, lcdint_t x2)
Definition: ssd1331_api.c:168
void(* send_pixels8)(uint8_t data)
Sends RGB pixel encoded in 3-3-2 format to OLED driver. Sends RGB pixel encoded in 3-3-2 format to OL...
Definition: lcd_common.h:142
void ssd1306_spiDataMode(uint8_t mode)
Definition: ssd1306_spi.c:50
void ssd1331_drawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2, uint16_t color)
Definition: ssd1331_api.c:50
void ssd1331_printChar8(uint8_t c)
Definition: ssd1331_api.c:309
uint8_t ascii_offset
ascii offset
size_t ssd1331_write8(uint8_t ch)
Prints single character to display at current cursor position.
Definition: ssd1331_api.c:319
void ssd1331_clearBlock8(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
Definition: ssd1331_api.c:292
ssd1306_lcd_t ssd1306_lcd
Definition: lcd_common.c:32
void ssd1331_setColor(uint16_t color)
Sets default color, generated by RGB_COLOR8 or RGB_COLOR16 macros.
Definition: ssd1331_api.c:40
ssd1306_interface_t ssd1306_intf
lcduint_t height
Definition: lcd_common.h:97
uint8_t width
width in pixels
void ssd1331_drawBufferFast8(lcdint_t x, lcdint_t y, lcduint_t w, lcduint_t h, const uint8_t *data)
Definition: ssd1331_api.c:110
void ssd1331_drawRect8(lcdint_t x1, lcdint_t y1, lcdint_t x2, lcdint_t y2)
Definition: ssd1331_api.c:222
void ssd1331_drawVLine8(lcdint_t x1, lcdint_t y1, lcdint_t y2)
Definition: ssd1331_api.c:157
void ssd1331_fillScreen8(uint8_t fill_Data)
Definition: ssd1331_api.c:134
size_t ssd1331_print8(const char ch[])
Prints null-terminated string to display at current cursor position.
Definition: ssd1331_api.c:350
void ssd1331_putPixel8(lcdint_t x, lcdint_t y)
Definition: ssd1331_api.c:150
lcduint_t width
Definition: lcd_common.h:94
void ssd1331_drawBitmap8(lcdint_t xpos, lcdint_t ypos, lcduint_t w, lcduint_t h, const uint8_t *bitmap)
Definition: ssd1331_api.c:280
void ssd1331_copyBlock(uint8_t left, uint8_t top, uint8_t right, uint8_t bottom, uint8_t newLeft, uint8_t newTop)
Definition: ssd1331_api.c:65
const uint8_t * data
font chars bits
EFontStyle
uint8_t pages
height in pages (each page height is 8-pixels)
uint8_t ssd1331_printFixed8(lcdint_t x, lcdint_t y, const char *ch, EFontStyle style)
Definition: ssd1331_api.c:361
#define ssd1306_swap_data(a, b, type)
Definition: io.h:69
void ssd1331_drawMonoBuffer8(lcdint_t xpos, lcdint_t ypos, lcduint_t w, lcduint_t h, const uint8_t *bitmap)
Definition: ssd1331_api.c:79
uint8_t height
height in pixels
void ssd1331_drawMonoBitmap8(lcdint_t xpos, lcdint_t ypos, lcduint_t w, lcduint_t h, const uint8_t *bitmap)
Definition: ssd1331_api.c:249