SSD1306 OLED display driver 1.7.8 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, int8_t arg)
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 = 21; // I2C_EXAMPLE_MASTER_SDA_IO;
133 conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
134 conf.scl_io_num = 22; // I2C_EXAMPLE_MASTER_SCL_IO;
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
ssd1306_platform_i2cInit
void ssd1306_platform_i2cInit(int8_t busId, uint8_t addr, int8_t arg)
Initializes i2c interface for platform being used.
s_ssd1306_dc
int8_t s_ssd1306_dc
Definition: ssd1306_spi.c:34
ssd1306_platform_spiInit
void ssd1306_platform_spiInit(int8_t busId, int8_t cesPin, int8_t dcPin)
Initializes spi interface for platform being used.
ssd1306_interface_t::send
void(* send)(uint8_t data)
Definition: ssd1306_interface.h:70
ssd1306_interface_t::stop
void(* stop)(void)
Definition: ssd1306_interface.h:65
s_ssd1306_spi_clock
uint32_t s_ssd1306_spi_clock
Definition: ssd1306_spi.c:35
io.h
ssd1306_spi.h
ssd1306_interface_t::start
void(* start)(void)
Definition: ssd1306_interface.h:61
ssd1306_interface_t::close
void(* close)(void)
deinitializes internal resources, allocated for interface.
Definition: ssd1306_interface.h:88
ssd1306_intf
ssd1306_interface_t ssd1306_intf
Definition: ssd1306_interface.c:29
ssd1306_interface.h
ssd1306_interface_t::spi
uint8_t spi
Definition: ssd1306_interface.h:57
ssd1306_interface_t::send_buffer
void(* send_buffer)(const uint8_t *buffer, uint16_t size)
Sends bytes to SSD1306 device.
Definition: ssd1306_interface.h:80
s_ssd1306_cs
int8_t s_ssd1306_cs
Definition: ssd1306_spi.c:33