Compare commits
28 Commits
feature/ap
...
master
Author | SHA1 | Date | |
---|---|---|---|
ceaa1d343a | |||
f1ab7aa361 | |||
7a0d5d7fcd | |||
7c9c016aef | |||
3bdd8d70c3 | |||
04a36d14a1 | |||
ac8520f31f | |||
df476e4f9c | |||
6e95095db0 | |||
a3abff89c5 | |||
3f5ca686cf | |||
ca9e25f40c | |||
27270c4f6a | |||
324a307fe3 | |||
b7476428a2 | |||
7098bf4665 | |||
0f5e2a9664 | |||
05660afc54 | |||
101103de03 | |||
7bff8e2c17 | |||
2da0f224a1 | |||
f0a1dae657 | |||
58d1039c78 | |||
e947dc3ac1 | |||
c8eb0817e8 | |||
ac33f67d77 | |||
c27418aaf1 | |||
40dde8cc89 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,3 +2,5 @@ build/
|
|||||||
sdkconfig
|
sdkconfig
|
||||||
sdkconfig.old
|
sdkconfig.old
|
||||||
.vscode/
|
.vscode/
|
||||||
|
managed_components/
|
||||||
|
.DS_Store
|
@ -4,7 +4,5 @@
|
|||||||
# CMakeLists in this exact order for cmake to work correctly
|
# CMakeLists in this exact order for cmake to work correctly
|
||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/led_strip)
|
|
||||||
|
|
||||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
project(display-ambient-light-board)
|
project(display-ambient-light-board)
|
BIN
assets/fonts/Roboto-Light.ttf
Normal file
BIN
assets/fonts/Roboto-Light.ttf
Normal file
Binary file not shown.
BIN
assets/fonts/fa-regular-400.ttf
Normal file
BIN
assets/fonts/fa-regular-400.ttf
Normal file
Binary file not shown.
21
dependencies.lock
Normal file
21
dependencies.lock
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
dependencies:
|
||||||
|
espressif/mdns:
|
||||||
|
component_hash: 3f3bf8ff67ec99dde4e935637af087ebc899b9fee396ffa1c9138d3775f1aca4
|
||||||
|
source:
|
||||||
|
service_url: https://api.components.espressif.com/
|
||||||
|
type: service
|
||||||
|
version: 1.0.9
|
||||||
|
idf:
|
||||||
|
component_hash: null
|
||||||
|
source:
|
||||||
|
type: idf
|
||||||
|
version: 5.0.1
|
||||||
|
lvgl/lvgl:
|
||||||
|
component_hash: 0f2006e7b800eee17b73ed4f92ffbaa76d61c02ba4779ec9efbcd5f453bb0102
|
||||||
|
source:
|
||||||
|
service_url: https://api.components.espressif.com/
|
||||||
|
type: service
|
||||||
|
version: 8.3.6~1
|
||||||
|
manifest_hash: 9a88337b9db92c26041847f5fd4efc58df1dcf0e9c6b8758da96aaac2e63c2a2
|
||||||
|
target: esp32c3
|
||||||
|
version: 1.0.0
|
36
docs/udp.md
Normal file
36
docs/udp.md
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# 基于 UDP 的上、下位机通讯规则
|
||||||
|
|
||||||
|
## 报文格式
|
||||||
|
|
||||||
|
开始的一个字节是命令,剩余字节是数据。缓冲区长度设为 1024 字节,所以单个 UDP 报文的数据最多为 1023 字节。
|
||||||
|
|
||||||
|
## 命令
|
||||||
|
|
||||||
|
### 上位机在线 `1`
|
||||||
|
|
||||||
|
### 更新灯带颜色 `2`
|
||||||
|
|
||||||
|
| 数据 | 长度(字节) | 说明 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 起始位置 | 2 | 0~65535 |
|
||||||
|
| 长度 | 2 | 0~65535 |
|
||||||
|
| 颜色 | 3 | RGB 顺序,$2^3 * 2^3 * 2^3 = 65535$ 真彩色 |
|
||||||
|
|
||||||
|
### 更新电脑显示器亮度 `3`
|
||||||
|
|
||||||
|
| 数据 | 长度(字节) | 说明 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 显示器序号 | 1 | 0~255 |
|
||||||
|
| 亮度 | 1 | 0~255 |
|
||||||
|
|
||||||
|
### 更新电脑音量 `4`
|
||||||
|
|
||||||
|
| 数据 | 长度(字节) | 说明 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 音量 | 1 | 0~255 |
|
||||||
|
|
||||||
|
### 更新灯带基本颜色校准 `5`
|
||||||
|
|
||||||
|
| 数据 | 长度(字节) | 说明 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| 颜色 | 3 | R、G、B 亮度上限 |
|
@ -1,2 +1,24 @@
|
|||||||
idf_component_register(SRCS "hw-ms03.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"
|
idf_component_register(
|
||||||
INCLUDE_DIRS ".")
|
SRCS
|
||||||
|
"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"
|
||||||
|
#
|
||||||
|
"desktop.c"
|
||||||
|
"main.c"
|
||||||
|
"wifi.c"
|
||||||
|
"light.c"
|
||||||
|
"led_strip_encoder/led_strip_encoder.c"
|
||||||
|
"gui.c"
|
||||||
|
"net_gateway_monitor.c"
|
||||||
|
"app_icon_8.c"
|
||||||
|
INCLUDE_DIRS "."
|
||||||
|
)
|
@ -120,9 +120,9 @@ void ambient_light_fetch(void* arg) {
|
|||||||
uint16_t als_ch0_raw;
|
uint16_t als_ch0_raw;
|
||||||
uint16_t als_ch1_raw;
|
uint16_t als_ch1_raw;
|
||||||
uint16_t proximity_raw;
|
uint16_t proximity_raw;
|
||||||
char als_ch0_str[10];
|
char als_ch0_str[20];
|
||||||
char als_ch1_str[10];
|
char als_ch1_str[20];
|
||||||
char proximity_str[10];
|
char proximity_str[20];
|
||||||
uint8_t als_ch0_buffer[] = {0, 0};
|
uint8_t als_ch0_buffer[] = {0, 0};
|
||||||
uint8_t als_ch1_buffer[] = {0, 0};
|
uint8_t als_ch1_buffer[] = {0, 0};
|
||||||
uint8_t proximity_buffer[] = {0, 0};
|
uint8_t proximity_buffer[] = {0, 0};
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
#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 "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "i2c.c"
|
#include "i2c.c"
|
||||||
|
|
||||||
@ -128,7 +129,7 @@
|
|||||||
|
|
||||||
#define APDS_9960_TAG "APDS-9960"
|
#define APDS_9960_TAG "APDS-9960"
|
||||||
|
|
||||||
static xQueueHandle apds_9960_int_evt_queue = NULL;
|
static QueueHandle_t apds_9960_int_evt_queue = NULL;
|
||||||
|
|
||||||
static int64_t last_apds_9960_int_time = 0;
|
static int64_t last_apds_9960_int_time = 0;
|
||||||
|
|
||||||
|
183
main/app_icon_8.c
Normal file
183
main/app_icon_8.c
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* Size: 8 px
|
||||||
|
* Bpp: 1
|
||||||
|
* Opts:
|
||||||
|
******************************************************************************/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "lvgl.h"
|
||||||
|
|
||||||
|
#ifndef APP_ICON_8
|
||||||
|
#define APP_ICON_8 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if APP_ICON_8
|
||||||
|
|
||||||
|
/*-----------------
|
||||||
|
* BITMAPS
|
||||||
|
*----------------*/
|
||||||
|
|
||||||
|
/*Store the image of the glyphs*/
|
||||||
|
static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
||||||
|
/* U+E1CB "" */
|
||||||
|
0x38, 0x31, 0x88, 0xfa, 0x49, 0x54, 0x44, 0x10, 0xf8,
|
||||||
|
|
||||||
|
/* U+E1CC "" */
|
||||||
|
0x80, 0x1f, 0xa, 0x22, 0x6b, 0xd4, 0x44, 0xd0, 0xc8, 0x1,
|
||||||
|
|
||||||
|
/* U+E29E "" */
|
||||||
|
0xe, 0x4, 0xa8, 0x32, 0x18, 0xe, 0xd, 0x8c, 0x7c,
|
||||||
|
|
||||||
|
/* U+F1EB "" */
|
||||||
|
0x1e, 0x18, 0x68, 0x4, 0x78, 0x21, 0x0, 0x0, 0xc0, 0x0,
|
||||||
|
|
||||||
|
/* U+F6AA "" */
|
||||||
|
0xc0,
|
||||||
|
|
||||||
|
/* U+F6AB "" */
|
||||||
|
0x79, 0x8, 0x1, 0x80,
|
||||||
|
|
||||||
|
/* U+F354 "" */
|
||||||
|
0x38, 0x28, 0x28, 0x28, 0xee, 0x82, 0x44, 0x28, 0x10,
|
||||||
|
|
||||||
|
/* U+F357 "" */
|
||||||
|
0x8, 0x14, 0x22, 0x41, 0x77, 0x14, 0x14, 0x14, 0x1c,
|
||||||
|
|
||||||
|
/* U+F354 "" */
|
||||||
|
0x31, 0x45, 0x37, 0x85, 0x23, 0x0,
|
||||||
|
|
||||||
|
/* U+F357 "" */
|
||||||
|
0x31, 0x28, 0x7b, 0x30, 0xc3, 0x0};
|
||||||
|
|
||||||
|
/*---------------------
|
||||||
|
* GLYPH DESCRIPTION
|
||||||
|
*--------------------*/
|
||||||
|
|
||||||
|
static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
|
||||||
|
{.bitmap_index = 0,
|
||||||
|
.adv_w = 0,
|
||||||
|
.box_w = 0,
|
||||||
|
.box_h = 0,
|
||||||
|
.ofs_x = 0,
|
||||||
|
.ofs_y = 0} /* id = 0 reserved */,
|
||||||
|
{.bitmap_index = 0,
|
||||||
|
.adv_w = 160,
|
||||||
|
.box_w = 10,
|
||||||
|
.box_h = 7,
|
||||||
|
.ofs_x = 0,
|
||||||
|
.ofs_y = 0},
|
||||||
|
{.bitmap_index = 9,
|
||||||
|
.adv_w = 160,
|
||||||
|
.box_w = 10,
|
||||||
|
.box_h = 8,
|
||||||
|
.ofs_x = 0,
|
||||||
|
.ofs_y = -1},
|
||||||
|
{.bitmap_index = 19,
|
||||||
|
.adv_w = 128,
|
||||||
|
.box_w = 9,
|
||||||
|
.box_h = 8,
|
||||||
|
.ofs_x = 0,
|
||||||
|
.ofs_y = -1},
|
||||||
|
{.bitmap_index = 28,
|
||||||
|
.adv_w = 160,
|
||||||
|
.box_w = 10,
|
||||||
|
.box_h = 8,
|
||||||
|
.ofs_x = 0,
|
||||||
|
.ofs_y = -1},
|
||||||
|
{.bitmap_index = 38,
|
||||||
|
.adv_w = 32,
|
||||||
|
.box_w = 2,
|
||||||
|
.box_h = 2,
|
||||||
|
.ofs_x = 4,
|
||||||
|
.ofs_y = -1},
|
||||||
|
{.bitmap_index = 39,
|
||||||
|
.adv_w = 112,
|
||||||
|
.box_w = 7,
|
||||||
|
.box_h = 4,
|
||||||
|
.ofs_x = 2,
|
||||||
|
.ofs_y = 0},
|
||||||
|
{.bitmap_index = 48,
|
||||||
|
.adv_w = 96,
|
||||||
|
.box_w = 6,
|
||||||
|
.box_h = 7,
|
||||||
|
.ofs_x = 0,
|
||||||
|
.ofs_y = 0},
|
||||||
|
{.bitmap_index = 54,
|
||||||
|
.adv_w = 96,
|
||||||
|
.box_w = 6,
|
||||||
|
.box_h = 7,
|
||||||
|
.ofs_x = 0,
|
||||||
|
.ofs_y = -1}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*---------------------
|
||||||
|
* CHARACTER MAPPING
|
||||||
|
*--------------------*/
|
||||||
|
|
||||||
|
static const uint16_t unicode_list_0[] = {0x0, 0x1, 0xd3,
|
||||||
|
0x1020, 0x14df, 0x14e0};
|
||||||
|
|
||||||
|
/*Collect the unicode lists and glyph_id offsets*/
|
||||||
|
static const lv_font_fmt_txt_cmap_t cmaps[] = {
|
||||||
|
{.range_start = 57803,
|
||||||
|
.range_length = 5345,
|
||||||
|
.glyph_id_start = 1,
|
||||||
|
.unicode_list = unicode_list_0,
|
||||||
|
.glyph_id_ofs_list = NULL,
|
||||||
|
.list_length = 6,
|
||||||
|
.type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY}};
|
||||||
|
|
||||||
|
/*--------------------
|
||||||
|
* ALL CUSTOM DATA
|
||||||
|
*--------------------*/
|
||||||
|
|
||||||
|
#if LV_VERSION_CHECK(8, 0, 0)
|
||||||
|
/*Store all the custom data of the font*/
|
||||||
|
static lv_font_fmt_txt_glyph_cache_t cache;
|
||||||
|
static const lv_font_fmt_txt_dsc_t font_dsc = {
|
||||||
|
#else
|
||||||
|
static lv_font_fmt_txt_dsc_t font_dsc = {
|
||||||
|
#endif
|
||||||
|
.glyph_bitmap = glyph_bitmap,
|
||||||
|
.glyph_dsc = glyph_dsc,
|
||||||
|
.cmaps = cmaps,
|
||||||
|
.kern_dsc = NULL,
|
||||||
|
.kern_scale = 0,
|
||||||
|
.cmap_num = 1,
|
||||||
|
.bpp = 1,
|
||||||
|
.kern_classes = 0,
|
||||||
|
.bitmap_format = 0,
|
||||||
|
#if LV_VERSION_CHECK(8, 0, 0)
|
||||||
|
.cache = &cache
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/*-----------------
|
||||||
|
* PUBLIC FONT
|
||||||
|
*----------------*/
|
||||||
|
|
||||||
|
/*Initialize a public general font descriptor*/
|
||||||
|
#if LV_VERSION_CHECK(8, 0, 0)
|
||||||
|
const lv_font_t app_icon_8 = {
|
||||||
|
#else
|
||||||
|
lv_font_t app_icon_8 = {
|
||||||
|
#endif
|
||||||
|
.get_glyph_dsc =
|
||||||
|
lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/
|
||||||
|
.get_glyph_bitmap =
|
||||||
|
lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/
|
||||||
|
.line_height = 8, /*The maximum line height required by the font*/
|
||||||
|
.base_line = 1, /*Baseline measured from the bottom of the line*/
|
||||||
|
#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0)
|
||||||
|
.subpx = LV_FONT_SUBPX_NONE,
|
||||||
|
#endif
|
||||||
|
#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8
|
||||||
|
.underline_position = -1,
|
||||||
|
.underline_thickness = 0,
|
||||||
|
#endif
|
||||||
|
.dsc = &font_dsc /*The custom font data. Will be accessed by
|
||||||
|
`get_glyph_bitmap/dsc` */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /*#if APP_ICON_8*/
|
19
main/app_nvs.c
Normal file
19
main/app_nvs.c
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "nvs.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
|
||||||
|
void app_nvs_init() {
|
||||||
|
esp_err_t err = nvs_flash_init();
|
||||||
|
if (err == ESP_ERR_NVS_NO_FREE_PAGES ||
|
||||||
|
err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||||
|
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||||
|
err = nvs_flash_init();
|
||||||
|
}
|
||||||
|
ESP_ERROR_CHECK(err);
|
||||||
|
}
|
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);
|
||||||
|
}
|
304
main/desktop.c
Normal file
304
main/desktop.c
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
#include <lwip/netdb.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_event.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_netif.h"
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "esp_wifi.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "gui.c"
|
||||||
|
#include "light.c"
|
||||||
|
#include "lwip/err.h"
|
||||||
|
#include "lwip/sockets.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
|
#include "ui_input.c"
|
||||||
|
|
||||||
|
#define UDP_PORT 23042
|
||||||
|
|
||||||
|
static const char *UDP_SERVER_TAG = "UDP_SERVER";
|
||||||
|
|
||||||
|
static bool desktop_connected = false;
|
||||||
|
static uint64_t last_desktop_ping_at = 0;
|
||||||
|
static struct sockaddr *desktop_addr = NULL;
|
||||||
|
|
||||||
|
static int sock = -1;
|
||||||
|
static uint8_t tx_buffer[128];
|
||||||
|
|
||||||
|
typedef struct desktop_value {
|
||||||
|
uint8_t value;
|
||||||
|
uint8_t max;
|
||||||
|
uint8_t min;
|
||||||
|
} desktop_value_t;
|
||||||
|
|
||||||
|
static desktop_value_t display1_brightness = {
|
||||||
|
.value = 20,
|
||||||
|
.max = 100,
|
||||||
|
.min = 0,
|
||||||
|
};
|
||||||
|
static desktop_value_t display2_brightness = {
|
||||||
|
.value = 20,
|
||||||
|
.max = 100,
|
||||||
|
.min = 0,
|
||||||
|
};
|
||||||
|
static desktop_value_t computer_volume = {
|
||||||
|
.value = 20,
|
||||||
|
.max = 100,
|
||||||
|
.min = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void udp_server_task(void *pvParameters) {
|
||||||
|
char rx_buffer[1024];
|
||||||
|
char addr_str[128];
|
||||||
|
int addr_family = (int)pvParameters;
|
||||||
|
int ip_protocol = 0;
|
||||||
|
struct sockaddr_in dest_addr;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
dest_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
dest_addr.sin_family = AF_INET;
|
||||||
|
dest_addr.sin_port = htons(UDP_PORT);
|
||||||
|
ip_protocol = IPPROTO_IP;
|
||||||
|
|
||||||
|
sock = socket(addr_family, SOCK_DGRAM, ip_protocol);
|
||||||
|
if (sock < 0) {
|
||||||
|
ESP_LOGE(UDP_SERVER_TAG, "Unable to create socket: errno %d. sock: %d",
|
||||||
|
errno, sock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ESP_LOGI(UDP_SERVER_TAG, "Socket created");
|
||||||
|
|
||||||
|
// Set timeout
|
||||||
|
struct timeval timeout;
|
||||||
|
timeout.tv_sec = 10;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof timeout);
|
||||||
|
|
||||||
|
int err = bind(sock, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
|
||||||
|
if (err < 0) {
|
||||||
|
ESP_LOGE(UDP_SERVER_TAG, "Socket unable to bind: errno %d. sock: %d",
|
||||||
|
errno, sock);
|
||||||
|
sock = -1;
|
||||||
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ESP_LOGI(UDP_SERVER_TAG, "Socket bound, port %d", UDP_PORT);
|
||||||
|
|
||||||
|
struct sockaddr source_addr; // Large enough for both IPv4 or IPv6
|
||||||
|
socklen_t socklen = sizeof(source_addr);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
// ESP_LOGI(UDP_SERVER_TAG, "Waiting for data");
|
||||||
|
int len = recvfrom(sock, rx_buffer, sizeof(rx_buffer) - 1, 0,
|
||||||
|
&source_addr, &socklen);
|
||||||
|
// Error occurred during receiving
|
||||||
|
if (len < 0) {
|
||||||
|
if (errno == EAGAIN) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ESP_LOGE(UDP_SERVER_TAG, "recvfrom failed: errno %d. len: %d", errno,
|
||||||
|
len);
|
||||||
|
}
|
||||||
|
// Data received
|
||||||
|
else {
|
||||||
|
// Get the sender's ip address as string
|
||||||
|
inet_ntoa_r(((struct sockaddr_in *)&source_addr)->sin_addr, addr_str,
|
||||||
|
sizeof(addr_str) - 1);
|
||||||
|
|
||||||
|
rx_buffer[len] = 0; // Null-terminate whatever we received and treat
|
||||||
|
// like a string...
|
||||||
|
|
||||||
|
switch (rx_buffer[0]) {
|
||||||
|
case 1:
|
||||||
|
last_desktop_ping_at = esp_timer_get_time();
|
||||||
|
ESP_LOGD(UDP_SERVER_TAG, "Received ping from %s", addr_str);
|
||||||
|
sendto(sock, rx_buffer, 1, 0, &source_addr, sizeof(source_addr));
|
||||||
|
desktop_addr = &source_addr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
set_display_ambient_light_colors(
|
||||||
|
((uint16_t)rx_buffer[1] << 8 | (uint16_t)rx_buffer[2]),
|
||||||
|
(uint8_t *)&(rx_buffer[3]), len - 3);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: // computer brightness changed
|
||||||
|
if (rx_buffer[1] == 0) {
|
||||||
|
display1_brightness.value = rx_buffer[2];
|
||||||
|
} else if (rx_buffer[1] == 1) {
|
||||||
|
display2_brightness.value = rx_buffer[2];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: // computer volume changed
|
||||||
|
computer_volume.value = rx_buffer[1];
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5: // color correction changed
|
||||||
|
ESP_LOGD(UDP_SERVER_TAG, "Color correction changed");
|
||||||
|
led_strip_set_color_calibration((float)rx_buffer[1] / 255,
|
||||||
|
(float)rx_buffer[2] / 255,
|
||||||
|
(float)rx_buffer[3] / 255);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ESP_LOG_BUFFER_HEXDUMP(UDP_SERVER_TAG, rx_buffer, len,
|
||||||
|
ESP_LOG_INFO);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ESP_LOGD(UDP_SERVER_TAG, "Received %d bytes from %s:", len, addr_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock != -1 && len < 0) {
|
||||||
|
ESP_LOGE(UDP_SERVER_TAG, "Shutting down socket and restarting...");
|
||||||
|
shutdown(sock, 0);
|
||||||
|
close(sock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t desktop_change_value(desktop_value_t *target, int8_t delta) {
|
||||||
|
if (delta > 0) {
|
||||||
|
if ((target->max - target->value) > delta) {
|
||||||
|
target->value += delta;
|
||||||
|
} else {
|
||||||
|
target->value = target->max;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((target->value - target->min) > -delta) {
|
||||||
|
target->value += delta;
|
||||||
|
} else {
|
||||||
|
target->value = target->min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return target->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t change_display_brightness(uint8_t display_index, int8_t delta) {
|
||||||
|
if (desktop_addr == NULL) {
|
||||||
|
ESP_LOGW(UDP_SERVER_TAG, "No desktop connected");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (display_index) {
|
||||||
|
case 0: {
|
||||||
|
uint8_t value = desktop_change_value(&display1_brightness, delta);
|
||||||
|
|
||||||
|
tx_buffer[0] = 3;
|
||||||
|
tx_buffer[1] = 0;
|
||||||
|
tx_buffer[2] = value;
|
||||||
|
int err =
|
||||||
|
sendto(sock, tx_buffer, 3, 0, desktop_addr, sizeof(*desktop_addr));
|
||||||
|
if (err < 0) {
|
||||||
|
ESP_LOGE(UDP_SERVER_TAG, "Socket unable to send: errno %d. sock: %d",
|
||||||
|
errno, sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_change_display_brightness(display_index, value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 1: {
|
||||||
|
uint8_t value = desktop_change_value(&display1_brightness, delta);
|
||||||
|
|
||||||
|
tx_buffer[0] = 3;
|
||||||
|
tx_buffer[1] = 1;
|
||||||
|
tx_buffer[2] = value;
|
||||||
|
int err =
|
||||||
|
sendto(sock, tx_buffer, 3, 0, desktop_addr, sizeof(*desktop_addr));
|
||||||
|
if (err < 0) {
|
||||||
|
ESP_LOGE(UDP_SERVER_TAG, "Socket unable to send: errno %d. sock: %d",
|
||||||
|
errno, sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_change_display_brightness(display_index, value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
ESP_LOGE(UDP_SERVER_TAG, "Invalid display index: %d", display_index);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static uint8_t change_volume(int8_t delta) {
|
||||||
|
if (desktop_addr == NULL) {
|
||||||
|
ESP_LOGW(UDP_SERVER_TAG, "No desktop connected");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t value = desktop_change_value(&computer_volume, delta);
|
||||||
|
|
||||||
|
tx_buffer[0] = 4;
|
||||||
|
tx_buffer[1] = value;
|
||||||
|
int err = sendto(sock, tx_buffer, 2, 0, desktop_addr, sizeof(*desktop_addr));
|
||||||
|
if (err < 0) {
|
||||||
|
char addr_str[128];
|
||||||
|
inet_ntoa_r(((struct sockaddr_in *)desktop_addr)->sin_addr, addr_str,
|
||||||
|
sizeof(addr_str) - 1);
|
||||||
|
ESP_LOGI(UDP_SERVER_TAG, "addr: %s", addr_str);
|
||||||
|
ESP_LOGE(UDP_SERVER_TAG, "Socket unable to send: errno %d. sock: %d", errno,
|
||||||
|
sock);
|
||||||
|
}
|
||||||
|
|
||||||
|
gui_change_volume_level(value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void desktop_watch_input_task(void *arg) {
|
||||||
|
s_ui_input_t input;
|
||||||
|
for (;;) {
|
||||||
|
if (xQueueReceive(ui_input_event, &input, portMAX_DELAY)) {
|
||||||
|
switch (input.key) {
|
||||||
|
case ui_input_key_display_0_brightness:
|
||||||
|
change_display_brightness(0, input.value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ui_input_key_display_1_brightness:
|
||||||
|
change_display_brightness(1, input.value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ui_input_key_computer_volume:
|
||||||
|
change_volume(input.value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void change_desktop_connection_status(bool connected) {
|
||||||
|
desktop_connected = connected;
|
||||||
|
if (connected) {
|
||||||
|
gui_set_server_connected();
|
||||||
|
} else {
|
||||||
|
gui_set_server_disconnected();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void desktop_online_check_task(void *pvParameters) {
|
||||||
|
while (1) {
|
||||||
|
if (esp_timer_get_time() - last_desktop_ping_at > 5000000) { // 2 seconds
|
||||||
|
change_desktop_connection_status(false);
|
||||||
|
} else {
|
||||||
|
change_desktop_connection_status(true);
|
||||||
|
}
|
||||||
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void udp_server_init(void) {
|
||||||
|
xTaskCreate(udp_server_task, "udp_server", 4096, (void *)AF_INET, 5, NULL);
|
||||||
|
xTaskCreate(desktop_online_check_task, "desktop_online_check", 1024, NULL, 10,
|
||||||
|
NULL);
|
||||||
|
xTaskCreate(desktop_watch_input_task, "desktop_watch_input", 4096, NULL, 7,
|
||||||
|
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);
|
|
||||||
}
|
|
2461
main/fonts/app_10.c
Normal file
2461
main/fonts/app_10.c
Normal file
File diff suppressed because it is too large
Load Diff
578
main/gui.c
Normal file
578
main/gui.c
Normal file
@ -0,0 +1,578 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "app_icon_8.c"
|
||||||
|
#include "ch1116.c"
|
||||||
|
#include "driver/i2c.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_timer.h"
|
||||||
|
#include "fonts/app_10.c"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "lvgl.h"
|
||||||
|
|
||||||
|
static const char *GUI_TAG = "LVGL_GUI";
|
||||||
|
|
||||||
|
#define I2C_HOST 0
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
// EF 9A AA
|
||||||
|
#define APP_WIFI_WEAK_SYMBOL "\xEF\x9A\xAA"
|
||||||
|
// EF 9A AB
|
||||||
|
#define APP_WIFI_FAIR_SYMBOL "\xEF\x9A\xAB"
|
||||||
|
// EF 87 AB
|
||||||
|
#define APP_WIFI_GOOD_SYMBOL "\xEF\x87\xAB"
|
||||||
|
|
||||||
|
// EE 87 8B
|
||||||
|
#define APP_CONNECTED_SYMBOL "\xEE\x87\x8B"
|
||||||
|
// EE 87 8C
|
||||||
|
#define APP_DISCONNECTED_SYMBOL "\xEE\x87\x8C"
|
||||||
|
|
||||||
|
// EE 8A 9E
|
||||||
|
#define APP_TIMER_SYMBOL "\xEE\x8A\x9E"
|
||||||
|
// EF 8D 97
|
||||||
|
#define APP_UP_SYMBOL "\xEF\x8D\x97"
|
||||||
|
// EF 8D 94
|
||||||
|
#define APP_DOWN_SYMBOL "\xEF\x8D\x94"
|
||||||
|
|
||||||
|
#define GUI_PANEL_TIMEOUT_US 3000000 // 3s
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct value_setting_panel {
|
||||||
|
lv_obj_t *panel;
|
||||||
|
lv_obj_t *bar;
|
||||||
|
lv_obj_t *label;
|
||||||
|
lv_obj_t *value_label;
|
||||||
|
int64_t last_updated_at;
|
||||||
|
} value_setting_panel_t;
|
||||||
|
|
||||||
|
static lv_obj_t *wifi_label;
|
||||||
|
static lv_anim_t wifi_animate;
|
||||||
|
|
||||||
|
static lv_obj_t *timer_label;
|
||||||
|
static lv_anim_t timer_animate;
|
||||||
|
|
||||||
|
static lv_obj_t *desktop_label;
|
||||||
|
static lv_anim_t desktop_animate;
|
||||||
|
|
||||||
|
value_setting_panel_t *value_setting_panel = NULL;
|
||||||
|
static bool panel_locked = false;
|
||||||
|
|
||||||
|
static lv_obj_t *scr;
|
||||||
|
|
||||||
|
typedef struct gui_network_speed_panel_s {
|
||||||
|
lv_obj_t *panel;
|
||||||
|
lv_obj_t *direct_upload_label;
|
||||||
|
lv_obj_t *direct_download_label;
|
||||||
|
lv_obj_t *proxy_upload_label;
|
||||||
|
lv_obj_t *proxy_download_label;
|
||||||
|
} gui_network_speed_panel_t;
|
||||||
|
|
||||||
|
static gui_network_speed_panel_t *gui_network_speed_panel = NULL;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_visible(void *obj, int32_t v) {
|
||||||
|
if (v) {
|
||||||
|
lv_obj_clear_flag(obj, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
} else {
|
||||||
|
lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_obj_blink_animate(lv_obj_t *obj, lv_anim_t *a) {
|
||||||
|
lv_anim_init(a);
|
||||||
|
lv_anim_set_exec_cb(a, set_visible);
|
||||||
|
lv_anim_set_time(a, 100);
|
||||||
|
lv_anim_set_playback_time(a, 100);
|
||||||
|
lv_anim_set_playback_delay(a, 200);
|
||||||
|
lv_anim_set_repeat_delay(a, 200);
|
||||||
|
lv_anim_set_values(a, 0, 1);
|
||||||
|
lv_anim_set_var(a, obj);
|
||||||
|
lv_anim_set_repeat_count(a, LV_ANIM_REPEAT_INFINITE);
|
||||||
|
lv_anim_start(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void change_wifi_icon(void *obj, int32_t v) {
|
||||||
|
switch (v) {
|
||||||
|
case 0:
|
||||||
|
lv_label_set_text(obj, APP_WIFI_WEAK_SYMBOL);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
lv_label_set_text(obj, APP_WIFI_FAIR_SYMBOL);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
lv_label_set_text(obj, APP_WIFI_GOOD_SYMBOL);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_LOGW(GUI_TAG, "Unknown wifi strength: %ld", v);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gui_set_wifi_connecting() {
|
||||||
|
lv_obj_clear_flag(wifi_label, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
|
||||||
|
lv_anim_init(&wifi_animate);
|
||||||
|
lv_anim_set_exec_cb(&wifi_animate, change_wifi_icon);
|
||||||
|
lv_anim_set_time(&wifi_animate, 300);
|
||||||
|
lv_anim_set_repeat_delay(&wifi_animate, 300);
|
||||||
|
lv_anim_set_values(&wifi_animate, 0, 2);
|
||||||
|
lv_anim_set_var(&wifi_animate, wifi_label);
|
||||||
|
lv_anim_set_repeat_count(&wifi_animate, LV_ANIM_REPEAT_INFINITE);
|
||||||
|
lv_anim_start(&wifi_animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gui_set_wifi_connected() {
|
||||||
|
lv_anim_del(wifi_label, NULL);
|
||||||
|
lv_obj_clear_flag(wifi_label, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_label_set_text(wifi_label, APP_WIFI_GOOD_SYMBOL);
|
||||||
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||||
|
lv_obj_clear_flag(wifi_label, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_label_set_text(wifi_label, APP_WIFI_GOOD_SYMBOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gui_set_wifi_disconnected() {
|
||||||
|
lv_anim_del(&wifi_label, NULL);
|
||||||
|
vTaskDelay(300 / portTICK_PERIOD_MS);
|
||||||
|
lv_obj_clear_flag(wifi_label, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_label_set_text(wifi_label, APP_WIFI_WEAK_SYMBOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gui_set_server_connecting() {
|
||||||
|
set_obj_blink_animate(desktop_label, &desktop_animate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gui_set_server_connected() {
|
||||||
|
lv_anim_del(desktop_label, NULL);
|
||||||
|
lv_obj_clear_flag(desktop_label, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_label_set_text(desktop_label, APP_CONNECTED_SYMBOL);
|
||||||
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||||
|
lv_obj_clear_flag(desktop_label, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_label_set_text(desktop_label, APP_CONNECTED_SYMBOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gui_set_server_disconnected() {
|
||||||
|
lv_anim_del(desktop_label, NULL);
|
||||||
|
vTaskDelay(300 / portTICK_PERIOD_MS);
|
||||||
|
lv_obj_clear_flag(desktop_label, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_label_set_text(desktop_label, APP_DISCONNECTED_SYMBOL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gui_bar_value_update_cb(lv_event_t *e) {
|
||||||
|
if (value_setting_panel == NULL) {
|
||||||
|
ESP_LOGW(GUI_TAG, "value_setting_panel is NULL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
lv_obj_t *value_label = value_setting_panel->value_label;
|
||||||
|
|
||||||
|
lv_obj_draw_part_dsc_t *dsc = lv_event_get_param(e);
|
||||||
|
if (dsc->part != LV_PART_INDICATOR) return;
|
||||||
|
|
||||||
|
lv_obj_t *obj = lv_event_get_target(e);
|
||||||
|
|
||||||
|
lv_draw_label_dsc_t label_dsc;
|
||||||
|
lv_draw_label_dsc_init(&label_dsc);
|
||||||
|
label_dsc.font = &lv_font_montserrat_10;
|
||||||
|
|
||||||
|
char buf[8];
|
||||||
|
lv_snprintf(buf, sizeof(buf), "%ld", lv_bar_get_value(obj));
|
||||||
|
|
||||||
|
lv_point_t txt_size;
|
||||||
|
lv_txt_get_size(&txt_size, buf, label_dsc.font, label_dsc.letter_space,
|
||||||
|
label_dsc.line_space, LV_COORD_MAX, label_dsc.flag);
|
||||||
|
|
||||||
|
lv_coord_t txt_x;
|
||||||
|
/*If the indicator is long enough put the text inside on the right*/
|
||||||
|
if (lv_area_get_width(dsc->draw_area) > txt_size.x + 20) {
|
||||||
|
txt_x = dsc->draw_area->x2 - 8 - txt_size.x + 1;
|
||||||
|
lv_obj_set_style_text_color(value_label, lv_color_white(), LV_PART_MAIN);
|
||||||
|
label_dsc.color = lv_color_white();
|
||||||
|
}
|
||||||
|
/*If the indicator is still short put the text out of it on the right*/
|
||||||
|
else {
|
||||||
|
txt_x = dsc->draw_area->x2 - 8 + txt_size.x - 1;
|
||||||
|
lv_obj_set_style_text_color(value_label, lv_color_black(), LV_PART_MAIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
lv_obj_align(value_label, LV_ALIGN_LEFT_MID, txt_x, 0);
|
||||||
|
lv_label_set_text(value_label, buf);
|
||||||
|
lv_obj_set_width(value_label, txt_size.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gui_close_value_setting_panel() {
|
||||||
|
if (value_setting_panel == NULL) return;
|
||||||
|
lv_obj_del(value_setting_panel->panel);
|
||||||
|
free(value_setting_panel);
|
||||||
|
value_setting_panel = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gui_check_value_setting_panel_task(void *pvParameters) {
|
||||||
|
vTaskDelay(GUI_PANEL_TIMEOUT_US / 1000 / portTICK_PERIOD_MS);
|
||||||
|
for (;;) {
|
||||||
|
if (!panel_locked &&
|
||||||
|
esp_timer_get_time() - value_setting_panel->last_updated_at >
|
||||||
|
GUI_PANEL_TIMEOUT_US) {
|
||||||
|
gui_close_value_setting_panel();
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gui_create_value_setting_panel() {
|
||||||
|
if (value_setting_panel != NULL) {
|
||||||
|
value_setting_panel->last_updated_at = esp_timer_get_time();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
value_setting_panel =
|
||||||
|
(value_setting_panel_t *)malloc(sizeof(value_setting_panel_t));
|
||||||
|
|
||||||
|
xTaskCreate(gui_check_value_setting_panel_task, "G_CHK_VAL_SET", 1024, NULL,
|
||||||
|
configMAX_PRIORITIES - 1, NULL);
|
||||||
|
|
||||||
|
value_setting_panel->panel = lv_obj_create(scr);
|
||||||
|
lv_obj_set_size(value_setting_panel->panel, 128, 40);
|
||||||
|
lv_obj_align(value_setting_panel->panel, LV_ALIGN_BOTTOM_MID, 0, 0);
|
||||||
|
lv_obj_set_style_border_width(value_setting_panel->panel, 1, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_border_color(value_setting_panel->panel, lv_color_black(),
|
||||||
|
LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_radius(value_setting_panel->panel, 5, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_pad_all(value_setting_panel->panel, 2, LV_PART_MAIN);
|
||||||
|
|
||||||
|
value_setting_panel->label = lv_label_create(value_setting_panel->panel);
|
||||||
|
lv_obj_align(value_setting_panel->label, LV_ALIGN_BOTTOM_LEFT, 0, 0);
|
||||||
|
|
||||||
|
value_setting_panel->bar = lv_bar_create(value_setting_panel->panel);
|
||||||
|
lv_obj_set_size(value_setting_panel->bar, 120, 12);
|
||||||
|
lv_obj_align(value_setting_panel->bar, LV_ALIGN_TOP_MID, 0, 0);
|
||||||
|
lv_bar_set_range(value_setting_panel->bar, 0, 100);
|
||||||
|
lv_bar_set_value(value_setting_panel->bar, 50, LV_ANIM_ON);
|
||||||
|
lv_obj_set_style_bg_color(value_setting_panel->bar, lv_color_white(),
|
||||||
|
LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_border_color(value_setting_panel->bar, lv_color_black(),
|
||||||
|
LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_border_width(value_setting_panel->bar, 1, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_radius(value_setting_panel->bar, 5, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_pad_hor(value_setting_panel->bar, 0, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_pad_ver(value_setting_panel->bar, 2, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_bg_color(value_setting_panel->bar, lv_color_black(),
|
||||||
|
LV_PART_INDICATOR);
|
||||||
|
lv_obj_add_event_cb(value_setting_panel->bar, gui_bar_value_update_cb,
|
||||||
|
LV_EVENT_DRAW_PART_END, NULL);
|
||||||
|
|
||||||
|
value_setting_panel->value_label = lv_label_create(value_setting_panel->bar);
|
||||||
|
lv_obj_align(value_setting_panel->value_label, LV_ALIGN_CENTER, 0, 0);
|
||||||
|
lv_obj_set_style_text_font(value_setting_panel->value_label,
|
||||||
|
&lv_font_montserrat_10, LV_PART_MAIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gui_change_strip_level(int32_t target_value) {
|
||||||
|
panel_locked = true;
|
||||||
|
gui_create_value_setting_panel();
|
||||||
|
lv_label_set_text(value_setting_panel->label, "Strip Level");
|
||||||
|
lv_bar_set_range(value_setting_panel->bar, 0, 255);
|
||||||
|
lv_bar_set_value(value_setting_panel->bar, target_value, LV_ANIM_ON);
|
||||||
|
panel_locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gui_change_display_brightness(int8_t display_index,
|
||||||
|
int32_t target_value) {
|
||||||
|
panel_locked = true;
|
||||||
|
gui_create_value_setting_panel();
|
||||||
|
lv_label_set_text_fmt(value_setting_panel->label, "Display#%d Brightness",
|
||||||
|
display_index);
|
||||||
|
lv_bar_set_range(value_setting_panel->bar, 0, 100);
|
||||||
|
lv_bar_set_value(value_setting_panel->bar, target_value, LV_ANIM_ON);
|
||||||
|
panel_locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gui_change_volume_level(int32_t target_value) {
|
||||||
|
panel_locked = true;
|
||||||
|
gui_create_value_setting_panel();
|
||||||
|
lv_label_set_text(value_setting_panel->label, "Volume Level");
|
||||||
|
lv_bar_set_range(value_setting_panel->bar, 0, 100);
|
||||||
|
lv_bar_set_value(value_setting_panel->bar, target_value, LV_ANIM_ON);
|
||||||
|
panel_locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gui_network_speed_human_readable(uint64_t *speed, char *str) {
|
||||||
|
if (*speed > 1024 * 1024 * 1024) {
|
||||||
|
float v = (float)*speed / 1024.0f / 1024.0f / 1024.0f;
|
||||||
|
if (v >= 1000) {
|
||||||
|
sprintf(str, "% 5.0f GB/s", v);
|
||||||
|
} else if (v >= 100) {
|
||||||
|
sprintf(str, "% 5.1f GB/s", v);
|
||||||
|
} else {
|
||||||
|
sprintf(str, "% 5.2f GB/s", v);
|
||||||
|
}
|
||||||
|
} else if (*speed > 1024 * 1024) {
|
||||||
|
float v = (float)*speed / 1024.0f / 1024.0f;
|
||||||
|
if (v >= 1000) {
|
||||||
|
sprintf(str, "% 5.0f MB/s", v);
|
||||||
|
} else if (v >= 100) {
|
||||||
|
sprintf(str, "% 5.1f MB/s", v);
|
||||||
|
} else {
|
||||||
|
sprintf(str, "% 5.2f MB/s", v);
|
||||||
|
}
|
||||||
|
} else if (*speed > 1024) {
|
||||||
|
float v = (float)*speed / 1024.0f;
|
||||||
|
if (v >= 1000) {
|
||||||
|
sprintf(str, "% 5.0f KB/s", v);
|
||||||
|
} else if (v >= 100) {
|
||||||
|
sprintf(str, "% 5.1f KB/s", v);
|
||||||
|
} else {
|
||||||
|
sprintf(str, "% 5.2f KB/s", v);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sprintf(str, "% 5d B/s", (uint8_t)*speed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gui_update_network_label_style(lv_obj_t *label, uint64_t *speed) {
|
||||||
|
if (*speed > 1024 * 1024 * 50 / 8) { // 50 Mbps
|
||||||
|
lv_obj_set_style_bg_color(label, lv_color_black(), LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_text_color(label, lv_color_white(), LV_PART_MAIN);
|
||||||
|
} else {
|
||||||
|
lv_obj_set_style_bg_color(label, lv_color_white(), LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_text_color(label, lv_color_black(), LV_PART_MAIN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gui_change_network_speed(uint64_t *direct_upload_speed,
|
||||||
|
uint64_t *direct_download_speed,
|
||||||
|
uint64_t *proxy_upload_speed,
|
||||||
|
uint64_t *proxy_download_speed) {
|
||||||
|
if (gui_network_speed_panel == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
static char str[32];
|
||||||
|
|
||||||
|
strcpy(str, APP_UP_SYMBOL);
|
||||||
|
gui_network_speed_human_readable(direct_upload_speed, &str[3]);
|
||||||
|
lv_label_set_text(gui_network_speed_panel->direct_upload_label, str);
|
||||||
|
gui_network_speed_human_readable(proxy_upload_speed, &str[3]);
|
||||||
|
lv_label_set_text(gui_network_speed_panel->proxy_upload_label, str);
|
||||||
|
|
||||||
|
strcpy(str, APP_DOWN_SYMBOL);
|
||||||
|
gui_network_speed_human_readable(direct_download_speed, &str[3]);
|
||||||
|
lv_label_set_text(gui_network_speed_panel->direct_download_label, str);
|
||||||
|
gui_network_speed_human_readable(proxy_download_speed, &str[3]);
|
||||||
|
lv_label_set_text(gui_network_speed_panel->proxy_download_label, str);
|
||||||
|
|
||||||
|
gui_update_network_label_style(gui_network_speed_panel->direct_upload_label,
|
||||||
|
direct_upload_speed);
|
||||||
|
gui_update_network_label_style(gui_network_speed_panel->direct_download_label,
|
||||||
|
direct_download_speed);
|
||||||
|
gui_update_network_label_style(gui_network_speed_panel->proxy_upload_label,
|
||||||
|
proxy_upload_speed);
|
||||||
|
gui_update_network_label_style(gui_network_speed_panel->proxy_download_label,
|
||||||
|
proxy_download_speed);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gui_init_network_speed(lv_obj_t *scr) {
|
||||||
|
gui_network_speed_panel =
|
||||||
|
(gui_network_speed_panel_t *)malloc(sizeof(gui_network_speed_panel_t));
|
||||||
|
|
||||||
|
gui_network_speed_panel->panel = lv_obj_create(scr);
|
||||||
|
lv_obj_set_size(gui_network_speed_panel->panel, 128, 40);
|
||||||
|
lv_obj_align(gui_network_speed_panel->panel, LV_ALIGN_BOTTOM_MID, 0, 0);
|
||||||
|
lv_obj_set_style_bg_color(gui_network_speed_panel->panel, lv_color_white(),
|
||||||
|
LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_border_color(gui_network_speed_panel->panel,
|
||||||
|
lv_color_black(), LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_border_width(gui_network_speed_panel->panel, 1,
|
||||||
|
LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_radius(gui_network_speed_panel->panel, 5, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_pad_hor(gui_network_speed_panel->panel, 1, LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_pad_ver(gui_network_speed_panel->panel, 1, LV_PART_MAIN);
|
||||||
|
|
||||||
|
gui_network_speed_panel->direct_upload_label =
|
||||||
|
lv_label_create(gui_network_speed_panel->panel);
|
||||||
|
lv_obj_align(gui_network_speed_panel->direct_upload_label, LV_ALIGN_TOP_LEFT,
|
||||||
|
0, 0);
|
||||||
|
lv_obj_set_style_text_font(gui_network_speed_panel->direct_upload_label,
|
||||||
|
&app_10, LV_PART_MAIN);
|
||||||
|
lv_label_set_text(gui_network_speed_panel->direct_upload_label,
|
||||||
|
APP_UP_SYMBOL " 0.00 KB/s");
|
||||||
|
lv_obj_set_style_bg_opa(gui_network_speed_panel->direct_upload_label,
|
||||||
|
LV_OPA_COVER, LV_PART_MAIN);
|
||||||
|
|
||||||
|
gui_network_speed_panel->direct_download_label =
|
||||||
|
lv_label_create(gui_network_speed_panel->panel);
|
||||||
|
lv_obj_align(gui_network_speed_panel->direct_download_label,
|
||||||
|
LV_ALIGN_BOTTOM_LEFT, 0, 0);
|
||||||
|
lv_obj_set_style_text_font(gui_network_speed_panel->direct_download_label,
|
||||||
|
&app_10, LV_PART_MAIN);
|
||||||
|
lv_label_set_text(gui_network_speed_panel->direct_download_label,
|
||||||
|
APP_DOWN_SYMBOL " 0.00 KB/s");
|
||||||
|
lv_obj_set_style_bg_opa(gui_network_speed_panel->direct_download_label,
|
||||||
|
LV_OPA_COVER, LV_PART_MAIN);
|
||||||
|
|
||||||
|
gui_network_speed_panel->proxy_upload_label =
|
||||||
|
lv_label_create(gui_network_speed_panel->panel);
|
||||||
|
lv_obj_align(gui_network_speed_panel->proxy_upload_label, LV_ALIGN_TOP_RIGHT,
|
||||||
|
0, 0);
|
||||||
|
lv_obj_set_style_text_font(gui_network_speed_panel->proxy_upload_label,
|
||||||
|
&app_10, LV_PART_MAIN);
|
||||||
|
lv_label_set_text(gui_network_speed_panel->proxy_upload_label,
|
||||||
|
APP_UP_SYMBOL " 0.00 KB/s");
|
||||||
|
lv_obj_set_style_bg_opa(gui_network_speed_panel->proxy_upload_label,
|
||||||
|
LV_OPA_COVER, LV_PART_MAIN);
|
||||||
|
|
||||||
|
gui_network_speed_panel->proxy_download_label =
|
||||||
|
lv_label_create(gui_network_speed_panel->panel);
|
||||||
|
lv_obj_align(gui_network_speed_panel->proxy_download_label,
|
||||||
|
LV_ALIGN_BOTTOM_RIGHT, 0, 0);
|
||||||
|
lv_obj_set_style_text_font(gui_network_speed_panel->proxy_download_label,
|
||||||
|
&app_10, LV_PART_MAIN);
|
||||||
|
lv_label_set_text(gui_network_speed_panel->proxy_download_label,
|
||||||
|
APP_DOWN_SYMBOL " 0.00 KB/s");
|
||||||
|
lv_obj_set_style_bg_opa(gui_network_speed_panel->proxy_download_label,
|
||||||
|
LV_OPA_COVER, LV_PART_MAIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gui_status_bar_create(lv_obj_t *scr) {
|
||||||
|
// wifi icon
|
||||||
|
wifi_label = lv_label_create(scr);
|
||||||
|
lv_label_set_long_mode(wifi_label, LV_LABEL_LONG_SCROLL_CIRCULAR);
|
||||||
|
lv_label_set_text(wifi_label, APP_WIFI_GOOD_SYMBOL);
|
||||||
|
lv_obj_set_width(wifi_label, 10);
|
||||||
|
lv_obj_align(wifi_label, LV_ALIGN_OUT_TOP_LEFT, 0, 0);
|
||||||
|
lv_obj_set_style_text_color(wifi_label, lv_color_black(), LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_text_font(wifi_label, &app_icon_8, LV_PART_MAIN);
|
||||||
|
lv_obj_add_flag(wifi_label, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
|
||||||
|
// timer icon
|
||||||
|
timer_label = lv_label_create(scr);
|
||||||
|
lv_label_set_long_mode(timer_label, LV_LABEL_LONG_SCROLL_CIRCULAR);
|
||||||
|
lv_label_set_text(timer_label, APP_TIMER_SYMBOL);
|
||||||
|
lv_obj_set_width(timer_label, 10);
|
||||||
|
lv_obj_align(timer_label, LV_ALIGN_OUT_TOP_LEFT, 12, 0);
|
||||||
|
lv_obj_set_style_text_color(timer_label, lv_color_black(), LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_text_font(timer_label, &app_icon_8, LV_PART_MAIN);
|
||||||
|
lv_obj_add_flag(timer_label, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
|
||||||
|
// desktop icon
|
||||||
|
desktop_label = lv_label_create(scr);
|
||||||
|
lv_label_set_long_mode(desktop_label, LV_LABEL_LONG_SCROLL_CIRCULAR);
|
||||||
|
lv_label_set_text(desktop_label, APP_CONNECTED_SYMBOL);
|
||||||
|
lv_obj_set_width(desktop_label, 10);
|
||||||
|
lv_obj_align(desktop_label, LV_ALIGN_OUT_TOP_LEFT, 24, 0);
|
||||||
|
lv_obj_set_style_text_color(desktop_label, lv_color_black(), LV_PART_MAIN);
|
||||||
|
lv_obj_set_style_text_font(desktop_label, &app_icon_8, LV_PART_MAIN);
|
||||||
|
lv_obj_add_flag(desktop_label, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void example_lvgl_demo_ui(lv_disp_t *disp) {
|
||||||
|
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 Ivan Li!");
|
||||||
|
lv_obj_set_width(label, 120);
|
||||||
|
lv_obj_align(label, LV_ALIGN_BOTTOM_RIGHT, 0, 0);
|
||||||
|
|
||||||
|
gui_status_bar_create(scr);
|
||||||
|
gui_init_network_speed(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,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "driver/gpio.h"
|
|
||||||
#include "freeRTOS/FreeRTOS.h"
|
|
||||||
|
|
||||||
#define HW_MS03_INT_GPIO 6
|
|
||||||
#define BEEP_GPIO 7
|
|
||||||
|
|
||||||
void hw_ms03_int_handler(void *arg) {
|
|
||||||
gpio_set_level(BEEP_GPIO, gpio_get_level(HW_MS03_INT_GPIO));
|
|
||||||
}
|
|
||||||
|
|
||||||
void hw_ms03_init() {
|
|
||||||
gpio_config_t io_conf = {};
|
|
||||||
|
|
||||||
io_conf.mode = GPIO_MODE_INPUT;
|
|
||||||
io_conf.pull_up_en = 0;
|
|
||||||
io_conf.pull_down_en = 1;
|
|
||||||
io_conf.intr_type = GPIO_INTR_ANYEDGE;
|
|
||||||
io_conf.pin_bit_mask = 1ULL << HW_MS03_INT_GPIO;
|
|
||||||
gpio_config(&io_conf);
|
|
||||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
|
||||||
io_conf.pin_bit_mask = 1ULL << BEEP_GPIO;
|
|
||||||
io_conf.pull_down_en = 0;
|
|
||||||
gpio_config(&io_conf);
|
|
||||||
|
|
||||||
gpio_isr_handler_add(HW_MS03_INT_GPIO, hw_ms03_int_handler, NULL);
|
|
||||||
}
|
|
@ -54,7 +54,7 @@ uint8_t i2c_check_slave_exists(uint8_t address) {
|
|||||||
i2c_master_start(cmd);
|
i2c_master_start(cmd);
|
||||||
i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
|
i2c_master_write_byte(cmd, (address << 1) | I2C_MASTER_WRITE, ACK_CHECK_EN);
|
||||||
i2c_master_stop(cmd);
|
i2c_master_stop(cmd);
|
||||||
esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 50 / portTICK_RATE_MS);
|
esp_err_t ret = i2c_master_cmd_begin(I2C_NUM_0, cmd, 50 / portTICK_PERIOD_MS);
|
||||||
i2c_cmd_link_delete(cmd);
|
i2c_cmd_link_delete(cmd);
|
||||||
|
|
||||||
if (ret == ESP_OK) {
|
if (ret == ESP_OK) {
|
||||||
|
18
main/idf_component.yml
Normal file
18
main/idf_component.yml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
## IDF Component Manager Manifest File
|
||||||
|
dependencies:
|
||||||
|
lvgl/lvgl: "^8.3.6~1"
|
||||||
|
espressif/mdns: "^1.0.9"
|
||||||
|
## Required IDF version
|
||||||
|
idf:
|
||||||
|
version: ">=5.0.1"
|
||||||
|
# # Put list of dependencies here
|
||||||
|
# # For components maintained by Espressif:
|
||||||
|
# component: "~1.0.0"
|
||||||
|
# # For 3rd party components:
|
||||||
|
# username/component: ">=1.0.0,<2.0.0"
|
||||||
|
# username2/component2:
|
||||||
|
# version: "~1.0.0"
|
||||||
|
# # For transient dependencies `public` flag can be set.
|
||||||
|
# # `public` flag doesn't have an effect dependencies of the `main` component.
|
||||||
|
# # All dependencies of `main` are public by default.
|
||||||
|
# public: true
|
141
main/led_strip_encoder/led_strip_encoder.c
Normal file
141
main/led_strip_encoder/led_strip_encoder.c
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "led_strip_encoder.h"
|
||||||
|
|
||||||
|
#include "esp_check.h"
|
||||||
|
|
||||||
|
static const char *TAG = "led_encoder";
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
rmt_encoder_t base;
|
||||||
|
rmt_encoder_t *bytes_encoder;
|
||||||
|
rmt_encoder_t *copy_encoder;
|
||||||
|
int state;
|
||||||
|
rmt_symbol_word_t reset_code;
|
||||||
|
} rmt_led_strip_encoder_t;
|
||||||
|
|
||||||
|
static size_t rmt_encode_led_strip(rmt_encoder_t *encoder,
|
||||||
|
rmt_channel_handle_t channel,
|
||||||
|
const void *primary_data, size_t data_size,
|
||||||
|
rmt_encode_state_t *ret_state) {
|
||||||
|
rmt_led_strip_encoder_t *led_encoder =
|
||||||
|
__containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||||
|
rmt_encoder_handle_t bytes_encoder = led_encoder->bytes_encoder;
|
||||||
|
rmt_encoder_handle_t copy_encoder = led_encoder->copy_encoder;
|
||||||
|
rmt_encode_state_t session_state = 0;
|
||||||
|
rmt_encode_state_t state = 0;
|
||||||
|
size_t encoded_symbols = 0;
|
||||||
|
switch (led_encoder->state) {
|
||||||
|
case 0: // send RGB data
|
||||||
|
encoded_symbols += bytes_encoder->encode(
|
||||||
|
bytes_encoder, channel, primary_data, data_size, &session_state);
|
||||||
|
if (session_state & RMT_ENCODING_COMPLETE) {
|
||||||
|
led_encoder->state =
|
||||||
|
1; // switch to next state when current encoding session finished
|
||||||
|
}
|
||||||
|
if (session_state & RMT_ENCODING_MEM_FULL) {
|
||||||
|
state |= RMT_ENCODING_MEM_FULL;
|
||||||
|
goto out; // yield if there's no free space for encoding artifacts
|
||||||
|
}
|
||||||
|
// fall-through
|
||||||
|
case 1: // send reset code
|
||||||
|
encoded_symbols +=
|
||||||
|
copy_encoder->encode(copy_encoder, channel, &led_encoder->reset_code,
|
||||||
|
sizeof(led_encoder->reset_code), &session_state);
|
||||||
|
if (session_state & RMT_ENCODING_COMPLETE) {
|
||||||
|
led_encoder->state = 0; // back to the initial encoding session
|
||||||
|
state |= RMT_ENCODING_COMPLETE;
|
||||||
|
}
|
||||||
|
if (session_state & RMT_ENCODING_MEM_FULL) {
|
||||||
|
state |= RMT_ENCODING_MEM_FULL;
|
||||||
|
goto out; // yield if there's no free space for encoding artifacts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
*ret_state = state;
|
||||||
|
return encoded_symbols;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t rmt_del_led_strip_encoder(rmt_encoder_t *encoder) {
|
||||||
|
rmt_led_strip_encoder_t *led_encoder =
|
||||||
|
__containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||||
|
rmt_del_encoder(led_encoder->bytes_encoder);
|
||||||
|
rmt_del_encoder(led_encoder->copy_encoder);
|
||||||
|
free(led_encoder);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t rmt_led_strip_encoder_reset(rmt_encoder_t *encoder) {
|
||||||
|
rmt_led_strip_encoder_t *led_encoder =
|
||||||
|
__containerof(encoder, rmt_led_strip_encoder_t, base);
|
||||||
|
rmt_encoder_reset(led_encoder->bytes_encoder);
|
||||||
|
rmt_encoder_reset(led_encoder->copy_encoder);
|
||||||
|
led_encoder->state = 0;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t *config,
|
||||||
|
rmt_encoder_handle_t *ret_encoder) {
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
rmt_led_strip_encoder_t *led_encoder = NULL;
|
||||||
|
ESP_GOTO_ON_FALSE(config && ret_encoder, ESP_ERR_INVALID_ARG, err, TAG,
|
||||||
|
"invalid argument");
|
||||||
|
led_encoder = calloc(1, sizeof(rmt_led_strip_encoder_t));
|
||||||
|
ESP_GOTO_ON_FALSE(led_encoder, ESP_ERR_NO_MEM, err, TAG,
|
||||||
|
"no mem for led strip encoder");
|
||||||
|
led_encoder->base.encode = rmt_encode_led_strip;
|
||||||
|
led_encoder->base.del = rmt_del_led_strip_encoder;
|
||||||
|
led_encoder->base.reset = rmt_led_strip_encoder_reset;
|
||||||
|
// different led strip might have its own timing requirements, following
|
||||||
|
// parameter is for WS2812
|
||||||
|
rmt_bytes_encoder_config_t bytes_encoder_config = {
|
||||||
|
.bit0 =
|
||||||
|
{
|
||||||
|
.level0 = 1,
|
||||||
|
.duration0 = 0.3 * config->resolution / 1000000, // T0H=0.3us
|
||||||
|
.level1 = 0,
|
||||||
|
.duration1 = 0.9 * config->resolution / 1000000, // T0L=0.9us
|
||||||
|
},
|
||||||
|
.bit1 =
|
||||||
|
{
|
||||||
|
.level0 = 1,
|
||||||
|
.duration0 = 0.9 * config->resolution / 1000000, // T1H=0.9us
|
||||||
|
.level1 = 0,
|
||||||
|
.duration1 = 0.3 * config->resolution / 1000000, // T1L=0.3us
|
||||||
|
},
|
||||||
|
.flags.msb_first = 1 // WS2812 transfer bit order: G7...G0R7...R0B7...B0
|
||||||
|
};
|
||||||
|
ESP_GOTO_ON_ERROR(
|
||||||
|
rmt_new_bytes_encoder(&bytes_encoder_config, &led_encoder->bytes_encoder),
|
||||||
|
err, TAG, "create bytes encoder failed");
|
||||||
|
rmt_copy_encoder_config_t copy_encoder_config = {};
|
||||||
|
ESP_GOTO_ON_ERROR(
|
||||||
|
rmt_new_copy_encoder(©_encoder_config, &led_encoder->copy_encoder),
|
||||||
|
err, TAG, "create copy encoder failed");
|
||||||
|
|
||||||
|
uint32_t reset_ticks = config->resolution / 1000000 * 50 /
|
||||||
|
2; // reset code duration defaults to 50us
|
||||||
|
led_encoder->reset_code = (rmt_symbol_word_t){
|
||||||
|
.level0 = 0,
|
||||||
|
.duration0 = reset_ticks,
|
||||||
|
.level1 = 0,
|
||||||
|
.duration1 = reset_ticks,
|
||||||
|
};
|
||||||
|
*ret_encoder = &led_encoder->base;
|
||||||
|
return ESP_OK;
|
||||||
|
err:
|
||||||
|
if (led_encoder) {
|
||||||
|
if (led_encoder->bytes_encoder) {
|
||||||
|
rmt_del_encoder(led_encoder->bytes_encoder);
|
||||||
|
}
|
||||||
|
if (led_encoder->copy_encoder) {
|
||||||
|
rmt_del_encoder(led_encoder->copy_encoder);
|
||||||
|
}
|
||||||
|
free(led_encoder);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
38
main/led_strip_encoder/led_strip_encoder.h
Normal file
38
main/led_strip_encoder/led_strip_encoder.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "driver/rmt_encoder.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type of led strip encoder configuration
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint32_t resolution; /*!< Encoder resolution, in Hz */
|
||||||
|
} led_strip_encoder_config_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create RMT encoder for encoding LED strip pixels into RMT symbols
|
||||||
|
*
|
||||||
|
* @param[in] config Encoder configuration
|
||||||
|
* @param[out] ret_encoder Returned encoder handle
|
||||||
|
* @return
|
||||||
|
* - ESP_ERR_INVALID_ARG for any invalid arguments
|
||||||
|
* - ESP_ERR_NO_MEM out of memory when creating led strip encoder
|
||||||
|
* - ESP_OK if creating encoder successfully
|
||||||
|
*/
|
||||||
|
esp_err_t rmt_new_led_strip_encoder(const led_strip_encoder_config_t *config,
|
||||||
|
rmt_encoder_handle_t *ret_encoder);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
423
main/light.c
423
main/light.c
@ -1,25 +1,22 @@
|
|||||||
/* RMT example -- RGB LED Strip
|
|
||||||
|
|
||||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, this
|
|
||||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
||||||
CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
*/
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "driver/rmt.h"
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "driver/rmt_tx.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
#include "esp_system.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "led_strip.h"
|
#include "led_strip_encoder/led_strip_encoder.h"
|
||||||
|
#include "nvs.h"
|
||||||
|
#include "nvs_flash.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
static const char *LIGHT_TAG = "DisplayAmbientLight_Light";
|
static const char *LIGHT_TAG = "DisplayAmbientLight_Light";
|
||||||
|
|
||||||
#define RMT_TX_CHANNEL RMT_CHANNEL_0
|
|
||||||
#define RMT_TX_GPIO 1
|
#define RMT_TX_GPIO 1
|
||||||
#define STRIP_LED_NUMBER CONFIG_NUMBER_OF_LEDS
|
#define STRIP_LED_NUMBER CONFIG_NUMBER_OF_LEDS
|
||||||
#define EXAMPLE_CHASE_SPEED_MS (10)
|
#define EXAMPLE_CHASE_SPEED_MS (10)
|
||||||
|
#define RMT_LED_STRIP_RESOLUTION_HZ 10000000
|
||||||
|
|
||||||
typedef enum light_mode_e {
|
typedef enum light_mode_e {
|
||||||
light_mode_init = 0,
|
light_mode_init = 0,
|
||||||
@ -31,11 +28,21 @@ typedef enum light_mode_e {
|
|||||||
light_mode_off = 6,
|
light_mode_off = 6,
|
||||||
} light_mode_t;
|
} light_mode_t;
|
||||||
|
|
||||||
led_strip_t *light_led_strip;
|
rmt_channel_handle_t led_chan = NULL;
|
||||||
|
static uint8_t led_strip_pixels[STRIP_LED_NUMBER * 3];
|
||||||
|
rmt_encoder_handle_t led_encoder = NULL;
|
||||||
|
rmt_transmit_config_t tx_config = {
|
||||||
|
.loop_count = 0, // no transfer loop
|
||||||
|
};
|
||||||
|
|
||||||
light_mode_t light_mode;
|
light_mode_t light_mode;
|
||||||
float display_ambient_light_brightness = 1;
|
float display_ambient_light_brightness = 1;
|
||||||
uint8_t display_ambient_lighting_level = 255;
|
uint8_t display_ambient_lighting_level = 255;
|
||||||
|
|
||||||
|
float led_strip_red_calibration = 1.0;
|
||||||
|
float led_strip_green_calibration = 1.0;
|
||||||
|
float led_strip_blue_calibration = 1.0;
|
||||||
|
|
||||||
void led_strip_fade_in_light_level(void *pvParameter) {
|
void led_strip_fade_in_light_level(void *pvParameter) {
|
||||||
float target = (float)display_ambient_lighting_level / 255.0;
|
float target = (float)display_ambient_lighting_level / 255.0;
|
||||||
float step_length = (target - display_ambient_light_brightness) / 40.0;
|
float step_length = (target - display_ambient_light_brightness) / 40.0;
|
||||||
@ -55,6 +62,78 @@ void led_strip_set_brightness(uint8_t level) {
|
|||||||
|
|
||||||
xTaskCreate(led_strip_fade_in_light_level, "LED_STRIP_FADE_IN_LIGHT_LEVEL",
|
xTaskCreate(led_strip_fade_in_light_level, "LED_STRIP_FADE_IN_LIGHT_LEVEL",
|
||||||
4096, NULL, 1, NULL);
|
4096, NULL, 1, NULL);
|
||||||
|
|
||||||
|
nvs_handle_t nvs_handle;
|
||||||
|
esp_err_t err = nvs_open("storage", NVS_READWRITE, &nvs_handle);
|
||||||
|
err = nvs_set_u8(nvs_handle, "brightness", level);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGW(LIGHT_TAG, "Error (%s) saving light level!\n",
|
||||||
|
esp_err_to_name(err));
|
||||||
|
nvs_close(nvs_handle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
err = nvs_commit(nvs_handle);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGW(LIGHT_TAG, "Error (%s) saving light level!\n",
|
||||||
|
esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
nvs_close(nvs_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_strip_set_color_calibration(float red, float green, float blue) {
|
||||||
|
led_strip_red_calibration = red;
|
||||||
|
led_strip_green_calibration = green;
|
||||||
|
led_strip_blue_calibration = blue;
|
||||||
|
|
||||||
|
ESP_LOGI(LIGHT_TAG, "Calibration: %f %f %f", red, green, blue);
|
||||||
|
|
||||||
|
nvs_handle_t local_nvs_handle;
|
||||||
|
|
||||||
|
esp_err_t err = nvs_open("storage", NVS_READWRITE, &local_nvs_handle);
|
||||||
|
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGW(LIGHT_TAG, "Error (%s) opening NVS handle!\n",
|
||||||
|
esp_err_to_name(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = nvs_set_u8(local_nvs_handle, "calibration_r", (uint32_t)(red * 255));
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
nvs_close(local_nvs_handle);
|
||||||
|
ESP_LOGW(LIGHT_TAG, "Error (%s) write calibration_r failed!",
|
||||||
|
esp_err_to_name(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
err = nvs_set_u8(local_nvs_handle, "calibration_g", (uint8_t)(green * 255));
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
nvs_close(local_nvs_handle);
|
||||||
|
ESP_LOGW(LIGHT_TAG, "Error (%s) calibration_g failed!",
|
||||||
|
esp_err_to_name(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
err = nvs_set_u8(local_nvs_handle, "calibration_b", (uint8_t)(blue * 255));
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
nvs_close(local_nvs_handle);
|
||||||
|
ESP_LOGW(LIGHT_TAG, "Error (%s) calibration_b failed!",
|
||||||
|
esp_err_to_name(err));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = nvs_commit(local_nvs_handle);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGW(LIGHT_TAG, "Error (%s) save led_strip_red_calibration failed!",
|
||||||
|
esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
nvs_close(local_nvs_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void light_strip_transmit_task(void *pvParameter) {
|
||||||
|
while (1) {
|
||||||
|
ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels,
|
||||||
|
sizeof(led_strip_pixels), &tx_config));
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,68 +189,111 @@ void led_strip_hsv2rgb(uint32_t h, uint32_t s, uint32_t v, uint32_t *r,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void update_desktop_connection_state() {
|
// void update_desktop_connection_state() {
|
||||||
static uint8_t tick = 0;
|
// static uint8_t tick = 0;
|
||||||
|
|
||||||
bool beat = tick / 10 % 2 ? 1 : 0;
|
// bool beat = tick / 10 % 2 ? 1 : 0;
|
||||||
|
|
||||||
switch (light_mode) {
|
// switch (light_mode) {
|
||||||
case light_mode_desktop_online:
|
// case light_mode_desktop_online:
|
||||||
if (beat) {
|
// if (beat) {
|
||||||
ESP_ERROR_CHECK(
|
// led_strip_pixels[0] = 0;
|
||||||
light_led_strip->set_pixel(light_led_strip, 0, 10, 10, 10));
|
// led_strip_pixels[1] = 0;
|
||||||
}
|
// led_strip_pixels[2] = 0;
|
||||||
ESP_ERROR_CHECK(
|
// }
|
||||||
light_led_strip->set_pixel(light_led_strip, 1, 10, 10, 10));
|
// led_strip_pixels[3] = 10
|
||||||
ESP_ERROR_CHECK(
|
// break;
|
||||||
light_led_strip->set_pixel(light_led_strip, 2, 10, 10, 10));
|
// case light_mode_mqtt_connected:
|
||||||
break;
|
// if (beat) {
|
||||||
case light_mode_mqtt_connected:
|
// ESP_ERROR_CHECK(
|
||||||
if (beat) {
|
// light_led_strip->set_pixel(light_led_strip, 0, 10, 10, 10));
|
||||||
ESP_ERROR_CHECK(
|
// ESP_ERROR_CHECK(
|
||||||
light_led_strip->set_pixel(light_led_strip, 0, 10, 10, 10));
|
// light_led_strip->set_pixel(light_led_strip, 1, 10, 10, 10));
|
||||||
ESP_ERROR_CHECK(
|
// }
|
||||||
light_led_strip->set_pixel(light_led_strip, 1, 10, 10, 10));
|
// ESP_ERROR_CHECK(
|
||||||
}
|
// light_led_strip->set_pixel(light_led_strip, 2, 22, 22, 22));
|
||||||
ESP_ERROR_CHECK(
|
// break;
|
||||||
light_led_strip->set_pixel(light_led_strip, 2, 22, 22, 22));
|
// case light_mode_idle:
|
||||||
break;
|
// if (beat) {
|
||||||
case light_mode_idle:
|
// ESP_ERROR_CHECK(
|
||||||
if (beat) {
|
// light_led_strip->set_pixel(light_led_strip, 0, 77, 77, 77));
|
||||||
ESP_ERROR_CHECK(
|
// ESP_ERROR_CHECK(
|
||||||
light_led_strip->set_pixel(light_led_strip, 0, 77, 77, 77));
|
// light_led_strip->set_pixel(light_led_strip, 1, 77, 77, 77));
|
||||||
ESP_ERROR_CHECK(
|
// ESP_ERROR_CHECK(
|
||||||
light_led_strip->set_pixel(light_led_strip, 1, 77, 77, 77));
|
// light_led_strip->set_pixel(light_led_strip, 2, 77, 77, 77));
|
||||||
ESP_ERROR_CHECK(
|
// }
|
||||||
light_led_strip->set_pixel(light_led_strip, 2, 77, 77, 77));
|
// break;
|
||||||
}
|
// default:
|
||||||
break;
|
// break;
|
||||||
default:
|
// }
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
tick++;
|
// tick++;
|
||||||
}
|
// }
|
||||||
|
|
||||||
void light_for_init() {
|
void light_for_init() {
|
||||||
ESP_LOGI(LIGHT_TAG, "light_for_init");
|
ESP_LOGI(LIGHT_TAG, "light_for_init");
|
||||||
ESP_ERROR_CHECK(light_led_strip->clear(light_led_strip, 100));
|
|
||||||
|
|
||||||
uint32_t red = 0, green = 0, blue = 0;
|
memset(led_strip_pixels, 0, sizeof(led_strip_pixels));
|
||||||
int8_t i = 0;
|
|
||||||
|
nvs_handle local_nvs_handle;
|
||||||
|
esp_err_t err = nvs_open("storage", NVS_READWRITE, &local_nvs_handle);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGW(LIGHT_TAG, "Error (%s) opening NVS handle!", esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t r = 255, g = 255, b = 255;
|
||||||
|
uint8_t brightness = 200;
|
||||||
|
err = nvs_get_u8(local_nvs_handle, "calibration_r", &r);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGW(LIGHT_TAG, "Error (%s) reading calibration_r!",
|
||||||
|
esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
err = nvs_get_u8(local_nvs_handle, "calibration_g", &g);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGW(LIGHT_TAG, "Error (%s) reading calibration_g!",
|
||||||
|
esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
err = nvs_get_u8(local_nvs_handle, "calibration_b", &b);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGW(LIGHT_TAG, "Error (%s) reading calibration_b!",
|
||||||
|
esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
err = nvs_get_u8(local_nvs_handle, "brightness", &brightness);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGW(LIGHT_TAG, "Error (%s) reading brightness!", esp_err_to_name(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
nvs_close(local_nvs_handle);
|
||||||
|
|
||||||
|
// set brightness
|
||||||
|
led_strip_set_brightness(brightness);
|
||||||
|
|
||||||
|
// play init light
|
||||||
|
float r_f = (float)r / 255.0;
|
||||||
|
float g_f = (float)g / 255.0;
|
||||||
|
float b_f = (float)b / 255.0;
|
||||||
|
|
||||||
|
uint8_t init_r, init_g, init_b;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
for (; i < 100; i++) {
|
for (uint8_t i = 0; i < 200; i++) {
|
||||||
|
init_r = (uint8_t)(r_f * (float)i);
|
||||||
|
init_g = (uint8_t)(g_f * (float)i);
|
||||||
|
init_b = (uint8_t)(b_f * (float)i);
|
||||||
|
|
||||||
for (int j = 0; j < STRIP_LED_NUMBER; j++) {
|
for (int j = 0; j < STRIP_LED_NUMBER; j++) {
|
||||||
led_strip_hsv2rgb(0, 0, i, &red, &green, &blue);
|
led_strip_pixels[j * 3 + 0] = init_g;
|
||||||
ESP_ERROR_CHECK(
|
led_strip_pixels[j * 3 + 1] = init_r;
|
||||||
light_led_strip->set_pixel(light_led_strip, j, red, green, blue));
|
led_strip_pixels[j * 3 + 2] = init_b;
|
||||||
}
|
}
|
||||||
ESP_ERROR_CHECK(light_led_strip->refresh(light_led_strip, 100));
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
vTaskDelay(pdMS_TO_TICKS(20));
|
||||||
}
|
}
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
} while (light_mode == light_mode_init);
|
} while (light_mode == light_mode_init);
|
||||||
|
|
||||||
|
led_strip_set_color_calibration((float)r / 255.0, (float)g / 255.0,
|
||||||
|
(float)b / 255.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void light_for_connecting_wifi() {
|
void light_for_connecting_wifi() {
|
||||||
@ -180,11 +302,21 @@ void light_for_connecting_wifi() {
|
|||||||
int8_t tick_tock = 0;
|
int8_t tick_tock = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ESP_ERROR_CHECK(
|
if (tick_tock) {
|
||||||
light_led_strip->set_pixel(light_led_strip, tick_tock, 150, 150, 0));
|
led_strip_pixels[0] = 150;
|
||||||
ESP_ERROR_CHECK(light_led_strip->set_pixel(light_led_strip,
|
led_strip_pixels[1] = 150;
|
||||||
(tick_tock + 1) % 2, 0, 200, 0));
|
led_strip_pixels[2] = 0;
|
||||||
ESP_ERROR_CHECK(light_led_strip->refresh(light_led_strip, 100));
|
led_strip_pixels[3] = 200;
|
||||||
|
led_strip_pixels[4] = 0;
|
||||||
|
led_strip_pixels[5] = 0;
|
||||||
|
} else {
|
||||||
|
led_strip_pixels[0] = 200;
|
||||||
|
led_strip_pixels[1] = 0;
|
||||||
|
led_strip_pixels[2] = 0;
|
||||||
|
led_strip_pixels[3] = 150;
|
||||||
|
led_strip_pixels[4] = 150;
|
||||||
|
led_strip_pixels[5] = 0;
|
||||||
|
}
|
||||||
tick_tock = !tick_tock;
|
tick_tock = !tick_tock;
|
||||||
vTaskDelay(pdMS_TO_TICKS(200));
|
vTaskDelay(pdMS_TO_TICKS(200));
|
||||||
} while (light_mode == light_mode_connection_wifi);
|
} while (light_mode == light_mode_connection_wifi);
|
||||||
@ -192,7 +324,10 @@ void light_for_connecting_wifi() {
|
|||||||
|
|
||||||
void light_for_idle() {
|
void light_for_idle() {
|
||||||
ESP_LOGI(LIGHT_TAG, "light_for_idle");
|
ESP_LOGI(LIGHT_TAG, "light_for_idle");
|
||||||
ESP_ERROR_CHECK(light_led_strip->clear(light_led_strip, 100));
|
|
||||||
|
memset(led_strip_pixels, 0, sizeof(led_strip_pixels));
|
||||||
|
ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels,
|
||||||
|
sizeof(led_strip_pixels), &tx_config));
|
||||||
|
|
||||||
uint32_t red = 0, green = 0, blue = 0;
|
uint32_t red = 0, green = 0, blue = 0;
|
||||||
uint16_t step_length = 360 / STRIP_LED_NUMBER;
|
uint16_t step_length = 360 / STRIP_LED_NUMBER;
|
||||||
@ -206,22 +341,21 @@ void light_for_idle() {
|
|||||||
// Build RGB values
|
// Build RGB values
|
||||||
led_strip_hsv2rgb(hue, 50, 30, &red, &green, &blue);
|
led_strip_hsv2rgb(hue, 50, 30, &red, &green, &blue);
|
||||||
|
|
||||||
red = red * display_ambient_light_brightness;
|
led_strip_pixels[j * 3 + 0] = green * display_ambient_light_brightness *
|
||||||
green = green * display_ambient_light_brightness;
|
led_strip_green_calibration;
|
||||||
blue = blue * display_ambient_light_brightness;
|
led_strip_pixels[j * 3 + 1] =
|
||||||
// Write RGB values to strip driver
|
red * display_ambient_light_brightness * led_strip_red_calibration;
|
||||||
ESP_ERROR_CHECK(
|
led_strip_pixels[j * 3 + 2] =
|
||||||
light_led_strip->set_pixel(light_led_strip, j, red, green, blue));
|
blue * display_ambient_light_brightness * led_strip_blue_calibration;
|
||||||
}
|
}
|
||||||
update_desktop_connection_state();
|
// update_desktop_connection_state();
|
||||||
ESP_ERROR_CHECK(light_led_strip->refresh(light_led_strip, 100));
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void light_strip_running_task(void *pv_parameters) {
|
void light_strip_running_task(void *pv_parameters) {
|
||||||
while (true) {
|
while (true) {
|
||||||
if (!light_led_strip) {
|
if (!led_chan) {
|
||||||
ESP_LOGE(LIGHT_TAG, "install WS2812 driver failed 2");
|
ESP_LOGE(LIGHT_TAG, "install WS2812 driver failed 2");
|
||||||
}
|
}
|
||||||
switch (light_mode) {
|
switch (light_mode) {
|
||||||
@ -245,47 +379,76 @@ void light_strip_running_task(void *pv_parameters) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void light_init_strip() {
|
void light_init_strip() {
|
||||||
rmt_config_t config = RMT_DEFAULT_CONFIG_TX(RMT_TX_GPIO, RMT_TX_CHANNEL);
|
rmt_tx_channel_config_t tx_chan_config = {
|
||||||
// set counter clock to 40MHz
|
.clk_src = RMT_CLK_SRC_DEFAULT, // select source clock
|
||||||
config.clk_div = 2;
|
.gpio_num = RMT_TX_GPIO,
|
||||||
|
.mem_block_symbols =
|
||||||
|
64, // increase the block size can make the LED less flickering
|
||||||
|
.resolution_hz = RMT_LED_STRIP_RESOLUTION_HZ,
|
||||||
|
.trans_queue_depth = 4, // set the number of transactions that can be
|
||||||
|
// pending in the background
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_chan_config, &led_chan));
|
||||||
|
|
||||||
ESP_ERROR_CHECK(rmt_config(&config));
|
ESP_LOGI(LIGHT_TAG, "Install led strip encoder");
|
||||||
ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0));
|
|
||||||
|
|
||||||
// install ws2812 driver
|
led_strip_encoder_config_t encoder_config = {
|
||||||
led_strip_config_t strip_config = LED_STRIP_DEFAULT_CONFIG(
|
.resolution = RMT_LED_STRIP_RESOLUTION_HZ,
|
||||||
STRIP_LED_NUMBER, (led_strip_dev_t)config.channel);
|
};
|
||||||
light_led_strip = led_strip_new_rmt_ws2812(&strip_config);
|
ESP_ERROR_CHECK(rmt_new_led_strip_encoder(&encoder_config, &led_encoder));
|
||||||
if (!light_led_strip) {
|
|
||||||
ESP_LOGE(LIGHT_TAG, "install WS2812 driver failed");
|
ESP_LOGI(LIGHT_TAG, "Enable RMT TX channel");
|
||||||
}
|
ESP_ERROR_CHECK(rmt_enable(led_chan));
|
||||||
// Clear LED strip (turn off all LEDs)
|
|
||||||
ESP_ERROR_CHECK(light_led_strip->clear(light_led_strip, 100));
|
ESP_LOGI(LIGHT_TAG, "Start LED rainbow chase");
|
||||||
// Show simple rainbow chasing pattern
|
|
||||||
ESP_LOGI(LIGHT_TAG, "LED Rainbow Chase Start");
|
|
||||||
|
|
||||||
light_mode = light_mode_init;
|
light_mode = light_mode_init;
|
||||||
|
|
||||||
xTaskCreate(light_strip_running_task, "LIGHT_STRIP_RUNNING_TASK", 4096, NULL,
|
xTaskCreate(light_strip_running_task, "LIGHT_STRIP_RUNNING_TASK", 4096, NULL,
|
||||||
1, NULL);
|
1, NULL);
|
||||||
|
|
||||||
|
xTaskCreate(light_strip_transmit_task, "LIGHT_STRIP_TRANSMIT_TASK", 4096,
|
||||||
|
NULL, 1, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void light_play_colors(uint16_t len, uint8_t *buffer) {
|
void light_play_colors(uint16_t len, uint8_t *buffer) {
|
||||||
light_mode = light_mode_desktop_sending_colors;
|
// light_mode = light_mode_desktop_sending_colors;
|
||||||
|
|
||||||
for (uint16_t led_index = 0, buffer_cursor = 0;
|
// uint16_t black_count = 0; // count of black pixels. r/g/b <= 10
|
||||||
led_index < STRIP_LED_NUMBER && buffer_cursor < len;
|
|
||||||
led_index++, buffer_cursor += 3) {
|
// for (uint16_t led_index = 0, buffer_cursor = 0;
|
||||||
uint8_t r = (uint8_t)((float)buffer[buffer_cursor] *
|
// led_index < STRIP_LED_NUMBER && buffer_cursor < len;
|
||||||
display_ambient_light_brightness),
|
// led_index++, buffer_cursor += 3) {
|
||||||
g = (uint8_t)((float)buffer[buffer_cursor + 1] *
|
// uint8_t r = (uint8_t)((float)buffer[buffer_cursor] *
|
||||||
display_ambient_light_brightness),
|
// display_ambient_light_brightness *
|
||||||
b = (uint8_t)((float)buffer[buffer_cursor + 2] *
|
// led_strip_red_calibration),
|
||||||
display_ambient_light_brightness);
|
// g = (uint8_t)((float)buffer[buffer_cursor + 1] *
|
||||||
ESP_ERROR_CHECK(
|
// display_ambient_light_brightness *
|
||||||
light_led_strip->set_pixel(light_led_strip, led_index, r, g, b));
|
// led_strip_green_calibration),
|
||||||
}
|
// b = (uint8_t)((float)buffer[buffer_cursor + 2] *
|
||||||
ESP_ERROR_CHECK(light_led_strip->refresh(light_led_strip, 100));
|
// display_ambient_light_brightness *
|
||||||
|
// led_strip_blue_calibration);
|
||||||
|
// if (r <= 7 && g <= 7 && b <= 7) {
|
||||||
|
// black_count++;
|
||||||
|
// }
|
||||||
|
// led_strip_pixels[led_index * 3 + 0] = g;
|
||||||
|
// led_strip_pixels[led_index * 3 + 1] = r;
|
||||||
|
// led_strip_pixels[led_index * 3 + 2] = b;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (black_count > STRIP_LED_NUMBER / 5 * 4) {
|
||||||
|
// uint8_t r = (uint8_t)((float)50 * display_ambient_light_brightness *
|
||||||
|
// led_strip_red_calibration),
|
||||||
|
// g = (uint8_t)((float)40 * display_ambient_light_brightness *
|
||||||
|
// led_strip_green_calibration),
|
||||||
|
// b = (uint8_t)((float)20 * display_ambient_light_brightness *
|
||||||
|
// led_strip_blue_calibration);
|
||||||
|
// for (uint16_t led_index = 0; led_index < STRIP_LED_NUMBER; led_index++) {
|
||||||
|
// led_strip_pixels[led_index * 3 + 0] = g;
|
||||||
|
// led_strip_pixels[led_index * 3 + 1] = r;
|
||||||
|
// led_strip_pixels[led_index * 3 + 2] = b;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,3 +456,53 @@ void light_play(light_mode_t mode) {
|
|||||||
ESP_LOGI(LIGHT_TAG, "light_play: %d", mode);
|
ESP_LOGI(LIGHT_TAG, "light_play: %d", mode);
|
||||||
light_mode = mode;
|
light_mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void set_display_ambient_light_colors(uint16_t offset, uint8_t *sub_pixels,
|
||||||
|
uint16_t len) {
|
||||||
|
// ESP_LOGI(LIGHT_TAG, "set_display_ambient_light_colors: offset: %d\t len:
|
||||||
|
// %d",
|
||||||
|
// offset, len);
|
||||||
|
light_mode = light_mode_desktop_sending_colors;
|
||||||
|
|
||||||
|
uint16_t black_count = 0; // count of black pixels. r/g/b <= 7
|
||||||
|
|
||||||
|
uint16_t global_end = len + offset * 3;
|
||||||
|
|
||||||
|
if (global_end > STRIP_LED_NUMBER * 3) {
|
||||||
|
global_end = STRIP_LED_NUMBER * 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint16_t global_index = offset * 3, local_index = 0;
|
||||||
|
global_index < global_end; global_index += 3, local_index += 3) {
|
||||||
|
uint8_t r = (uint8_t)((float)sub_pixels[local_index + 0] *
|
||||||
|
display_ambient_light_brightness *
|
||||||
|
led_strip_red_calibration),
|
||||||
|
g = (uint8_t)((float)sub_pixels[local_index + 1] *
|
||||||
|
display_ambient_light_brightness *
|
||||||
|
led_strip_green_calibration),
|
||||||
|
b = (uint8_t)((float)sub_pixels[local_index + 2] *
|
||||||
|
display_ambient_light_brightness *
|
||||||
|
led_strip_blue_calibration);
|
||||||
|
if (r <= 7 && g <= 7 && b <= 7) {
|
||||||
|
black_count++;
|
||||||
|
}
|
||||||
|
led_strip_pixels[global_index + 0] = g;
|
||||||
|
led_strip_pixels[global_index + 1] = r;
|
||||||
|
led_strip_pixels[global_index + 2] = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (black_count == len / 3) {
|
||||||
|
uint8_t r = (uint8_t)((float)10 * display_ambient_light_brightness *
|
||||||
|
led_strip_red_calibration),
|
||||||
|
g = (uint8_t)((float)7 * display_ambient_light_brightness *
|
||||||
|
led_strip_green_calibration),
|
||||||
|
b = (uint8_t)((float)7 * display_ambient_light_brightness *
|
||||||
|
led_strip_blue_calibration);
|
||||||
|
for (uint16_t global_index = offset * 3; global_index < global_end;
|
||||||
|
global_index += 3) {
|
||||||
|
led_strip_pixels[global_index + 0] = g;
|
||||||
|
led_strip_pixels[global_index + 1] = r;
|
||||||
|
led_strip_pixels[global_index + 2] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
72
main/main.c
72
main/main.c
@ -1,53 +1,69 @@
|
|||||||
#include "apds_9960.c"
|
// #include "apds_9960.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 "hw-ms03.c"
|
#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 "temperature.c"
|
#include "service_discovery.c"
|
||||||
|
// #include "temperature.c"
|
||||||
|
#include "desktop.c"
|
||||||
|
#include "net_gateway_monitor.c"
|
||||||
#include "ui_input.c"
|
#include "ui_input.c"
|
||||||
#include "wifi.c"
|
#include "wifi.c"
|
||||||
|
|
||||||
static const char *TAG = "DisplayAmbientLight";
|
static const char *APP_TAG = "DisplayAmbientLight";
|
||||||
|
|
||||||
void app_main(void) {
|
void app_main(void) {
|
||||||
|
app_nvs_init();
|
||||||
light_init_strip();
|
light_init_strip();
|
||||||
|
|
||||||
gpio_install_isr_service(0);
|
gpio_install_isr_service(0);
|
||||||
init_i2c();
|
init_i2c();
|
||||||
i2c_check_slaves();
|
i2c_check_slaves();
|
||||||
|
|
||||||
init_display();
|
ch1116_main();
|
||||||
display_print8_str(0, 0, "Ambient Light");
|
gui_main();
|
||||||
// hw_ms03_init();
|
|
||||||
// ci_03t_init();
|
gui_set_wifi_connecting();
|
||||||
apds_9960_init();
|
gui_set_server_connecting();
|
||||||
apds_9960_auto_fetch();
|
|
||||||
auto_fetch_temperature();
|
// display_print8_str(0, 0, "Ambient Light");
|
||||||
|
|
||||||
|
ci_03t_init();
|
||||||
|
// apds_9960_init();
|
||||||
|
// apds_9960_auto_fetch();
|
||||||
|
// 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()) {
|
||||||
|
gui_set_wifi_connected();
|
||||||
light_play(light_mode_idle);
|
light_play(light_mode_idle);
|
||||||
|
} else {
|
||||||
|
gui_set_wifi_disconnected();
|
||||||
}
|
}
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
udp_server_init();
|
||||||
mqtt_app_start();
|
net_gateway_monitor_init();
|
||||||
if (waiting_for_mqtt_connected()) {
|
service_discovery_init();
|
||||||
light_play(light_mode_mqtt_connected);
|
// vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
}
|
// mqtt_app_start();
|
||||||
if (waiting_for_desktop_online()) {
|
// if (waiting_for_mqtt_connected()) {
|
||||||
light_play(light_mode_desktop_online);
|
// light_play(light_mode_mqtt_connected);
|
||||||
}
|
// }
|
||||||
while (waiting_and_get_colors()) {
|
// if (waiting_for_desktop_online()) {
|
||||||
light_play_colors(NUMBER_OF_LEDS * 3, mqtt_colors_buffer);
|
// light_play(light_mode_desktop_online);
|
||||||
}
|
// }
|
||||||
|
// while (waiting_and_get_colors()) {
|
||||||
|
// light_play_colors(NUMBER_OF_LEDS * 3, mqtt_colors_buffer);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
281
main/mqtt.c
281
main/mqtt.c
@ -1,281 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "cJSON.h"
|
|
||||||
#include "ci_03t.c"
|
|
||||||
#include "embedded_display.c"
|
|
||||||
#include "esp_bit_defs.h"
|
|
||||||
#include "esp_event.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_system.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/event_groups.h"
|
|
||||||
#include "freertos/queue.h"
|
|
||||||
#include "freertos/semphr.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "mqtt_client.h"
|
|
||||||
#include "ui_input.c"
|
|
||||||
|
|
||||||
#define MQTT_BROKER_URL CONFIG_MQTT_BROKER_URL
|
|
||||||
#define NUMBER_OF_LEDS CONFIG_NUMBER_OF_LEDS
|
|
||||||
|
|
||||||
#define MQTT_FAILED_BIT BIT0
|
|
||||||
#define MQTT_CONNECTED_BIT BIT1
|
|
||||||
#define MQTT_DISCONNECTED_BIT BIT2
|
|
||||||
#define MQTT_DESKTOP_ONLINE_BIT BIT3
|
|
||||||
#define MQTT_DESKTOP_OFFLINE_BIT BIT4
|
|
||||||
#define MQTT_DESKTOP_SENDING_BIT BIT5
|
|
||||||
#define MQTT_COLORS_STAND_BY_BIT BIT6
|
|
||||||
|
|
||||||
#define MQTT_BOARD_KEY_PREFIX "display-ambient-light/board/"
|
|
||||||
#define MQTT_DESKTOP_KEY_PREFIX "display-ambient-light/desktop/"
|
|
||||||
#define MQTT_ONLINE_SUFFIX "online"
|
|
||||||
#define MQTT_COLORS_SUFFIX "colors"
|
|
||||||
#define MQTT_CMD_SUFFIX "cmd"
|
|
||||||
#define MQTT_ALL_SUFFIX "#"
|
|
||||||
|
|
||||||
#define MQTT_KEY_BOARD_ONLINE MQTT_BOARD_KEY_PREFIX MQTT_ONLINE_SUFFIX
|
|
||||||
#define MQTT_KEY_DISPLAY_BRIGHTNESS_INPUT MQTT_BOARD_KEY_PREFIX "brightness"
|
|
||||||
#define MQTT_KEY_DESKTOP_ONLINE MQTT_DESKTOP_KEY_PREFIX MQTT_ONLINE_SUFFIX
|
|
||||||
#define MQTT_KEY_DESKTOP_COLORS MQTT_DESKTOP_KEY_PREFIX MQTT_COLORS_SUFFIX
|
|
||||||
#define MQTT_KEY_DESKTOP_ALL MQTT_DESKTOP_KEY_PREFIX MQTT_ALL_SUFFIX
|
|
||||||
|
|
||||||
#define MQTT_KEY_BOARD_CMD MQTT_BOARD_KEY_PREFIX MQTT_CMD_SUFFIX
|
|
||||||
#define MQTT_KEY_DESKTOP_DISPLAY_0_BRIGHTNESS \
|
|
||||||
MQTT_DESKTOP_KEY_PREFIX "display0/brightness"
|
|
||||||
#define MQTT_KEY_DESKTOP_DISPLAY_1_BRIGHTNESS \
|
|
||||||
MQTT_DESKTOP_KEY_PREFIX "display1/brightness"
|
|
||||||
|
|
||||||
static const char *MQTT_TAG = "DisplayAmbientLight_MQTT";
|
|
||||||
|
|
||||||
static EventGroupHandle_t s_mqtt_event_group;
|
|
||||||
static xQueueHandle mqtt_cmd_event = NULL;
|
|
||||||
static esp_mqtt_client_handle_t client = NULL;
|
|
||||||
|
|
||||||
typedef struct colors {
|
|
||||||
uint8_t *buffer;
|
|
||||||
uint8_t number;
|
|
||||||
} s_colors_t;
|
|
||||||
|
|
||||||
static uint8_t *mqtt_colors_buffer;
|
|
||||||
|
|
||||||
static void log_error_if_nonzero(const char *message, int error_code) {
|
|
||||||
if (error_code != 0) {
|
|
||||||
ESP_LOGE(MQTT_TAG, "Last error %s: 0x%x", message, error_code);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mqtt_event_handler(void *handler_args, esp_event_base_t base,
|
|
||||||
int32_t event_id, void *event_data) {
|
|
||||||
ESP_LOGD(MQTT_TAG, "Event dispatched from event loop base=%s, event_id=%d",
|
|
||||||
base, event_id);
|
|
||||||
esp_mqtt_event_handle_t event = event_data;
|
|
||||||
client = event->client;
|
|
||||||
int msg_id;
|
|
||||||
switch ((esp_mqtt_event_id_t)event_id) {
|
|
||||||
case MQTT_EVENT_CONNECTED:
|
|
||||||
ESP_LOGI(MQTT_TAG, "MQTT_EVENT_CONNECTED");
|
|
||||||
xEventGroupSetBits(s_mqtt_event_group, MQTT_CONNECTED_BIT);
|
|
||||||
msg_id = esp_mqtt_client_publish(client, MQTT_KEY_BOARD_ONLINE, "ONLINE",
|
|
||||||
0, 1, 0);
|
|
||||||
ESP_LOGI(MQTT_TAG, "sent publish successful, msg_id=%d", msg_id);
|
|
||||||
esp_mqtt_client_subscribe(client, MQTT_KEY_DESKTOP_ALL, 1);
|
|
||||||
break;
|
|
||||||
case MQTT_EVENT_DISCONNECTED:
|
|
||||||
ESP_LOGI(MQTT_TAG, "MQTT_EVENT_DISCONNECTED");
|
|
||||||
xEventGroupSetBits(s_mqtt_event_group, MQTT_DISCONNECTED_BIT);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MQTT_EVENT_SUBSCRIBED:
|
|
||||||
ESP_LOGI(MQTT_TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
|
|
||||||
break;
|
|
||||||
case MQTT_EVENT_UNSUBSCRIBED:
|
|
||||||
ESP_LOGI(MQTT_TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
|
|
||||||
break;
|
|
||||||
case MQTT_EVENT_PUBLISHED:
|
|
||||||
ESP_LOGI(MQTT_TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
|
|
||||||
break;
|
|
||||||
case MQTT_EVENT_DATA:
|
|
||||||
// ESP_LOGI(MQTT_TAG, "MQTT_EVENT_DATA");
|
|
||||||
if (strncmp(event->topic, MQTT_KEY_DESKTOP_ONLINE, event->topic_len) ==
|
|
||||||
0) {
|
|
||||||
xEventGroupSetBits(s_mqtt_event_group, MQTT_DESKTOP_ONLINE_BIT);
|
|
||||||
} else if (strncmp(event->topic, MQTT_KEY_DESKTOP_COLORS,
|
|
||||||
event->topic_len) == 0) {
|
|
||||||
// printf("LEN=%d, DATA=%.*s\r\n", event->data_len, event->data_len,
|
|
||||||
// event->data);
|
|
||||||
memcpy(mqtt_colors_buffer, event->data,
|
|
||||||
MIN(event->data_len, NUMBER_OF_LEDS * 3));
|
|
||||||
xEventGroupSetBits(s_mqtt_event_group,
|
|
||||||
MQTT_DESKTOP_SENDING_BIT | MQTT_COLORS_STAND_BY_BIT);
|
|
||||||
} else {
|
|
||||||
if (strncmp(event->topic, MQTT_KEY_DESKTOP_DISPLAY_0_BRIGHTNESS,
|
|
||||||
event->topic_len) == 0) {
|
|
||||||
s_ui_input_t mqtt_event = {
|
|
||||||
.key = ui_input_key_display_0_brightness,
|
|
||||||
.value = (uint16_t)(event->data[0] << 8 | event->data[1]),
|
|
||||||
};
|
|
||||||
xQueueSend(mqtt_cmd_event, &mqtt_event, NULL);
|
|
||||||
} else if (strncmp(event->topic, MQTT_KEY_DESKTOP_DISPLAY_1_BRIGHTNESS,
|
|
||||||
event->topic_len) == 0) {
|
|
||||||
s_ui_input_t mqtt_event = {
|
|
||||||
.key = ui_input_key_display_1_brightness,
|
|
||||||
.value = (uint16_t)(event->data[0] << 8 | event->data[1]),
|
|
||||||
};
|
|
||||||
xQueueSend(mqtt_cmd_event, &mqtt_event, NULL);
|
|
||||||
} else {
|
|
||||||
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
|
|
||||||
printf("DATA=%.*s\r\n", event->data_len, event->data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case MQTT_EVENT_ERROR:
|
|
||||||
ESP_LOGI(MQTT_TAG, "MQTT_EVENT_ERROR");
|
|
||||||
xEventGroupSetBits(s_mqtt_event_group, MQTT_FAILED_BIT);
|
|
||||||
if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
|
|
||||||
log_error_if_nonzero("reported from esp-tls",
|
|
||||||
event->error_handle->esp_tls_last_esp_err);
|
|
||||||
log_error_if_nonzero("reported from tls stack",
|
|
||||||
event->error_handle->esp_tls_stack_err);
|
|
||||||
log_error_if_nonzero("captured as transport's socket errno",
|
|
||||||
event->error_handle->esp_transport_sock_errno);
|
|
||||||
ESP_LOGI(MQTT_TAG, "Last errno string (%s)",
|
|
||||||
strerror(event->error_handle->esp_transport_sock_errno));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ESP_LOGI(MQTT_TAG, "Other event id:%d", event->event_id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mqtt_cmd_event_handler(void *arg) {
|
|
||||||
s_ui_input_t event;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
if (xQueueReceive(mqtt_cmd_event, &event, portMAX_DELAY)) {
|
|
||||||
ESP_LOGI(MQTT_TAG, "mqtt_cmd_event_handler");
|
|
||||||
|
|
||||||
gui_update_config_uint8(ui_input_key_display_0_brightness,
|
|
||||||
(uint8_t)(event.value & 0xFF));
|
|
||||||
switch (event.key) {
|
|
||||||
case ui_input_key_display_0_brightness: {
|
|
||||||
ESP_LOGI(MQTT_TAG, "ui_input_key_display_0_brightness %x",
|
|
||||||
event.value);
|
|
||||||
uint8_t data[] = {0x02, (uint8_t)(event.value & 0xFF)};
|
|
||||||
ci_03t_send_data(data, sizeof(data));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ui_input_key_display_1_brightness: {
|
|
||||||
ESP_LOGI(MQTT_TAG, "ui_input_key_display_0_brightness %x",
|
|
||||||
event.value);
|
|
||||||
uint8_t data[] = {0x03, (uint8_t)(event.value & 0xFF)};
|
|
||||||
ci_03t_send_data(data, sizeof(data));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mqtt_app_start() {
|
|
||||||
mqtt_colors_buffer = (uint8_t *)malloc(sizeof(uint8_t) * NUMBER_OF_LEDS * 3);
|
|
||||||
s_mqtt_event_group = xEventGroupCreate();
|
|
||||||
mqtt_cmd_event = xQueueCreate(10, sizeof(s_ui_input_t));
|
|
||||||
xTaskCreate(mqtt_cmd_event_handler, "mqtt_cmd_event", 2048, NULL, 10, NULL);
|
|
||||||
|
|
||||||
const esp_mqtt_client_config_t mqtt_cfg = {
|
|
||||||
.uri = MQTT_BROKER_URL,
|
|
||||||
};
|
|
||||||
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
|
|
||||||
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler,
|
|
||||||
client);
|
|
||||||
esp_mqtt_client_start(client);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool waiting_for_mqtt_connected() {
|
|
||||||
EventBits_t bits = xEventGroupWaitBits(s_mqtt_event_group,
|
|
||||||
MQTT_CONNECTED_BIT | MQTT_FAILED_BIT,
|
|
||||||
pdFALSE, pdFALSE, portMAX_DELAY);
|
|
||||||
|
|
||||||
if (bits & MQTT_CONNECTED_BIT) {
|
|
||||||
return 1;
|
|
||||||
} else if (bits & MQTT_FAILED_BIT) {
|
|
||||||
ESP_LOGE(MQTT_TAG, "BBB Failed to connect to MQTT.");
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(MQTT_TAG, "UNEXPECTED EVENT");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static bool waiting_for_desktop_online() {
|
|
||||||
EventBits_t bits = xEventGroupWaitBits(
|
|
||||||
s_mqtt_event_group, MQTT_DESKTOP_ONLINE_BIT | MQTT_DESKTOP_SENDING_BIT,
|
|
||||||
pdFALSE, pdFALSE, portMAX_DELAY);
|
|
||||||
|
|
||||||
if (bits & MQTT_DESKTOP_ONLINE_BIT) {
|
|
||||||
return 1;
|
|
||||||
} else if (bits & MQTT_DESKTOP_SENDING_BIT) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(MQTT_TAG, "UNEXPECTED EVENT");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static bool waiting_for_desktop_sending_colors() {
|
|
||||||
EventBits_t bits =
|
|
||||||
xEventGroupWaitBits(s_mqtt_event_group, MQTT_DESKTOP_SENDING_BIT, pdFALSE,
|
|
||||||
pdFALSE, portMAX_DELAY);
|
|
||||||
|
|
||||||
ESP_LOGE(MQTT_TAG, "MQTT_DESKTOP_SENDING_BIT");
|
|
||||||
|
|
||||||
if (bits & MQTT_DESKTOP_SENDING_BIT) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(MQTT_TAG, "UNEXPECTED EVENT");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
static bool waiting_and_get_colors() {
|
|
||||||
EventBits_t bits =
|
|
||||||
xEventGroupWaitBits(s_mqtt_event_group, MQTT_COLORS_STAND_BY_BIT, pdFALSE,
|
|
||||||
pdFALSE, portMAX_DELAY);
|
|
||||||
if (bits & MQTT_COLORS_STAND_BY_BIT) {
|
|
||||||
xEventGroupClearBits(s_mqtt_event_group, MQTT_COLORS_STAND_BY_BIT);
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(MQTT_TAG, "UNEXPECTED EVENT");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void mqtt_publish_ui_input(void *arg) {
|
|
||||||
s_ui_input_t input;
|
|
||||||
for (;;) {
|
|
||||||
if (xQueueReceive(ui_input_event, &input, portMAX_DELAY)) {
|
|
||||||
switch (input.key) {
|
|
||||||
case ui_input_key_display_0_brightness:
|
|
||||||
case ui_input_key_display_1_brightness: {
|
|
||||||
cJSON *publish_json_root, *brightness;
|
|
||||||
publish_json_root = cJSON_CreateObject();
|
|
||||||
cJSON_AddNumberToObject(
|
|
||||||
publish_json_root, "display_index",
|
|
||||||
ui_input_key_display_0_brightness == input.key ? 0 : 1);
|
|
||||||
cJSON_AddItemToObject(publish_json_root, "brightness",
|
|
||||||
brightness = cJSON_CreateObject());
|
|
||||||
cJSON_AddNumberToObject(brightness, "Relative", input.value);
|
|
||||||
char *publish_str = cJSON_Print(publish_json_root);
|
|
||||||
cJSON_Delete(publish_json_root);
|
|
||||||
esp_mqtt_client_publish(client, MQTT_KEY_DISPLAY_BRIGHTNESS_INPUT,
|
|
||||||
publish_str, 0, 1, 0);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
147
main/net_gateway_monitor.c
Normal file
147
main/net_gateway_monitor.c
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
#include <lwip/netdb.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_event.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_netif.h"
|
||||||
|
#include "esp_system.h"
|
||||||
|
#include "esp_wifi.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "gui.c"
|
||||||
|
#include "lwip/err.h"
|
||||||
|
#include "lwip/sockets.h"
|
||||||
|
#include "lwip/sys.h"
|
||||||
|
|
||||||
|
#define NET_GATEWAY_MONITOR_UDP_PORT 23043
|
||||||
|
#define NET_GATEWAY_MONITOR_SERVER_ADDR 0xC0A81F05 // 192.168.31.5
|
||||||
|
#define NET_GATEWAY_MONITOR_SERVER_PORT 17890
|
||||||
|
|
||||||
|
static const char *NET_GATEWAY_MONITOR_TAG = "NET_GATE_MONITOR";
|
||||||
|
static int net_gateway_monitor_socket = -1;
|
||||||
|
|
||||||
|
static void net_gateway_monitor_request_task(void *pvParameters) {
|
||||||
|
int sock = net_gateway_monitor_socket;
|
||||||
|
struct sockaddr_in server_addr;
|
||||||
|
server_addr.sin_addr.s_addr = htonl(NET_GATEWAY_MONITOR_SERVER_ADDR);
|
||||||
|
server_addr.sin_family = AF_INET;
|
||||||
|
server_addr.sin_port = htons(NET_GATEWAY_MONITOR_SERVER_PORT);
|
||||||
|
while (sock == net_gateway_monitor_socket) {
|
||||||
|
int err = sendto(net_gateway_monitor_socket, "ping", 4, 0, &server_addr,
|
||||||
|
sizeof(server_addr));
|
||||||
|
if (err < 0) {
|
||||||
|
ESP_LOGE(NET_GATEWAY_MONITOR_TAG,
|
||||||
|
"Error occurred during sending: errno %d. sock: %d", errno,
|
||||||
|
net_gateway_monitor_socket);
|
||||||
|
}
|
||||||
|
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void net_gateway_monitor_run_task(void *pvParameters) {
|
||||||
|
char rx_buffer[1024];
|
||||||
|
char addr_str[128];
|
||||||
|
int addr_family = (int)pvParameters;
|
||||||
|
int ip_protocol = 0;
|
||||||
|
struct sockaddr_in dest_addr;
|
||||||
|
struct sockaddr_in server_addr;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
dest_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
dest_addr.sin_family = AF_INET;
|
||||||
|
dest_addr.sin_port = htons(NET_GATEWAY_MONITOR_UDP_PORT);
|
||||||
|
ip_protocol = IPPROTO_IP;
|
||||||
|
|
||||||
|
server_addr.sin_addr.s_addr = htonl(NET_GATEWAY_MONITOR_SERVER_ADDR);
|
||||||
|
server_addr.sin_family = AF_INET;
|
||||||
|
server_addr.sin_port = htons(NET_GATEWAY_MONITOR_SERVER_PORT);
|
||||||
|
|
||||||
|
net_gateway_monitor_socket = socket(addr_family, SOCK_DGRAM, ip_protocol);
|
||||||
|
if (net_gateway_monitor_socket < 0) {
|
||||||
|
ESP_LOGE(NET_GATEWAY_MONITOR_TAG,
|
||||||
|
"Unable to create socket: errno %d. sock: %d", errno,
|
||||||
|
net_gateway_monitor_socket);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ESP_LOGI(NET_GATEWAY_MONITOR_TAG, "Socket created");
|
||||||
|
|
||||||
|
// Set timeout
|
||||||
|
struct timeval timeout;
|
||||||
|
timeout.tv_sec = 10;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
setsockopt(net_gateway_monitor_socket, SOL_SOCKET, SO_RCVTIMEO, &timeout,
|
||||||
|
sizeof timeout);
|
||||||
|
|
||||||
|
int err = bind(net_gateway_monitor_socket, (struct sockaddr *)&dest_addr,
|
||||||
|
sizeof(dest_addr));
|
||||||
|
if (err < 0) {
|
||||||
|
ESP_LOGE(NET_GATEWAY_MONITOR_TAG,
|
||||||
|
"Socket unable to bind: errno %d. sock: %d", errno,
|
||||||
|
net_gateway_monitor_socket);
|
||||||
|
net_gateway_monitor_socket = -1;
|
||||||
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// err = connect(net_gateway_monitor_socket, (struct sockaddr
|
||||||
|
// *)&server_addr,
|
||||||
|
// sizeof(server_addr));
|
||||||
|
if (err < 0) {
|
||||||
|
ESP_LOGE(NET_GATEWAY_MONITOR_TAG,
|
||||||
|
"Socket unable to connect: errno %d. sock: %d", errno,
|
||||||
|
net_gateway_monitor_socket);
|
||||||
|
net_gateway_monitor_socket = -1;
|
||||||
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(NET_GATEWAY_MONITOR_TAG, "Socket bound, port %d",
|
||||||
|
NET_GATEWAY_MONITOR_UDP_PORT);
|
||||||
|
|
||||||
|
xTaskCreate(net_gateway_monitor_request_task, "net_gateway_monitor_request",
|
||||||
|
1024, NULL, 5, NULL);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
uint8_t from_len = sizeof(server_addr);
|
||||||
|
// ESP_LOGI(NET_GATEWAY_MONITOR_TAG, "Waiting for data");
|
||||||
|
int len =
|
||||||
|
recv(net_gateway_monitor_socket, rx_buffer, sizeof(rx_buffer) - 1, 0);
|
||||||
|
// Error occurred during receiving
|
||||||
|
if (len < 0) {
|
||||||
|
if (errno == EAGAIN) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ESP_LOGE(NET_GATEWAY_MONITOR_TAG, "recvfrom failed: errno %d. len: %d",
|
||||||
|
errno, len);
|
||||||
|
}
|
||||||
|
// Data received
|
||||||
|
else {
|
||||||
|
// Get the sender's ip address as string
|
||||||
|
inet_ntoa_r(server_addr.sin_addr, addr_str, sizeof(addr_str) - 1);
|
||||||
|
|
||||||
|
rx_buffer[len] = 0; // Null-terminate whatever we received and treat
|
||||||
|
// like a string...
|
||||||
|
gui_change_network_speed(
|
||||||
|
(uint64_t *)&rx_buffer[0], (uint64_t *)&rx_buffer[8],
|
||||||
|
(uint64_t *)&rx_buffer[16], (uint64_t *)&rx_buffer[24]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (net_gateway_monitor_socket != -1 && len < 0) {
|
||||||
|
ESP_LOGE(NET_GATEWAY_MONITOR_TAG,
|
||||||
|
"Shutting down socket and restarting...");
|
||||||
|
shutdown(net_gateway_monitor_socket, 0);
|
||||||
|
close(net_gateway_monitor_socket);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void net_gateway_monitor_init() {
|
||||||
|
ESP_LOGI(NET_GATEWAY_MONITOR_TAG, "Start net gateway monitor");
|
||||||
|
xTaskCreate(net_gateway_monitor_run_task, "net_gateway_monitor_run", 4096,
|
||||||
|
(void *)AF_INET, 5, NULL);
|
||||||
|
}
|
@ -3,7 +3,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "driver/i2c.h"
|
#include "driver/i2c.h"
|
||||||
#include "embedded_display.c"
|
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "i2c.c"
|
#include "i2c.c"
|
||||||
|
|
||||||
@ -79,19 +78,15 @@ void pca9555_fetch(void* arg) {
|
|||||||
esp_err_t error;
|
esp_err_t error;
|
||||||
uint8_t buff;
|
uint8_t buff;
|
||||||
char disp_str[17];
|
char disp_str[17];
|
||||||
display_fill_rect(0, 6, 128, 8, 0x00);
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
error = pca9555_read_one_input(PCA95555_CMD_INPUT_PORT_1, &buff);
|
error = pca9555_read_one_input(PCA95555_CMD_INPUT_PORT_1, &buff);
|
||||||
if (error != ESP_OK) {
|
if (error != ESP_OK) {
|
||||||
ESP_LOGW(PCA_9555_TAG, "read failed. %x", error);
|
ESP_LOGW(PCA_9555_TAG, "read failed. %x", error);
|
||||||
} else {
|
} else {
|
||||||
sprintf(disp_str, "IO0: 0x%2x ", buff);
|
|
||||||
display_print8_str(8, 6, disp_str);
|
|
||||||
ESP_LOGD(PCA_9555_TAG, "IO0: 0x%2x", buff);
|
ESP_LOGD(PCA_9555_TAG, "IO0: 0x%2x", buff);
|
||||||
}
|
}
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
vTaskDelay(pdMS_TO_TICKS(10));
|
||||||
}
|
}
|
||||||
display_fill_rect(0, 6, 128, 8, 0x00);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pca9555_auto_fetch() {
|
void pca9555_auto_fetch() {
|
||||||
|
28
main/service_discovery.c
Normal file
28
main/service_discovery.c
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "mdns.h"
|
||||||
|
|
||||||
|
static const char *SERVICE_DISCOVERY_TAG = "SERVICE_DISCOVERY_TAG";
|
||||||
|
|
||||||
|
static void service_discovery_init() { // 初始化 mDNS 服务
|
||||||
|
esp_err_t err = mdns_init();
|
||||||
|
if (err) {
|
||||||
|
ESP_LOGE(SERVICE_DISCOVERY_TAG, "MDNS Init failed: %d\n", err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置 hostname
|
||||||
|
mdns_hostname_set("ambient-light-board");
|
||||||
|
// 设置默认实例
|
||||||
|
mdns_instance_name_set("ivan");
|
||||||
|
// 添加服务
|
||||||
|
mdns_service_add(NULL, "_ambient_light", "_udp", 23042, NULL, 0);
|
||||||
|
mdns_service_add(NULL, "_http", "_tcp", 80, NULL, 0);
|
||||||
|
|
||||||
|
// 注意:必须先添加服务,然后才能设置其属性
|
||||||
|
// web 服务器使用自定义的实例名
|
||||||
|
mdns_service_instance_name_set("_ambientlight_web", "_tcp",
|
||||||
|
"Ambient Light Board Web Server");
|
||||||
|
}
|
@ -22,7 +22,7 @@
|
|||||||
void fetch_temperature(void* arg) {
|
void fetch_temperature(void* arg) {
|
||||||
esp_err_t error;
|
esp_err_t error;
|
||||||
float temperature = DEFAULT_TEMPERATURE;
|
float temperature = DEFAULT_TEMPERATURE;
|
||||||
char temperature_str[10];
|
char temperature_str[20];
|
||||||
uint8_t temperature_buffer[] = {0, 0};
|
uint8_t temperature_buffer[] = {0, 0};
|
||||||
display_fill_rect(0, 0, 128, 2, 0x00);
|
display_fill_rect(0, 0, 128, 2, 0x00);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -6,10 +6,10 @@
|
|||||||
|
|
||||||
#include "config_key.h"
|
#include "config_key.h"
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
#include "embedded_display.c"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/queue.h"
|
#include "freertos/queue.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
#include "gui.c"
|
||||||
#include "light.c"
|
#include "light.c"
|
||||||
#include "pca9555.c"
|
#include "pca9555.c"
|
||||||
|
|
||||||
@ -34,8 +34,8 @@
|
|||||||
|
|
||||||
static const char *UI_INPUT_TAG = "UiInput";
|
static const char *UI_INPUT_TAG = "UiInput";
|
||||||
|
|
||||||
static xQueueHandle ui_input_event = NULL;
|
static QueueHandle_t ui_input_event = NULL;
|
||||||
static xQueueHandle ui_input_raw_event = NULL;
|
static QueueHandle_t ui_input_raw_event = NULL;
|
||||||
|
|
||||||
typedef struct encoder_state {
|
typedef struct encoder_state {
|
||||||
e_ui_input_raw_key_t key;
|
e_ui_input_raw_key_t key;
|
||||||
@ -51,7 +51,10 @@ static encoder_state_t encoder_1_state = {.key = ui_input_raw_key_encoder_1,
|
|||||||
|
|
||||||
uint8_t level_byte;
|
uint8_t level_byte;
|
||||||
int8_t delta = 0;
|
int8_t delta = 0;
|
||||||
char changing_str[12] = "NC";
|
int64_t ec0_last_time = 0;
|
||||||
|
int64_t ec1_last_time = 0;
|
||||||
|
int64_t ec0_interval = 0;
|
||||||
|
int64_t ec1_interval = 0;
|
||||||
|
|
||||||
static void IRAM_ATTR gpio_isr_handler(void *arg) {
|
static void IRAM_ATTR gpio_isr_handler(void *arg) {
|
||||||
xQueueSendFromISR(ui_input_raw_event, NULL, NULL);
|
xQueueSendFromISR(ui_input_raw_event, NULL, NULL);
|
||||||
@ -59,7 +62,7 @@ static void IRAM_ATTR gpio_isr_handler(void *arg) {
|
|||||||
|
|
||||||
static void ui_input_update_embedded_display(void *arg) {
|
static void ui_input_update_embedded_display(void *arg) {
|
||||||
s_ui_input_t input;
|
s_ui_input_t input;
|
||||||
char changing_str[12] = "NC";
|
char changing_str[20] = "NC";
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (xQueueReceive(ui_input_event, &input, portMAX_DELAY)) {
|
if (xQueueReceive(ui_input_event, &input, portMAX_DELAY)) {
|
||||||
switch (input.key) {
|
switch (input.key) {
|
||||||
@ -73,7 +76,6 @@ static void ui_input_update_embedded_display(void *arg) {
|
|||||||
sprintf(changing_str, "CVol: % 3d", input.value);
|
sprintf(changing_str, "CVol: % 3d", input.value);
|
||||||
break;
|
break;
|
||||||
case ui_input_key_display_ambient_lighting_level:
|
case ui_input_key_display_ambient_lighting_level:
|
||||||
sprintf(changing_str, "ALLv: % 3d", display_ambient_lighting_level);
|
|
||||||
break;
|
break;
|
||||||
case ui_input_key_display_ambient_lighting_mode:
|
case ui_input_key_display_ambient_lighting_mode:
|
||||||
sprintf(changing_str, "ALMd: % 3d", input.value);
|
sprintf(changing_str, "ALMd: % 3d", input.value);
|
||||||
@ -89,8 +91,8 @@ static void ui_input_update_embedded_display(void *arg) {
|
|||||||
strcpy(changing_str, "NC");
|
strcpy(changing_str, "NC");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
display_fill_rect(0, 6, 128, 8, 0);
|
|
||||||
display_print8_str(8, 6, changing_str);
|
ESP_LOGI(UI_INPUT_TAG, "%s", changing_str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -151,20 +153,47 @@ static void encoder_value_change(encoder_state_t *state) {
|
|||||||
|
|
||||||
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) {
|
||||||
|
ec0_interval = esp_timer_get_time() - ec0_last_time;
|
||||||
|
if (ec0_interval < 10000) { // 100ms
|
||||||
|
event.value = event.value * 5;
|
||||||
|
} else if (ec0_interval < 20000) { // 100ms
|
||||||
|
event.value = event.value * 4;
|
||||||
|
} else if (ec0_interval < 50000) { // 100ms
|
||||||
|
event.value = event.value * 3;
|
||||||
|
} else if (ec0_interval < 100000) { // 100ms
|
||||||
|
event.value = event.value * 2;
|
||||||
|
}
|
||||||
|
ec0_last_time = esp_timer_get_time();
|
||||||
|
|
||||||
if (state->value & 1) {
|
if (state->value & 1) {
|
||||||
event.key = ui_input_key_computer_volume;
|
event.key = ui_input_key_computer_volume;
|
||||||
} else {
|
} else {
|
||||||
event.key = ui_input_key_display_0_brightness;
|
event.key = ui_input_key_display_1_brightness;
|
||||||
}
|
}
|
||||||
} else if (state->key == ui_input_raw_key_encoder_1) {
|
} else if (state->key == ui_input_raw_key_encoder_1) {
|
||||||
if (state->value & 1) {
|
if (state->value & 1) {
|
||||||
|
ec1_interval = esp_timer_get_time() - ec1_last_time;
|
||||||
|
if (ec1_interval < 20000) { // 100ms
|
||||||
|
event.value = event.value * 7;
|
||||||
|
} else if (ec1_interval < 30000) { // 100ms
|
||||||
|
event.value = event.value * 5;
|
||||||
|
} else if (ec1_interval < 40000) { // 100ms
|
||||||
|
event.value = event.value * 3;
|
||||||
|
} else if (ec1_interval < 50000) {
|
||||||
|
event.value = event.value * 2;
|
||||||
|
}
|
||||||
|
ec1_last_time = esp_timer_get_time();
|
||||||
|
|
||||||
event.key = ui_input_key_display_ambient_lighting_level;
|
event.key = ui_input_key_display_ambient_lighting_level;
|
||||||
led_strip_set_brightness(display_ambient_lighting_level + delta);
|
led_strip_set_brightness(display_ambient_lighting_level + event.value);
|
||||||
|
gui_change_strip_level(display_ambient_lighting_level);
|
||||||
} else {
|
} else {
|
||||||
event.key = ui_input_key_display_1_brightness;
|
event.key = ui_input_key_display_0_brightness;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xQueueSend(ui_input_event, &event, NULL);
|
xQueueSend(ui_input_event, &event, NULL);
|
||||||
|
ESP_LOGD(UI_INPUT_TAG, "key: %d, delta: %d. delay: %lld, %lld", state->key,
|
||||||
|
event.value, ec0_interval, ec1_interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ui_input_raw_handler(void *arg) {
|
static void ui_input_raw_handler(void *arg) {
|
||||||
@ -193,13 +222,13 @@ void ui_input_init(void) {
|
|||||||
gpio_config(&io_conf);
|
gpio_config(&io_conf);
|
||||||
|
|
||||||
// start encoder task
|
// start encoder task
|
||||||
ui_input_event = xQueueCreate(10, sizeof(s_ui_input_t));
|
ui_input_event = xQueueCreate(5, sizeof(s_ui_input_t));
|
||||||
ui_input_raw_event = xQueueCreate(10, 0);
|
ui_input_raw_event = xQueueCreate(10, 0);
|
||||||
|
|
||||||
// hook isr handler for specific gpio pin
|
// hook isr handler for specific gpio pin
|
||||||
gpio_isr_handler_add(ENCODER_INT_GPIO, gpio_isr_handler, NULL);
|
gpio_isr_handler_add(ENCODER_INT_GPIO, gpio_isr_handler, NULL);
|
||||||
|
|
||||||
xTaskCreate(ui_input_update_embedded_display, "ui_input_event", 2048, NULL,
|
// xTaskCreate(ui_input_update_embedded_display, "ui_input_event", 2048, NULL,
|
||||||
10, NULL);
|
// 10, NULL);
|
||||||
xTaskCreate(ui_input_raw_handler, "ui_input_event", 2048, NULL, 10, NULL);
|
xTaskCreate(ui_input_raw_handler, "ui_input_event", 2048, NULL, 10, NULL);
|
||||||
}
|
}
|
||||||
|
@ -151,14 +151,7 @@ bool wifi_init_sta(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool connect_wifi(void) {
|
bool connect_wifi(void) {
|
||||||
// Initialize NVS
|
//! Should init NVS before wifi init
|
||||||
esp_err_t ret = nvs_flash_init();
|
|
||||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
|
|
||||||
ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
|
||||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
|
||||||
ret = nvs_flash_init();
|
|
||||||
}
|
|
||||||
ESP_ERROR_CHECK(ret);
|
|
||||||
|
|
||||||
ESP_LOGI(WIFI_TAG, "ESP_WIFI_MODE_STA");
|
ESP_LOGI(WIFI_TAG, "ESP_WIFI_MODE_STA");
|
||||||
return wifi_init_sta();
|
return wifi_init_sta();
|
||||||
|
Loading…
Reference in New Issue
Block a user