mirror of
https://github.com/nopnop2002/esp-idf-ssd1306.git
synced 2024-10-03 18:18:47 -04:00
Added new i2c driver
This commit is contained in:
parent
78f3f5611a
commit
22097a5ec3
@ -14,6 +14,10 @@ ESP-IDF V5.1 is required when using i2c of ESP32C2.
|
||||
__Note for ESP32C6.__
|
||||
ESP-IDF V5.1 is required when using ESP32C6.
|
||||
|
||||
__Note for ESP-IDF V5.2.__
|
||||
A new i2c driver is now available in ESP-IDF V5.2.
|
||||
Under ESP-IDF V5.2 this project uses a new i2c driver.
|
||||
|
||||
# Installation
|
||||
|
||||
```
|
||||
|
@ -1,5 +1,12 @@
|
||||
set(component_srcs "ssd1306.c" "ssd1306_i2c.c" "ssd1306_spi.c")
|
||||
set(component_srcs "ssd1306.c" "ssd1306_spi.c")
|
||||
|
||||
idf_component_register(SRCS "${component_srcs}"
|
||||
PRIV_REQUIRES driver
|
||||
INCLUDE_DIRS ".")
|
||||
# get IDF version for comparison
|
||||
set(idf_version "${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}")
|
||||
|
||||
if(idf_version VERSION_GREATER_EQUAL "5.2")
|
||||
list(APPEND component_srcs "ssd1306_i2c_new.c")
|
||||
else()
|
||||
list(APPEND component_srcs "ssd1306_i2c_legacy.c")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "${component_srcs}" PRIV_REQUIRES driver INCLUDE_DIRS ".")
|
||||
|
@ -57,8 +57,7 @@ menu "SSD1306 Configuration"
|
||||
int "SCL GPIO number"
|
||||
range 0 GPIO_RANGE_MAX
|
||||
default 22 if IDF_TARGET_ESP32
|
||||
default 12 if IDF_TARGET_ESP32S2
|
||||
default 12 if IDF_TARGET_ESP32S3
|
||||
default 12 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
default 6 # C3 and others
|
||||
help
|
||||
GPIO number (IOxx) to I2C SCL.
|
||||
@ -70,8 +69,7 @@ menu "SSD1306 Configuration"
|
||||
int "SDA GPIO number"
|
||||
range 0 GPIO_RANGE_MAX
|
||||
default 21 if IDF_TARGET_ESP32
|
||||
default 11 if IDF_TARGET_ESP32S2
|
||||
default 11 if IDF_TARGET_ESP32S3
|
||||
default 11 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
default 5 # C3 and others
|
||||
help
|
||||
GPIO number (IOxx) to I2C SDA.
|
||||
@ -83,8 +81,7 @@ menu "SSD1306 Configuration"
|
||||
int "MOSI GPIO number"
|
||||
range 0 GPIO_RANGE_MAX
|
||||
default 23 if IDF_TARGET_ESP32
|
||||
default 35 if IDF_TARGET_ESP32S2
|
||||
default 35 if IDF_TARGET_ESP32S3
|
||||
default 35 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
default 1 # C3 and others
|
||||
help
|
||||
GPIO number (IOxx) to SPI MOSI.
|
||||
@ -97,8 +94,7 @@ menu "SSD1306 Configuration"
|
||||
int "SCLK GPIO number"
|
||||
range 0 GPIO_RANGE_MAX
|
||||
default 18 if IDF_TARGET_ESP32
|
||||
default 36 if IDF_TARGET_ESP32S2
|
||||
default 36 if IDF_TARGET_ESP32S3
|
||||
default 36 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
default 2 # C3 and others
|
||||
help
|
||||
GPIO number (IOxx) to SPI SCLK.
|
||||
@ -111,8 +107,7 @@ menu "SSD1306 Configuration"
|
||||
int "CS GPIO number"
|
||||
range 0 GPIO_RANGE_MAX
|
||||
default 5 if IDF_TARGET_ESP32
|
||||
default 34 if IDF_TARGET_ESP32S2
|
||||
default 34 if IDF_TARGET_ESP32S3
|
||||
default 34 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
default 10 # C3 and others
|
||||
help
|
||||
GPIO number (IOxx) to SPI CS.
|
||||
@ -124,8 +119,7 @@ menu "SSD1306 Configuration"
|
||||
int "DC GPIO number"
|
||||
range 0 GPIO_RANGE_MAX
|
||||
default 4 if IDF_TARGET_ESP32
|
||||
default 37 if IDF_TARGET_ESP32S2
|
||||
default 37 if IDF_TARGET_ESP32S3
|
||||
default 37 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
default 3 # C3 and others
|
||||
help
|
||||
GPIO number (IOxx) to SPI DC.
|
||||
@ -136,8 +130,7 @@ menu "SSD1306 Configuration"
|
||||
int "RESET GPIO number"
|
||||
range -1 GPIO_RANGE_MAX
|
||||
default 15 if IDF_TARGET_ESP32
|
||||
default 38 if IDF_TARGET_ESP32S2
|
||||
default 38 if IDF_TARGET_ESP32S3
|
||||
default 38 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
default 4 # C3 and others
|
||||
help
|
||||
GPIO number (IOxx) to RESET.
|
||||
@ -156,7 +149,7 @@ menu "SSD1306 Configuration"
|
||||
help
|
||||
Use I2C_PORT_0.
|
||||
config I2C_PORT_1
|
||||
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
depends on IDF_TARGET_ARCH_XTENSA
|
||||
bool "I2C_PORT_1"
|
||||
help
|
||||
Use I2C_PORT_1.
|
||||
@ -173,7 +166,7 @@ menu "SSD1306 Configuration"
|
||||
help
|
||||
Use SPI2_HOST. This is also called HSPI_HOST.
|
||||
config SPI3_HOST
|
||||
depends on IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
depends on IDF_TARGET_ARCH_XTENSA
|
||||
bool "SPI3_HOST"
|
||||
help
|
||||
USE SPI3_HOST. This is also called VSPI_HOST
|
||||
|
@ -19,7 +19,7 @@ typedef union out_column_t {
|
||||
|
||||
void ssd1306_init(SSD1306_t * dev, int width, int height)
|
||||
{
|
||||
if (dev->_address == SPIAddress) {
|
||||
if (dev->_address == SPI_ADDRESS) {
|
||||
spi_init(dev, width, height);
|
||||
} else {
|
||||
i2c_init(dev, width, height);
|
||||
@ -47,7 +47,7 @@ int ssd1306_get_pages(SSD1306_t * dev)
|
||||
|
||||
void ssd1306_show_buffer(SSD1306_t * dev)
|
||||
{
|
||||
if (dev->_address == SPIAddress) {
|
||||
if (dev->_address == SPI_ADDRESS) {
|
||||
for (int page=0; page<dev->_pages;page++) {
|
||||
spi_display_image(dev, page, 0, dev->_page[page]._segs, dev->_width);
|
||||
}
|
||||
@ -78,7 +78,7 @@ void ssd1306_get_buffer(SSD1306_t * dev, uint8_t * buffer)
|
||||
|
||||
void ssd1306_display_image(SSD1306_t * dev, int page, int seg, uint8_t * images, int width)
|
||||
{
|
||||
if (dev->_address == SPIAddress) {
|
||||
if (dev->_address == SPI_ADDRESS) {
|
||||
spi_display_image(dev, page, seg, images, width);
|
||||
} else {
|
||||
i2c_display_image(dev, page, seg, images, width);
|
||||
@ -101,7 +101,7 @@ void ssd1306_display_text(SSD1306_t * dev, int page, char * text, int text_len,
|
||||
if (dev->_flip) ssd1306_flip(image, 8);
|
||||
ssd1306_display_image(dev, page, seg, image, 8);
|
||||
#if 0
|
||||
if (dev->_address == SPIAddress) {
|
||||
if (dev->_address == SPI_ADDRESS) {
|
||||
spi_display_image(dev, page, seg, image, 8);
|
||||
} else {
|
||||
i2c_display_image(dev, page, seg, image, 8);
|
||||
@ -154,7 +154,7 @@ ssd1306_display_text_x3(SSD1306_t * dev, int page, char * text, int text_len, bo
|
||||
}
|
||||
if (invert) ssd1306_invert(image, 24);
|
||||
if (dev->_flip) ssd1306_flip(image, 24);
|
||||
if (dev->_address == SPIAddress) {
|
||||
if (dev->_address == SPI_ADDRESS) {
|
||||
spi_display_image(dev, page+yy, seg, image, 24);
|
||||
} else {
|
||||
i2c_display_image(dev, page+yy, seg, image, 24);
|
||||
@ -183,7 +183,7 @@ void ssd1306_clear_line(SSD1306_t * dev, int page, bool invert)
|
||||
|
||||
void ssd1306_contrast(SSD1306_t * dev, int contrast)
|
||||
{
|
||||
if (dev->_address == SPIAddress) {
|
||||
if (dev->_address == SPI_ADDRESS) {
|
||||
spi_contrast(dev, contrast);
|
||||
} else {
|
||||
i2c_contrast(dev, contrast);
|
||||
@ -213,7 +213,7 @@ void ssd1306_scroll_text(SSD1306_t * dev, char * text, int text_len, bool invert
|
||||
if (dev->_scEnable == false) return;
|
||||
|
||||
void (*func)(SSD1306_t * dev, int page, int seg, uint8_t * images, int width);
|
||||
if (dev->_address == SPIAddress) {
|
||||
if (dev->_address == SPI_ADDRESS) {
|
||||
func = spi_display_image;
|
||||
} else {
|
||||
func = i2c_display_image;
|
||||
@ -255,7 +255,7 @@ void ssd1306_scroll_clear(SSD1306_t * dev)
|
||||
|
||||
void ssd1306_hardware_scroll(SSD1306_t * dev, ssd1306_scroll_type_t scroll)
|
||||
{
|
||||
if (dev->_address == SPIAddress) {
|
||||
if (dev->_address == SPI_ADDRESS) {
|
||||
spi_hardware_scroll(dev, scroll);
|
||||
} else {
|
||||
i2c_hardware_scroll(dev, scroll);
|
||||
@ -399,7 +399,7 @@ void ssd1306_wrap_arround(SSD1306_t * dev, ssd1306_scroll_type_t scroll, int sta
|
||||
|
||||
if (delay >= 0) {
|
||||
for (int page=0;page<dev->_pages;page++) {
|
||||
if (dev->_address == SPIAddress) {
|
||||
if (dev->_address == SPI_ADDRESS) {
|
||||
spi_display_image(dev, page, 0, dev->_page[page]._segs, 128);
|
||||
} else {
|
||||
i2c_display_image(dev, page, 0, dev->_page[page]._segs, 128);
|
||||
@ -581,7 +581,7 @@ uint8_t ssd1306_rotate_byte(uint8_t ch1) {
|
||||
void ssd1306_fadeout(SSD1306_t * dev)
|
||||
{
|
||||
void (*func)(SSD1306_t * dev, int page, int seg, uint8_t * images, int width);
|
||||
if (dev->_address == SPIAddress) {
|
||||
if (dev->_address == SPI_ADDRESS) {
|
||||
func = spi_display_image;
|
||||
} else {
|
||||
func = i2c_display_image;
|
||||
|
@ -68,8 +68,8 @@ Usage:
|
||||
#define OLED_CMD_ACTIVE_SCROLL 0x2F
|
||||
#define OLED_CMD_VERTICAL 0xA3
|
||||
|
||||
#define I2CAddress 0x3C
|
||||
#define SPIAddress 0xFF
|
||||
#define I2C_ADDRESS 0x3C
|
||||
#define SPI_ADDRESS 0xFF
|
||||
|
||||
typedef enum {
|
||||
SCROLL_RIGHT = 1,
|
||||
|
@ -2,13 +2,13 @@
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "ssd1306.h"
|
||||
|
||||
#define tag "SSD1306"
|
||||
#define TAG "SSD1306"
|
||||
|
||||
#if CONFIG_I2C_PORT_0
|
||||
#define I2C_NUM I2C_NUM_0
|
||||
@ -18,10 +18,12 @@
|
||||
#define I2C_NUM I2C_NUM_0 // if spi is selected
|
||||
#endif
|
||||
|
||||
#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C clock of SSD1306 can run at 400 kHz max. */
|
||||
#define I2C_MASTER_FREQ_HZ 400000 // I2C clock of SSD1306 can run at 400 kHz max.
|
||||
#define I2C_TICKS_TO_WAIT 100 // Maximum ticks to wait before issuing a timeout.
|
||||
|
||||
void i2c_master_init(SSD1306_t * dev, int16_t sda, int16_t scl, int16_t reset)
|
||||
{
|
||||
ESP_LOGI(TAG, "Legacy i2c driver is used");
|
||||
i2c_config_t i2c_config = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = sda,
|
||||
@ -41,7 +43,7 @@ void i2c_master_init(SSD1306_t * dev, int16_t sda, int16_t scl, int16_t reset)
|
||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||
gpio_set_level(reset, 1);
|
||||
}
|
||||
dev->_address = I2CAddress;
|
||||
dev->_address = I2C_ADDRESS;
|
||||
dev->_flip = false;
|
||||
}
|
||||
|
||||
@ -56,19 +58,19 @@ void i2c_init(SSD1306_t * dev, int width, int height) {
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (dev->_address << 1) | I2C_MASTER_WRITE, true);
|
||||
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
|
||||
i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_OFF, true); // AE
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_MUX_RATIO, true); // A8
|
||||
i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_OFF, true); // AE
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_MUX_RATIO, true); // A8
|
||||
if (dev->_height == 64) i2c_master_write_byte(cmd, 0x3F, true);
|
||||
if (dev->_height == 32) i2c_master_write_byte(cmd, 0x1F, true);
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_DISPLAY_OFFSET, true); // D3
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_DISPLAY_OFFSET, true); // D3
|
||||
i2c_master_write_byte(cmd, 0x00, true);
|
||||
//i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_DATA_STREAM, true); // 40
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_DISPLAY_START_LINE, true); // 40
|
||||
//i2c_master_write_byte(cmd, OLED_CMD_SET_SEGMENT_REMAP, true); // A1
|
||||
if (dev->_flip) {
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_SEGMENT_REMAP_0, true); // A0
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_SEGMENT_REMAP_0, true); // A0
|
||||
} else {
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_SEGMENT_REMAP_1, true); // A1
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_SEGMENT_REMAP_1, true); // A1
|
||||
}
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_COM_SCAN_MODE, true); // C8
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_DISPLAY_CLK_DIV, true); // D5
|
||||
@ -96,19 +98,17 @@ void i2c_init(SSD1306_t * dev, int width, int height) {
|
||||
|
||||
i2c_master_stop(cmd);
|
||||
|
||||
esp_err_t espRc = i2c_master_cmd_begin(I2C_NUM, cmd, 10/portTICK_PERIOD_MS);
|
||||
if (espRc == ESP_OK) {
|
||||
ESP_LOGI(tag, "OLED configured successfully");
|
||||
esp_err_t res = i2c_master_cmd_begin(I2C_NUM, cmd, I2C_TICKS_TO_WAIT);
|
||||
if (res == ESP_OK) {
|
||||
ESP_LOGI(TAG, "OLED configured successfully");
|
||||
} else {
|
||||
ESP_LOGE(tag, "OLED configuration failed. code: 0x%.2X", espRc);
|
||||
ESP_LOGE(TAG, "OLED configuration failed. code: 0x%.2X", res);
|
||||
}
|
||||
i2c_cmd_link_delete(cmd);
|
||||
}
|
||||
|
||||
|
||||
void i2c_display_image(SSD1306_t * dev, int page, int seg, uint8_t * images, int width) {
|
||||
i2c_cmd_handle_t cmd;
|
||||
|
||||
if (page >= dev->_pages) return;
|
||||
if (seg >= dev->_width) return;
|
||||
|
||||
@ -121,7 +121,7 @@ void i2c_display_image(SSD1306_t * dev, int page, int seg, uint8_t * images, int
|
||||
_page = (dev->_pages - page) - 1;
|
||||
}
|
||||
|
||||
cmd = i2c_cmd_link_create();
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (dev->_address << 1) | I2C_MASTER_WRITE, true);
|
||||
|
||||
@ -134,72 +134,78 @@ void i2c_display_image(SSD1306_t * dev, int page, int seg, uint8_t * images, int
|
||||
i2c_master_write_byte(cmd, 0xB0 | _page, true);
|
||||
|
||||
i2c_master_stop(cmd);
|
||||
i2c_master_cmd_begin(I2C_NUM, cmd, 10/portTICK_PERIOD_MS);
|
||||
esp_err_t res = i2c_master_cmd_begin(I2C_NUM, cmd, I2C_TICKS_TO_WAIT);
|
||||
if (res != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Scroll command failed. code: 0x%.2X", res);
|
||||
}
|
||||
i2c_cmd_link_delete(cmd);
|
||||
|
||||
cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (dev->_address << 1) | I2C_MASTER_WRITE, true);
|
||||
|
||||
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_DATA_STREAM, true);
|
||||
i2c_master_write(cmd, images, width, true);
|
||||
|
||||
i2c_master_stop(cmd);
|
||||
i2c_master_cmd_begin(I2C_NUM, cmd, 10/portTICK_PERIOD_MS);
|
||||
|
||||
res = i2c_master_cmd_begin(I2C_NUM, cmd, I2C_TICKS_TO_WAIT);
|
||||
if (res != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Scroll command failed. code: 0x%.2X", res);
|
||||
}
|
||||
i2c_cmd_link_delete(cmd);
|
||||
}
|
||||
|
||||
void i2c_contrast(SSD1306_t * dev, int contrast) {
|
||||
i2c_cmd_handle_t cmd;
|
||||
int _contrast = contrast;
|
||||
if (contrast < 0x0) _contrast = 0;
|
||||
if (contrast > 0xFF) _contrast = 0xFF;
|
||||
|
||||
cmd = i2c_cmd_link_create();
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, (dev->_address << 1) | I2C_MASTER_WRITE, true);
|
||||
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_CONTRAST, true); // 81
|
||||
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true); // 00
|
||||
i2c_master_write_byte(cmd, OLED_CMD_SET_CONTRAST, true); // 81
|
||||
i2c_master_write_byte(cmd, _contrast, true);
|
||||
i2c_master_stop(cmd);
|
||||
i2c_master_cmd_begin(I2C_NUM, cmd, 10/portTICK_PERIOD_MS);
|
||||
|
||||
esp_err_t res = i2c_master_cmd_begin(I2C_NUM, cmd, I2C_TICKS_TO_WAIT);
|
||||
if (res != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Scroll command failed. code: 0x%.2X", res);
|
||||
}
|
||||
i2c_cmd_link_delete(cmd);
|
||||
}
|
||||
|
||||
|
||||
void i2c_hardware_scroll(SSD1306_t * dev, ssd1306_scroll_type_t scroll) {
|
||||
esp_err_t espRc;
|
||||
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
|
||||
i2c_master_write_byte(cmd, (dev->_address << 1) | I2C_MASTER_WRITE, true);
|
||||
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
|
||||
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true); // 00
|
||||
|
||||
if (scroll == SCROLL_RIGHT) {
|
||||
i2c_master_write_byte(cmd, OLED_CMD_HORIZONTAL_RIGHT, true); // 26
|
||||
i2c_master_write_byte(cmd, OLED_CMD_HORIZONTAL_RIGHT, true); // 26
|
||||
i2c_master_write_byte(cmd, 0x00, true); // Dummy byte
|
||||
i2c_master_write_byte(cmd, 0x00, true); // Define start page address
|
||||
i2c_master_write_byte(cmd, 0x07, true); // Frame frequency
|
||||
i2c_master_write_byte(cmd, 0x07, true); // Define end page address
|
||||
i2c_master_write_byte(cmd, 0x00, true); //
|
||||
i2c_master_write_byte(cmd, 0xFF, true); //
|
||||
i2c_master_write_byte(cmd, OLED_CMD_ACTIVE_SCROLL, true); // 2F
|
||||
i2c_master_write_byte(cmd, OLED_CMD_ACTIVE_SCROLL, true); // 2F
|
||||
}
|
||||
|
||||
if (scroll == SCROLL_LEFT) {
|
||||
i2c_master_write_byte(cmd, OLED_CMD_HORIZONTAL_LEFT, true); // 27
|
||||
i2c_master_write_byte(cmd, OLED_CMD_HORIZONTAL_LEFT, true); // 27
|
||||
i2c_master_write_byte(cmd, 0x00, true); // Dummy byte
|
||||
i2c_master_write_byte(cmd, 0x00, true); // Define start page address
|
||||
i2c_master_write_byte(cmd, 0x07, true); // Frame frequency
|
||||
i2c_master_write_byte(cmd, 0x07, true); // Define end page address
|
||||
i2c_master_write_byte(cmd, 0x00, true); //
|
||||
i2c_master_write_byte(cmd, 0xFF, true); //
|
||||
i2c_master_write_byte(cmd, OLED_CMD_ACTIVE_SCROLL, true); // 2F
|
||||
i2c_master_write_byte(cmd, OLED_CMD_ACTIVE_SCROLL, true); // 2F
|
||||
}
|
||||
|
||||
if (scroll == SCROLL_DOWN) {
|
||||
i2c_master_write_byte(cmd, OLED_CMD_CONTINUOUS_SCROLL, true); // 29
|
||||
i2c_master_write_byte(cmd, OLED_CMD_CONTINUOUS_SCROLL, true); // 29
|
||||
i2c_master_write_byte(cmd, 0x00, true); // Dummy byte
|
||||
i2c_master_write_byte(cmd, 0x00, true); // Define start page address
|
||||
i2c_master_write_byte(cmd, 0x07, true); // Frame frequency
|
||||
@ -207,18 +213,18 @@ void i2c_hardware_scroll(SSD1306_t * dev, ssd1306_scroll_type_t scroll) {
|
||||
i2c_master_write_byte(cmd, 0x00, true); // Define end page address
|
||||
i2c_master_write_byte(cmd, 0x3F, true); // Vertical scrolling offset
|
||||
|
||||
i2c_master_write_byte(cmd, OLED_CMD_VERTICAL, true); // A3
|
||||
i2c_master_write_byte(cmd, OLED_CMD_VERTICAL, true); // A3
|
||||
i2c_master_write_byte(cmd, 0x00, true);
|
||||
if (dev->_height == 64)
|
||||
//i2c_master_write_byte(cmd, 0x7F, true);
|
||||
i2c_master_write_byte(cmd, 0x40, true);
|
||||
if (dev->_height == 32)
|
||||
i2c_master_write_byte(cmd, 0x20, true);
|
||||
i2c_master_write_byte(cmd, OLED_CMD_ACTIVE_SCROLL, true); // 2F
|
||||
i2c_master_write_byte(cmd, OLED_CMD_ACTIVE_SCROLL, true); // 2F
|
||||
}
|
||||
|
||||
if (scroll == SCROLL_UP) {
|
||||
i2c_master_write_byte(cmd, OLED_CMD_CONTINUOUS_SCROLL, true); // 29
|
||||
i2c_master_write_byte(cmd, OLED_CMD_CONTINUOUS_SCROLL, true); // 29
|
||||
i2c_master_write_byte(cmd, 0x00, true); // Dummy byte
|
||||
i2c_master_write_byte(cmd, 0x00, true); // Define start page address
|
||||
i2c_master_write_byte(cmd, 0x07, true); // Frame frequency
|
||||
@ -226,28 +232,26 @@ void i2c_hardware_scroll(SSD1306_t * dev, ssd1306_scroll_type_t scroll) {
|
||||
i2c_master_write_byte(cmd, 0x00, true); // Define end page address
|
||||
i2c_master_write_byte(cmd, 0x01, true); // Vertical scrolling offset
|
||||
|
||||
i2c_master_write_byte(cmd, OLED_CMD_VERTICAL, true); // A3
|
||||
i2c_master_write_byte(cmd, OLED_CMD_VERTICAL, true); // A3
|
||||
i2c_master_write_byte(cmd, 0x00, true);
|
||||
if (dev->_height == 64)
|
||||
//i2c_master_write_byte(cmd, 0x7F, true);
|
||||
i2c_master_write_byte(cmd, 0x40, true);
|
||||
if (dev->_height == 32)
|
||||
i2c_master_write_byte(cmd, 0x20, true);
|
||||
i2c_master_write_byte(cmd, OLED_CMD_ACTIVE_SCROLL, true); // 2F
|
||||
i2c_master_write_byte(cmd, OLED_CMD_ACTIVE_SCROLL, true); // 2F
|
||||
}
|
||||
|
||||
if (scroll == SCROLL_STOP) {
|
||||
i2c_master_write_byte(cmd, OLED_CMD_DEACTIVE_SCROLL, true); // 2E
|
||||
i2c_master_write_byte(cmd, OLED_CMD_DEACTIVE_SCROLL, true); // 2E
|
||||
}
|
||||
|
||||
i2c_master_stop(cmd);
|
||||
espRc = i2c_master_cmd_begin(I2C_NUM, cmd, 10/portTICK_PERIOD_MS);
|
||||
if (espRc == ESP_OK) {
|
||||
ESP_LOGD(tag, "Scroll command succeeded");
|
||||
} else {
|
||||
ESP_LOGE(tag, "Scroll command failed. code: 0x%.2X", espRc);
|
||||
}
|
||||
|
||||
esp_err_t res = i2c_master_cmd_begin(I2C_NUM, cmd, I2C_TICKS_TO_WAIT);
|
||||
if (res != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Scroll command failed. code: 0x%.2X", res);
|
||||
}
|
||||
i2c_cmd_link_delete(cmd);
|
||||
}
|
||||
|
262
components/ssd1306/ssd1306_i2c_new.c
Normal file
262
components/ssd1306/ssd1306_i2c_new.c
Normal file
@ -0,0 +1,262 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c_master.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "ssd1306.h"
|
||||
|
||||
#define TAG "SSD1306"
|
||||
|
||||
#if CONFIG_I2C_PORT_0
|
||||
#define I2C_NUM I2C_NUM_0
|
||||
#elif CONFIG_I2C_PORT_1
|
||||
#define I2C_NUM I2C_NUM_1
|
||||
#else
|
||||
#define I2C_NUM I2C_NUM_0 // if spi is selected
|
||||
#endif
|
||||
|
||||
#define I2C_MASTER_FREQ_HZ 400000 // I2C clock of SSD1306 can run at 400 kHz max.
|
||||
#define I2C_TICKS_TO_WAIT 100 // Maximum ticks to wait before issuing a timeout.
|
||||
|
||||
i2c_master_dev_handle_t dev_handle;
|
||||
|
||||
void i2c_master_init(SSD1306_t * dev, int16_t sda, int16_t scl, int16_t reset)
|
||||
{
|
||||
ESP_LOGI(TAG, "New i2c driver is used");
|
||||
i2c_master_bus_config_t i2c_mst_config = {
|
||||
.clk_source = I2C_CLK_SRC_DEFAULT,
|
||||
.glitch_ignore_cnt = 7,
|
||||
.i2c_port = I2C_NUM,
|
||||
.scl_io_num = scl,
|
||||
.sda_io_num = sda,
|
||||
.flags.enable_internal_pullup = true,
|
||||
};
|
||||
i2c_master_bus_handle_t bus_handle;
|
||||
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_config, &bus_handle));
|
||||
|
||||
i2c_device_config_t dev_cfg = {
|
||||
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
|
||||
.device_address = I2C_ADDRESS,
|
||||
.scl_speed_hz = I2C_MASTER_FREQ_HZ,
|
||||
};
|
||||
//i2c_master_dev_handle_t dev_handle;
|
||||
ESP_ERROR_CHECK(i2c_master_bus_add_device(bus_handle, &dev_cfg, &dev_handle));
|
||||
|
||||
#if 0
|
||||
i2c_config_t i2c_config = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = sda,
|
||||
.scl_io_num = scl,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = I2C_MASTER_FREQ_HZ
|
||||
};
|
||||
ESP_ERROR_CHECK(i2c_param_config(I2C_NUM, &i2c_config));
|
||||
ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM, I2C_MODE_MASTER, 0, 0, 0));
|
||||
#endif
|
||||
|
||||
if (reset >= 0) {
|
||||
//gpio_pad_select_gpio(reset);
|
||||
gpio_reset_pin(reset);
|
||||
gpio_set_direction(reset, GPIO_MODE_OUTPUT);
|
||||
gpio_set_level(reset, 0);
|
||||
vTaskDelay(50 / portTICK_PERIOD_MS);
|
||||
gpio_set_level(reset, 1);
|
||||
}
|
||||
dev->_address = I2C_ADDRESS;
|
||||
dev->_flip = false;
|
||||
}
|
||||
|
||||
void i2c_init(SSD1306_t * dev, int width, int height) {
|
||||
dev->_width = width;
|
||||
dev->_height = height;
|
||||
dev->_pages = 8;
|
||||
if (dev->_height == 32) dev->_pages = 4;
|
||||
|
||||
uint8_t out_buf[27];
|
||||
int out_index = 0;
|
||||
out_buf[out_index++] = OLED_CONTROL_BYTE_CMD_STREAM;
|
||||
out_buf[out_index++] = OLED_CMD_DISPLAY_OFF; // AE
|
||||
out_buf[out_index++] = OLED_CMD_SET_MUX_RATIO; // A8
|
||||
if (dev->_height == 64) out_buf[out_index++] = 0x3F;
|
||||
if (dev->_height == 32) out_buf[out_index++] = 0x1F;
|
||||
out_buf[out_index++] = OLED_CMD_SET_DISPLAY_OFFSET; // D3
|
||||
out_buf[out_index++] = 0x00;
|
||||
//out_buf[out_index++] = OLED_CONTROL_BYTE_DATA_STREAM; // 40
|
||||
out_buf[out_index++] = OLED_CMD_SET_DISPLAY_START_LINE; // 40
|
||||
//out_buf[out_index++] = OLED_CMD_SET_SEGMENT_REMAP; // A1
|
||||
if (dev->_flip) {
|
||||
out_buf[out_index++] = OLED_CMD_SET_SEGMENT_REMAP_0; // A0
|
||||
} else {
|
||||
out_buf[out_index++] = OLED_CMD_SET_SEGMENT_REMAP_1; // A1
|
||||
}
|
||||
out_buf[out_index++] = OLED_CMD_SET_COM_SCAN_MODE; // C8
|
||||
out_buf[out_index++] = OLED_CMD_SET_DISPLAY_CLK_DIV; // D5
|
||||
out_buf[out_index++] = 0x80;
|
||||
out_buf[out_index++] = OLED_CMD_SET_COM_PIN_MAP; // DA
|
||||
if (dev->_height == 64) out_buf[out_index++] = 0x12;
|
||||
if (dev->_height == 32) out_buf[out_index++] = 0x02;
|
||||
out_buf[out_index++] = OLED_CMD_SET_CONTRAST; // 81
|
||||
out_buf[out_index++] = 0xFF;
|
||||
out_buf[out_index++] = OLED_CMD_DISPLAY_RAM; // A4
|
||||
out_buf[out_index++] = OLED_CMD_SET_VCOMH_DESELCT; // DB
|
||||
out_buf[out_index++] = 0x40;
|
||||
out_buf[out_index++] = OLED_CMD_SET_MEMORY_ADDR_MODE; // 20
|
||||
//out_buf[out_index++] = OLED_CMD_SET_HORI_ADDR_MODE; // 00
|
||||
out_buf[out_index++] = OLED_CMD_SET_PAGE_ADDR_MODE; // 02
|
||||
// Set Lower Column Start Address for Page Addressing Mode
|
||||
out_buf[out_index++] = 0x00;
|
||||
// Set Higher Column Start Address for Page Addressing Mode
|
||||
out_buf[out_index++] = 0x10;
|
||||
out_buf[out_index++] = OLED_CMD_SET_CHARGE_PUMP; // 8D
|
||||
out_buf[out_index++] = 0x14;
|
||||
out_buf[out_index++] = OLED_CMD_DEACTIVE_SCROLL; // 2E
|
||||
out_buf[out_index++] = OLED_CMD_DISPLAY_NORMAL; // A6
|
||||
out_buf[out_index++] = OLED_CMD_DISPLAY_ON; // AF
|
||||
|
||||
esp_err_t res;
|
||||
res = i2c_master_transmit(dev_handle, out_buf, out_index, I2C_TICKS_TO_WAIT);
|
||||
if (res == ESP_OK) {
|
||||
ESP_LOGI(TAG, "OLED configured successfully");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Could not write to device [0x%02x at %d]: %d (%s)", dev->_address, I2C_NUM, res, esp_err_to_name(res));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void i2c_display_image(SSD1306_t * dev, int page, int seg, uint8_t * images, int width) {
|
||||
if (page >= dev->_pages) return;
|
||||
if (seg >= dev->_width) return;
|
||||
|
||||
int _seg = seg + CONFIG_OFFSETX;
|
||||
uint8_t columLow = _seg & 0x0F;
|
||||
uint8_t columHigh = (_seg >> 4) & 0x0F;
|
||||
|
||||
int _page = page;
|
||||
if (dev->_flip) {
|
||||
_page = (dev->_pages - page) - 1;
|
||||
}
|
||||
|
||||
uint8_t *out_buf;
|
||||
out_buf = malloc(width + 1);
|
||||
if (out_buf == NULL) {
|
||||
ESP_LOGE(TAG, "malloc fail");
|
||||
return;
|
||||
}
|
||||
int out_index = 0;
|
||||
out_buf[out_index++] = OLED_CONTROL_BYTE_CMD_STREAM;
|
||||
// Set Lower Column Start Address for Page Addressing Mode
|
||||
out_buf[out_index++] = (0x00 + columLow);
|
||||
// Set Higher Column Start Address for Page Addressing Mode
|
||||
out_buf[out_index++] = (0x10 + columHigh);
|
||||
// Set Page Start Address for Page Addressing Mode
|
||||
out_buf[out_index++] = 0xB0 | _page;
|
||||
|
||||
esp_err_t res;
|
||||
res = i2c_master_transmit(dev_handle, out_buf, out_index, I2C_TICKS_TO_WAIT);
|
||||
if (res != ESP_OK)
|
||||
ESP_LOGE(TAG, "Could not write to device [0x%02x at %d]: %d (%s)", dev->_address, I2C_NUM, res, esp_err_to_name(res));
|
||||
|
||||
out_buf[0] = OLED_CONTROL_BYTE_DATA_STREAM;
|
||||
memcpy(&out_buf[1], images, width);
|
||||
|
||||
res = i2c_master_transmit(dev_handle, out_buf, width + 1, I2C_TICKS_TO_WAIT);
|
||||
if (res != ESP_OK)
|
||||
ESP_LOGE(TAG, "Could not write to device [0x%02x at %d]: %d (%s)", dev->_address, I2C_NUM, res, esp_err_to_name(res));
|
||||
free(out_buf);
|
||||
}
|
||||
|
||||
void i2c_contrast(SSD1306_t * dev, int contrast) {
|
||||
uint8_t _contrast = contrast;
|
||||
if (contrast < 0x0) _contrast = 0;
|
||||
if (contrast > 0xFF) _contrast = 0xFF;
|
||||
|
||||
uint8_t out_buf[3];
|
||||
int out_index = 0;
|
||||
out_buf[out_index++] = OLED_CONTROL_BYTE_CMD_STREAM; // 00
|
||||
out_buf[out_index++] = OLED_CMD_SET_CONTRAST; // 81
|
||||
out_buf[out_index++] = _contrast;
|
||||
|
||||
esp_err_t res = i2c_master_transmit(dev_handle, out_buf, 3, I2C_TICKS_TO_WAIT);
|
||||
if (res != ESP_OK)
|
||||
ESP_LOGE(TAG, "Could not write to device [0x%02x at %d]: %d (%s)", dev->_address, I2C_NUM, res, esp_err_to_name(res));
|
||||
}
|
||||
|
||||
|
||||
void i2c_hardware_scroll(SSD1306_t * dev, ssd1306_scroll_type_t scroll) {
|
||||
uint8_t out_buf[11];
|
||||
int out_index = 0;
|
||||
out_buf[out_index++] = OLED_CONTROL_BYTE_CMD_STREAM; // 00
|
||||
|
||||
if (scroll == SCROLL_RIGHT) {
|
||||
out_buf[out_index++] = OLED_CMD_HORIZONTAL_RIGHT; // 26
|
||||
out_buf[out_index++] = 0x00; // Dummy byte
|
||||
out_buf[out_index++] = 0x00; // Define start page address
|
||||
out_buf[out_index++] = 0x07; // Frame frequency
|
||||
out_buf[out_index++] = 0x07; // Define end page address
|
||||
out_buf[out_index++] = 0x00; //
|
||||
out_buf[out_index++] = 0xFF; //
|
||||
out_buf[out_index++] = OLED_CMD_ACTIVE_SCROLL; // 2F
|
||||
}
|
||||
|
||||
if (scroll == SCROLL_LEFT) {
|
||||
out_buf[out_index++] = OLED_CMD_HORIZONTAL_LEFT; // 27
|
||||
out_buf[out_index++] = 0x00; // Dummy byte
|
||||
out_buf[out_index++] = 0x00; // Define start page address
|
||||
out_buf[out_index++] = 0x07; // Frame frequency
|
||||
out_buf[out_index++] = 0x07; // Define end page address
|
||||
out_buf[out_index++] = 0x00; //
|
||||
out_buf[out_index++] = 0xFF; //
|
||||
out_buf[out_index++] = OLED_CMD_ACTIVE_SCROLL; // 2F
|
||||
}
|
||||
|
||||
if (scroll == SCROLL_DOWN) {
|
||||
out_buf[out_index++] = OLED_CMD_CONTINUOUS_SCROLL; // 29
|
||||
out_buf[out_index++] = 0x00; // Dummy byte
|
||||
out_buf[out_index++] = 0x00; // Define start page address
|
||||
out_buf[out_index++] = 0x07; // Frame frequency
|
||||
//out_buf[out_index++] = 0x01; // Define end page address
|
||||
out_buf[out_index++] = 0x00; // Define end page address
|
||||
out_buf[out_index++] = 0x3F; // Vertical scrolling offset
|
||||
|
||||
out_buf[out_index++] = OLED_CMD_VERTICAL; // A3
|
||||
out_buf[out_index++] = 0x00;
|
||||
if (dev->_height == 64)
|
||||
//out_buf[out_index++] = 0x7F;
|
||||
out_buf[out_index++] = 0x40;
|
||||
if (dev->_height == 32)
|
||||
out_buf[out_index++] = 0x20;
|
||||
out_buf[out_index++] = OLED_CMD_ACTIVE_SCROLL; // 2F
|
||||
}
|
||||
|
||||
if (scroll == SCROLL_UP) {
|
||||
out_buf[out_index++] = OLED_CMD_CONTINUOUS_SCROLL; // 29
|
||||
out_buf[out_index++] = 0x00; // Dummy byte
|
||||
out_buf[out_index++] = 0x00; // Define start page address
|
||||
out_buf[out_index++] = 0x07; // Frame frequency
|
||||
//out_buf[out_index++] = 0x01; // Define end page address
|
||||
out_buf[out_index++] = 0x00; // Define end page address
|
||||
out_buf[out_index++] = 0x01; // Vertical scrolling offset
|
||||
|
||||
out_buf[out_index++] = OLED_CMD_VERTICAL; // A3
|
||||
out_buf[out_index++] = 0x00;
|
||||
if (dev->_height == 64)
|
||||
//out_buf[out_index++] = 0x7F;
|
||||
out_buf[out_index++] = 0x40;
|
||||
if (dev->_height == 32)
|
||||
out_buf[out_index++] = 0x20;
|
||||
out_buf[out_index++] = OLED_CMD_ACTIVE_SCROLL; // 2F
|
||||
}
|
||||
|
||||
if (scroll == SCROLL_STOP) {
|
||||
out_buf[out_index++] = OLED_CMD_DEACTIVE_SCROLL; // 2E
|
||||
}
|
||||
|
||||
esp_err_t res = i2c_master_transmit(dev_handle, out_buf, 3, I2C_TICKS_TO_WAIT);
|
||||
if (res != ESP_OK)
|
||||
ESP_LOGE(TAG, "Could not write to device [0x%02x at %d]: %d (%s)", dev->_address, I2C_NUM, res, esp_err_to_name(res));
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "driver/spi_master.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
@ -19,26 +18,23 @@
|
||||
#define HOST_ID SPI2_HOST // If i2c is selected
|
||||
#endif
|
||||
|
||||
static const int SPI_Command_Mode = 0;
|
||||
static const int SPI_Data_Mode = 1;
|
||||
static const int SPI_Frequency = 1000000; // 1MHz
|
||||
#define SPI_COMMAND_MODE 0
|
||||
#define SPI_DATA_MODE 1
|
||||
#define SPI_FREQUENCY 1000000; // 1MHz
|
||||
|
||||
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)
|
||||
{
|
||||
esp_err_t ret;
|
||||
|
||||
//gpio_pad_select_gpio( GPIO_CS );
|
||||
gpio_reset_pin( GPIO_CS );
|
||||
gpio_set_direction( GPIO_CS, GPIO_MODE_OUTPUT );
|
||||
gpio_set_level( GPIO_CS, 0 );
|
||||
|
||||
//gpio_pad_select_gpio( GPIO_DC );
|
||||
gpio_reset_pin( GPIO_DC );
|
||||
gpio_set_direction( GPIO_DC, GPIO_MODE_OUTPUT );
|
||||
gpio_set_level( GPIO_DC, 0 );
|
||||
|
||||
if ( GPIO_RESET >= 0 ) {
|
||||
//gpio_pad_select_gpio( GPIO_RESET );
|
||||
gpio_reset_pin( GPIO_RESET );
|
||||
gpio_set_direction( GPIO_RESET, GPIO_MODE_OUTPUT );
|
||||
gpio_set_level( GPIO_RESET, 0 );
|
||||
@ -63,7 +59,7 @@ void spi_master_init(SSD1306_t * dev, int16_t GPIO_MOSI, int16_t GPIO_SCLK, int1
|
||||
|
||||
spi_device_interface_config_t devcfg;
|
||||
memset( &devcfg, 0, sizeof( spi_device_interface_config_t ) );
|
||||
devcfg.clock_speed_hz = SPI_Frequency;
|
||||
devcfg.clock_speed_hz = SPI_FREQUENCY;
|
||||
devcfg.spics_io_num = GPIO_CS;
|
||||
devcfg.queue_size = 1;
|
||||
|
||||
@ -73,7 +69,7 @@ void spi_master_init(SSD1306_t * dev, int16_t GPIO_MOSI, int16_t GPIO_SCLK, int1
|
||||
assert(ret==ESP_OK);
|
||||
dev->_dc = GPIO_DC;
|
||||
dev->_SPIHandle = handle;
|
||||
dev->_address = SPIAddress;
|
||||
dev->_address = SPI_ADDRESS;
|
||||
dev->_flip = false;
|
||||
}
|
||||
|
||||
@ -96,13 +92,13 @@ bool spi_master_write_command(SSD1306_t * dev, uint8_t Command )
|
||||
{
|
||||
static uint8_t CommandByte = 0;
|
||||
CommandByte = Command;
|
||||
gpio_set_level( dev->_dc, SPI_Command_Mode );
|
||||
gpio_set_level( dev->_dc, SPI_COMMAND_MODE );
|
||||
return spi_master_write_byte( dev->_SPIHandle, &CommandByte, 1 );
|
||||
}
|
||||
|
||||
bool spi_master_write_data(SSD1306_t * dev, const uint8_t* Data, size_t DataLength )
|
||||
{
|
||||
gpio_set_level( dev->_dc, SPI_Data_Mode );
|
||||
gpio_set_level( dev->_dc, SPI_DATA_MODE );
|
||||
return spi_master_write_byte( dev->_SPIHandle, Data, DataLength );
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user