esp32-warm-water
esp32 based project for the control of a heating element based on temperature
ssd1306.c
Go to the documentation of this file.
1 /*
2  * MIT License
3  *
4  * Copyright (c) 2020 nopnop2002
5  * Copyright (c) 2021 wolffshots
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in all
15  * copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25 
31 #include <string.h>
32 
33 #include "freertos/FreeRTOS.h"
34 #include "freertos/task.h"
35 
36 #include "esp_log.h"
37 
38 #include "ssd1306.h"
39 #include "font8x8_basic.h"
40 #include "font8x8_readable.h"
41 #include "font8x8_readable_thin.h"
42 #include "font8x8_space.h"
43 
44 #include <string.h>
45 
46 #define tag CONFIG_SSD1306_TAG
47 
48 int center, top, bottom;
49 
54 {
55 #if CONFIG_I2C_INTERFACE
56  i2c_master_init(dev, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, CONFIG_RESET_GPIO);
57 #endif // CONFIG_I2C_INTERFACE
58 
59 #if CONFIG_SPI_INTERFACE
60  spi_master_init(dev, CONFIG_MOSI_GPIO, CONFIG_SCLK_GPIO, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO);
61 #endif // CONFIG_SPI_INTERFACE
62 #if CONFIG_FLIP
63  dev._flip = true;
64 #endif
65  int width = 128;
66  int height;
67 #if CONFIG_SSD1306_128x64
68  height = 64;
69 #endif // CONFIG_SSD1306_128x64
70 #if CONFIG_SSD1306_128x32
71  height = 32;
72 #endif // CONFIG_SSD1306_128x32
73  if (dev->_address == SPIAddress)
74  {
75  spi_init(dev, width, height);
76  }
77  else
78  {
79  i2c_init(dev, width, height);
80  }
81  ssd1306_clear_screen(dev, false);
82  ssd1306_contrast(dev, 0xff);
83 #if CONFIG_SSD1306_128x64
84  top = 2;
85  center = 3;
86  bottom = 8;
87 #endif // CONFIG_SSD1306_128x64
88 #if CONFIG_SSD1306_128x32
89  top = 1;
90  center = 1;
91  bottom = 4;
92 #endif // CONFIG_SSD1306_128x32
93  ssd1306_clear_screen(dev, false);
94  ssd1306_contrast(dev, 0xff);
95 }
101 {
103 }
112 void ssd1306_display_text(SSD1306_t *dev, int page, char *text, int text_len, bool invert)
113 {
114  if (page >= dev->_pages)
115  return;
116  int _text_len = text_len;
117  if (_text_len > 16)
118  _text_len = 16;
119 
120  uint8_t seg = 0;
121  uint8_t image[8];
122  for (uint8_t i = 0; i < _text_len; i++)
123  {
124  memcpy(image, font8x8[(uint8_t)text[i]], 8);
125  if (invert)
126  ssd1306_invert(image, 8);
127  if (dev->_flip)
128  ssd1306_flip(image, 8);
129  if (dev->_address == SPIAddress)
130  {
131  spi_display_image(dev, page, seg, image, 8);
132  }
133  else
134  {
135  i2c_display_image(dev, page, seg, image, 8);
136  }
137  seg = seg + 8;
138  }
139 }
146 void ssd1306_wrapped_display_text(SSD1306_t *dev, int line, char *text)
147 {
148  ssd1306_clear_line(dev, line, false);
149  ssd1306_display_text(dev, line, text, strlen(text), false);
150 }
159 void ssd1306_display_image(SSD1306_t *dev, int page, int seg, uint8_t *images, int width)
160 {
161  if (dev->_address == SPIAddress)
162  {
163  spi_display_image(dev, page, seg, images, width);
164  }
165  else
166  {
167  i2c_display_image(dev, page, seg, images, width);
168  }
169 }
175 void ssd1306_clear_screen(SSD1306_t *dev, bool invert)
176 {
177  char space[16];
178  memset(space, 0x20, sizeof(space));
179  for (int page = 0; page < dev->_pages; page++)
180  {
181  ssd1306_display_text(dev, page, space, sizeof(space), invert);
182  }
183 }
190 void ssd1306_clear_line(SSD1306_t *dev, int page, bool invert)
191 {
192  char space[16];
193  memset(space, 0x20, sizeof(space));
194  ssd1306_display_text(dev, page, space, sizeof(space), invert);
195 }
201 void ssd1306_contrast(SSD1306_t *dev, int contrast)
202 {
203  if (dev->_address == SPIAddress)
204  {
205  spi_contrast(dev, contrast);
206  }
207  else
208  {
209  i2c_contrast(dev, contrast);
210  }
211 }
218 void ssd1306_software_scroll(SSD1306_t *dev, int start, int end)
219 {
220  ESP_LOGI(tag, "software_scroll start=%d end=%d _pages=%d", start, end, dev->_pages);
221  if (start < 0 || end < 0)
222  {
223  dev->_scEnable = false;
224  }
225  else if (start >= dev->_pages || end >= dev->_pages)
226  {
227  dev->_scEnable = false;
228  }
229  else
230  {
231  dev->_scEnable = true;
232  dev->_scStart = start;
233  dev->_scEnd = end;
234  dev->_scDirection = 1;
235  if (start > end)
236  dev->_scDirection = -1;
237  for (int i = 0; i < dev->_pages; i++)
238  {
239  dev->_page[i]._valid = false;
240  dev->_page[i]._segLen = 0;
241  }
242  }
243 }
251 void ssd1306_scroll_text(SSD1306_t *dev, char *text, int text_len, bool invert)
252 {
253  ESP_LOGI(tag, "dev->_scEnable=%d", dev->_scEnable);
254  if (dev->_scEnable == false)
255  return;
256 
257  void (*func)(SSD1306_t * dev, int page, int seg, uint8_t *images, int width);
258  if (dev->_address == SPIAddress)
259  {
260  func = spi_display_image;
261  }
262  else
263  {
264  func = i2c_display_image;
265  }
266 
267  int srcIndex = dev->_scEnd - dev->_scDirection;
268  while (1)
269  {
270  int dstIndex = srcIndex + dev->_scDirection;
271  ESP_LOGD(tag, "srcIndex=%d dstIndex=%d", srcIndex, dstIndex);
272  dev->_page[dstIndex]._valid = dev->_page[srcIndex]._valid;
273  dev->_page[dstIndex]._segLen = dev->_page[srcIndex]._segLen;
274  for (int seg = 0; seg < dev->_width; seg++)
275  {
276  dev->_page[dstIndex]._segs[seg] = dev->_page[srcIndex]._segs[seg];
277  }
278  ESP_LOGD(tag, "_valid=%d", dev->_page[dstIndex]._valid);
279  if (dev->_page[dstIndex]._valid)
280  (*func)(dev, dstIndex, 0, dev->_page[dstIndex]._segs, dev->_page[srcIndex]._segLen);
281  if (srcIndex == dev->_scStart)
282  break;
283  srcIndex = srcIndex - dev->_scDirection;
284  }
285 
286  int _text_len = text_len;
287  if (_text_len > 16)
288  _text_len = 16;
289 
290  uint8_t seg = 0;
291  uint8_t image[8];
292  for (uint8_t i = 0; i < _text_len; i++)
293  {
294  memcpy(image, font8x8[(uint8_t)text[i]], 8);
295  if (invert)
296  ssd1306_invert(image, 8);
297  if (dev->_flip)
298  ssd1306_flip(image, 8);
299  (*func)(dev, srcIndex, seg, image, 8);
300  for (int j = 0; j < 8; j++)
301  dev->_page[srcIndex]._segs[seg + j] = image[j];
302  seg = seg + 8;
303  }
304  dev->_page[srcIndex]._valid = true;
305  dev->_page[srcIndex]._segLen = seg;
306 }
312 {
313  ESP_LOGD(tag, "dev->_scEnable=%d", dev->_scEnable);
314  if (dev->_scEnable == false)
315  return;
316 
317  int srcIndex = dev->_scEnd - dev->_scDirection;
318  while (1)
319  {
320  int dstIndex = srcIndex + dev->_scDirection;
321  ESP_LOGD(tag, "srcIndex=%d dstIndex=%d", srcIndex, dstIndex);
322  ssd1306_clear_line(dev, dstIndex, false);
323  dev->_page[dstIndex]._valid = false;
324  if (dstIndex == dev->_scStart)
325  break;
326  srcIndex = srcIndex - dev->_scDirection;
327  }
328 }
335 {
336  if (dev->_address == SPIAddress)
337  {
338  spi_hardware_scroll(dev, scroll);
339  }
340  else
341  {
342  i2c_hardware_scroll(dev, scroll);
343  }
344 }
352 {
353  if (dev->_address == SPIAddress)
354  {
355  spi_hardware_scroll_line(dev, page, scroll);
356  }
357  else
358  {
359  i2c_hardware_scroll_line(dev, page, scroll);
360  }
361 }
367 void ssd1306_invert(uint8_t *buf, size_t blen)
368 {
369  uint8_t wk;
370  for (int i = 0; i < blen; i++)
371  {
372  wk = buf[i];
373  buf[i] = ~wk;
374  }
375 }
376 
377 // Flip upside down
383 void ssd1306_flip(uint8_t *buf, size_t blen)
384 {
385  for (int i = 0; i < blen; i++)
386  {
387  buf[i] = ssd1306_rotate(buf[i]);
388  }
389 }
390 
391 // Rotate 8-bit data
392 // 0x12-->0x48
398 uint8_t ssd1306_rotate(uint8_t ch1)
399 {
400  uint8_t ch2 = 0;
401  for (int j = 0; j < 8; j++)
402  {
403  ch2 = (ch2 << 1) + (ch1 & 0x01);
404  ch1 = ch1 >> 1;
405  }
406  return ch2;
407 }
413 {
414  void (*func)(SSD1306_t * dev, int page, int seg, uint8_t *images, int width);
415  if (dev->_address == SPIAddress)
416  {
417  func = spi_display_image;
418  }
419  else
420  {
421  func = i2c_display_image;
422  }
423 
424  uint8_t image[1];
425  for (int page = 0; page < dev->_pages; page++)
426  {
427  image[0] = 0xFF;
428  for (int line = 0; line < 8; line++)
429  {
430  if (dev->_flip)
431  {
432  image[0] = image[0] >> 1;
433  }
434  else
435  {
436  image[0] = image[0] << 1;
437  }
438  for (int seg = 0; seg < 128; seg++)
439  {
440  (*func)(dev, page, seg, image, 1);
441  }
442  }
443  }
444 }
450 {
451  printf("_address=%x\n", dev._address);
452  printf("_width=%x\n", dev._width);
453  printf("_height=%x\n", dev._height);
454  printf("_pages=%x\n", dev._pages);
455 }
basic font to use with an ssd1306 screen
a clean simple font to use with an ssd1306 screen
a clean simple font to use with an ssd1306 screen
SSD1306_t dev
device for oled
Definition: main.c:81
void ssd1306_contrast(SSD1306_t *dev, int contrast)
Definition: ssd1306.c:201
void ssd1306_software_scroll(SSD1306_t *dev, int start, int end)
Definition: ssd1306.c:218
int bottom
positions for oled
Definition: ssd1306.c:48
void ssd1306_hardware_scroll_line(SSD1306_t *dev, int page, ssd1306_scroll_type_t scroll)
Definition: ssd1306.c:351
void ssd1306_deinit(SSD1306_t *dev)
Definition: ssd1306.c:100
void ssd1306_wrapped_display_text(SSD1306_t *dev, int line, char *text)
Definition: ssd1306.c:146
void ssd1306_flip(uint8_t *buf, size_t blen)
Definition: ssd1306.c:383
void ssd1306_display_image(SSD1306_t *dev, int page, int seg, uint8_t *images, int width)
Definition: ssd1306.c:159
uint8_t ssd1306_rotate(uint8_t ch1)
Definition: ssd1306.c:398
void ssd1306_fadeout(SSD1306_t *dev)
Definition: ssd1306.c:412
void ssd1306_scroll_text(SSD1306_t *dev, char *text, int text_len, bool invert)
Definition: ssd1306.c:251
void ssd1306_invert(uint8_t *buf, size_t blen)
Definition: ssd1306.c:367
int center
Definition: ssd1306.c:48
void ssd1306_hardware_scroll(SSD1306_t *dev, ssd1306_scroll_type_t scroll)
Definition: ssd1306.c:334
void ssd1306_init(SSD1306_t *dev)
Definition: ssd1306.c:53
void ssd1306_clear_line(SSD1306_t *dev, int page, bool invert)
Definition: ssd1306.c:190
void ssd1306_display_text(SSD1306_t *dev, int page, char *text, int text_len, bool invert)
Definition: ssd1306.c:112
void ssd1306_scroll_clear(SSD1306_t *dev)
Definition: ssd1306.c:311
int top
Definition: ssd1306.c:48
void ssd1306_dump(SSD1306_t dev)
Definition: ssd1306.c:449
void ssd1306_clear_screen(SSD1306_t *dev, bool invert)
Definition: ssd1306.c:175
#define tag
tag for logging library
Definition: ssd1306.c:46
defininitions for setting up, interacting with and sending commands to an ssd1306 driven screen via i...
ssd1306_scroll_type_t
Definition: ssd1306.h:105
void i2c_contrast(SSD1306_t *dev, int contrast)
Definition: ssd1306_i2c.c:211
void spi_hardware_scroll(SSD1306_t *dev, ssd1306_scroll_type_t scroll)
Definition: ssd1306_spi.c:275
void i2c_master_init(SSD1306_t *dev, int16_t sda, int16_t scl, int16_t reset)
Definition: ssd1306_i2c.c:50
void spi_display_image(SSD1306_t *dev, int page, int seg, uint8_t *images, int width)
Definition: ssd1306_spi.c:226
void spi_master_init(SSD1306_t *dev, int16_t GPIO_MOSI, int16_t GPIO_SCLK, int16_t GPIO_CS, int16_t GPIO_DC, int16_t GPIO_RESET)
Definition: ssd1306_spi.c:65
void spi_hardware_scroll_line(SSD1306_t *dev, int page, ssd1306_scroll_type_t scroll)
Definition: ssd1306_spi.c:352
void spi_init(SSD1306_t *dev, int width, int height)
Definition: ssd1306_spi.c:165
#define SPIAddress
Definition: ssd1306.h:102
void i2c_init(SSD1306_t *dev, int width, int height)
Definition: ssd1306_i2c.c:80
void spi_contrast(SSD1306_t *dev, int contrast)
Definition: ssd1306_spi.c:258
void i2c_hardware_scroll_line(SSD1306_t *dev, int page, ssd1306_scroll_type_t scroll)
Definition: ssd1306_i2c.c:335
void i2c_display_image(SSD1306_t *dev, int page, int seg, uint8_t *images, int width)
Definition: ssd1306_i2c.c:159
void i2c_hardware_scroll(SSD1306_t *dev, ssd1306_scroll_type_t scroll)
Definition: ssd1306_i2c.c:236
int _segLen
Definition: ssd1306.h:116
uint8_t _segs[128]
Definition: ssd1306.h:117
bool _valid
Definition: ssd1306.h:115
int _scEnd
Definition: ssd1306.h:130
int _address
Definition: ssd1306.h:122
int _scStart
Definition: ssd1306.h:129
int _pages
Definition: ssd1306.h:125
bool _flip
Definition: ssd1306.h:133
PAGE_t _page[8]
Definition: ssd1306.h:132
int _height
Definition: ssd1306.h:124
int _scDirection
Definition: ssd1306.h:131
bool _scEnable
Definition: ssd1306.h:128
int _width
Definition: ssd1306.h:123