esp32-warm-water
esp32 based project for the control of a heating element based on temperature
ssd1306_i2c.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 "driver/i2c.h"
37 #include "esp_log.h"
38 
39 #include "ssd1306.h"
40 
41 #define tag CONFIG_SSD1306_I2C_TAG
42 
50 void i2c_master_init(SSD1306_t *dev, int16_t sda, int16_t scl, int16_t reset)
51 {
52  i2c_config_t i2c_config = {
53  .mode = I2C_MODE_MASTER,
54  .sda_io_num = sda,
55  .scl_io_num = scl,
56  .sda_pullup_en = GPIO_PULLUP_ENABLE,
57  .scl_pullup_en = GPIO_PULLUP_ENABLE,
58  .master.clk_speed = 1000000};
59  i2c_param_config(I2C_NUM_0, &i2c_config);
60  i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0);
61 
62  if (reset >= 0)
63  {
64  gpio_pad_select_gpio(reset);
65  gpio_set_direction(reset, GPIO_MODE_OUTPUT);
66  gpio_set_level(reset, 0);
67  vTaskDelay(50 / portTICK_PERIOD_MS);
68  gpio_set_level(reset, 1);
69  }
71  dev->_flip = false;
72 }
73 
80 void i2c_init(SSD1306_t *dev, int width, int height)
81 {
82  dev->_width = width;
83  dev->_height = height;
84  dev->_pages = 8;
85  if (dev->_height == 32)
86  dev->_pages = 4;
87 
88  i2c_cmd_handle_t cmd = i2c_cmd_link_create();
89 
90  i2c_master_start(cmd);
91  i2c_master_write_byte(cmd, (dev->_address << 1) | I2C_MASTER_WRITE, true);
92  i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
93  i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_OFF, true); // AE
94  i2c_master_write_byte(cmd, OLED_CMD_SET_MUX_RATIO, true); // A8
95  if (dev->_height == 64)
96  i2c_master_write_byte(cmd, 0x3F, true);
97  if (dev->_height == 32)
98  i2c_master_write_byte(cmd, 0x1F, true);
99  i2c_master_write_byte(cmd, OLED_CMD_SET_DISPLAY_OFFSET, true); // D3
100  i2c_master_write_byte(cmd, 0x00, true);
101  i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_DATA_STREAM, true); // 40
102  //i2c_master_write_byte(cmd, OLED_CMD_SET_SEGMENT_REMAP, true); // A1
103  if (dev->_flip)
104  {
105  i2c_master_write_byte(cmd, OLED_CMD_SET_SEGMENT_REMAP_0, true); // A0
106  }
107  else
108  {
109  i2c_master_write_byte(cmd, OLED_CMD_SET_SEGMENT_REMAP_1, true); // A1
110  }
111  i2c_master_write_byte(cmd, OLED_CMD_SET_COM_SCAN_MODE, true); // C8
112  i2c_master_write_byte(cmd, OLED_CMD_SET_DISPLAY_CLK_DIV, true); // D5
113  i2c_master_write_byte(cmd, 0x80, true);
114  i2c_master_write_byte(cmd, OLED_CMD_SET_COM_PIN_MAP, true); // DA
115  if (dev->_height == 64)
116  i2c_master_write_byte(cmd, 0x12, true);
117  if (dev->_height == 32)
118  i2c_master_write_byte(cmd, 0x02, true);
119  i2c_master_write_byte(cmd, OLED_CMD_SET_CONTRAST, true); // 81
120  i2c_master_write_byte(cmd, 0xFF, true);
121  i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_RAM, true); // A4
122  i2c_master_write_byte(cmd, OLED_CMD_SET_VCOMH_DESELCT, true); // DB
123  i2c_master_write_byte(cmd, 0x40, true);
124  i2c_master_write_byte(cmd, OLED_CMD_SET_MEMORY_ADDR_MODE, true); // 20
125  //i2c_master_write_byte(cmd, OLED_CMD_SET_HORI_ADDR_MODE, true); // 00
126  i2c_master_write_byte(cmd, OLED_CMD_SET_PAGE_ADDR_MODE, true); // 02
127  // Set Lower Column Start Address for Page Addressing Mode
128  i2c_master_write_byte(cmd, 0x00, true);
129  // Set Higher Column Start Address for Page Addressing Mode
130  i2c_master_write_byte(cmd, 0x10, true);
131  i2c_master_write_byte(cmd, OLED_CMD_SET_CHARGE_PUMP, true); // 8D
132  i2c_master_write_byte(cmd, 0x14, true);
133  i2c_master_write_byte(cmd, OLED_CMD_DEACTIVE_SCROLL, true); // 2E
134  i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_NORMAL, true); // A6
135  i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_ON, true); // AF
136 
137  i2c_master_stop(cmd);
138 
139  esp_err_t espRc = i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS);
140  if (espRc == ESP_OK)
141  {
142  ESP_LOGI(tag, "OLED configured successfully");
143  }
144  else
145  {
146  ESP_LOGE(tag, "OLED configuration failed. code: 0x%.2X", espRc);
147  }
148  i2c_cmd_link_delete(cmd);
149 }
150 
159 void i2c_display_image(SSD1306_t *dev, int page, int seg, uint8_t *images, int width)
160 {
161  i2c_cmd_handle_t cmd;
162 
163  if (page >= dev->_pages)
164  return;
165  if (seg >= dev->_width)
166  return;
167 
168  int _seg = seg + CONFIG_OFFSETX;
169  uint8_t columLow = _seg & 0x0F;
170  uint8_t columHigh = (_seg >> 4) & 0x0F;
171 
172  int _page = page;
173  if (dev->_flip)
174  {
175  _page = (dev->_pages - page) - 1;
176  }
177 
178  cmd = i2c_cmd_link_create();
179  i2c_master_start(cmd);
180  i2c_master_write_byte(cmd, (dev->_address << 1) | I2C_MASTER_WRITE, true);
181 
182  i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
183  // Set Lower Column Start Address for Page Addressing Mode
184  i2c_master_write_byte(cmd, (0x00 + columLow), true);
185  // Set Higher Column Start Address for Page Addressing Mode
186  i2c_master_write_byte(cmd, (0x10 + columHigh), true);
187  // Set Page Start Address for Page Addressing Mode
188  i2c_master_write_byte(cmd, 0xB0 | _page, true);
189 
190  i2c_master_stop(cmd);
191  i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS);
192  i2c_cmd_link_delete(cmd);
193 
194  cmd = i2c_cmd_link_create();
195  i2c_master_start(cmd);
196  i2c_master_write_byte(cmd, (dev->_address << 1) | I2C_MASTER_WRITE, true);
197 
198  i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_DATA_STREAM, true);
199  i2c_master_write(cmd, images, width, true);
200 
201  i2c_master_stop(cmd);
202  i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS);
203  i2c_cmd_link_delete(cmd);
204 }
205 
211 void i2c_contrast(SSD1306_t *dev, int contrast)
212 {
213  i2c_cmd_handle_t cmd;
214  int _contrast = contrast;
215  if (contrast < 0x0)
216  _contrast = 0;
217  if (contrast > 0xFF)
218  _contrast = 0xFF;
219 
220  cmd = i2c_cmd_link_create();
221  i2c_master_start(cmd);
222  i2c_master_write_byte(cmd, (dev->_address << 1) | I2C_MASTER_WRITE, true);
223  i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
224  i2c_master_write_byte(cmd, OLED_CMD_SET_CONTRAST, true); // 81
225  i2c_master_write_byte(cmd, _contrast, true);
226  i2c_master_stop(cmd);
227  i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS);
228  i2c_cmd_link_delete(cmd);
229 }
230 
237 {
238  esp_err_t espRc;
239 
240  i2c_cmd_handle_t cmd = i2c_cmd_link_create();
241  i2c_master_start(cmd);
242 
243  i2c_master_write_byte(cmd, (dev->_address << 1) | I2C_MASTER_WRITE, true);
244  i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
245 
246  if (scroll == SCROLL_RIGHT)
247  {
248  i2c_master_write_byte(cmd, OLED_CMD_HORIZONTAL_RIGHT, true); // 26
249  i2c_master_write_byte(cmd, 0x00, true); // Dummy byte
250  i2c_master_write_byte(cmd, 0x00, true); // Define start page address
251  i2c_master_write_byte(cmd, CONFIG_SSD1306_FRAME_FREQ, true); // Frame frequency
252  i2c_master_write_byte(cmd, 0x07, true); // Define end page address
253  i2c_master_write_byte(cmd, 0x00, true); //
254  i2c_master_write_byte(cmd, 0xFF, true); //
255  i2c_master_write_byte(cmd, OLED_CMD_ACTIVE_SCROLL, true); // 2F
256  }
257 
258  if (scroll == SCROLL_LEFT)
259  {
260  i2c_master_write_byte(cmd, OLED_CMD_HORIZONTAL_LEFT, true); // 27
261  i2c_master_write_byte(cmd, 0x00, true); // Dummy byte
262  i2c_master_write_byte(cmd, 0x00, true); // Define start page address
263  i2c_master_write_byte(cmd, CONFIG_SSD1306_FRAME_FREQ, true); // Frame frequency
264  i2c_master_write_byte(cmd, 0x07, true); // Define end page address
265  i2c_master_write_byte(cmd, 0x00, true); //
266  i2c_master_write_byte(cmd, 0xFF, true); //
267  i2c_master_write_byte(cmd, OLED_CMD_ACTIVE_SCROLL, true); // 2F
268  }
269 
270  if (scroll == SCROLL_DOWN)
271  {
272  i2c_master_write_byte(cmd, OLED_CMD_CONTINUOUS_SCROLL, true); // 29
273  i2c_master_write_byte(cmd, 0x00, true); // Dummy byte
274  i2c_master_write_byte(cmd, 0x00, true); // Define start page address
275  i2c_master_write_byte(cmd, CONFIG_SSD1306_FRAME_FREQ, true); // Frame frequency
276  //i2c_master_write_byte(cmd, 0x01, true); // Define end page address
277  i2c_master_write_byte(cmd, 0x00, true); // Define end page address
278  i2c_master_write_byte(cmd, 0x3F, true); // Vertical scrolling offset
279 
280  i2c_master_write_byte(cmd, OLED_CMD_VERTICAL, true); // A3
281  i2c_master_write_byte(cmd, 0x00, true);
282  if (dev->_height == 64)
283  //i2c_master_write_byte(cmd, 0x7F, true);
284  i2c_master_write_byte(cmd, 0x40, true);
285  if (dev->_height == 32)
286  i2c_master_write_byte(cmd, 0x20, true);
287  i2c_master_write_byte(cmd, OLED_CMD_ACTIVE_SCROLL, true); // 2F
288  }
289 
290  if (scroll == SCROLL_UP)
291  {
292  i2c_master_write_byte(cmd, OLED_CMD_CONTINUOUS_SCROLL, true); // 29
293  i2c_master_write_byte(cmd, 0x00, true); // Dummy byte
294  i2c_master_write_byte(cmd, 0x00, true); // Define start page address
295  i2c_master_write_byte(cmd, CONFIG_SSD1306_FRAME_FREQ, true); // Frame frequency
296  //i2c_master_write_byte(cmd, 0x01, true); // Define end page address
297  i2c_master_write_byte(cmd, 0x00, true); // Define end page address
298  i2c_master_write_byte(cmd, 0x01, true); // Vertical scrolling offset
299 
300  i2c_master_write_byte(cmd, OLED_CMD_VERTICAL, true); // A3
301  i2c_master_write_byte(cmd, 0x00, true);
302  if (dev->_height == 64)
303  //i2c_master_write_byte(cmd, 0x7F, true);
304  i2c_master_write_byte(cmd, 0x40, true);
305  if (dev->_height == 32)
306  i2c_master_write_byte(cmd, 0x20, true);
307  i2c_master_write_byte(cmd, OLED_CMD_ACTIVE_SCROLL, true); // 2F
308  }
309 
310  if (scroll == SCROLL_STOP)
311  {
312  i2c_master_write_byte(cmd, OLED_CMD_DEACTIVE_SCROLL, true); // 2E
313  }
314 
315  i2c_master_stop(cmd);
316  espRc = i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS);
317  if (espRc == ESP_OK)
318  {
319  ESP_LOGD(tag, "Scroll command succeeded");
320  }
321  else
322  {
323  ESP_LOGE(tag, "Scroll command failed. code: 0x%.2X", espRc);
324  }
325 
326  i2c_cmd_link_delete(cmd);
327 }
328 
336 {
337  esp_err_t espRc;
338 
339  i2c_cmd_handle_t cmd = i2c_cmd_link_create();
340  i2c_master_start(cmd);
341 
342  i2c_master_write_byte(cmd, (dev->_address << 1) | I2C_MASTER_WRITE, true);
343  i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
344 
345  if (scroll == SCROLL_RIGHT)
346  {
347  i2c_master_write_byte(cmd, OLED_CMD_HORIZONTAL_RIGHT, true); // 26
348  i2c_master_write_byte(cmd, 0x00, true); // Dummy byte
349  i2c_master_write_byte(cmd, page, true); // Define start page address
350  i2c_master_write_byte(cmd, CONFIG_SSD1306_FRAME_FREQ, true); // Frame frequency
351  i2c_master_write_byte(cmd, page, true); // Define end page address
352  i2c_master_write_byte(cmd, 0x00, true); //
353  i2c_master_write_byte(cmd, 0xFF, true); //
354  i2c_master_write_byte(cmd, OLED_CMD_ACTIVE_SCROLL, true); // 2F
355  }
356 
357  if (scroll == SCROLL_LEFT)
358  {
359  i2c_master_write_byte(cmd, OLED_CMD_HORIZONTAL_LEFT, true); // 27
360  i2c_master_write_byte(cmd, 0x00, true); // Dummy byte
361  i2c_master_write_byte(cmd, page, true); // Define start page address
362  i2c_master_write_byte(cmd, CONFIG_SSD1306_FRAME_FREQ, true); // Frame frequency
363  i2c_master_write_byte(cmd, page, true); // Define end page address
364  i2c_master_write_byte(cmd, 0x00, true); //
365  i2c_master_write_byte(cmd, 0xFF, true); //
366  i2c_master_write_byte(cmd, OLED_CMD_ACTIVE_SCROLL, true); // 2F
367  }
368 
369  if (scroll == SCROLL_STOP)
370  {
371  i2c_master_write_byte(cmd, OLED_CMD_DEACTIVE_SCROLL, true); // 2E
372  }
373 
374  i2c_master_stop(cmd);
375  espRc = i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS);
376  if (espRc == ESP_OK)
377  {
378  ESP_LOGD(tag, "Scroll command succeeded");
379  }
380  else
381  {
382  ESP_LOGE(tag, "Scroll command failed. code: 0x%.2X", espRc);
383  }
384 
385  i2c_cmd_link_delete(cmd);
386 }
SSD1306_t dev
device for oled
Definition: main.c:81
defininitions for setting up, interacting with and sending commands to an ssd1306 driven screen via i...
ssd1306_scroll_type_t
Definition: ssd1306.h:105
@ SCROLL_STOP
Definition: ssd1306.h:110
@ SCROLL_LEFT
Definition: ssd1306.h:107
@ SCROLL_DOWN
Definition: ssd1306.h:108
@ SCROLL_RIGHT
Definition: ssd1306.h:106
@ SCROLL_UP
Definition: ssd1306.h:109
#define OLED_CMD_SET_DISPLAY_OFFSET
Definition: ssd1306.h:81
#define OLED_CMD_ACTIVE_SCROLL
Definition: ssd1306.h:98
#define OLED_CMD_SET_CHARGE_PUMP
Definition: ssd1306.h:91
#define OLED_CMD_DISPLAY_ON
Definition: ssd1306.h:65
#define OLED_CMD_DISPLAY_OFF
Definition: ssd1306.h:64
#define OLED_CONTROL_BYTE_CMD_STREAM
Definition: ssd1306.h:54
#define OLED_CMD_SET_MUX_RATIO
Definition: ssd1306.h:79
#define OLED_CMD_DISPLAY_NORMAL
Definition: ssd1306.h:62
#define OLED_CMD_SET_SEGMENT_REMAP_0
Definition: ssd1306.h:77
#define OLED_CMD_SET_SEGMENT_REMAP_1
Definition: ssd1306.h:78
#define OLED_CMD_SET_COM_PIN_MAP
Definition: ssd1306.h:82
#define OLED_CMD_HORIZONTAL_LEFT
Definition: ssd1306.h:95
#define I2CAddress
Definition: ssd1306.h:101
#define OLED_CMD_SET_CONTRAST
Definition: ssd1306.h:59
#define OLED_CONTROL_BYTE_DATA_STREAM
Definition: ssd1306.h:56
#define OLED_CMD_SET_COM_SCAN_MODE
Definition: ssd1306.h:80
#define OLED_CMD_HORIZONTAL_RIGHT
Definition: ssd1306.h:94
#define OLED_CMD_SET_DISPLAY_CLK_DIV
Definition: ssd1306.h:86
#define OLED_CMD_SET_PAGE_ADDR_MODE
Definition: ssd1306.h:71
#define OLED_CMD_DISPLAY_RAM
Definition: ssd1306.h:60
#define OLED_CMD_DEACTIVE_SCROLL
Definition: ssd1306.h:97
#define OLED_CMD_VERTICAL
Definition: ssd1306.h:99
#define OLED_CMD_SET_VCOMH_DESELCT
Definition: ssd1306.h:88
#define OLED_CMD_SET_MEMORY_ADDR_MODE
Definition: ssd1306.h:68
#define OLED_CMD_CONTINUOUS_SCROLL
Definition: ssd1306.h:96
void i2c_contrast(SSD1306_t *dev, int contrast)
Definition: ssd1306_i2c.c:211
void i2c_master_init(SSD1306_t *dev, int16_t sda, int16_t scl, int16_t reset)
Definition: ssd1306_i2c.c:50
void i2c_init(SSD1306_t *dev, int width, int height)
Definition: ssd1306_i2c.c:80
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
#define tag
tag for logging library
Definition: ssd1306_i2c.c:41
int _address
Definition: ssd1306.h:122
int _pages
Definition: ssd1306.h:125
bool _flip
Definition: ssd1306.h:133
int _height
Definition: ssd1306.h:124
int _width
Definition: ssd1306.h:123