8 Commits

15 changed files with 682 additions and 159 deletions

View File

@ -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)

View File

@ -1,2 +1,2 @@
idf_component_register(SRCS "app_nvs.c" "apds_9960.c" "pca9555.c" "i2c.c" "asr_pro.c" "ci_03t.c" "ui_input.c" "ambient_light.c" "temperature.c" "embedded_display.c" "mqtt.c" "main.c" "wifi.c" "light.c" "mqtt.c" idf_component_register(SRCS "hw-ms03.c" "app_nvs.c" "apds_9960.c" "pca9555.c" "i2c.c" "asr_pro.c" "ci_03t.c" "ui_input.c" "ambient_light.c" "temperature.c" "embedded_display.c" "mqtt.c" "main.c" "wifi.c" "light.c" "mqtt.c" "led_strip_encoder/led_strip_encoder.c"
INCLUDE_DIRS ".") INCLUDE_DIRS ".")

View File

@ -146,3 +146,12 @@ menu "UART Configuration"
help help
UART NUM UART NUM
endmenu endmenu
menu "ADPS 9960"
config APDS_9960_INT_GPIO
int "APDS 996O INT GPIO"
range 0 32
default 2
help
APDS 996O INT GPIO
endmenu

View File

@ -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};

View File

@ -1,14 +1,20 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "common.h"
#include "driver/gpio.h"
#include "driver/i2c.h" #include "driver/i2c.h"
#include "embedded_display.c" #include "embedded_display.c"
#include "esp_log.h" #include "esp_log.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "i2c.c" #include "i2c.c"
// #define APDS_9930_CMD_REPEATED 0x80 // 命令重复地址 #define APDS_9960_INT_GPIO CONFIG_APDS_9960_INT_GPIO
// #define APDS_9930_CMD_AUTO_INCREMENT 0x90 // 命令自动递增地址
// ===============================================
// Register addresses
// ===============================================
// 0x80 ENABLE R/W Enable states and interrupts 0x00 // 0x80 ENABLE R/W Enable states and interrupts 0x00
// 0x81 ATIME R/W ADC integration time 0xFF // 0x81 ATIME R/W ADC integration time 0xFF
// 0x83 WTIME R/W Wait time (non-gesture) 0xFF // 0x83 WTIME R/W Wait time (non-gesture) 0xFF
@ -109,13 +115,40 @@
#define APDS_9960_REG_GFIFO_L 0xFE // 手势 FIFO 数据左 0x00 #define APDS_9960_REG_GFIFO_L 0xFE // 手势 FIFO 数据左 0x00
#define APDS_9960_REG_GFIFO_R 0xFF // 手势 FIFO 数据右 0x00 #define APDS_9960_REG_GFIFO_R 0xFF // 手势 FIFO 数据右 0x00
#define APDS_9960_CONTROL_VALUE \ #define APDS_9960_GVALID 0b00000001 // GVALID
0b00001010 // 50 mA LED, Reserved, 2x PGAIN, 4x ALS/Cain GAIN #define APDS_9960_GFOV 0b00000010 // GFOV
#define APDS_9960_ENABLE_VALUE 0b00000111 #define APDS_9960_PINT 0x20 // PINT
#define APDS_9930_OFFSET_VALUE 0x8f #define APDS_9960_AINT 0x10 // AINT
#define APDS_9960_GINT 0x04 // GINT
// 50 mA LED, Reserved, 2x PGAIN, 4x ALS/Cain GAIN
#define APDS_9960_CONTROL_VALUE 0b00001010
// Enable Gesture, Proximity, ALS, Power
// X, GEN, PIEN, AIEN, WEN, PEN, AEN, PON
#define APDS_9960_ENABLE_VALUE 0b01100111
#define APDS_9960_TAG "APDS-9960" #define APDS_9960_TAG "APDS-9960"
static QueueHandle_t apds_9960_int_evt_queue = NULL;
static int64_t last_apds_9960_int_time = 0;
esp_err_t apds_9960_write_empty(uint8_t command) {
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, APDS_9960_ADDRESS << 1 | I2C_MASTER_WRITE,
ACK_CHECK_EN);
i2c_master_write_byte(cmd, command, ACK_CHECK_DIS);
i2c_master_stop(cmd);
esp_err_t error =
i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 10 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
if (error != ESP_OK) {
ESP_LOGW(APDS_9960_TAG, "write failed. %d", error);
}
return error;
}
esp_err_t apds_9960_write(uint8_t command, uint8_t data) { esp_err_t apds_9960_write(uint8_t command, uint8_t data) {
i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd); i2c_master_start(cmd);
@ -125,7 +158,7 @@ esp_err_t apds_9960_write(uint8_t command, uint8_t data) {
i2c_master_write_byte(cmd, data, ACK_CHECK_EN); i2c_master_write_byte(cmd, data, ACK_CHECK_EN);
i2c_master_stop(cmd); i2c_master_stop(cmd);
esp_err_t error = esp_err_t error =
i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS); i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 10 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd); i2c_cmd_link_delete(cmd);
if (error != ESP_OK) { if (error != ESP_OK) {
ESP_LOGW(APDS_9960_TAG, "write failed. %d", error); ESP_LOGW(APDS_9960_TAG, "write failed. %d", error);
@ -145,10 +178,10 @@ esp_err_t apds_9960_read_byte(uint8_t command, uint8_t* data) {
i2c_master_read_byte(cmd, data, NACK_VAL); i2c_master_read_byte(cmd, data, NACK_VAL);
i2c_master_stop(cmd); i2c_master_stop(cmd);
esp_err_t error = esp_err_t error =
i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS); i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 10 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd); i2c_cmd_link_delete(cmd);
if (error != ESP_OK) { if (error != ESP_OK) {
ESP_LOGW(APDS_9960_TAG, "write failed. %d", error); ESP_LOGW(APDS_9960_TAG, "read failed. %d", error);
} }
return error; return error;
} }
@ -167,42 +200,87 @@ esp_err_t apds_9960_read_word(uint8_t command, uint16_t* data) {
i2c_master_read_byte(cmd, (uint8_t*)data + 1, NACK_VAL); i2c_master_read_byte(cmd, (uint8_t*)data + 1, NACK_VAL);
i2c_master_stop(cmd); i2c_master_stop(cmd);
esp_err_t error = esp_err_t error =
i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS); i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 10 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd); i2c_cmd_link_delete(cmd);
if (error != ESP_OK) { if (error != ESP_OK) {
ESP_LOGW(APDS_9960_TAG, "write failed. %d", error); ESP_LOGW(APDS_9960_TAG, "read failed. %d", error);
} }
return error; return error;
} }
void apes_9960_fetch(void* arg) { // read bytes by length
ESP_LOGI(APDS_9960_TAG, "apes_9960_fetch"); esp_err_t apds_9960_read_bytes_len(uint8_t command, uint8_t* data,
uint8_t len) {
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, APDS_9960_ADDRESS << 1 | I2C_MASTER_WRITE,
ACK_CHECK_EN);
i2c_master_write_byte(cmd, command, ACK_CHECK_EN);
i2c_master_start(cmd);
i2c_master_write_byte(cmd, APDS_9960_ADDRESS << 1 | I2C_MASTER_READ,
ACK_CHECK_EN);
for (int i = 0; i < len; i++) {
if (i == len - 1) {
i2c_master_read_byte(cmd, (uint8_t*)data + i, NACK_VAL);
} else {
i2c_master_read_byte(cmd, (uint8_t*)data + i, ACK_VAL);
}
}
i2c_master_stop(cmd);
esp_err_t error =
i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 100 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
if (error != ESP_OK) {
ESP_LOGW(APDS_9960_TAG, "read failed. %d", error);
}
return error;
}
void apds_9960_clear_all_int(void) {
ESP_LOGI(APDS_9960_TAG, "apds_9960_clear_all_int");
ESP_ERROR_CHECK_WITHOUT_ABORT(apds_9960_write_empty(APDS_9960_REG_AICLEAR));
ESP_ERROR_CHECK_WITHOUT_ABORT(apds_9960_write(APDS_9960_REG_GCONF4, 0x06));
}
void apds_9960_fetch(void* arg) {
ESP_LOGI(APDS_9960_TAG, "apds_9960_fetch");
esp_err_t error; esp_err_t error;
uint16_t red_raw; uint16_t red_raw;
uint16_t green_raw; uint16_t green_raw;
uint16_t blue_raw; uint16_t blue_raw;
uint16_t clear_raw; uint16_t clear_raw;
uint8_t proximity_raw; uint8_t byte_buffer;
char red_str[10]; uint8_t gesture_status_raw;
char green_str[10]; uint8_t status_raw;
char blue_str[10]; char red_str[20];
char clear_str[10]; char green_str[20];
char proximity_str[10]; char blue_str[20];
char clear_str[20];
char status_str[20];
uint8_t interrupt = 0;
display_fill_rect(0, 2, 128, 8, 0x00); display_fill_rect(0, 2, 128, 8, 0x00);
for (;;) { for (;;) {
// Proximity if (last_apds_9960_int_time + 1000000 < esp_timer_get_time()) {
error = apds_9960_read_byte(APDS_9960_REG_PDATA, &proximity_raw); interrupt = gpio_get_level(APDS_9960_INT_GPIO);
if (interrupt == 1 ||
last_apds_9960_int_time + 10000000 < esp_timer_get_time()) {
apds_9960_clear_all_int();
}
}
// clear
error = apds_9960_read_word(APDS_9960_REG_CDATAL, &clear_raw);
if (error != ESP_OK) { if (error != ESP_OK) {
ESP_LOGW(APDS_9960_TAG, "read proximity failed. %x", error); ESP_LOGW(APDS_9960_TAG, "read failed. %d", error);
} else { } else {
sprintf(proximity_str, "Prox: % 5d ", proximity_raw); sprintf(clear_str, "C:% 5d", clear_raw);
display_print8_str(8, 2, proximity_str); display_print8_str(64, 6, clear_str);
ESP_LOGD(APDS_9960_TAG, "Prox: %d %x", proximity_raw); ESP_LOGD(APDS_9960_TAG, "Clear: %d", clear_raw);
} }
// red // red
error = apds_9960_read_word(APDS_9960_REG_RDATAL, &red_raw); error = apds_9960_read_word(APDS_9960_REG_RDATAL, &red_raw);
if (error != ESP_OK) { if (error != ESP_OK) {
ESP_LOGW(APDS_9960_TAG, "read failed. %x", error); ESP_LOGW(APDS_9960_TAG, "read failed. %d", error);
} else { } else {
sprintf(red_str, "R:% 5d", red_raw); sprintf(red_str, "R:% 5d", red_raw);
display_print8_str(0, 4, red_str); display_print8_str(0, 4, red_str);
@ -211,7 +289,7 @@ void apes_9960_fetch(void* arg) {
// green // green
error = apds_9960_read_word(APDS_9960_REG_GDATAL, &green_raw); error = apds_9960_read_word(APDS_9960_REG_GDATAL, &green_raw);
if (error != ESP_OK) { if (error != ESP_OK) {
ESP_LOGW(APDS_9960_TAG, "read failed. %x", error); ESP_LOGW(APDS_9960_TAG, "read failed. %d", error);
} else { } else {
sprintf(green_str, "G:% 5d", green_raw); sprintf(green_str, "G:% 5d", green_raw);
display_print8_str(64, 4, green_str); display_print8_str(64, 4, green_str);
@ -220,43 +298,228 @@ void apes_9960_fetch(void* arg) {
// blue // blue
error = apds_9960_read_word(APDS_9960_REG_BDATAL, &blue_raw); error = apds_9960_read_word(APDS_9960_REG_BDATAL, &blue_raw);
if (error != ESP_OK) { if (error != ESP_OK) {
ESP_LOGW(APDS_9960_TAG, "read failed. %x", error); ESP_LOGW(APDS_9960_TAG, "read failed. %d", error);
} else { } else {
sprintf(blue_str, "B:% 5d", blue_raw); sprintf(blue_str, "B:% 5d", blue_raw);
display_print8_str(0, 6, blue_str); display_print8_str(0, 6, blue_str);
ESP_LOGD(APDS_9960_TAG, "Blue: %d", blue_raw); ESP_LOGD(APDS_9960_TAG, "Blue: %d", blue_raw);
} }
// clear
error = apds_9960_read_word(APDS_9960_REG_CDATAL, &clear_raw);
if (error != ESP_OK) {
ESP_LOGW(APDS_9960_TAG, "read failed. %x", error);
} else {
sprintf(clear_str, "C:% 4d", clear_raw);
display_print8_str(64, 6, clear_str);
ESP_LOGD(APDS_9960_TAG, "Clear: %d", clear_raw);
}
vTaskDelay(pdMS_TO_TICKS(1000)); vTaskDelay(pdMS_TO_TICKS(1000));
} }
display_fill_rect(0, 2, 128, 8, 0x00); display_fill_rect(0, 2, 128, 8, 0x00);
} }
void apes_9960_auto_fetch() { void apds_9960_auto_fetch() {
if (is_apds_9960_online == 0) { if (is_apds_9960_online == 0) {
return; return;
} }
xTaskCreate(apes_9960_fetch, "APDS-9960-fetch", 2048, NULL, 10, NULL); xTaskCreate(apds_9960_fetch, "APDS-9960-fetch", 2048, NULL, 10, NULL);
} }
void apes_9960_init() { void apds_9960_read_gesture() {
ESP_LOGI(APDS_9960_TAG, "apes_9960_gesture_fetch");
uint8_t byte_buffer;
esp_err_t error;
uint32_t gesture_values_raw_arr[32];
char gesture_values_str_arr[20];
error = apds_9960_read_byte(APDS_9960_REG_GSTATUS, &byte_buffer);
if (error != ESP_OK) {
ESP_LOGW(APDS_9960_TAG, "read APDS_9960_REG_GSTATUS failed. %d", error);
return;
}
ESP_LOGD(APDS_9960_TAG, "APDS-9960 interrupt. status: %x", byte_buffer);
if (!(byte_buffer & APDS_9960_GVALID)) {
ESP_LOGI(APDS_9960_TAG, "Gesture no valid");
return;
}
ESP_LOGD(APDS_9960_TAG, "Gesture interrupt");
error = apds_9960_read_byte(APDS_9960_REG_GFLVL, &byte_buffer);
if (error != ESP_OK) {
ESP_LOGW(APDS_9960_TAG, "read APDS_9960_REG_GFLVL failed. %d", error);
apds_9960_write(APDS_9960_REG_GCONF4, 0x06);
return;
}
if (byte_buffer < 4) {
ESP_LOGD(APDS_9960_TAG, "Gesture FIFO level too low: %d", byte_buffer);
apds_9960_write(APDS_9960_REG_GCONF4, 0x06);
return;
}
ESP_LOGD(APDS_9960_TAG, "Gesture FIFO Level: %d", byte_buffer);
error = apds_9960_read_bytes_len(
APDS_9960_REG_GFIFO_U, (uint8_t*)gesture_values_raw_arr, byte_buffer * 4);
apds_9960_write(APDS_9960_REG_GCONF4, 0x06);
if (error != ESP_OK) {
ESP_LOGW(APDS_9960_TAG, "read APDS_9960_REG_GFIFO(len: %d) failed. % d",
byte_buffer * 4, error);
} else {
int16_t before_ud = 0, before_lr = 0, after_ud = 0, after_lr = 0;
int16_t u = 0, d = 0, l = 0, r = 0;
uint8_t last_2_index = byte_buffer - 2;
// head 2
for (int i = 0; i < 2; i++) {
u = gesture_values_raw_arr[i] & 0xff;
d = gesture_values_raw_arr[i] >> 8 & 0xff;
l = gesture_values_raw_arr[i] >> 16 & 0xff;
r = gesture_values_raw_arr[i] >> 24 & 0xff;
before_ud += (u - d) * 100 / u + d;
before_lr += (l - r) * 100 / l + r;
}
// last 2
for (int i = last_2_index; i < byte_buffer; i++) {
u = gesture_values_raw_arr[i] & 0xff;
d = gesture_values_raw_arr[i] >> 8 & 0xff;
l = gesture_values_raw_arr[i] >> 16 & 0xff;
r = gesture_values_raw_arr[i] >> 24 & 0xff;
after_ud += (u - d) * 100 / u + d;
after_lr += (l - r) * 100 / l + r;
}
for (int i = 0; i < byte_buffer; i++) {
if (i < 2) {
u = gesture_values_raw_arr[i] & 0xff;
d = gesture_values_raw_arr[i] >> 8 & 0xff;
l = gesture_values_raw_arr[i] >> 16 & 0xff;
r = gesture_values_raw_arr[i] >> 24 & 0xff;
before_ud += (u - d) * 100 / u + d;
before_lr += (l - r) * 100 / l + r;
} else if (i >= last_2_index) {
u = gesture_values_raw_arr[i] & 0xff;
d = gesture_values_raw_arr[i] >> 8 & 0xff;
l = gesture_values_raw_arr[i] >> 16 & 0xff;
r = gesture_values_raw_arr[i] >> 24 & 0xff;
after_ud += (u - d) * 100 / u + d;
after_lr += (l - r) * 100 / l + r;
}
}
printf("Δud: %d, Δlr: %d \n", after_ud - before_ud, after_lr - before_lr);
display_fill_rect(0, 0, 128, 2, 0x00);
if (abs(after_ud - before_ud) * 2 > abs(after_lr - before_lr)) {
if (after_ud - before_ud < -80) {
display_print8_str(0, 0, "Gesture: up");
} else if (after_ud - before_ud > 80) {
display_print8_str(0, 0, "Gesture: down");
}
} else {
if (after_lr - before_lr < -120) {
display_print8_str(0, 0, "Gesture: left");
} else if (after_lr - before_lr > 120) {
display_print8_str(0, 0, "Gesture: right");
}
}
// display_print8_str(0, 0, gesture_str);
}
}
void apds_9960_read_proximity() {
uint8_t proximity_raw;
char proximity_str[20];
esp_err_t error;
// Proximity
error = apds_9960_read_byte(APDS_9960_REG_PDATA, &proximity_raw);
if (error != ESP_OK) {
ESP_LOGW(APDS_9960_TAG, "read proximity failed. %x", error);
} else {
ESP_LOGD(APDS_9960_TAG, "Prox: % 5d ", proximity_raw);
sprintf(proximity_str, "Prox: % 5d ", proximity_raw);
display_print8_str(8, 2, proximity_str);
}
}
void apds_9960_int_handler(void* arg) {
xQueueSendFromISR(apds_9960_int_evt_queue, &arg, NULL);
}
void apds_9960_int_evt_handler() {
if (is_apds_9960_online == 0) {
return;
}
apds_9960_clear_all_int();
esp_err_t error;
uint8_t status_raw;
while (xQueueReceive(apds_9960_int_evt_queue, NULL, portMAX_DELAY)) {
last_apds_9960_int_time = esp_timer_get_time();
ESP_ERROR_RETRY(apds_9960_read_byte(APDS_9960_REG_STATUS, &status_raw), 10);
ESP_ERROR_RETRY(apds_9960_write_empty(APDS_9960_REG_AICLEAR), 10);
ESP_LOGD(
APDS_9960_TAG, "[apds_9960_int_evt_handler] status %d%d%d%d %d%d%d%d",
(status_raw >> 7) & 1, (status_raw >> 6) & 1, (status_raw >> 5) & 1,
(status_raw >> 4) & 1, (status_raw >> 3) & 1, (status_raw >> 2) & 1,
(status_raw >> 1) & 1, status_raw & 1);
if (status_raw & APDS_9960_PINT) {
apds_9960_read_proximity();
}
if (status_raw & APDS_9960_GINT) {
apds_9960_read_gesture();
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
}
void apds_9960_init() {
if (is_apds_9960_online == 0) { if (is_apds_9960_online == 0) {
ESP_LOGI(APDS_9960_TAG, "APDS-9960 is offline"); ESP_LOGI(APDS_9960_TAG, "APDS-9960 is offline");
return; return;
} }
ESP_LOGI(APDS_9960_TAG, "Initializing APDS-9960"); ESP_LOGI(APDS_9960_TAG, "Initializing APDS-9960");
// esp_log_level_set(APDS_9960_TAG, ESP_LOG_DEBUG);
gpio_config_t io_conf = {};
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pull_up_en = 0;
io_conf.pull_down_en = 0;
io_conf.intr_type = GPIO_INTR_NEGEDGE;
io_conf.pin_bit_mask = 1ULL << APDS_9960_INT_GPIO;
gpio_config(&io_conf);
gpio_isr_handler_add(APDS_9960_INT_GPIO, apds_9960_int_handler, NULL);
// 环境光 ADC 积分时间
ESP_ERROR_CHECK(apds_9960_write(APDS_9960_REG_ATIME, 246)); // 27.8ms
// 增益
ESP_ERROR_CHECK( ESP_ERROR_CHECK(
apds_9960_write(APDS_9960_REG_CONTROL, APDS_9960_CONTROL_VALUE)); apds_9960_write(APDS_9960_REG_CONTROL, APDS_9960_CONTROL_VALUE));
// enable gesture interrupt
ESP_ERROR_CHECK(apds_9960_write(APDS_9960_REG_GCONF4, 0x06));
// 累积的手势数据达到 4 组时触发中断
ESP_ERROR_CHECK(apds_9960_write(APDS_9960_REG_GCONF1, 0x40));
// Gesture Enter Threshold
ESP_ERROR_CHECK(apds_9960_write(APDS_9960_REG_GPENTH, 3));
// Gesture Exit Threshold
ESP_ERROR_CHECK(apds_9960_write(APDS_9960_REG_GEXTH, 3));
// Gesture Drive Strength
ESP_ERROR_CHECK(apds_9960_write(APDS_9960_REG_GCONF2, 0b0110000));
// // set wait time
// ESP_ERROR_CHECK(apds_9960_write(APDS_9960_REG_WTIME, 171));
// set interrupt persistence
ESP_ERROR_CHECK(apds_9960_write(APDS_9960_REG_PERS, 0x44));
ESP_ERROR_CHECK(apds_9960_write(APDS_9960_REG_PILT, 0x80));
ESP_ERROR_CHECK(apds_9960_write(APDS_9960_REG_PIHT, 0x40));
ESP_ERROR_CHECK(apds_9960_write(APDS_9960_REG_CONFIG2, 0x80));
// // enable sleep after interrupt
// ESP_ERROR_CHECK(apds_9960_write(APDS_9960_REG_CONFIG3, 0x10));
ESP_ERROR_CHECK( ESP_ERROR_CHECK(
apds_9960_write(APDS_9960_REG_ENABLE, APDS_9960_ENABLE_VALUE)); apds_9960_write(APDS_9960_REG_ENABLE, APDS_9960_ENABLE_VALUE));
apds_9960_int_evt_queue = xQueueCreate(10, NULL);
xTaskCreate(apds_9960_int_evt_handler, "apds_9960_gesture_fetch", 2048, NULL,
10, NULL);
} }

20
main/common.h Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include "esp_log.h"
#define ESP_ERROR_RETRY(action, max_retries) \
{ \
uint8_t retry_count = 0; \
esp_err_t error; \
while (retry_count < max_retries) { \
error = action; \
if (error == ESP_OK) break; \
retry_count++; \
ESP_LOGI("RETRY", "Retrying... (%d/%d)\n", retry_count + 1, \
max_retries); \
} \
if (error != ESP_OK) { \
ESP_LOGE("RETRY", "retry failed. %d", error); \
ESP_ERROR_CHECK(error); \
} \
}

27
main/hw-ms03.c Normal file
View File

@ -0,0 +1,27 @@
#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);
}

View File

@ -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) {

View 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(&copy_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;
}

View 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

View File

@ -1,28 +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 "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.h"
#include "nvs_flash.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,
@ -34,7 +28,13 @@ 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;
@ -179,52 +179,53 @@ 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));
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));
nvs_handle local_nvs_handle; nvs_handle local_nvs_handle;
esp_err_t err = nvs_open("storage", NVS_READWRITE, &local_nvs_handle); esp_err_t err = nvs_open("storage", NVS_READWRITE, &local_nvs_handle);
@ -273,10 +274,13 @@ void light_for_init() {
init_b = (uint8_t)(b_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++) {
ESP_ERROR_CHECK(light_led_strip->set_pixel(light_led_strip, j, init_r, led_strip_pixels[j * 3 + 0] = init_g;
init_g, init_b)); led_strip_pixels[j * 3 + 1] = init_r;
led_strip_pixels[j * 3 + 2] = init_b;
} }
ESP_ERROR_CHECK(light_led_strip->refresh(light_led_strip, 100));
ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels,
sizeof(led_strip_pixels), &tx_config));
vTaskDelay(pdMS_TO_TICKS(20)); vTaskDelay(pdMS_TO_TICKS(20));
} }
vTaskDelay(pdMS_TO_TICKS(100)); vTaskDelay(pdMS_TO_TICKS(100));
@ -292,19 +296,34 @@ 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;
ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels,
sizeof(led_strip_pixels), &tx_config));
vTaskDelay(pdMS_TO_TICKS(200)); vTaskDelay(pdMS_TO_TICKS(200));
} while (light_mode == light_mode_connection_wifi); } while (light_mode == light_mode_connection_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;
@ -318,24 +337,23 @@ 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_red_calibration; led_strip_pixels[j * 3 + 0] = green * display_ambient_light_brightness *
green = green * display_ambient_light_brightness * led_strip_green_calibration;
led_strip_green_calibration; led_strip_pixels[j * 3 + 1] =
blue = red * display_ambient_light_brightness * led_strip_red_calibration;
led_strip_pixels[j * 3 + 2] =
blue * display_ambient_light_brightness * led_strip_blue_calibration; blue * display_ambient_light_brightness * led_strip_blue_calibration;
// Write RGB values to strip driver
ESP_ERROR_CHECK(
light_led_strip->set_pixel(light_led_strip, j, red, green, blue));
} }
update_desktop_connection_state(); // update_desktop_connection_state();
ESP_ERROR_CHECK(light_led_strip->refresh(light_led_strip, 100)); ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels,
sizeof(led_strip_pixels), &tx_config));
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) {
@ -359,24 +377,28 @@ 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;
@ -401,27 +423,30 @@ void light_play_colors(uint16_t len, uint8_t *buffer) {
b = (uint8_t)((float)buffer[buffer_cursor + 2] * b = (uint8_t)((float)buffer[buffer_cursor + 2] *
display_ambient_light_brightness * display_ambient_light_brightness *
led_strip_blue_calibration); led_strip_blue_calibration);
if (r <= 10 && g <= 10 && b <= 10) { if (r <= 7 && g <= 7 && b <= 7) {
black_count++; black_count++;
} }
ESP_ERROR_CHECK( led_strip_pixels[led_index * 3 + 0] = g;
light_led_strip->set_pixel(light_led_strip, led_index, r, g, b)); led_strip_pixels[led_index * 3 + 1] = r;
led_strip_pixels[led_index * 3 + 2] = b;
} }
if (black_count > STRIP_LED_NUMBER / 4 * 3) { if (black_count > STRIP_LED_NUMBER / 5 * 4) {
ESP_ERROR_CHECK(light_led_strip->clear(light_led_strip, 100)); uint8_t r = (uint8_t)((float)50 * display_ambient_light_brightness *
uint8_t r = (uint8_t)((float)100 * display_ambient_light_brightness *
led_strip_red_calibration), led_strip_red_calibration),
g = (uint8_t)((float)100 * display_ambient_light_brightness * g = (uint8_t)((float)40 * display_ambient_light_brightness *
led_strip_green_calibration), led_strip_green_calibration),
b = (uint8_t)((float)100 * display_ambient_light_brightness * b = (uint8_t)((float)20 * display_ambient_light_brightness *
led_strip_blue_calibration); led_strip_blue_calibration);
for (uint16_t led_index = 0; led_index < STRIP_LED_NUMBER; led_index++) { for (uint16_t led_index = 0; led_index < STRIP_LED_NUMBER; led_index++) {
ESP_ERROR_CHECK( led_strip_pixels[led_index * 3 + 0] = g;
light_led_strip->set_pixel(light_led_strip, led_index, r, g, b)); led_strip_pixels[led_index * 3 + 1] = r;
led_strip_pixels[led_index * 3 + 2] = b;
} }
} }
ESP_ERROR_CHECK(light_led_strip->refresh(light_led_strip, 100));
ESP_ERROR_CHECK(rmt_transmit(led_chan, led_encoder, led_strip_pixels,
sizeof(led_strip_pixels), &tx_config));
vTaskDelay(pdMS_TO_TICKS(10)); vTaskDelay(pdMS_TO_TICKS(10));
} }

