SSD1306 OLED display driver  1.7.20
This library is developed to control SSD1306/SSD1331/SSD1351/IL9163/PCD8554 RGB i2c/spi LED displays
platform.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_hal/io.h"
26 
27 #if defined(SSD1306_ESP_PLATFORM)
28 
29 #include "intf/ssd1306_interface.h"
30 
31 #include "freertos/FreeRTOS.h"
32 #include "freertos/task.h"
33 #include "driver/gpio.h"
34 
35 #if 1
36 // TODO: To complete support. Any help is welcome
37 int digitalRead(int pin) // digitalRead()
38 {
39  return gpio_get_level(pin);
40 }
41 
42 void digitalWrite(int pin, int level) // digitalWrite()
43 {
44  gpio_set_level(pin, level);
45 }
46 
47 void pinMode(int pin, int mode)
48 {
49  if (mode == INPUT)
50  gpio_set_direction(pin, GPIO_MODE_INPUT);
51  else if (mode == OUTPUT)
52  gpio_set_direction(pin, GPIO_MODE_OUTPUT);
53 }
54 
55 uint32_t millis(void)
56 {
57  return xTaskGetTickCount() * portTICK_PERIOD_MS;
58 }
59 
60 void delay(uint32_t ms) // delay()
61 {
62  vTaskDelay(ms / portTICK_PERIOD_MS);
63 }
64 
65 #endif
66 
68 // !!! PLATFORM I2C IMPLEMENTATION OPTIONAL !!!
69 #if defined(CONFIG_PLATFORM_I2C_AVAILABLE) && defined(CONFIG_PLATFORM_I2C_ENABLE)
70 
71 #include <stdio.h>
72 #include "driver/i2c.h"
73 
74 static uint8_t s_i2c_addr = 0x3C;
75 static int8_t s_bus_id;
76 
77 static i2c_cmd_handle_t s_cmd_handle;
78 
79 static void platform_i2c_start(void)
80 {
81  // ... Open i2c channel for your device with specific s_i2c_addr
82  s_cmd_handle = i2c_cmd_link_create();
83  i2c_master_start(s_cmd_handle);
84  i2c_master_write_byte(s_cmd_handle, ( s_i2c_addr << 1 ) | I2C_MASTER_WRITE, 0x1);
85 }
86 
87 static void platform_i2c_stop(void)
88 {
89  // ... Complete i2c communication
90  i2c_master_stop(s_cmd_handle);
91  /*esp_err_t ret =*/ i2c_master_cmd_begin(s_bus_id, s_cmd_handle, 1000 / portTICK_RATE_MS);
92  i2c_cmd_link_delete(s_cmd_handle);
93 }
94 
95 static void platform_i2c_send(uint8_t data)
96 {
97  // ... Send byte to i2c communication channel
98  i2c_master_write_byte(s_cmd_handle, data, 0x1);
99 }
100 
101 static void platform_i2c_close(void)
102 {
103  // ... free all i2c resources here
104  i2c_driver_delete(s_bus_id);
105 }
106 
107 static void platform_i2c_send_buffer(const uint8_t *data, uint16_t len)
108 {
109  // ... Send len bytes to i2c communication channel here
110  while (len--)
111  {
112  platform_i2c_send(*data);
113  data++;
114  }
115 // i2c_master_write(cmd, data_wr, size, ACK_CHECK_EN);
116 }
117 
118 void ssd1306_platform_i2cInit(int8_t busId, uint8_t addr, ssd1306_platform_i2cConfig_t * cfg)
119 {
120  if (addr) s_i2c_addr = addr;
121  ssd1306_intf.spi = 0;
122  ssd1306_intf.start = &platform_i2c_start;
123  ssd1306_intf.stop = &platform_i2c_stop;
124  ssd1306_intf.send = &platform_i2c_send;
125  ssd1306_intf.close = &platform_i2c_close;
126  ssd1306_intf.send_buffer = &platform_i2c_send_buffer;
127  // init your interface here
128  if ( busId < 0) busId = I2C_NUM_1;
129  s_bus_id = busId;
130  i2c_config_t conf;
131  conf.mode = I2C_MODE_MASTER;
132  conf.sda_io_num = cfg->sda >= 0 ? cfg->sda : 21;
133  conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
134  conf.scl_io_num = cfg->scl >= 0 ? cfg->scl : 22;
135  conf.scl_pullup_en = GPIO_PULLUP_ENABLE;
136  conf.master.clk_speed = 400000; //I2C_EXAMPLE_MASTER_FREQ_HZ;
137  i2c_param_config(s_bus_id, &conf);
138  i2c_driver_install(s_bus_id, conf.mode, 0, 0, 0);
139 // I2C_EXAMPLE_MASTER_RX_BUF_DISABLE,
140 // I2C_EXAMPLE_MASTER_TX_BUF_DISABLE, 0);
141 }
142 #endif
143 
145 // !!! PLATFORM SPI IMPLEMENTATION OPTIONAL !!!
146 #if defined(CONFIG_PLATFORM_SPI_AVAILABLE) && defined(CONFIG_PLATFORM_SPI_ENABLE)
147 
148 #include "intf/spi/ssd1306_spi.h"
149 #include "driver/spi_master.h"
150 
151 // Store spi handle globally for all spi callbacks
152 static spi_device_handle_t s_spi;
153 static int8_t s_spi_bus_id;
154 // s_first_spi_session is used for delayed spi initialization.
155 // Some oled displays have slow max SPI speed, so display init function can change
156 // spi frequency s_ssd1306_spi_clock. Register device, only when frequency is known.
157 static uint8_t s_first_spi_session = 0;
158 
159 static void platform_spi_start(void)
160 {
161  // ... Open spi channel for your device with specific s_ssd1306_cs, s_ssd1306_dc
162  if (s_first_spi_session)
163  {
164  spi_device_interface_config_t devcfg=
165  {
166  .clock_speed_hz = s_ssd1306_spi_clock,
167  .mode=0,
168  .spics_io_num=s_ssd1306_cs,
169  .queue_size=7, // max 7 transactions at a time
170  };
171  spi_bus_add_device(s_spi_bus_id ? VSPI_HOST : HSPI_HOST, &devcfg, &s_spi);
172  s_first_spi_session = 0;
173  }
174 }
175 
176 static void platform_spi_stop(void)
177 {
178  // ... Complete spi communication
179  // no complete actions required for this implementation
180 }
181 
182 static void platform_spi_send(uint8_t data)
183 {
184  // ... Send byte to spi communication channel
185  // We do not care here about DC line state, because
186  // ssd1306 library already set DC pin via ssd1306_spiDataMode() before call to send().
187  spi_transaction_t t;
188  memset(&t, 0, sizeof(t));
189  t.length = 8; // 8 bits
190  t.tx_buffer=&data;
191  spi_device_transmit(s_spi, &t); // Transmit!
192 }
193 
194 static void platform_spi_close(void)
195 {
196  // ... free all spi resources here
197  if (!s_first_spi_session)
198  {
199  spi_bus_remove_device( s_spi );
200  }
201  spi_bus_free( s_spi_bus_id ? VSPI_HOST : HSPI_HOST );
202 }
203 
204 static void platform_spi_send_buffer(const uint8_t *data, uint16_t len)
205 {
206  // ... Send len bytes to spi communication channel here
207  while (len)
208  {
209  size_t sz = len > 32 ? 32: len;
210  spi_transaction_t t;
211  memset(&t, 0, sizeof(t));
212  t.length=8*sz; // 8 bits
213  t.tx_buffer=data;
214  spi_device_transmit(s_spi, &t);
215  data+=sz;
216  len-=sz;
217  }
218 }
219 
220 void ssd1306_platform_spiInit(int8_t busId,
221  int8_t cesPin,
222  int8_t dcPin)
223 {
224  // Use VSPI by default
225  if (busId < 0) busId = 1;
226  s_spi_bus_id = busId;
227 
228  // If cesPin is not provided, select by default
229  if (cesPin < 0)
230  {
231  cesPin = s_spi_bus_id ? 5 : 15;
232  }
233  s_ssd1306_cs = cesPin;
234  if (dcPin>=0) s_ssd1306_dc = dcPin;
235 
236  if (cesPin >=0) pinMode(cesPin, OUTPUT);
237  if (dcPin >= 0) pinMode(dcPin, OUTPUT);
238 
239  ssd1306_intf.spi = 1;
240  ssd1306_intf.start = &platform_spi_start;
241  ssd1306_intf.stop = &platform_spi_stop;
242  ssd1306_intf.send = &platform_spi_send;
243  ssd1306_intf.close = &platform_spi_close;
244  ssd1306_intf.send_buffer = &platform_spi_send_buffer;
245 
246  // init your interface here
247  spi_bus_config_t buscfg=
248  {
249  .miso_io_num= s_spi_bus_id ? 19 : 12,
250  .mosi_io_num= s_spi_bus_id ? 23 : 13,
251  .sclk_io_num= s_spi_bus_id ? 18 : 14,
252  .quadwp_io_num=-1,
253  .quadhd_io_num=-1,
254  .max_transfer_sz=32
255  };
256  spi_bus_initialize(s_spi_bus_id ? VSPI_HOST : HSPI_HOST, &buscfg, 0); // 0 -no dma
257  s_first_spi_session = 1;
258 }
259 #endif
260 
261 #endif // SSD1306_ESP_PLATFORM
int8_t scl
clock pin number
Definition: io.h:82
int8_t s_ssd1306_dc
Definition: ssd1306_spi.c:34
void ssd1306_platform_spiInit(int8_t busId, int8_t cesPin, int8_t dcPin)
Initializes spi interface for platform being used.
void(* send)(uint8_t data)
uint32_t s_ssd1306_spi_clock
Definition: ssd1306_spi.c:35
void ssd1306_platform_i2cInit(int8_t busId, uint8_t addr, ssd1306_platform_i2cConfig_t *cfg)
Initializes i2c interface for platform being used.
void(* close)(void)
deinitializes internal resources, allocated for interface.
ssd1306_interface_t ssd1306_intf
int8_t sda
data pin number
Definition: io.h:81
void(* send_buffer)(const uint8_t *buffer, uint16_t size)
Sends bytes to SSD1306 device.
int8_t s_ssd1306_cs
Definition: ssd1306_spi.c:33