Feature: 支持 LVGL 作为嵌入式显示屏的底层。 #7
@ -10,6 +10,12 @@ dependencies:
|
|||||||
source:
|
source:
|
||||||
type: idf
|
type: idf
|
||||||
version: 5.0.1
|
version: 5.0.1
|
||||||
manifest_hash: d23f3b15e8b95dfe5da6cf83768d24158a3a0222f95694b1fa09c3ca8602f79f
|
lvgl/lvgl:
|
||||||
|
component_hash: 2567762b19953712ee38789ad8f8de57ad1f6e39283adefbbfc7184ffe662831
|
||||||
|
source:
|
||||||
|
service_url: https://api.components.espressif.com/
|
||||||
|
type: service
|
||||||
|
version: 8.2.0
|
||||||
|
manifest_hash: bef1e4573234ace0f846d8355b65d9ec82a4aeada7c2fa638efbec574f134e54
|
||||||
target: esp32c3
|
target: esp32c3
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
|
@ -1,2 +1,24 @@
|
|||||||
idf_component_register(SRCS "udp_server.c" "service_discovery.c" "app_nvs.c" "apds_9960.c" "pca9555.c" "i2c.c" "asr_pro.c" "ci_03t.c" "ui_input.c" "ambient_light.c" "temperature.c" "embedded_display.c" "mqtt.c" "main.c" "wifi.c" "light.c" "mqtt.c" "led_strip_encoder/led_strip_encoder.c"
|
idf_component_register(
|
||||||
INCLUDE_DIRS ".")
|
SRCS
|
||||||
|
"udp_server.c"
|
||||||
|
"service_discovery.c"
|
||||||
|
"app_nvs.c"
|
||||||
|
"ch1116.c"
|
||||||
|
# "apds_9960.c"
|
||||||
|
# "pca9555.c"
|
||||||
|
"i2c.c"
|
||||||
|
"asr_pro.c"
|
||||||
|
"ci_03t.c"
|
||||||
|
# "ui_input.c"
|
||||||
|
# "ambient_light.c"
|
||||||
|
# "temperature.c"
|
||||||
|
# "mqtt.c"
|
||||||
|
"main.c"
|
||||||
|
"wifi.c"
|
||||||
|
"light.c"
|
||||||
|
# "mqtt.c"
|
||||||
|
"led_strip_encoder/led_strip_encoder.c"
|
||||||
|
"gui.c"
|
||||||
|
"lvgl_demo_ui.c"
|
||||||
|
INCLUDE_DIRS "."
|
||||||
|
)
|
@ -1,10 +1,10 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "ch1116.c"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "driver/i2c.h"
|
#include "driver/i2c.h"
|
||||||
#include "embedded_display.c"
|
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
|
269
main/ch1116.c
Normal file
269
main/ch1116.c
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#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"
|
||||||
|
|
||||||
|
#define CH1116_TAG "CH1116"
|
||||||
|
|
||||||
|
#define SDA_PIN GPIO_NUM_4
|
||||||
|
#define SCL_PIN GPIO_NUM_5
|
||||||
|
|
||||||
|
#define CH1116_WIDTH 128
|
||||||
|
#define CH1116_HEIGHT 64
|
||||||
|
|
||||||
|
#define CH1116_ADDRESS 0x3C // 011110+SA0 - 0x3C or 0x3D
|
||||||
|
|
||||||
|
// CH1116 Control
|
||||||
|
|
||||||
|
#define CH1116_CONTROL_BYTE_COMMAND_SINGLE 0x80
|
||||||
|
#define CH1116_CONTROL_BYTE_COMMAND_STREAM 0x00
|
||||||
|
#define CH1116_CONTROL_BYTE_DATA_SINGLE 0xC0
|
||||||
|
#define CH1116_CONTROL_BYTE_DATA_STREAM 0x40
|
||||||
|
|
||||||
|
// CH1116 Config Commands
|
||||||
|
|
||||||
|
#define CH1116_DISPLAY_OFF 0xAE // #13
|
||||||
|
|
||||||
|
#define CH1116_LOWER_COLUMN_ADDRESS 0x02 // #1 0x02-0x0F
|
||||||
|
#define CH1116_HIGHER_COLUMN_ADDRESS 0x10 // #2 0x10-0x1F
|
||||||
|
|
||||||
|
#define CH1116_DISPLAY_START_LINE 0x40 // #3
|
||||||
|
|
||||||
|
#define CH1116_PAGE_ADDRESS 0xB0 // #18 0xB0-0xB7
|
||||||
|
|
||||||
|
#define CH1116_CONTRACT_CONTROL 0x81 // #10
|
||||||
|
#define CH1116_CONTRACT_CONTROL_128 0xCF // #10
|
||||||
|
|
||||||
|
#define CH1116_SEGMENT_REMAP 0xA1 // #12 ADC=1 (right)
|
||||||
|
|
||||||
|
#define CH1116_NORMAL_DISPLAY 0xA6 // #14
|
||||||
|
|
||||||
|
#define CH1116_MULTIPLEX_RATIO 0xA8 // #15
|
||||||
|
#define CH1116_MULTIPLEX_RATIO_1_64 0x3F
|
||||||
|
|
||||||
|
// VCC Generated by Internal DC/DC Circuit
|
||||||
|
#define CH1116_CHARGE_PUMP_ENABLE 0xAD // #16
|
||||||
|
#define CH1116_CHARGE_PUMP_ENABLE_INTERNAL_VCC 0x8B // #16
|
||||||
|
|
||||||
|
#define CH1116_CHARGE_PUMP_VOLTAGE_9V 0x33 // #8
|
||||||
|
|
||||||
|
#define CH1116_COM_SCAN_DIRECTION 0xC8 // #19
|
||||||
|
|
||||||
|
#define CH1116_DISPLAY_OFFSET 0xD3 // #20
|
||||||
|
#define CH1116_DISPLAY_OFFSET_0 0x00 // #20
|
||||||
|
|
||||||
|
#define CH1116_SET_OSC_DIVISION 0xD5 // #21
|
||||||
|
#define CH1116_SET_OSC_DIVISION_1 0x80 // #21
|
||||||
|
|
||||||
|
#define CH1116_SET_PRE_CHARGE_PERIOD 0xD9 // #22
|
||||||
|
#define CH1116_SET_PRE_CHARGE_PERIOD_1 0x1F // #22
|
||||||
|
|
||||||
|
#define CH1116_SET_COM_PINS 0xDA // #23
|
||||||
|
#define CH1116_SET_COM_PINS_1 0x12 // #23
|
||||||
|
|
||||||
|
#define CH1116_SET_VCOMH 0xDB // #24
|
||||||
|
#define CH1116_SET_VCOMH_1 0x40 // #24
|
||||||
|
|
||||||
|
#define CH1116_DISPLAY_ON 0xAF // #13
|
||||||
|
|
||||||
|
void ch1116_init() {
|
||||||
|
esp_err_t err;
|
||||||
|
|
||||||
|
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||||
|
|
||||||
|
i2c_master_start(cmd);
|
||||||
|
i2c_master_write_byte(cmd, (CH1116_ADDRESS << 1) | I2C_MASTER_WRITE, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_CONTROL_BYTE_COMMAND_STREAM, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_DISPLAY_OFF, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_LOWER_COLUMN_ADDRESS, true);
|
||||||
|
i2c_master_write_byte(cmd, CH1116_HIGHER_COLUMN_ADDRESS, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_DISPLAY_START_LINE, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_PAGE_ADDRESS, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_CONTRACT_CONTROL, true);
|
||||||
|
i2c_master_write_byte(cmd, CH1116_CONTRACT_CONTROL_128, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_SEGMENT_REMAP, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_NORMAL_DISPLAY, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_MULTIPLEX_RATIO, true);
|
||||||
|
i2c_master_write_byte(cmd, CH1116_MULTIPLEX_RATIO_1_64, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_CHARGE_PUMP_ENABLE, true);
|
||||||
|
i2c_master_write_byte(cmd, CH1116_CHARGE_PUMP_ENABLE_INTERNAL_VCC, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_CHARGE_PUMP_VOLTAGE_9V, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_COM_SCAN_DIRECTION, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_DISPLAY_OFFSET, true);
|
||||||
|
i2c_master_write_byte(cmd, CH1116_DISPLAY_OFFSET_0, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_SET_OSC_DIVISION, true);
|
||||||
|
i2c_master_write_byte(cmd, CH1116_SET_OSC_DIVISION_1, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_SET_PRE_CHARGE_PERIOD, true);
|
||||||
|
i2c_master_write_byte(cmd, CH1116_SET_PRE_CHARGE_PERIOD_1, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_SET_COM_PINS, true);
|
||||||
|
i2c_master_write_byte(cmd, CH1116_SET_COM_PINS_1, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_SET_VCOMH, true);
|
||||||
|
i2c_master_write_byte(cmd, CH1116_SET_VCOMH_1, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_DISPLAY_ON, true);
|
||||||
|
|
||||||
|
i2c_master_stop(cmd);
|
||||||
|
|
||||||
|
err = i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS);
|
||||||
|
if (err == ESP_OK) {
|
||||||
|
ESP_LOGI(CH1116_TAG, "OLED configured successfully");
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(CH1116_TAG, "OLED configuration failed. code: %s",
|
||||||
|
esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
i2c_cmd_link_delete(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void task_ch1116_display_pattern(void *ignore) {
|
||||||
|
i2c_cmd_handle_t cmd;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 8; i++) {
|
||||||
|
cmd = i2c_cmd_link_create();
|
||||||
|
i2c_master_start(cmd);
|
||||||
|
i2c_master_write_byte(cmd, (CH1116_ADDRESS << 1) | I2C_MASTER_WRITE, true);
|
||||||
|
i2c_master_write_byte(cmd, CH1116_CONTROL_BYTE_COMMAND_SINGLE, true);
|
||||||
|
i2c_master_write_byte(cmd, 0xB0 | i, true);
|
||||||
|
i2c_master_write_byte(cmd, CH1116_CONTROL_BYTE_DATA_STREAM, true);
|
||||||
|
for (uint8_t j = 0; j < 132; j++) {
|
||||||
|
i2c_master_write_byte(cmd, 0xFF >> (j % 8), true);
|
||||||
|
}
|
||||||
|
i2c_master_stop(cmd);
|
||||||
|
i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS);
|
||||||
|
i2c_cmd_link_delete(cmd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void task_ch1116_display_clear(void *ignore) {
|
||||||
|
i2c_cmd_handle_t cmd;
|
||||||
|
|
||||||
|
uint8_t zero[132];
|
||||||
|
memset(zero, 0, 132);
|
||||||
|
for (uint8_t i = 0; i < 8; i++) {
|
||||||
|
cmd = i2c_cmd_link_create();
|
||||||
|
i2c_master_start(cmd);
|
||||||
|
i2c_master_write_byte(cmd, (CH1116_ADDRESS << 1) | I2C_MASTER_WRITE, true);
|
||||||
|
i2c_master_write_byte(cmd, CH1116_CONTROL_BYTE_COMMAND_SINGLE, true);
|
||||||
|
i2c_master_write_byte(cmd, 0xB0 | i, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_CONTROL_BYTE_DATA_STREAM, true);
|
||||||
|
i2c_master_write(cmd, zero, 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, CH1116_CONTROL_BYTE_COMMAND_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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t ch1116_draw_bitmap(int x_start, int y_start, int x_end,
|
||||||
|
int y_end, const void *color_data) {
|
||||||
|
assert((x_start < x_end) && (y_start < y_end) &&
|
||||||
|
"start position must be smaller than end position");
|
||||||
|
|
||||||
|
// one page contains 8 rows (COMs)
|
||||||
|
uint8_t page_start = y_start / 8;
|
||||||
|
uint8_t page_end = y_end / 8;
|
||||||
|
// define an area of frame memory where MCU can access
|
||||||
|
|
||||||
|
esp_err_t err;
|
||||||
|
|
||||||
|
i2c_cmd_handle_t cmd;
|
||||||
|
|
||||||
|
uint8_t *color_data_ptr = (uint8_t *)color_data;
|
||||||
|
uint16_t page_data_size = (x_end - x_start + 1);
|
||||||
|
|
||||||
|
// ESP_LOGI(CH1116_TAG, "y_start: %d, y_end: %d, page_start: %d, page_end:
|
||||||
|
// %d",
|
||||||
|
// y_start, y_end, page_start, page_end);
|
||||||
|
// ESP_LOGI(CH1116_TAG, "x_start: %d, x_end: %d, page_data_size: %d", x_start,
|
||||||
|
// x_end, page_data_size);
|
||||||
|
|
||||||
|
for (int page = page_start; page <= page_end; page++) {
|
||||||
|
cmd = i2c_cmd_link_create();
|
||||||
|
|
||||||
|
i2c_master_start(cmd);
|
||||||
|
i2c_master_write_byte(cmd, (CH1116_ADDRESS << 1) | I2C_MASTER_WRITE, true);
|
||||||
|
|
||||||
|
// set cursor position
|
||||||
|
i2c_master_write_byte(cmd, CH1116_CONTROL_BYTE_COMMAND_STREAM, true);
|
||||||
|
i2c_master_write_byte(cmd, CH1116_LOWER_COLUMN_ADDRESS | (x_start & 0x0f),
|
||||||
|
true);
|
||||||
|
i2c_master_write_byte(cmd, CH1116_HIGHER_COLUMN_ADDRESS | (x_start >> 4),
|
||||||
|
true);
|
||||||
|
i2c_master_write_byte(cmd, CH1116_PAGE_ADDRESS | (page & 0x0f), true);
|
||||||
|
|
||||||
|
i2c_master_stop(cmd);
|
||||||
|
|
||||||
|
err = i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
i2c_cmd_link_delete(cmd);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
i2c_cmd_link_delete(cmd);
|
||||||
|
|
||||||
|
// write page data
|
||||||
|
cmd = i2c_cmd_link_create();
|
||||||
|
|
||||||
|
i2c_master_start(cmd);
|
||||||
|
i2c_master_write_byte(cmd, (CH1116_ADDRESS << 1) | I2C_MASTER_WRITE, true);
|
||||||
|
|
||||||
|
i2c_master_write_byte(cmd, CH1116_CONTROL_BYTE_DATA_STREAM, true);
|
||||||
|
i2c_master_write(cmd, color_data_ptr, page_data_size, true);
|
||||||
|
|
||||||
|
i2c_master_stop(cmd);
|
||||||
|
|
||||||
|
err = i2c_master_cmd_begin(I2C_NUM_0, cmd, 10 / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
|
// ESP_LOG_BUFFER_HEXDUMP(CH1116_TAG, color_data_ptr, page_data_size,
|
||||||
|
// ESP_LOG_INFO);
|
||||||
|
|
||||||
|
color_data_ptr += page_data_size;
|
||||||
|
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
i2c_cmd_link_delete(cmd);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
i2c_cmd_link_delete(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ch1116_main(void) {
|
||||||
|
ch1116_init();
|
||||||
|
|
||||||
|
task_ch1116_display_pattern(NULL);
|
||||||
|
// vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
|
// task_ch1116_display_clear(NULL);
|
||||||
|
}
|
@ -1,145 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "codetab.h"
|
|
||||||
#include "config_key.h"
|
|
||||||
#include "driver/i2c.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "i2c.c"
|
|
||||||
|
|
||||||
#define Brightness 0xCF
|
|
||||||
#define X_WIDTH 128
|
|
||||||
#define Y_WIDTH 64
|
|
||||||
|
|
||||||
void i2cWriteByte(uint8_t reg, uint8_t data) {
|
|
||||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
|
||||||
i2c_master_start(cmd);
|
|
||||||
i2c_master_write_byte(cmd, SSD1306_ADDRESS << 1 | I2C_MASTER_WRITE, true);
|
|
||||||
i2c_master_write_byte(cmd, reg, true);
|
|
||||||
i2c_master_write_byte(cmd, data, true);
|
|
||||||
i2c_master_stop(cmd);
|
|
||||||
i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
|
|
||||||
i2c_cmd_link_delete(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void i2cWriteCommand(uint8_t data) { i2cWriteByte(0x00, data); }
|
|
||||||
|
|
||||||
void i2cWriteData(uint8_t data) { i2cWriteByte(0x40, data); }
|
|
||||||
|
|
||||||
void display_fill(uint8_t bmpData) {
|
|
||||||
for (int y = 0; y < 8; y++) {
|
|
||||||
i2cWriteCommand(0xB0 + y);
|
|
||||||
i2cWriteCommand(0x01);
|
|
||||||
i2cWriteCommand(0x10);
|
|
||||||
for (int x = 0; x < X_WIDTH; x++) {
|
|
||||||
i2cWriteData(bmpData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void display_fill_rect(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1,
|
|
||||||
uint8_t bmpData) {
|
|
||||||
for (int y = y0; y < y1; y++) {
|
|
||||||
i2cWriteCommand(0xB0 + y);
|
|
||||||
i2cWriteCommand(0x01);
|
|
||||||
i2cWriteCommand(0x10);
|
|
||||||
for (int x = x0; x < x1; x++) {
|
|
||||||
i2cWriteData(bmpData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void display_set_pos(uint8_t x, uint8_t y) {
|
|
||||||
i2cWriteCommand(0xB0 + y);
|
|
||||||
i2cWriteCommand(((x & 0xF0) >> 4) | 0x10);
|
|
||||||
i2cWriteCommand((x & 0x0F) | 0x01);
|
|
||||||
}
|
|
||||||
|
|
||||||
void display_print8_str(uint8_t x, uint8_t y, char str[]) {
|
|
||||||
if (!is_embedded_display_online) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint8_t c;
|
|
||||||
for (uint8_t ch, ci = 0; ch = str[ci], ch != '\0'; ci++, x += 8) {
|
|
||||||
c = ch - 0x20;
|
|
||||||
display_set_pos(x, y);
|
|
||||||
for (uint8_t cx = 0; cx < 8; cx++) {
|
|
||||||
i2cWriteData(F8X16[c * 16 + cx]);
|
|
||||||
}
|
|
||||||
display_set_pos(x, y + 1);
|
|
||||||
for (uint8_t cx = 0; cx < 8; cx++) {
|
|
||||||
i2cWriteData(F8X16[c * 16 + cx + 8]);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_display() {
|
|
||||||
if (is_embedded_display_online == 0) {
|
|
||||||
ESP_LOGE("display", "display is offline");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
i2cWriteCommand(0xAE); // display off
|
|
||||||
i2cWriteCommand(0x00); // set lower column address
|
|
||||||
i2cWriteCommand(0x10); // set higher column address
|
|
||||||
i2cWriteCommand(0x40); // set start line address
|
|
||||||
i2cWriteCommand(0x81); // set contrast control register
|
|
||||||
i2cWriteCommand(0xCF); // set contrast
|
|
||||||
i2cWriteCommand(0xA1); // set segment re-map
|
|
||||||
i2cWriteCommand(0xC8); // set COM output scan direction
|
|
||||||
i2cWriteCommand(0xA6); // set normal display
|
|
||||||
i2cWriteCommand(0xA8); // set multiplex ratio(1 to 64)
|
|
||||||
i2cWriteCommand(0x3F); // 1/64 duty
|
|
||||||
i2cWriteCommand(0xD3); // set display offset
|
|
||||||
i2cWriteCommand(0x00); // not offset
|
|
||||||
i2cWriteCommand(0xD5); // set display clock divide ratio/oscillator frequency
|
|
||||||
i2cWriteCommand(0x80); // set divide ratio
|
|
||||||
i2cWriteCommand(0xD9); // set pre-charge period
|
|
||||||
i2cWriteCommand(0xF1); // set pre-charge voltage
|
|
||||||
i2cWriteCommand(0xDA); // set com pins hardware configuration
|
|
||||||
i2cWriteCommand(0x12);
|
|
||||||
i2cWriteCommand(0xDB); // set vcomh
|
|
||||||
i2cWriteCommand(0x40); // 0.77*vcc
|
|
||||||
i2cWriteCommand(0x20); // set memory addressing mode
|
|
||||||
i2cWriteCommand(0x02); // set page addressing mode
|
|
||||||
i2cWriteCommand(0x8D); // set charge pump enable/disable
|
|
||||||
i2cWriteCommand(0x14); // set(0x10) disable
|
|
||||||
i2cWriteCommand(0xAF); // display on
|
|
||||||
|
|
||||||
display_fill(0x00);
|
|
||||||
display_set_pos(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gui_update_config_uint8(uint8_t key, uint8_t value) {
|
|
||||||
char changing_str[12] = "NC";
|
|
||||||
switch (key) {
|
|
||||||
case ui_input_key_display_0_brightness:
|
|
||||||
sprintf(changing_str, "Dis0: % 3d", value);
|
|
||||||
break;
|
|
||||||
case ui_input_key_display_1_brightness:
|
|
||||||
sprintf(changing_str, "Dis1: % 3d", value);
|
|
||||||
break;
|
|
||||||
case ui_input_key_computer_volume:
|
|
||||||
sprintf(changing_str, "CVol: % 3d", value);
|
|
||||||
break;
|
|
||||||
case ui_input_key_display_ambient_lighting_level:
|
|
||||||
sprintf(changing_str, "ALLv: % 3d", value);
|
|
||||||
break;
|
|
||||||
case ui_input_key_display_ambient_lighting_mode:
|
|
||||||
sprintf(changing_str, "ALMd: % 3d", value);
|
|
||||||
break;
|
|
||||||
case ui_input_key_display_0_mode:
|
|
||||||
sprintf(changing_str, "Dis0M: % 2d", value);
|
|
||||||
break;
|
|
||||||
case ui_input_key_display_1_mode:
|
|
||||||
sprintf(changing_str, "Dis1M: % 2d", value);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
strcpy(changing_str, "NC");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
display_fill_rect(0, 6, 128, 8, 0);
|
|
||||||
display_print8_str(8, 6, changing_str);
|
|
||||||
}
|
|
171
main/gui.c
Normal file
171
main/gui.c
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "ch1116.c"
|
||||||
|
#include "driver/i2c.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_timer.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "lvgl.h"
|
||||||
|
|
||||||
|
static const char *GUI_TAG = "LVGL_GUI";
|
||||||
|
|
||||||
|
#define I2C_HOST 0
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//////////////////// Please update the following configuration according to your
|
||||||
|
/// LCD spec //////////////////////////////
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#define EXAMPLE_LCD_PIXEL_CLOCK_HZ (400 * 1000)
|
||||||
|
|
||||||
|
#define EXAMPLE_LCD_H_RES CH1116_WIDTH
|
||||||
|
#define EXAMPLE_LCD_V_RES CH1116_HEIGHT
|
||||||
|
|
||||||
|
#define EXAMPLE_LVGL_TICK_PERIOD_MS 2
|
||||||
|
|
||||||
|
extern void example_lvgl_demo_ui(lv_disp_t *disp);
|
||||||
|
|
||||||
|
static void example_lvgl_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area,
|
||||||
|
lv_color_t *color_map) {
|
||||||
|
int offsetx1 = area->x1;
|
||||||
|
int offsetx2 = area->x2;
|
||||||
|
int offsety1 = area->y1;
|
||||||
|
int offsety2 = area->y2;
|
||||||
|
// copy a buffer's content to a specific area of the display
|
||||||
|
ch1116_draw_bitmap(offsetx1, offsety1, offsetx2, offsety2, color_map);
|
||||||
|
lv_disp_flush_ready(drv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void example_lvgl_set_px_cb(lv_disp_drv_t *disp_drv, uint8_t *buf,
|
||||||
|
lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
|
||||||
|
lv_color_t color, lv_opa_t opa) {
|
||||||
|
uint16_t byte_index = x + ((y >> 3) * buf_w);
|
||||||
|
uint8_t bit_index = y & 0x7;
|
||||||
|
|
||||||
|
if ((color.full == 0) && (LV_OPA_TRANSP != opa)) {
|
||||||
|
buf[byte_index] |= (1 << bit_index);
|
||||||
|
} else {
|
||||||
|
buf[byte_index] &= ~(1 << bit_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void example_lvgl_rounder(lv_disp_drv_t *disp_drv, lv_area_t *area) {
|
||||||
|
area->y1 = area->y1 & (~0x7);
|
||||||
|
area->y2 = area->y2 | 0x7;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void example_increase_lvgl_tick(void *arg) {
|
||||||
|
/* Tell LVGL how many milliseconds has elapsed */
|
||||||
|
lv_tick_inc(EXAMPLE_LVGL_TICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_value(void *bar, int32_t v) {
|
||||||
|
lv_bar_set_value(bar, v, LV_ANIM_OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void lv_example_bar_6(lv_obj_t *src) {
|
||||||
|
static lv_style_t style_bar;
|
||||||
|
lv_style_init(&style_bar);
|
||||||
|
|
||||||
|
lv_style_set_bg_color(&style_bar, lv_color_white());
|
||||||
|
lv_style_set_border_width(&style_bar, 1);
|
||||||
|
lv_style_set_border_color(&style_bar, lv_color_black());
|
||||||
|
lv_style_set_pad_hor(&style_bar, 4);
|
||||||
|
lv_style_set_pad_ver(&style_bar, 2);
|
||||||
|
|
||||||
|
static lv_style_t style_indic;
|
||||||
|
lv_style_init(&style_indic);
|
||||||
|
|
||||||
|
lv_style_set_bg_color(&style_indic, lv_color_black());
|
||||||
|
|
||||||
|
lv_obj_t *bar = lv_bar_create(src);
|
||||||
|
lv_obj_set_size(bar, 100, 10);
|
||||||
|
lv_obj_center(bar);
|
||||||
|
lv_obj_add_style(bar, &style_bar, LV_PART_MAIN);
|
||||||
|
lv_obj_add_style(bar, &style_indic, LV_PART_INDICATOR);
|
||||||
|
lv_bar_set_range(bar, 0, 100);
|
||||||
|
lv_bar_set_value(bar, 0, LV_ANIM_ON);
|
||||||
|
|
||||||
|
lv_anim_t a;
|
||||||
|
lv_anim_init(&a);
|
||||||
|
lv_anim_set_exec_cb(&a, set_value);
|
||||||
|
lv_anim_set_time(&a, 3000);
|
||||||
|
lv_anim_set_playback_time(&a, 3000);
|
||||||
|
lv_anim_set_var(&a, bar);
|
||||||
|
lv_anim_set_values(&a, 0, 50);
|
||||||
|
lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
|
||||||
|
lv_anim_start(&a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void example_lvgl_demo_ui(lv_disp_t *disp) {
|
||||||
|
lv_obj_t *scr = lv_disp_get_scr_act(disp);
|
||||||
|
|
||||||
|
lv_obj_t *label = lv_label_create(scr);
|
||||||
|
lv_label_set_long_mode(label,
|
||||||
|
LV_LABEL_LONG_SCROLL_CIRCULAR); /* Circular scroll
|
||||||
|
*/
|
||||||
|
lv_label_set_text(label, "Hello Espressif, Hello LVGL.");
|
||||||
|
lv_obj_set_width(label, 120);
|
||||||
|
lv_obj_center(label);
|
||||||
|
|
||||||
|
lv_example_bar_6(scr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gui_tick(void *pvParameters) {
|
||||||
|
while (1) {
|
||||||
|
// raise the task priority of LVGL and/or reduce the handler period can
|
||||||
|
// improve the performance
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
// The task running lv_timer_handler should have lower priority than that
|
||||||
|
// running `lv_tick_inc`
|
||||||
|
lv_timer_handler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void gui_main(void) {
|
||||||
|
static lv_disp_draw_buf_t
|
||||||
|
disp_buf; // contains internal graphic buffer(s) called draw buffer(s)
|
||||||
|
static lv_disp_drv_t disp_drv; // contains callback functions
|
||||||
|
|
||||||
|
ESP_LOGI(GUI_TAG, "Initialize LVGL library");
|
||||||
|
lv_init();
|
||||||
|
// alloc draw buffers used by LVGL
|
||||||
|
// it's recommended to choose the size of the draw buffer(s) to be at least
|
||||||
|
// 1/10 screen sized
|
||||||
|
lv_color_t *buf1 = malloc(EXAMPLE_LCD_H_RES * 20 * sizeof(lv_color_t));
|
||||||
|
assert(buf1);
|
||||||
|
lv_color_t *buf2 = malloc(EXAMPLE_LCD_H_RES * 20 * sizeof(lv_color_t));
|
||||||
|
assert(buf2);
|
||||||
|
// initialize LVGL draw buffers
|
||||||
|
lv_disp_draw_buf_init(&disp_buf, buf1, buf2, EXAMPLE_LCD_H_RES * 20);
|
||||||
|
|
||||||
|
ESP_LOGI(GUI_TAG, "Register display driver to LVGL");
|
||||||
|
lv_disp_drv_init(&disp_drv);
|
||||||
|
disp_drv.hor_res = EXAMPLE_LCD_H_RES;
|
||||||
|
disp_drv.ver_res = EXAMPLE_LCD_V_RES;
|
||||||
|
disp_drv.flush_cb = example_lvgl_flush_cb;
|
||||||
|
disp_drv.draw_buf = &disp_buf;
|
||||||
|
disp_drv.rounder_cb = example_lvgl_rounder;
|
||||||
|
disp_drv.set_px_cb = example_lvgl_set_px_cb;
|
||||||
|
lv_disp_t *disp = lv_disp_drv_register(&disp_drv);
|
||||||
|
|
||||||
|
ESP_LOGI(GUI_TAG, "Install LVGL tick timer");
|
||||||
|
// Tick interface for LVGL (using esp_timer to generate 2ms periodic event)
|
||||||
|
const esp_timer_create_args_t lvgl_tick_timer_args = {
|
||||||
|
.callback = &example_increase_lvgl_tick, .name = "lvgl_tick"};
|
||||||
|
esp_timer_handle_t lvgl_tick_timer = NULL;
|
||||||
|
ESP_ERROR_CHECK(esp_timer_create(&lvgl_tick_timer_args, &lvgl_tick_timer));
|
||||||
|
ESP_ERROR_CHECK(esp_timer_start_periodic(lvgl_tick_timer,
|
||||||
|
EXAMPLE_LVGL_TICK_PERIOD_MS * 1000));
|
||||||
|
|
||||||
|
ESP_LOGI(GUI_TAG, "Display LVGL Scroll Text");
|
||||||
|
example_lvgl_demo_ui(disp);
|
||||||
|
|
||||||
|
xTaskCreate(gui_tick, "gui_tick", 4096, (void *)NULL, 5, NULL);
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
## IDF Component Manager Manifest File
|
## IDF Component Manager Manifest File
|
||||||
dependencies:
|
dependencies:
|
||||||
|
lvgl/lvgl: "~8.2.0"
|
||||||
espressif/mdns: "^1.0.9"
|
espressif/mdns: "^1.0.9"
|
||||||
## Required IDF version
|
## Required IDF version
|
||||||
idf:
|
idf:
|
||||||
|
19
main/lvgl_demo_ui.c
Executable file
19
main/lvgl_demo_ui.c
Executable file
@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "lvgl.h"
|
||||||
|
|
||||||
|
void example_lvgl_demo_ui(lv_disp_t *disp) {
|
||||||
|
lv_obj_t *scr = lv_disp_get_scr_act(disp);
|
||||||
|
|
||||||
|
lv_obj_t *label = lv_label_create(scr);
|
||||||
|
lv_label_set_long_mode(label,
|
||||||
|
LV_LABEL_LONG_SCROLL_CIRCULAR); /* Circular scroll
|
||||||
|
*/
|
||||||
|
lv_label_set_text(label, "Hello Espressif, Hello LVGL.");
|
||||||
|
lv_obj_set_width(label, 120);
|
||||||
|
lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 0);
|
||||||
|
}
|
40
main/main.c
40
main/main.c
@ -1,19 +1,20 @@
|
|||||||
#include "apds_9960.c"
|
// #include "apds_9960.c"
|
||||||
#include "app_nvs.c"
|
#include "app_nvs.c"
|
||||||
|
#include "ch1116.c"
|
||||||
#include "ci_03t.c"
|
#include "ci_03t.c"
|
||||||
#include "embedded_display.c"
|
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
#include "gui.c"
|
||||||
#include "i2c.c"
|
#include "i2c.c"
|
||||||
#include "light.c"
|
#include "light.c"
|
||||||
#include "mqtt.c"
|
// #include "mqtt.c"
|
||||||
#include "pca9555.c"
|
// #include "pca9555.c"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "service_discovery.c"
|
#include "service_discovery.c"
|
||||||
#include "temperature.c"
|
// #include "temperature.c"
|
||||||
#include "udp_server.c"
|
#include "udp_server.c"
|
||||||
#include "ui_input.c"
|
// #include "ui_input.c"
|
||||||
#include "wifi.c"
|
#include "wifi.c"
|
||||||
|
|
||||||
static const char *APP_TAG = "DisplayAmbientLight";
|
static const char *APP_TAG = "DisplayAmbientLight";
|
||||||
@ -26,17 +27,18 @@ void app_main(void) {
|
|||||||
init_i2c();
|
init_i2c();
|
||||||
i2c_check_slaves();
|
i2c_check_slaves();
|
||||||
|
|
||||||
init_display();
|
ch1116_main();
|
||||||
display_print8_str(0, 0, "Ambient Light");
|
gui_main();
|
||||||
|
// display_print8_str(0, 0, "Ambient Light");
|
||||||
|
|
||||||
ci_03t_init();
|
ci_03t_init();
|
||||||
apds_9960_init();
|
// apds_9960_init();
|
||||||
apds_9960_auto_fetch();
|
// apds_9960_auto_fetch();
|
||||||
auto_fetch_temperature();
|
// auto_fetch_temperature();
|
||||||
pca9555_init();
|
// pca9555_init();
|
||||||
ui_input_init();
|
// ui_input_init();
|
||||||
xTaskCreate(mqtt_publish_ui_input, "mqtt_publish_ui_input", 2048, NULL, 10,
|
// xTaskCreate(mqtt_publish_ui_input, "mqtt_publish_ui_input", 2048, NULL, 10,
|
||||||
NULL);
|
// NULL);
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
light_play(light_mode_connection_wifi);
|
light_play(light_mode_connection_wifi);
|
||||||
if (connect_wifi()) {
|
if (connect_wifi()) {
|
||||||
@ -45,14 +47,14 @@ void app_main(void) {
|
|||||||
udp_server_init();
|
udp_server_init();
|
||||||
service_discovery_init();
|
service_discovery_init();
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
mqtt_app_start();
|
// mqtt_app_start();
|
||||||
// if (waiting_for_mqtt_connected()) {
|
// if (waiting_for_mqtt_connected()) {
|
||||||
// light_play(light_mode_mqtt_connected);
|
// light_play(light_mode_mqtt_connected);
|
||||||
// }
|
// }
|
||||||
// if (waiting_for_desktop_online()) {
|
// if (waiting_for_desktop_online()) {
|
||||||
// light_play(light_mode_desktop_online);
|
// light_play(light_mode_desktop_online);
|
||||||
// }
|
// }
|
||||||
while (waiting_and_get_colors()) {
|
// while (waiting_and_get_colors()) {
|
||||||
light_play_colors(NUMBER_OF_LEDS * 3, mqtt_colors_buffer);
|
// light_play_colors(NUMBER_OF_LEDS * 3, mqtt_colors_buffer);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "cJSON.h"
|
#include "cJSON.h"
|
||||||
#include "ci_03t.c"
|
#include "ci_03t.c"
|
||||||
#include "embedded_display.c"
|
|
||||||
#include "esp_bit_defs.h"
|
#include "esp_bit_defs.h"
|
||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
@ -148,6 +148,8 @@ static void encoder_value_change(encoder_state_t *state) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(UI_INPUT_TAG, "key: %d, delta: %d", state->key, delta);
|
||||||
|
|
||||||
s_ui_input_t event = {.value = delta};
|
s_ui_input_t event = {.value = delta};
|
||||||
if (state->key == ui_input_raw_key_encoder_0) {
|
if (state->key == ui_input_raw_key_encoder_0) {
|
||||||
if (state->value & 1) {
|
if (state->value & 1) {
|
||||||
|
Loading…
Reference in New Issue
Block a user