8000 Sun Feb 12 12:15:04 CST 2017 · mwerschy/esp32-snippets@7ddb504 · GitHub
[go: up one dir, main page]

Skip to content

Commit 7ddb504

Browse files
author
kolban
committed
Sun Feb 12 12:15:04 CST 2017
1 parent cb81167 commit 7ddb504

File tree

4 files changed

+376
-0
lines changed

4 files changed

+376
-0
lines changed

hardware/displays/U8G2/README.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#ESP32 U8G2 library support
2+
There is an excellent open source library called `u8g2` that can be found on Github here:
3+
4+
[https://github.com/olikraus/u8g2](https://github.com/olikraus/u8g2)
5+
6+
The purpose of the library is to provide a display independent driver layer for monochrome displays including LCD and OLED.
7+
The library "knows" how to driver the underlying displays as well as providing drawing primitives including text, fonts, lines and
8+
other geometrical shapes.
9+
10+
A version of the library is available in cleanly compiling C and compiles without incident on the ESP32-IDF framework.
11+
12+
However, since the library is agnostic of MCU environments and will work on a variety of boards, there has to be a mapping from
13+
the functions expected by the library and the underlying MCU board hardware. This includes driving GPIOs, I2C, SPI and more.
14+
15+
The code in this folder provides a mapping from U8g2 to the ESP32 ESP-IDF. This should be included in your build of U8g2 applications.
16+
17+
To use with the ESP32, we must invoke the `u8g2_esp32_hal_init()` function before invoking any of the normal U8g2 functons. What
18+
this call does is tell the ESP32 what pins we wish to map. Here is an example of use:
19+
20+
```
21+
u8g2_esp32_hal_t u8g2_esp32_hal = U8G2_ESP32_HAL_DEFAULT;
22+
u8g2_esp32_hal.clk = PIN_CLK;
23+
u8g2_esp32_hal.mosi = PIN_MOSI;
24+
u8g2_esp32_hal.cs = PIN_CS;
25+
u8g2_esp32_hal.dc = PIN_DC;
26+
u8g2_esp32_hal.reset = PIN_RESET;
27+
u8g2_esp32_hal_init(u8g2_esp32_hal);
28+
```
29+
30+
The function takes as input a `u8g2_esp32_hal` structure instance which has the logical pins that U8g2 needs mapped to the
31+
physical pin on the ESP32 that we wish to use. If we don't use a specific pin for our specific display, set the value to
32+
be `U8G2_ESP32_HAL_UNDEFINED` which is the default initialization value.
33+
34+
Remember, ESP32 pins are not hard-coded to functions and as such, all the GPIO pins on the ESP32 are open for use. Following
35+
this initialization, we can use U8g2 as normal and described in the U8g2 documentation.
36+
37+
##Compiling U8G2
38+
To use the actual U8g2 library in your ESP32 project, perform the following steps:
39+
40+
1. Create a directory called `components` in your main project directory.
41+
2. Change into the `components` directory.
42+
3. Run `git clone https://github.com/olikraus/u8g2.git` to bring in a the latest copy of u8g2 library.
43+
4. Change into the `u8g2` directory.
44+
5. Create a file called `component.mk`
45+
6. Enter the following in the `component.mk` file:
46+
```
47+
COMPONENT_SRCDIRS:=csrc
48+
COMPONENT_ADD_INCLUDEDIRS:=csrc
49+
```
50+
51+
52+
##Development
53+
While in principal, there should be nothing specific needed beyond this addition to make U8g2 work on the ESP32, only a small
54+
number of boards have been tested. In addition, currently only SPI displays have been tested. This will be remidied over time.

hardware/displays/U8G2/test_SSD1306.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#include <driver/gpio.h>
2+
#include <driver/spi_master.h>
3+
#include <esp_log.h>
4+
#include <freertos/FreeRTOS.h>
5+
#include <freertos/task.h>
6+
#include <stdio.h>
7+
#include <string.h>
8+
#include <u8g2.h>
9+
10+
#include "sdkconfig.h"
11+
#include "u8g2_esp32_hal.h"
12+
13+
// CLK - GPIO14
14+
#define PIN_CLK 14
15+
16+
// MOSI - GPIO 13
17+
#define PIN_MOSI 13
18+
19+
// RESET - GPIO 26
20+
#define PIN_RESET 26
21+
22+
// DC - GPIO 27
23+
#define PIN_DC 27
24+
25+
// CS - GPIO 15
26+
#define PIN_CS 15
27+
static char tag[] = "test_SSD1306";
28+
29+
void task_test_SSD1306(void *ignore) {
30+
u8g2_esp32_hal_t u8g2_esp32_hal = U8G2_ESP32_HAL_DEFAULT;
31+
u8g2_esp32_hal.clk = PIN_CLK;
32+
u8g2_esp32_hal.mosi = PIN_MOSI;
33+
u8g2_esp32_hal.cs = PIN_CS;
34+
u8g2_esp32_hal.dc = PIN_DC;
35+
u8g2_esp32_hal.reset = PIN_RESET;
36+
u8g2_esp32_hal_init(u8g2_esp32_hal);
37+
38+
39+
u8g2_t u8g2; // a structure which will contain all the data for one display
40+
u8g2_Setup_ssd1306_128x64_noname_f(
41+
&u8g2,
42+
U8G2_R0,
43+
u8g2_esp32_msg_comms_cb,
44+
u8g2_esp32_msg_gpio_and_delay_cb); // init u8g2 structure
45+
46+
u8g2_InitDisplay(&u8g2); // send init sequence to the display, display is in sleep mode after this,
47+
48+
u8g2_SetPowerSave(&u8g2, 0); // wake up display
49+
u8g2_ClearBuffer(&u8g2);
50+
u8g2_DrawBox(&u8g2, 10,20, 20, 30);
51+
u8g2_SetFont(&u8g2, u8g2_font_ncenB14_tr);
52+
u8g2_DrawStr(&u8g2, 0,15,"Hello World!");
53+
u8g2_SendBuffer(&u8g2);
54+
55+
ESP_LOGD(tag, "All done!");
56+
57+
vTaskDelete(NULL);
58+
}
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
#include <driver/gpio.h>
2+
#include <driver/spi_master.h>
3+
#include <esp_log.h>
4+
#include <freertos/FreeRTOS.h>
5+
#include <freertos/task.h>
6+
#include <stdio.h>
7+
#include <string.h>
8+
#include <u8g2.h>
9+
10+
#include "sdkconfig.h"
11+
#include "u8g2_esp32_hal.h"
12+
13+
//static char tag[] = "u8g2_esp32_hal";
14+
15+
static spi_device_handle_t handle; // SPI handle.
16+
static u8g2_esp32_hal_t u8g2_esp32_hal; // HAL state data.
17+
18+
/*
19+
* Initialze the ESP32 HAL.
20+
*/
21+
void u8g2_esp32_hal_init(u8g2_esp32_hal_t u8g2_esp32_hal_param) {
22+
u8g2_esp32_hal = u8g2_esp32_hal_param;
23+
} // u8g2_esp32_hal_init
24+
25+
26+
/*
27+
static char *bytesToString(int length, char *data) {
28+
static char ret[1024];
29+
strcpy(ret, "");
30+
int i;
31+
char temp[10];
32+
for (i=0; i<length; i++) {
33+
sprintf(temp, "%.2x ", data[i]);
34+
strcat(ret, temp);
35+
}
36+
return ret;
37+
}
38+
39+
40+
static char *msgToString(uint8_t msg, uint8_t arg_int, void *arg_ptr) {
41+
static char buf[1024];
42+
switch(msg)
43+
{
44+
case U8X8_MSG_GPIO_AND_DELAY_INIT: // called once during init phase of u8g2/u8x8
45+
return "U8X8_MSG_GPIO_AND_DELAY_INIT"; // can be used to setup pins
46+
47+
case U8X8_MSG_DELAY_NANO: // delay arg_int * 1 nano second
48+
sprintf(buf, "U8X8_MSG_DELAY_NANO: %d ns", arg_int);
49+
return buf;
50+
51+
case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
52+
return "U8X8_MSG_DELAY_100NANO";
53+
case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
54+
return "U8X8_MSG_DELAY_10MICRO";
55+
56+
case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
57+
sprintf(buf, "U8X8_MSG_DELAY_MILLI: %d ms", arg_int);
58+
return buf;
59+
60+
case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz
61+
return "U8X8_MSG_DELAY_I2C";
62+
break; // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us
63+
case U8X8_MSG_GPIO_D0: // D0 or SPI clock pin: Output level in arg_int
64+
//case U8X8_MSG_GPIO_SPI_CLOCK:
65+
return "U8X8_MSG_GPIO_D0";
66+
case U8X8_MSG_GPIO_D1: // D1 or SPI data pin: Output level in arg_int
67+
//case U8X8_MSG_GPIO_SPI_DATA:
68+
return "U8X8_MSG_GPIO_D1";
69+
case U8X8_MSG_GPIO_D2: // D2 pin: Output level in arg_int
70+
return "U8X8_MSG_GPIO_D2";
71+
case U8X8_MSG_GPIO_D3: // D3 pin: Output level in arg_int
72+
return "U8X8_MSG_GPIO_D3";
73+
case U8X8_MSG_GPIO_D4: // D4 pin: Output level in arg_int
74+
return "U8X8_MSG_GPIO_D4";
75+
case U8X8_MSG_GPIO_D5: // D5 pin: Output level in arg_int
76+
return "U8X8_MSG_GPIO_D5";
77+
case U8X8_MSG_GPIO_D6: // D6 pin: Output level in arg_int
78+
return "U8X8_MSG_GPIO_D6";
79+
case U8X8_MSG_GPIO_D7: // D7 pin: Output level in arg_int
80+
return "U8X8_MSG_GPIO_D7";
81+
case U8X8_MSG_GPIO_E: // E/WR pin: Output level in arg_int
82+
return "U8X8_MSG_GPIO_E";
83+
case U8X8_MSG_GPIO_CS: // CS (chip select) pin: Output level in arg_int
84+
return "U8X8_MSG_GPIO_CS";
85+
case U8X8_MSG_GPIO_DC: // DC (data/cmd, A0, register select) pin: Output level in arg_int
86+
return "U8X8_MSG_GPIO_DC";
87+
case U8X8_MSG_GPIO_RESET: // Reset pin: Output level in arg_int
88+
sprintf(buf, "U8X8_MSG_GPIO_RESET -> %d", arg_int);
89+
return buf;
90+
91+
case U8X8_MSG_GPIO_CS1: // CS1 (chip select) pin: Output level in arg_int
92+
return "U8X8_MSG_GPIO_CS1";
93+
case U8X8_MSG_GPIO_CS2: // CS2 (chip select) pin: Output level in arg_int
94+
return "U8X8_MSG_GPIO_CS2";
95+
case U8X8_MSG_GPIO_I2C_CLOCK: // arg_int=0: Output low at I2C clock pin
96+
return "U8X8_MSG_GPIO_I2C_CLOCK"; // arg_int=1: Input dir with pullup high for I2C clock pin
97+
case U8X8_MSG_GPIO_I2C_DATA: // arg_int=0: Output low at I2C data pin
98+
return "U8X8_MSG_GPIO_I2C_DATA"; // arg_int=1: Input dir with pullup high for I2C data pin
99+
case U8X8_MSG_GPIO_MENU_SELECT:
100+
return "U8X8_MSG_GPIO_MENU_SELECT";
101+
case U8X8_MSG_GPIO_MENU_NEXT:
102+
return "U8X8_MSG_GPIO_MENU_NEXT";
103+
case U8X8_MSG_GPIO_MENU_PREV:
104+
return "U8X8_MSG_GPIO_MENU_PREV";
105+
case U8X8_MSG_GPIO_MENU_HOME:
106+
return "U8X8_MSG_GPIO_MENU_HOME";
107+
case U8X8_MSG_BYTE_SEND:
108+
sprintf(buf, "U8X8_MSG_BYTE_SEND: length=%d %s", arg_int, bytesToString(arg_int, arg_ptr));
109+
return buf;
110+
case U8X8_MSG_BYTE_INIT:
111+
return "U8X8_MSG_BYTE_INIT";
112+
case U8X8_MSG_BYTE_END_TRANSFER:
113+
return "U8X8_MSG_BYTE_END_TRANSFER";
114+
case U8X8_MSG_BYTE_START_TRANSFER:
115+
return "U8X8_MSG_BYTE_START_TRANSFER";
116+
case U8X8_MSG_BYTE_SET_DC:
117+
sprintf(buf, "U8X8_MSG_BYTE_SET_DC -> %d", arg_int);
118+
return buf;
119+
default:
120+
return "Unknown";
121+
}
122+
}
123+
*/
124+
125+
126+
/*
127+
* HAL callback function as prescribed by the U8G2 library. This callback is invoked
128+
* to handle callbacks for communications.
129+
*/
130+
uint8_t u8g2_esp32_msg_comms_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) {
131+
//ESP_LOGD(tag, "msg_comms_cb: Received a msg: %d: %s", msg, msgToString(msg, arg_int, arg_ptr));
132+
switch(msg) {
133+
case U8X8_MSG_BYTE_SET_DC:
134+
if (u8g2_esp32_hal.dc != U8G2_ESP32_HAL_UNDEFINED) {
135+
gpio_set_level(u8g2_esp32_hal.dc, arg_int);
136+
}
137+
break;
138+
139+
case U8X8_MSG_BYTE_INIT: {
140+
if (u8g2_esp32_hal.clk == U8G2_ESP32_HAL_UNDEFINED ||
141+
u8g2_esp32_hal.mosi == U8G2_ESP32_HAL_UNDEFINED ||
142+
u8g2_esp32_hal.cs == U8G2_ESP32_HAL_UNDEFINED) {
143+
break;
144+
}
145+
146+
spi_bus_config_t bus_config;
147+
bus_config.sclk_io_num = u8g2_esp32_hal.clk; // CLK
148+
bus_config.mosi_io_num = u8g2_esp32_hal.mosi; // MOSI
149+
bus_config.miso_io_num = -1; // MISO
150+
bus_config.quadwp_io_num = -1; // Not used
151+
bus_config.quadhd_io_num = -1; // Not used
152+
//ESP_LOGI(tag, "... Initializing bus.");
153+
ESP_ERROR_CHECK(spi_bus_initialize(HSPI_HOST, &bus_config, 1));
154+
155+
156+
spi_device_interface_config_t dev_config;
157+
dev_config.address_bits = 0;
158+
dev_config.command_bits = 0;
159+
dev_config.dummy_bits = 0;
160+
dev_config.mode = 0;
161+
dev_config.duty_cycle_pos = 0;
162+
dev_config.cs_ena_posttrans = 0;
163+
dev_config.cs_ena_pretrans = 0;
164+
dev_config.clock_speed_hz = 10000;
165+
dev_config.spics_io_num = u8g2_esp32_hal.cs;
166+
dev_config.flags = 0;
167+
dev_config.queue_size = 200;
168+
dev_config.pre_cb = NULL;
169+
dev_config.post_cb = NULL;
170+
//ESP_LOGI(tag, "... Adding device bus.");
171+
ESP_ERROR_CHECK(spi_bus_add_device(HSPI_HOST, &dev_config, &handle));
172+
break;
173+
}
174+
175+
case U8X8_MSG_BYTE_SEND: {
176+
spi_transaction_t trans_desc;
177+
trans_desc.address = 0;
178+
trans_desc.command = 0;
179+
trans_desc.flags = 0;
180+
trans_desc.length = 8 * arg_int; // Number of bits NOT number of bytes.
181+
trans_desc.rxlength = 0;
182+
trans_desc.tx_buffer = arg_ptr;
183+
trans_desc.rx_buffer = NULL;
184+
185+
//ESP_LOGI(tag, "... Transmitting %d bytes.", arg_int);
186+
ESP_ERROR_CHECK(spi_device_transmit(handle, &trans_desc));
187+
break;
188+
}
189+
}
190+
return 0;
191+
} // u8g2_esp32_msg_comms_cb
192+
193+
194+
/*
195+
* HAL callback function as prescribed by the U8G2 library. This callback is invoked
196+
* to handle callbacks for GPIO and delay functions.
197+
*/
198+
uint8_t u8g2_esp32_msg_gpio_and_delay_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) {
199+
//ESP_LOGD(tag, "msg_gpio_and_delay_cb: Received a msg: %d: %s", msg, msgToString(msg, arg_int, arg_ptr));
200+
switch(msg) {
201+
202+
// Initialize the GPIO and DELAY HAL functions. If the pins for DC and RESET have been
203+
// specified then we define those pins as GPIO outputs.
204+
case U8X8_MSG_GPIO_AND_DELAY_INIT: {
205+
uint64_t bitmask = 0;
206+
if (u8g2_esp32_hal.dc != U8G2_ESP32_HAL_UNDEFINED) {
207+
bitmask = bitmask | (1<<u8g2_esp32_hal.dc);
208+
}
209+
if (u8g2_esp32_hal.reset != U8G2_ESP32_HAL_UNDEFINED) {
210+
bitmask = bitmask | (1<<u8g2_esp32_hal.reset);
211+
}
212+
213+
gpio_config_t gpioConfig;
214+
gpioConfig.pin_bit_mask = bitmask;
215+
gpioConfig.mode = GPIO_MODE_OUTPUT;
216+
gpioConfig.pull_up_en = GPIO_PULLUP_DISABLE;
217+
gpioConfig.pull_down_en = GPIO_PULLDOWN_ENABLE;
218+
gpioConfig.intr_type = GPIO_INTR_DISABLE;
219+
gpio_config(&gpioConfig);
220+
break;
221+
}
222+
223+
// Set the GPIO reset pin to the value passed in through arg_int.
224+
case U8X8_MSG_GPIO_RESET:
225+
if (u8g2_esp32_hal.reset != U8G2_ESP32_HAL_UNDEFINED) {
226+
gpio_set_level(u8g2_esp32_hal.reset, arg_int);
227+
}
228+
break;
229+
230+
// Delay for the number of milliseconds passed in through arg_int.
231+
case U8X8_MSG_DELAY_MILLI:
232+
vTaskDelay(arg_int/portTICK_PERIOD_MS);
233+
break;
234+
}
235+
return 0;
236+
} // u8g2_esp32_msg_gpio_and_delay_cb
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* u8g2_esp32_hal.h
3+
*
4+
* Created on: Feb 12, 2017
5+
* Author: kolban
6+
*/
7+
8+
#ifndef U8G2_ESP32_HAL_H_
9+
#define U8G2_ESP32_HAL_H_
10+
#include <driver/gpio.h>
11+
#include <u8g2.h>
12+
13+
#define U8G2_ESP32_HAL_UNDEFINED (-1)
14+
15+
typedef struct {
16+
gpio_num_t clk;
17+
gpio_num_t mosi;
18+
gpio_num_t cs;
19+
gpio_num_t reset;
20+
gpio_num_t dc;
21+
} u8g2_esp32_hal_t ;
22+
23+
#define U8G2_ESP32_HAL_DEFAULT {U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED, U8G2_ESP32_HAL_UNDEFINED }
24+
25+
void u8g2_esp32_hal_init(u8g2_esp32_hal_t u8g2_esp32_hal_param);
26+
uint8_t u8g2_esp32_msg_comms_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
27+
uint8_t u8g2_esp32_msg_gpio_and_delay_cb(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
28+
#endif /* U8G2_ESP32_HAL_H_ */

0 commit comments

Comments
 (0)
0