View File

@ -5,6 +5,7 @@
#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 "i2c.c" #include "i2c.c"
#include "light.c" #include "light.c"
#include "mqtt.c" #include "mqtt.c"
@ -19,14 +20,18 @@ static const char *TAG = "DisplayAmbientLight";
void app_main(void) { void app_main(void) {
app_nvs_init(); app_nvs_init();
light_init_strip(); light_init_strip();
gpio_install_isr_service(0);
init_i2c(); init_i2c();
i2c_check_slaves(); i2c_check_slaves();
init_display(); init_display();
display_print8_str(0, 0, "Ambient Light"); display_print8_str(0, 0, "Ambient Light");
// hw_ms03_init();
ci_03t_init(); ci_03t_init();
apes_9960_init(); apds_9960_init();
// apes_9960_auto_fetch(); apds_9960_auto_fetch();
// auto_fetch_temperature(); auto_fetch_temperature();
pca9555_init(); pca9555_init();
ui_input_init(); ui_input_init();
xTaskCreate(mqtt_publish_ui_input, "mqtt_publish_ui_input", 2048, NULL, 10, xTaskCreate(mqtt_publish_ui_input, "mqtt_publish_ui_input", 2048, NULL, 10,

View File

@ -52,7 +52,7 @@
static const char *MQTT_TAG = "DisplayAmbientLight_MQTT"; static const char *MQTT_TAG = "DisplayAmbientLight_MQTT";
static EventGroupHandle_t s_mqtt_event_group; static EventGroupHandle_t s_mqtt_event_group;
static xQueueHandle mqtt_cmd_event = NULL; static QueueHandle_t mqtt_cmd_event = NULL;
static esp_mqtt_client_handle_t client = NULL; static esp_mqtt_client_handle_t client = NULL;
typedef struct colors { typedef struct colors {
@ -69,8 +69,8 @@ static void log_error_if_nonzero(const char *message, int error_code) {
} }
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, static void mqtt_event_handler(void *handler_args, esp_event_base_t base,
int32_t event_id, void *event_data) { long event_id, void *event_data) {
ESP_LOGD(MQTT_TAG, "Event dispatched from event loop base=%s, event_id=%d", ESP_LOGD(MQTT_TAG, "Event dispatched from event loop base=%s, event_id=%ld",
base, event_id); base, event_id);
esp_mqtt_event_handle_t event = event_data; esp_mqtt_event_handle_t event = event_data;
client = event->client; client = event->client;
@ -195,7 +195,7 @@ static void mqtt_app_start() {
xTaskCreate(mqtt_cmd_event_handler, "mqtt_cmd_event", 2048, NULL, 10, NULL); xTaskCreate(mqtt_cmd_event_handler, "mqtt_cmd_event", 2048, NULL, 10, NULL);
const esp_mqtt_client_config_t mqtt_cfg = { const esp_mqtt_client_config_t mqtt_cfg = {
.uri = MQTT_BROKER_URL, .broker.address.uri = MQTT_BROKER_URL,
}; };
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg); 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, esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler,

View File

@ -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 (;;) {

View File

@ -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,6 @@ 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";
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 +58,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) {
@ -196,8 +195,6 @@ void ui_input_init(void) {
ui_input_event = xQueueCreate(10, sizeof(s_ui_input_t)); ui_input_event = xQueueCreate(10, sizeof(s_ui_input_t));
ui_input_raw_event = xQueueCreate(10, 0); ui_input_raw_event = xQueueCreate(10, 0);
// install gpio isr service
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
// 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);