205 lines
6.4 KiB
C++
205 lines
6.4 KiB
C++
|
|
#include "ssd1366.h"
|
|
#include "font8x8_basic.h"
|
|
#include <string.h>
|
|
#include "driver/gpio.h"
|
|
|
|
#define SSD1366_SDA_PIN GPIO_NUM_4
|
|
#define SSD1366_SCL_PIN GPIO_NUM_15
|
|
#define SSD1366_RST_PIN GPIO_NUM_16
|
|
#define SSD1366_VEXT_PIN GPIO_NUM_21
|
|
|
|
|
|
|
|
|
|
#define I2C_NUM I2C_NUM_0
|
|
//#define I2C_NUM I2C_NUM
|
|
|
|
#define I2C_MASTER_FREQ_HZ 400000U /*!< I2C clock of SSD1306 can run at 400 kHz max. */
|
|
|
|
|
|
#define tag "SSD1306"
|
|
|
|
void i2c_master_init()
|
|
{
|
|
i2c_config_t i2c_config;
|
|
|
|
i2c_config.mode = I2C_MODE_MASTER;
|
|
i2c_config.sda_io_num = SSD1366_SDA_PIN;
|
|
i2c_config.scl_io_num = SSD1366_SCL_PIN;
|
|
i2c_config.sda_pullup_en = GPIO_PULLUP_ENABLE;
|
|
i2c_config.scl_pullup_en = GPIO_PULLUP_ENABLE;
|
|
i2c_config.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));
|
|
}
|
|
|
|
void ssd1306_init()
|
|
{
|
|
esp_err_t espRc;
|
|
gpio_set_direction(SSD1366_RST_PIN, GPIO_MODE_OUTPUT);
|
|
gpio_set_direction(SSD1366_VEXT_PIN, GPIO_MODE_OUTPUT);
|
|
gpio_set_level(SSD1366_VEXT_PIN, 0); //enable power to oled
|
|
gpio_set_level(SSD1366_RST_PIN, 0);
|
|
vTaskDelay(50 / portTICK_PERIOD_MS);
|
|
gpio_set_level(SSD1366_RST_PIN, 1);
|
|
|
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
|
|
|
i2c_master_start(cmd);
|
|
i2c_master_write_byte(cmd, (OLED_I2C_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, 0x3F, true);
|
|
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_CMD_SET_DISPLAY_START_LINE, true); // 40
|
|
|
|
i2c_master_write_byte(cmd, OLED_CMD_SET_SEGMENT_REMAP, true); // reverse left-right mapping
|
|
i2c_master_write_byte(cmd, OLED_CMD_SET_COM_SCAN_MODE, true); // reverse up-bottom mapping
|
|
|
|
i2c_master_write_byte(cmd, OLED_CMD_SET_DISPLAY_CLK_DIV, true); // D5
|
|
i2c_master_write_byte(cmd, 0x80, true);
|
|
i2c_master_write_byte(cmd, OLED_CMD_SET_COM_PIN_MAP, true); // DA
|
|
i2c_master_write_byte(cmd, 0x12, true);
|
|
i2c_master_write_byte(cmd, OLED_CMD_SET_CONTRAST, true); // 81
|
|
i2c_master_write_byte(cmd, 0xFF, true);
|
|
i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_RAM, true); // A4
|
|
i2c_master_write_byte(cmd, OLED_CMD_SET_VCOMH_DESELCT, true); // DB
|
|
i2c_master_write_byte(cmd, 0x40, true);
|
|
i2c_master_write_byte(cmd, OLED_CMD_SET_MEMORY_ADDR_MODE, true); // 20
|
|
//i2c_master_write_byte(cmd, OLED_CMD_SET_HORI_ADDR_MODE, true); // 00
|
|
i2c_master_write_byte(cmd, OLED_CMD_SET_PAGE_ADDR_MODE, true); // 02
|
|
// Set Lower Column Start Address for Page Addressing Mode
|
|
i2c_master_write_byte(cmd, 0x00, true);
|
|
// Set Higher Column Start Address for Page Addressing Mode
|
|
i2c_master_write_byte(cmd, 0x10, true);
|
|
i2c_master_write_byte(cmd, OLED_CMD_SET_CHARGE_PUMP, true); // 8D
|
|
i2c_master_write_byte(cmd, 0x14, true);
|
|
i2c_master_write_byte(cmd, OLED_CMD_DEACTIVE_SCROLL, true); // 2E
|
|
i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_NORMAL, true); // A6
|
|
i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_ON, true);
|
|
|
|
i2c_master_stop(cmd);
|
|
|
|
espRc = i2c_master_cmd_begin(I2C_NUM, cmd, 10/portTICK_PERIOD_MS);
|
|
if (espRc == ESP_OK)
|
|
{
|
|
ESP_LOGI(tag, "OLED configured successfully");
|
|
}
|
|
else
|
|
{
|
|
ESP_LOGE(tag, "OLED configuration failed. code: 0x%.2X", espRc);
|
|
}
|
|
i2c_cmd_link_delete(cmd);
|
|
}
|
|
|
|
void i2c_contrast( 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_master_start(cmd);
|
|
i2c_master_write_byte(cmd, (OLED_I2C_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, _contrast, true);
|
|
i2c_master_stop(cmd);
|
|
i2c_master_cmd_begin(I2C_NUM, cmd, 10/portTICK_PERIOD_MS);
|
|
i2c_cmd_link_delete(cmd);
|
|
}
|
|
|
|
void ssd1306_display_clear(void) {
|
|
i2c_cmd_handle_t cmd;
|
|
uint8_t zero[128] = {0};
|
|
for (uint8_t i = 0; i < 8; i++) {
|
|
cmd = i2c_cmd_link_create();
|
|
i2c_master_start(cmd);
|
|
i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
|
|
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_SINGLE, true);
|
|
i2c_master_write_byte(cmd, 0xB0 | i, true); // Set GDDRAM page start address
|
|
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_DATA_STREAM, true);
|
|
i2c_master_write(cmd, zero, 128, true);
|
|
i2c_master_stop(cmd);
|
|
i2c_master_cmd_begin(I2C_NUM_0, cmd, 10/portTICK_PERIOD_MS);
|
|
i2c_cmd_link_delete(cmd);
|
|
}
|
|
}
|
|
|
|
void ssd1306_display_text(char* text, uint16_t text_len)
|
|
{
|
|
|
|
i2c_cmd_handle_t cmd;
|
|
|
|
uint8_t cur_page = 0;
|
|
|
|
cmd = i2c_cmd_link_create();
|
|
i2c_master_start(cmd);
|
|
i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
|
|
|
|
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
|
|
i2c_master_write_byte(cmd, 0x00, true); // reset column
|
|
i2c_master_write_byte(cmd, 0x10, true);
|
|
i2c_master_write_byte(cmd, 0xB0 | cur_page, true); // reset page
|
|
|
|
i2c_master_stop(cmd);
|
|
i2c_master_cmd_begin(I2C_NUM, cmd, 10/portTICK_PERIOD_MS);
|
|
i2c_cmd_link_delete(cmd);
|
|
|
|
for (uint8_t i = 0; i < text_len; i++)
|
|
{
|
|
if (text[i] == '\n')
|
|
{
|
|
cmd = i2c_cmd_link_create();
|
|
i2c_master_start(cmd);
|
|
i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
|
|
|
|
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_CMD_STREAM, true);
|
|
i2c_master_write_byte(cmd, 0x00, true); // reset column
|
|
i2c_master_write_byte(cmd, 0x10, true);
|
|
i2c_master_write_byte(cmd, 0xB0 | ++cur_page, true); // increment page
|
|
|
|
i2c_master_stop(cmd);
|
|
i2c_master_cmd_begin(I2C_NUM, cmd, 10/portTICK_PERIOD_MS);
|
|
i2c_cmd_link_delete(cmd);
|
|
}
|
|
else
|
|
{
|
|
cmd = i2c_cmd_link_create();
|
|
i2c_master_start(cmd);
|
|
i2c_master_write_byte(cmd, (OLED_I2C_ADDRESS << 1) | I2C_MASTER_WRITE, true);
|
|
|
|
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_DATA_STREAM, true);
|
|
i2c_master_write(cmd, font8x8_basic_tr[(uint8_t)text[i]], 8, true);
|
|
|
|
i2c_master_stop(cmd);
|
|
i2c_master_cmd_begin(I2C_NUM, cmd, 10/portTICK_PERIOD_MS);
|
|
i2c_cmd_link_delete(cmd);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void task_ssd1306_display_text(void *pvParameters)
|
|
{
|
|
char *pcTaskName;
|
|
pcTaskName = (char *) pvParameters;
|
|
|
|
//char text[13] = "Hello world!";
|
|
//uint8_t text_len = strlen(text);
|
|
|
|
ssd1306_display_text(pcTaskName, strlen(pcTaskName));
|
|
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
|
|
|
|
|