181 lines
5.5 KiB
C
181 lines
5.5 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "driver/gpio.h"
|
|
#include "driver/i2c.h"
|
|
#include "esp_err.h"
|
|
#include "esp_log.h"
|
|
#include "freertos/task.h"
|
|
|
|
|
|
#include "sdkconfig.h" // generated by "make menuconfig"
|
|
|
|
#include "sh1106.h"
|
|
#include "font8x8_basic.h"
|
|
|
|
//#define SDA_PIN GPIO_NUM_21
|
|
//#define SCL_PIN GPIO_NUM_22
|
|
|
|
#define tag "SH1106"
|
|
|
|
/*
|
|
bool i2c_master_init()
|
|
{
|
|
i2c_config_t i2c_config = {
|
|
.mode = I2C_MODE_MASTER,
|
|
.sda_io_num = SDA_PIN,
|
|
.scl_io_num = SCL_PIN,
|
|
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
|
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
|
.master.clk_speed = 1000000
|
|
};
|
|
i2c_param_config(I2C_NUM_0, &i2c_config);
|
|
i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0);
|
|
return true;
|
|
}
|
|
*/
|
|
void sh1106_set_display_start_line(i2c_cmd_handle_t cmd, uint_fast8_t start_line)
|
|
{
|
|
// REQUIRES:
|
|
// 0 <= start_line <= 63
|
|
if (start_line <= 63)
|
|
{
|
|
i2c_master_write_byte(cmd, OLED_CMD_SET_DISPLAY_START_LINE | start_line, true);
|
|
}
|
|
}
|
|
|
|
esp_err_t sh1106_init()
|
|
{
|
|
esp_err_t espRc;
|
|
|
|
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_SET_CHARGE_PUMP_CTRL, true);
|
|
i2c_master_write_byte(cmd, OLED_CMD_SET_CHARGE_PUMP_ON, true);
|
|
|
|
i2c_master_write_byte(cmd, OLED_CMD_SET_SEGMENT_REMAP_INVERSE, true); // reverse left-right mapping
|
|
i2c_master_write_byte(cmd, OLED_CMD_SET_COM_SCAN_MODE_REVERSE, true); // reverse up-bottom mapping
|
|
|
|
i2c_master_write_byte(cmd, OLED_CMD_DISPLAY_ON, true);
|
|
|
|
i2c_master_write_byte(cmd, 0x00, true); // reset column low bits
|
|
i2c_master_write_byte(cmd, 0x10, true); // reset column high bits
|
|
i2c_master_write_byte(cmd, 0xB0, true); // reset page
|
|
i2c_master_write_byte(cmd, 0x40, true); // set start line
|
|
i2c_master_write_byte(cmd, OLED_CMD_SET_DISPLAY_OFFSET, true);
|
|
i2c_master_write_byte(cmd, 0x00, true);
|
|
|
|
i2c_master_stop(cmd);
|
|
|
|
espRc = i2c_master_cmd_begin(I2C_NUM_0, 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);
|
|
return espRc;
|
|
}
|
|
|
|
|
|
void task_sh1106_display_clear(void *ignore)
|
|
{
|
|
i2c_cmd_handle_t cmd;
|
|
uint8_t S[132] = { 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);
|
|
|
|
i2c_master_write_byte(cmd, OLED_CONTROL_BYTE_DATA_STREAM, true);
|
|
i2c_master_write(cmd, S, 132, true);
|
|
i2c_master_stop(cmd);
|
|
i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS);
|
|
i2c_cmd_link_delete(cmd);
|
|
}
|
|
|
|
cmd = i2c_cmd_link_create();
|
|
i2c_master_start(cmd);
|
|
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, true); // reset page
|
|
i2c_master_stop(cmd);
|
|
i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS);
|
|
i2c_cmd_link_delete(cmd);
|
|
}
|
|
|
|
void task_sh1106_contrast(void *ignore)
|
|
{
|
|
i2c_cmd_handle_t cmd;
|
|
|
|
uint8_t contrast = 0;
|
|
uint8_t direction = 1;
|
|
while (true)
|
|
{
|
|
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);
|
|
i2c_master_write_byte(cmd, contrast, true);
|
|
i2c_master_stop(cmd);
|
|
i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS);
|
|
i2c_cmd_link_delete(cmd);
|
|
vTaskDelay(1 / portTICK_PERIOD_MS);
|
|
|
|
contrast += direction;
|
|
if (contrast == 0xFF)
|
|
{
|
|
direction = -1;
|
|
}
|
|
if (contrast == 0x0)
|
|
{
|
|
direction = 1;
|
|
}
|
|
}
|
|
vTaskDelete(NULL);
|
|
}
|
|
|
|
void task_sh1106_write_string(const void *arg_text, uint8_t strpos)
|
|
{
|
|
uint8_t S[132] = { 0 };
|
|
unsigned char *text = (unsigned char*) arg_text;
|
|
uint8_t text_len = strlen((const char*)text);
|
|
if (text_len > 22) return;
|
|
for (uint8_t i = 0; i < text_len; i++)
|
|
{
|
|
memcpy(&S[i*6], font6x8[(uint8_t)*(text + i)], 6);
|
|
}
|
|
i2c_cmd_handle_t cmd;
|
|
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, 0x01, true); // reset column
|
|
i2c_master_write_byte(cmd, 0x10, true);
|
|
i2c_master_write_byte(cmd, 0xB0 | strpos, true); // reset page
|
|
i2c_master_stop(cmd);
|
|
i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS);
|
|
i2c_cmd_link_delete(cmd);
|
|
|
|
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, S, 132, true);
|
|
i2c_master_stop(cmd);
|
|
i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS);
|
|
i2c_cmd_link_delete(cmd);
|
|
}
|