Enhance DALI Component Configuration and Functionality

- Updated README.md to include new configuration options for native timing values, TX/RX polarity, power-down polling, and logging levels.
- Introduced new default values for query response timeout and double-send delay in dali.c.
- Implemented a function to drain stale RX frames from the queue to improve query handling.
- Enhanced DALI HAL implementation in dali_hal_idf5.c with additional configuration options for timer resolution and bus power check intervals.
- Added logging capabilities to track bus states and message transmissions in the DALI HAL.
- Improved error handling and message response mechanisms in dali_domain.cpp and gateway_usb_setup.cpp for better communication reliability.
- Refactored GPIO handling to support configurable TX/RX active states in dali_hal.h.
- Introduced legacy query response handling for backward compatibility in the DALI domain.

Signed-off-by: Tony <tonylu@tony-cloud.com>
This commit is contained in:
Tony
2026-05-15 01:26:13 +08:00
parent 4553ed32e7
commit 0b2d00472e
11 changed files with 3798 additions and 104 deletions
+31 -13
View File
@@ -603,15 +603,13 @@ CONFIG_GATEWAY_CHANNEL_COUNT=1
# #
CONFIG_GATEWAY_CHANNEL1_GW_ID=3 CONFIG_GATEWAY_CHANNEL1_GW_ID=3
# CONFIG_GATEWAY_CHANNEL1_PHY_DISABLED is not set # CONFIG_GATEWAY_CHANNEL1_PHY_DISABLED is not set
# CONFIG_GATEWAY_CHANNEL1_PHY_NATIVE is not set CONFIG_GATEWAY_CHANNEL1_PHY_NATIVE=y
CONFIG_GATEWAY_CHANNEL1_PHY_UART1=y # CONFIG_GATEWAY_CHANNEL1_PHY_UART1 is not set
# CONFIG_GATEWAY_CHANNEL1_PHY_UART2 is not set # CONFIG_GATEWAY_CHANNEL1_PHY_UART2 is not set
CONFIG_GATEWAY_CHANNEL1_SERIAL_TX_PIN=1 CONFIG_GATEWAY_CHANNEL1_NATIVE_BUS_ID=0
CONFIG_GATEWAY_CHANNEL1_SERIAL_RX_PIN=2 CONFIG_GATEWAY_CHANNEL1_NATIVE_TX_PIN=2
CONFIG_GATEWAY_CHANNEL1_SERIAL_BAUDRATE=9600 CONFIG_GATEWAY_CHANNEL1_NATIVE_RX_PIN=1
CONFIG_GATEWAY_CHANNEL1_SERIAL_RX_BUFFER=512 CONFIG_GATEWAY_CHANNEL1_NATIVE_BAUDRATE=1200
CONFIG_GATEWAY_CHANNEL1_SERIAL_TX_BUFFER=512
CONFIG_GATEWAY_CHANNEL1_SERIAL_QUERY_TIMEOUT_MS=100
# end of Gateway Channel 1 # end of Gateway Channel 1
# #
@@ -626,7 +624,7 @@ CONFIG_GATEWAY_CACHE_SUPPORTED=y
CONFIG_GATEWAY_CACHE_START_ENABLED=y CONFIG_GATEWAY_CACHE_START_ENABLED=y
CONFIG_GATEWAY_CACHE_RECONCILIATION_ENABLED=y CONFIG_GATEWAY_CACHE_RECONCILIATION_ENABLED=y
# CONFIG_GATEWAY_CACHE_FULL_STATE_MIRROR is not set # CONFIG_GATEWAY_CACHE_FULL_STATE_MIRROR is not set
CONFIG_GATEWAY_CACHE_FLUSH_INTERVAL_MS=5000 CONFIG_GATEWAY_CACHE_FLUSH_INTERVAL_MS=60000
CONFIG_GATEWAY_CACHE_OUTSIDE_BUS_FIRST=y CONFIG_GATEWAY_CACHE_OUTSIDE_BUS_FIRST=y
# CONFIG_GATEWAY_CACHE_LOCAL_GATEWAY_FIRST is not set # CONFIG_GATEWAY_CACHE_LOCAL_GATEWAY_FIRST is not set
# end of Gateway Cache # end of Gateway Cache
@@ -696,6 +694,7 @@ CONFIG_GATEWAY_KNX_TP_UART_PORT=0
CONFIG_GATEWAY_KNX_TP_TX_PIN=-1 CONFIG_GATEWAY_KNX_TP_TX_PIN=-1
CONFIG_GATEWAY_KNX_TP_RX_PIN=-1 CONFIG_GATEWAY_KNX_TP_RX_PIN=-1
CONFIG_GATEWAY_KNX_TP_BAUDRATE=19200 CONFIG_GATEWAY_KNX_TP_BAUDRATE=19200
CONFIG_GATEWAY_KNX_TP_UART_9BIT_MODE=y
CONFIG_GATEWAY_BRIDGE_KNX_TASK_STACK_SIZE=12288 CONFIG_GATEWAY_BRIDGE_KNX_TASK_STACK_SIZE=12288
CONFIG_GATEWAY_BRIDGE_KNX_TASK_PRIORITY=5 CONFIG_GATEWAY_BRIDGE_KNX_TASK_PRIORITY=5
CONFIG_GATEWAY_CLOUD_BRIDGE_SUPPORTED=y CONFIG_GATEWAY_CLOUD_BRIDGE_SUPPORTED=y
@@ -2772,13 +2771,32 @@ CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN=y
# #
CONFIG_DALI_PHY_COUNT=16 CONFIG_DALI_PHY_COUNT=16
CONFIG_DALI_DEFAULT_BAUDRATE=1200 CONFIG_DALI_DEFAULT_BAUDRATE=1200
CONFIG_DALI_API_QUEUE_LEN=10 CONFIG_DALI_TIMER_RESOLUTION_HZ=3000000
CONFIG_DALI_TX_QUEUE_LEN=1 CONFIG_DALI_CUSTOM_HALF_BIT_TIME_X100_US=0
CONFIG_DALI_TX_STOP_CONDITION_US=0
CONFIG_DALI_RX_STOP_CONDITION_US=0
CONFIG_DALI_QUERY_RESPONSE_TIMEOUT_MS=25
CONFIG_DALI_DOUBLE_SEND_DELAY_MS=12
CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS=500
CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS=3000
# CONFIG_DALI_LOG_LEVEL_NONE is not set
# CONFIG_DALI_LOG_LEVEL_ERROR is not set
# CONFIG_DALI_LOG_LEVEL_WARN is not set
# CONFIG_DALI_LOG_LEVEL_INFO is not set
# CONFIG_DALI_LOG_LEVEL_DEBUG is not set
CONFIG_DALI_LOG_LEVEL_VERBOSE=y
CONFIG_DALI_LOG_LEVEL=5
CONFIG_DALI_TX_ACTIVE_LOW=y
# CONFIG_DALI_TX_ACTIVE_HIGH is not set
CONFIG_DALI_RX_ACTIVE_LOW=y
# CONFIG_DALI_RX_ACTIVE_HIGH is not set
CONFIG_DALI_API_QUEUE_LEN=64
CONFIG_DALI_TX_QUEUE_LEN=4
CONFIG_DALI_TX_REPLY_QUEUE_LEN=4 CONFIG_DALI_TX_REPLY_QUEUE_LEN=4
CONFIG_DALI_RX_QUEUE_LEN=50 CONFIG_DALI_RX_QUEUE_LEN=50
CONFIG_DALI_DEBUG_QUEUE_LEN=100 CONFIG_DALI_DEBUG_QUEUE_LEN=100
# CONFIG_DALI_ENABLE_DEBUG_TASK is not set CONFIG_DALI_ENABLE_DEBUG_TASK=y
CONFIG_DALI_DALI_TASK_STACK_SIZE=2048 CONFIG_DALI_DALI_TASK_STACK_SIZE=8192
CONFIG_DALI_DALI_TASK_PRIORITY=2 CONFIG_DALI_DALI_TASK_PRIORITY=2
CONFIG_DALI_DEBUG_TASK_STACK_SIZE=2048 CONFIG_DALI_DEBUG_TASK_STACK_SIZE=2048
CONFIG_DALI_DEBUG_TASK_PRIORITY=1 CONFIG_DALI_DEBUG_TASK_PRIORITY=1
File diff suppressed because it is too large Load Diff
+33 -26
View File
@@ -596,38 +596,25 @@ CONFIG_PARTITION_TABLE_MD5=y
# #
# Gateway App # Gateway App
# #
CONFIG_GATEWAY_CHANNEL_COUNT=2 CONFIG_GATEWAY_CHANNEL_COUNT=1
# #
# Gateway Channel 1 # Gateway Channel 1
# #
CONFIG_GATEWAY_CHANNEL1_GW_ID=3 CONFIG_GATEWAY_CHANNEL1_GW_ID=3
# CONFIG_GATEWAY_CHANNEL1_PHY_DISABLED is not set # CONFIG_GATEWAY_CHANNEL1_PHY_DISABLED is not set
# CONFIG_GATEWAY_CHANNEL1_PHY_NATIVE is not set CONFIG_GATEWAY_CHANNEL1_PHY_NATIVE=y
CONFIG_GATEWAY_CHANNEL1_PHY_UART1=y # CONFIG_GATEWAY_CHANNEL1_PHY_UART1 is not set
# CONFIG_GATEWAY_CHANNEL1_PHY_UART2 is not set # CONFIG_GATEWAY_CHANNEL1_PHY_UART2 is not set
CONFIG_GATEWAY_CHANNEL1_SERIAL_TX_PIN=1 CONFIG_GATEWAY_CHANNEL1_NATIVE_BUS_ID=0
CONFIG_GATEWAY_CHANNEL1_SERIAL_RX_PIN=2 CONFIG_GATEWAY_CHANNEL1_NATIVE_TX_PIN=2
CONFIG_GATEWAY_CHANNEL1_SERIAL_BAUDRATE=9600 CONFIG_GATEWAY_CHANNEL1_NATIVE_RX_PIN=1
CONFIG_GATEWAY_CHANNEL1_SERIAL_RX_BUFFER=512 CONFIG_GATEWAY_CHANNEL1_NATIVE_BAUDRATE=1200
CONFIG_GATEWAY_CHANNEL1_SERIAL_TX_BUFFER=512
CONFIG_GATEWAY_CHANNEL1_SERIAL_QUERY_TIMEOUT_MS=100
# end of Gateway Channel 1 # end of Gateway Channel 1
# #
# Gateway Channel 2 # Gateway Channel 2
# #
CONFIG_GATEWAY_CHANNEL2_GW_ID=4
# CONFIG_GATEWAY_CHANNEL2_PHY_DISABLED is not set
# CONFIG_GATEWAY_CHANNEL2_PHY_NATIVE is not set
# CONFIG_GATEWAY_CHANNEL2_PHY_UART1 is not set
CONFIG_GATEWAY_CHANNEL2_PHY_UART2=y
CONFIG_GATEWAY_CHANNEL2_SERIAL_TX_PIN=6
CONFIG_GATEWAY_CHANNEL2_SERIAL_RX_PIN=7
CONFIG_GATEWAY_CHANNEL2_SERIAL_BAUDRATE=9600
CONFIG_GATEWAY_CHANNEL2_SERIAL_RX_BUFFER=512
CONFIG_GATEWAY_CHANNEL2_SERIAL_TX_BUFFER=512
CONFIG_GATEWAY_CHANNEL2_SERIAL_QUERY_TIMEOUT_MS=100
# end of Gateway Channel 2 # end of Gateway Channel 2
# #
@@ -637,7 +624,7 @@ CONFIG_GATEWAY_CACHE_SUPPORTED=y
CONFIG_GATEWAY_CACHE_START_ENABLED=y CONFIG_GATEWAY_CACHE_START_ENABLED=y
CONFIG_GATEWAY_CACHE_RECONCILIATION_ENABLED=y CONFIG_GATEWAY_CACHE_RECONCILIATION_ENABLED=y
# CONFIG_GATEWAY_CACHE_FULL_STATE_MIRROR is not set # CONFIG_GATEWAY_CACHE_FULL_STATE_MIRROR is not set
CONFIG_GATEWAY_CACHE_FLUSH_INTERVAL_MS=5000 CONFIG_GATEWAY_CACHE_FLUSH_INTERVAL_MS=60000
CONFIG_GATEWAY_CACHE_OUTSIDE_BUS_FIRST=y CONFIG_GATEWAY_CACHE_OUTSIDE_BUS_FIRST=y
# CONFIG_GATEWAY_CACHE_LOCAL_GATEWAY_FIRST is not set # CONFIG_GATEWAY_CACHE_LOCAL_GATEWAY_FIRST is not set
# end of Gateway Cache # end of Gateway Cache
@@ -707,7 +694,8 @@ CONFIG_GATEWAY_KNX_TP_UART_PORT=0
CONFIG_GATEWAY_KNX_TP_TX_PIN=-1 CONFIG_GATEWAY_KNX_TP_TX_PIN=-1
CONFIG_GATEWAY_KNX_TP_RX_PIN=-1 CONFIG_GATEWAY_KNX_TP_RX_PIN=-1
CONFIG_GATEWAY_KNX_TP_BAUDRATE=19200 CONFIG_GATEWAY_KNX_TP_BAUDRATE=19200
CONFIG_GATEWAY_BRIDGE_KNX_TASK_STACK_SIZE=8192 CONFIG_GATEWAY_KNX_TP_UART_9BIT_MODE=y
CONFIG_GATEWAY_BRIDGE_KNX_TASK_STACK_SIZE=12288
CONFIG_GATEWAY_BRIDGE_KNX_TASK_PRIORITY=5 CONFIG_GATEWAY_BRIDGE_KNX_TASK_PRIORITY=5
CONFIG_GATEWAY_CLOUD_BRIDGE_SUPPORTED=y CONFIG_GATEWAY_CLOUD_BRIDGE_SUPPORTED=y
# CONFIG_GATEWAY_START_CLOUD_BRIDGE_ENABLED is not set # CONFIG_GATEWAY_START_CLOUD_BRIDGE_ENABLED is not set
@@ -1818,7 +1806,7 @@ CONFIG_ESP_SYSTEM_MEMPROT_FEATURE_LOCK=y
CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304
CONFIG_ESP_MAIN_TASK_STACK_SIZE=3584 CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y
# CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set # CONFIG_ESP_MAIN_TASK_AFFINITY_CPU1 is not set
# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set # CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set
@@ -2783,13 +2771,32 @@ CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN=y
# #
CONFIG_DALI_PHY_COUNT=16 CONFIG_DALI_PHY_COUNT=16
CONFIG_DALI_DEFAULT_BAUDRATE=1200 CONFIG_DALI_DEFAULT_BAUDRATE=1200
CONFIG_DALI_API_QUEUE_LEN=10 CONFIG_DALI_TIMER_RESOLUTION_HZ=3000000
CONFIG_DALI_TX_QUEUE_LEN=1 CONFIG_DALI_CUSTOM_HALF_BIT_TIME_X100_US=0
CONFIG_DALI_TX_STOP_CONDITION_US=0
CONFIG_DALI_RX_STOP_CONDITION_US=0
CONFIG_DALI_QUERY_RESPONSE_TIMEOUT_MS=25
CONFIG_DALI_DOUBLE_SEND_DELAY_MS=12
CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS=500
CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS=3000
# CONFIG_DALI_LOG_LEVEL_NONE is not set
# CONFIG_DALI_LOG_LEVEL_ERROR is not set
# CONFIG_DALI_LOG_LEVEL_WARN is not set
# CONFIG_DALI_LOG_LEVEL_INFO is not set
# CONFIG_DALI_LOG_LEVEL_DEBUG is not set
CONFIG_DALI_LOG_LEVEL_VERBOSE=y
CONFIG_DALI_LOG_LEVEL=5
CONFIG_DALI_TX_ACTIVE_LOW=y
# CONFIG_DALI_TX_ACTIVE_HIGH is not set
CONFIG_DALI_RX_ACTIVE_LOW=y
# CONFIG_DALI_RX_ACTIVE_HIGH is not set
CONFIG_DALI_API_QUEUE_LEN=64
CONFIG_DALI_TX_QUEUE_LEN=4
CONFIG_DALI_TX_REPLY_QUEUE_LEN=4 CONFIG_DALI_TX_REPLY_QUEUE_LEN=4
CONFIG_DALI_RX_QUEUE_LEN=50 CONFIG_DALI_RX_QUEUE_LEN=50
CONFIG_DALI_DEBUG_QUEUE_LEN=100 CONFIG_DALI_DEBUG_QUEUE_LEN=100
# CONFIG_DALI_ENABLE_DEBUG_TASK is not set # CONFIG_DALI_ENABLE_DEBUG_TASK is not set
CONFIG_DALI_DALI_TASK_STACK_SIZE=2048 CONFIG_DALI_DALI_TASK_STACK_SIZE=8192
CONFIG_DALI_DALI_TASK_PRIORITY=2 CONFIG_DALI_DALI_TASK_PRIORITY=2
CONFIG_DALI_DEBUG_TASK_STACK_SIZE=2048 CONFIG_DALI_DEBUG_TASK_STACK_SIZE=2048
CONFIG_DALI_DEBUG_TASK_PRIORITY=1 CONFIG_DALI_DEBUG_TASK_PRIORITY=1
+135 -1
View File
@@ -14,6 +14,140 @@ config DALI_DEFAULT_BAUDRATE
help help
Default baudrate used during initialization. Default baudrate used during initialization.
config DALI_TIMER_RESOLUTION_HZ
int "Native DALI timer resolution Hz"
range 1000000 8000000
default 3000000
help
GPTimer resolution for native DALI Manchester timing. The default 3 MHz
allows a 1200 bps half-bit period of 416.67 us to be represented as
1250 timer ticks.
config DALI_CUSTOM_HALF_BIT_TIME_X100_US
int "Custom native DALI half-bit time x100 us"
range 0 500000
default 0
help
Development override for the native DALI half-bit period, expressed in
1/100 us. Set to 0 to derive the value from the configured baudrate.
Standard 1200 bps DALI is 41667, meaning 416.67 us.
config DALI_TX_STOP_CONDITION_US
int "Custom TX stop condition us"
range 0 10000
default 0
help
Development override for the native TX stop-condition wait. Set to 0 to
use the scaled standard timing.
config DALI_RX_STOP_CONDITION_US
int "Custom RX stop condition us"
range 0 10000
default 0
help
Development override for the native RX stop-condition wait. Set to 0 to
use the scaled standard timing.
config DALI_QUERY_RESPONSE_TIMEOUT_MS
int "DALI query response timeout ms"
range 10 100
default 25
help
Time to wait for a complete backward frame after a forward query has
finished transmitting. DALI backward frames start 5.5-10.5 ms after the
forward frame and last about 9.95 ms, so 25 ms leaves margin without the
legacy 50 ms no-response delay.
config DALI_DOUBLE_SEND_DELAY_MS
int "Double-send delay ms"
range 0 100
default 10
help
Delay between the two frames sent by dali_send_double(), measured after
the first frame has completed. Exposed for development tuning.
config DALI_BUS_POWER_CHECK_INTERVAL_MS
int "Bus power-down check interval ms"
range 10 5000
default 100
help
Interval used to resample the RX pin while the native DALI bus is marked
power-down. This lets the HAL recover when the bus was already powered
before gateway startup and no RX edge is generated.
config DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS
int "Legacy bus abnormal report interval ms"
range 0 60000
default 1000
help
Interval for publishing the legacy two-byte FF FD bus-abnormal raw frame
while the native DALI bus is power-down. Set to 0 to disable the report.
choice DALI_LOG_LEVEL_CHOICE
prompt "DALI log level"
default DALI_LOG_LEVEL_WARN
help
Runtime log level applied to the native DALI HAL ESP-IDF log tag.
config DALI_LOG_LEVEL_NONE
bool "No output"
config DALI_LOG_LEVEL_ERROR
bool "Error"
config DALI_LOG_LEVEL_WARN
bool "Warning"
config DALI_LOG_LEVEL_INFO
bool "Info"
config DALI_LOG_LEVEL_DEBUG
bool "Debug"
config DALI_LOG_LEVEL_VERBOSE
bool "Verbose"
endchoice
config DALI_LOG_LEVEL
int
default 0 if DALI_LOG_LEVEL_NONE
default 1 if DALI_LOG_LEVEL_ERROR
default 2 if DALI_LOG_LEVEL_WARN
default 3 if DALI_LOG_LEVEL_INFO
default 4 if DALI_LOG_LEVEL_DEBUG
default 5 if DALI_LOG_LEVEL_VERBOSE
choice DALI_TX_ACTIVE_LEVEL
prompt "DALI TX pin active level"
default DALI_TX_ACTIVE_LOW
help
Select the physical GPIO level that drives the DALI bus active. The
native gateway default is TX active low.
config DALI_TX_ACTIVE_LOW
bool "Active low"
config DALI_TX_ACTIVE_HIGH
bool "Active high"
endchoice
choice DALI_RX_ACTIVE_LEVEL
prompt "DALI RX pin active level"
default DALI_RX_ACTIVE_HIGH
help
Select the physical GPIO level read when the DALI bus is active. The
native gateway default is RX active high.
config DALI_RX_ACTIVE_LOW
bool "Active low"
config DALI_RX_ACTIVE_HIGH
bool "Active high"
endchoice
config DALI_API_QUEUE_LEN config DALI_API_QUEUE_LEN
int "Global API queue length" int "Global API queue length"
range 1 64 range 1 64
@@ -48,7 +182,7 @@ config DALI_ENABLE_DEBUG_TASK
config DALI_DALI_TASK_STACK_SIZE config DALI_DALI_TASK_STACK_SIZE
int "DALI task stack size" int "DALI task stack size"
range 1024 8192 range 1024 8192
default 2048 default 4096
config DALI_DALI_TASK_PRIORITY config DALI_DALI_TASK_PRIORITY
int "DALI task priority" int "DALI task priority"
+16
View File
@@ -41,10 +41,26 @@ void app_main(void) {
Use `menuconfig` under `DALI Component` to configure: Use `menuconfig` under `DALI Component` to configure:
- Bus count and default baudrate. - Bus count and default baudrate.
- Native timing values for development, including timer resolution, half-bit period,
TX/RX stop conditions, query response timeout, and double-send delay.
- TX/RX active polarity. The native gateway default is TX active low and RX active high.
- Native bus power-down polling and legacy `FF FD` bus-abnormal raw-frame reporting intervals.
- Native DALI HAL log level for the `dali_hal` ESP-IDF log tag.
- Queue sizes. - Queue sizes.
- Task stack sizes and priorities. - Task stack sizes and priorities.
- Optional debug task. - Optional debug task.
The native bus monitor uses `CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS` to resample RX while
power-down and `CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS` to publish legacy `FF FD`
raw frames while down. The report interval defaults to 1000 ms; set it to 0 to disable the
compatibility report.
Native timing defaults target standard 1200 bps DALI: a 416.67 us half-bit period is
generated by the default 3 MHz timer as 1250 ticks. `CONFIG_DALI_CUSTOM_HALF_BIT_TIME_X100_US`
can override the half-bit period for development; keep it at 0 for baudrate-derived timing.
Query no-response timeout defaults to 25 ms, which covers the 5.5-10.5 ms backward-frame
start window plus the approximately 9.95 ms backward frame duration.
## API Note ## API Note
The global TX response queue symbol was renamed: The global TX response queue symbol was renamed:
+28 -7
View File
@@ -6,6 +6,14 @@
#include <memory.h> // for memset #include <memory.h> // for memset
#include "freertos/semphr.h" #include "freertos/semphr.h"
#ifndef CONFIG_DALI_QUERY_RESPONSE_TIMEOUT_MS
#define CONFIG_DALI_QUERY_RESPONSE_TIMEOUT_MS 25
#endif
#ifndef CONFIG_DALI_DOUBLE_SEND_DELAY_MS
#define CONFIG_DALI_DOUBLE_SEND_DELAY_MS 10
#endif
static SemaphoreHandle_t s_dali_core_lock; static SemaphoreHandle_t s_dali_core_lock;
static SemaphoreHandle_t dali_core_mutex(void) static SemaphoreHandle_t dali_core_mutex(void)
@@ -31,6 +39,20 @@ static inline void dali_core_unlock(void)
} }
} }
static UBaseType_t drain_rx_queue(QueueHandle_t rx_q)
{
if (rx_q == NULL) {
return 0;
}
Dali_msg_t stale = {0};
UBaseType_t drained = 0;
while (xQueueReceive(rx_q, &stale, 0) == pdTRUE) {
drained++;
}
return drained;
}
Dali_msg_t dali_msg_new_generic(uint8_t bit_length, uint8_t address, uint8_t cmd1, uint8_t cmd2, uint8_t cmd3) { Dali_msg_t dali_msg_new_generic(uint8_t bit_length, uint8_t address, uint8_t cmd1, uint8_t cmd2, uint8_t cmd3) {
Dali_msg_t dali_msg; Dali_msg_t dali_msg;
dali_msg.id = 0; dali_msg.id = 0;
@@ -90,7 +112,7 @@ void dali_send_double(Dali_msg_t *dali_msg) {
dali_send_locked(dali_msg); dali_send_locked(dali_msg);
// TODO check status // TODO check status
dali_msg->id++; // increment message ID dali_msg->id++; // increment message ID
dali_delay_ms(10); // delay 13ms 101.8.1.2: 13.5 - 75ms dali_delay_ms(CONFIG_DALI_DOUBLE_SEND_DELAY_MS);
dali_send_locked(dali_msg); dali_send_locked(dali_msg);
// TODO check status // TODO check status
dali_core_unlock(); dali_core_unlock();
@@ -110,17 +132,16 @@ int dali_query(Dali_msg_t *tx_msg, Dali_msg_t *rx_msg) {
return -1; return -1;
} }
// TODO check empty queue dali_core_lock();
if(xQueueReceive(rx_q, rx_msg, 0) == pdTRUE) { UBaseType_t drained = drain_rx_queue(rx_q);
printf("Queue not empty\n"); if (drained > 0) {
return -1; printf("dali_query: dropped %u stale RX frame(s)\n", (unsigned)drained);
} }
// printf("check A tx=%d tm=%d[ms] st=%d len=%d d0=0x%X\n", ret, tx_msg->type, tx_msg->status, tx_msg->length, tx_msg->data[0]); // printf("check A tx=%d tm=%d[ms] st=%d len=%d d0=0x%X\n", ret, tx_msg->type, tx_msg->status, tx_msg->length, tx_msg->data[0]);
dali_core_lock();
dali_send_locked(tx_msg); dali_send_locked(tx_msg);
// receive message from DALI task // receive message from DALI task
ret = xQueueReceive(rx_q, rx_msg, pdMS_TO_TICKS(50)); ret = xQueueReceive(rx_q, rx_msg, pdMS_TO_TICKS(CONFIG_DALI_QUERY_RESPONSE_TIMEOUT_MS));
dali_core_unlock(); dali_core_unlock();
// printf("B rx=%d tm=%d[ms] st=%d len=%d d0=0x%X\n", ret, rx_msg->type, rx_msg->status, rx_msg->length, rx_msg->data[0]); // printf("B rx=%d tm=%d[ms] st=%d len=%d d0=0x%X\n", ret, rx_msg->type, rx_msg->status, rx_msg->length, rx_msg->data[0]);
return ret; return ret;
+420 -44
View File
@@ -4,6 +4,15 @@
//ESP-IDF HAL //ESP-IDF HAL
#ifdef CONFIG_IDF_TARGET #ifdef CONFIG_IDF_TARGET
#include "sdkconfig.h" #include "sdkconfig.h"
#ifndef CONFIG_DALI_LOG_LEVEL
#define CONFIG_DALI_LOG_LEVEL 2
#endif
#ifndef LOG_LOCAL_LEVEL
#define LOG_LOCAL_LEVEL CONFIG_DALI_LOG_LEVEL
#endif
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/queue.h" #include "freertos/queue.h"
@@ -39,7 +48,7 @@
#endif #endif
#ifndef CONFIG_DALI_DALI_TASK_STACK_SIZE #ifndef CONFIG_DALI_DALI_TASK_STACK_SIZE
#define CONFIG_DALI_DALI_TASK_STACK_SIZE 2048 #define CONFIG_DALI_DALI_TASK_STACK_SIZE 4096
#endif #endif
#ifndef CONFIG_DALI_DALI_TASK_PRIORITY #ifndef CONFIG_DALI_DALI_TASK_PRIORITY
@@ -54,14 +63,41 @@
#define CONFIG_DALI_DEBUG_TASK_PRIORITY 1 #define CONFIG_DALI_DEBUG_TASK_PRIORITY 1
#endif #endif
#ifndef CONFIG_DALI_TIMER_RESOLUTION_HZ
#define CONFIG_DALI_TIMER_RESOLUTION_HZ 3000000
#endif
#ifndef CONFIG_DALI_CUSTOM_HALF_BIT_TIME_X100_US
#define CONFIG_DALI_CUSTOM_HALF_BIT_TIME_X100_US 0
#endif
#ifndef CONFIG_DALI_TX_STOP_CONDITION_US
#define CONFIG_DALI_TX_STOP_CONDITION_US 0
#endif
#ifndef CONFIG_DALI_RX_STOP_CONDITION_US
#define CONFIG_DALI_RX_STOP_CONDITION_US 0
#endif
#ifndef CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS
#define CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS 100
#endif
#ifndef CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS
#define CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS 1000
#endif
#define WITHIN_RANGE(x, min, max) ((x) > (min) && (x) < (max)) #define WITHIN_RANGE(x, min, max) ((x) > (min) && (x) < (max))
#define MAX_DELTA_RELOAD_TIME 600000000 // 600s - max u32: 4,294,967,295~4,294s #define MAX_DELTA_RELOAD_TIME 600000000 // 600s - max u32: 4,294,967,295~4,294s
#define DALI_BAUDRATE_MIN 400U #define DALI_BAUDRATE_MIN 400U
#define DALI_BAUDRATE_MAX 2400U #define DALI_BAUDRATE_MAX 2400U
#define DALI_BUS_POWER_CHECK_INTERVAL_US ((uint64_t)CONFIG_DALI_BUS_POWER_CHECK_INTERVAL_MS * 1000ULL)
#define DALI_BUS_ABNORMAL_REPORT_INTERVAL_US ((uint64_t)CONFIG_DALI_BUS_ABNORMAL_REPORT_INTERVAL_MS * 1000ULL)
typedef struct { typedef struct {
uint32_t hb; uint32_t hb;
uint32_t timer_alarm_ticks;
uint32_t rx_hb_min; uint32_t rx_hb_min;
uint32_t rx_hb_max; uint32_t rx_hb_max;
uint32_t rx_2hb_min; uint32_t rx_2hb_min;
@@ -76,6 +112,11 @@ typedef struct {
static const char *TAG = "dali_hal"; static const char *TAG = "dali_hal";
static inline void apply_dali_log_level(void)
{
esp_log_level_set(TAG, (esp_log_level_t)CONFIG_DALI_LOG_LEVEL);
}
typedef struct { typedef struct {
uint8_t bus_id; uint8_t bus_id;
uint8_t tx_pin; uint8_t tx_pin;
@@ -91,6 +132,10 @@ typedef struct {
uint32_t rx_tx_delta; uint32_t rx_tx_delta;
uint32_t rx_pulse_width; uint32_t rx_pulse_width;
uint8_t rx_level; uint8_t rx_level;
uint8_t tx_level;
uint64_t bus_level_check_time;
uint64_t bus_abnormal_report_time;
Dali_msg_t tx_data; Dali_msg_t tx_data;
Dali_msg_t rx_data; Dali_msg_t rx_data;
@@ -137,17 +182,31 @@ static inline void dali_hal_unlock(void)
} }
} }
static uint32_t dali_half_bit_from_baud(uint32_t baudrate) static uint32_t dali_half_bit_x100_from_baud(uint32_t baudrate)
{ {
if (baudrate < DALI_BAUDRATE_MIN || baudrate > DALI_BAUDRATE_MAX) { if (baudrate < DALI_BAUDRATE_MIN || baudrate > DALI_BAUDRATE_MAX) {
return 0; return 0;
} }
uint64_t hb = 500000ULL + (baudrate / 2U); // round to nearest uint64_t hb_x100 = 50000000ULL + (baudrate / 2U); // round to nearest 0.01 us
hb /= baudrate; hb_x100 /= baudrate;
if (hb == 0 || hb > 2000000ULL) { // should never happen with checked bounds if (hb_x100 == 0 || hb_x100 > 200000000ULL) { // should never happen with checked bounds
return 0; return 0;
} }
return (uint32_t)hb; return (uint32_t)hb_x100;
}
static uint32_t half_bit_us_from_x100(uint32_t hb_x100)
{
return (hb_x100 + 50U) / 100U;
}
static uint32_t timer_alarm_ticks_from_x100(uint32_t hb_x100)
{
uint64_t ticks = ((uint64_t)CONFIG_DALI_TIMER_RESOLUTION_HZ * hb_x100 + 50000000ULL) / 100000000ULL;
if (ticks == 0 || ticks > UINT32_MAX) {
return 0;
}
return (uint32_t)ticks;
} }
static inline uint32_t scale_time_by_hb(uint32_t base_us, uint32_t hb_us) static inline uint32_t scale_time_by_hb(uint32_t base_us, uint32_t hb_us)
@@ -155,25 +214,40 @@ static inline uint32_t scale_time_by_hb(uint32_t base_us, uint32_t hb_us)
return (uint32_t)(((uint64_t)base_us * hb_us + (DALI_TIME_HB / 2U)) / DALI_TIME_HB); return (uint32_t)(((uint64_t)base_us * hb_us + (DALI_TIME_HB / 2U)) / DALI_TIME_HB);
} }
static inline uint32_t configured_or_scaled_time(uint32_t configured_us, uint32_t base_us,
uint32_t hb_us)
{
return configured_us > 0 ? configured_us : scale_time_by_hb(base_us, hb_us);
}
static esp_err_t update_timing_locked(uint32_t baudrate) static esp_err_t update_timing_locked(uint32_t baudrate)
{ {
uint32_t hb = dali_half_bit_from_baud(baudrate); uint32_t hb_x100 = CONFIG_DALI_CUSTOM_HALF_BIT_TIME_X100_US;
if (hb == 0) { if (hb_x100 == 0) {
ESP_LOGE(TAG, "invalid baudrate: %u", baudrate); hb_x100 = dali_half_bit_x100_from_baud(baudrate);
}
uint32_t hb = half_bit_us_from_x100(hb_x100);
uint32_t timer_alarm_ticks = timer_alarm_ticks_from_x100(hb_x100);
if (hb == 0 || timer_alarm_ticks == 0) {
ESP_LOGE(TAG, "invalid native timing: baudrate=%u hbX100Us=%u timerHz=%u",
baudrate, hb_x100, CONFIG_DALI_TIMER_RESOLUTION_HZ);
return ESP_ERR_INVALID_ARG; return ESP_ERR_INVALID_ARG;
} }
dali_timing_t new_timing = { dali_timing_t new_timing = {
.hb = hb, .hb = hb,
.timer_alarm_ticks = timer_alarm_ticks,
.rx_hb_min = scale_time_by_hb(DALI_RX_HB_MIN, hb), .rx_hb_min = scale_time_by_hb(DALI_RX_HB_MIN, hb),
.rx_hb_max = scale_time_by_hb(DALI_RX_HB_MAX, hb), .rx_hb_max = scale_time_by_hb(DALI_RX_HB_MAX, hb),
.rx_2hb_min = scale_time_by_hb(DALI_RX_2HB_MIN, hb), .rx_2hb_min = scale_time_by_hb(DALI_RX_2HB_MIN, hb),
.rx_2hb_max = scale_time_by_hb(DALI_RX_2HB_MAX, hb), .rx_2hb_max = scale_time_by_hb(DALI_RX_2HB_MAX, hb),
.rx_stop_cond = scale_time_by_hb(DALI_RX_STOP_COND, hb), .rx_stop_cond = configured_or_scaled_time(CONFIG_DALI_RX_STOP_CONDITION_US,
DALI_RX_STOP_COND, hb),
.time_bus_down = scale_time_by_hb(DALI_TIME_BUS_DOWN, hb), .time_bus_down = scale_time_by_hb(DALI_TIME_BUS_DOWN, hb),
.time_break_min = scale_time_by_hb(DALI_TIME_BREAK_MIN, hb), .time_break_min = scale_time_by_hb(DALI_TIME_BREAK_MIN, hb),
.time_recovery_min = scale_time_by_hb(DALI_TIME_RECOVERY_MIN, hb), .time_recovery_min = scale_time_by_hb(DALI_TIME_RECOVERY_MIN, hb),
.tx_stop_cond = scale_time_by_hb(DALI_TX_STOP_COND, hb), .tx_stop_cond = configured_or_scaled_time(CONFIG_DALI_TX_STOP_CONDITION_US,
DALI_TX_STOP_COND, hb),
.collision_txrx_delta = scale_time_by_hb(DALI_COLLISION_TXRX_DELTA, hb), .collision_txrx_delta = scale_time_by_hb(DALI_COLLISION_TXRX_DELTA, hb),
}; };
@@ -199,7 +273,7 @@ static esp_err_t apply_timer_alarm_locked(void)
return ESP_OK; return ESP_OK;
} }
gptimer_alarm_config_t timer_alarm_config = { gptimer_alarm_config_t timer_alarm_config = {
.alarm_count = s_timing.hb, .alarm_count = s_timing.timer_alarm_ticks,
.reload_count = 0, .reload_count = 0,
.flags = { .flags = {
.auto_reload_on_alarm = true, .auto_reload_on_alarm = true,
@@ -235,22 +309,221 @@ static bool s_debug_task_created = false;
#endif #endif
static bool s_dali_task_created = false; static bool s_dali_task_created = false;
#define DALI_SET_BUS_HIGH(bus) gpio_set_level((bus)->tx_pin, DALI_TX_HIGH) // set bus level #define DALI_SET_BUS_HIGH(bus) do { gpio_set_level((bus)->tx_pin, DALI_TX_HIGH); (bus)->tx_level = 1; } while (0)
#define DALI_SET_BUS_LOW(bus) gpio_set_level((bus)->tx_pin, DALI_TX_LOW) // set bus level #define DALI_SET_BUS_LOW(bus) do { gpio_set_level((bus)->tx_pin, DALI_TX_LOW); (bus)->tx_level = 0; } while (0)
#define DALI_SET_BUS_LEVEL(bus, x) gpio_set_level((bus)->tx_pin, ((x)==DALI_TX_HIGH)) // set bus level #define DALI_SET_BUS_LEVEL(bus, x) do { \
uint8_t level = (x) ? 1 : 0; \
gpio_set_level((bus)->tx_pin, level ? DALI_TX_HIGH : DALI_TX_LOW); \
(bus)->tx_level = level; \
} while (0)
// !!! read from RX pin, we need real bus level, not logic level of TX pin // !!! read from RX pin, we need real bus level, not logic level of TX pin
// return: 0 - bus level low, active state // return: 0 - bus level low, active state
// 1 - bus level high, idle state // 1 - bus level high, idle state
#define DALI_GET_BUS_LEVEL(bus) (gpio_get_level((bus)->rx_pin) == (DALI_RX_HIGH)) // get bus level #define DALI_GET_BUS_LEVEL(bus) (gpio_get_level((bus)->rx_pin) == (DALI_RX_HIGH)) // get bus level
// return: 0 - tx pin drive bus low, active state // return: 0 - TX drives bus low, active state
// 1 - tx pin drive bus high, idle state // 1 - TX releases/drives bus high, idle state
#define DALI_GET_TX_LEVEL(bus) (gpio_get_level((bus)->tx_pin) == (DALI_TX_HIGH)) // get TX pin level #define DALI_GET_TX_LEVEL(bus) ((bus)->tx_level)
static inline bool bus_valid(uint8_t bus_id) { static inline bool bus_valid(uint8_t bus_id) {
return bus_id < DALI_PHY_COUNT && s_bus[bus_id].inited; return bus_id < DALI_PHY_COUNT && s_bus[bus_id].inited;
} }
static const char *bus_state_name(dali_bus_state_t state)
{
switch (state) {
case DALI_BUS_UNKNOWN: return "unknown";
case DALI_BUS_POWER_DOWN: return "power_down";
case DALI_BUS_ERROR: return "error";
case DALI_BUS_READY: return "ready";
case DALI_BUS_TRANSMITTING: return "transmitting";
case DALI_BUS_RECEIVING: return "receiving";
case DALI_BUS_TIME_BREAK: return "time_break";
case DALI_BUS_RECOVERY: return "recovery";
default: return "invalid";
}
}
static const char *tx_state_name(dali_tx_state_t state)
{
switch (state) {
case TX_STATE_ERROR: return "error";
case TX_STATE_COLLISION: return "collision";
case TX_STATE_IDLE: return "idle";
case TX_STATE_START: return "start";
case TX_STATE_DATA: return "data";
case TX_STATE_STOP: return "stop";
default: return "invalid";
}
}
static const char *rx_state_name(dali_rx_state_t state)
{
switch (state) {
case RX_STATE_ERROR: return "error";
case RX_STATE_IDLE: return "idle";
case RX_STATE_START: return "start";
case RX_STATE_DATA: return "data";
case RX_STATE_STOP: return "stop";
case RX_STATE_END: return "end";
default: return "invalid";
}
}
static uint32_t tx_completion_timeout_ms(const Dali_msg_t *msg)
{
uint32_t hb = s_timing_ready ? s_timing.hb : DALI_TIME_HB;
uint32_t stop_us = s_timing_ready ? s_timing.tx_stop_cond : DALI_TX_STOP_COND;
uint32_t bits = msg ? msg->length : DALI_MAX_BITS;
if (bits == 0 || bits > DALI_MAX_BITS) {
bits = DALI_MAX_BITS;
}
uint64_t frame_us = ((uint64_t)(2U + bits * 2U) * hb) + stop_us;
uint32_t frame_ms = (uint32_t)((frame_us + 999U) / 1000U);
uint32_t timeout_ms = frame_ms + 30U;
if (timeout_ms < 30U) {
timeout_ms = 30U;
}
if (timeout_ms > 500U) {
timeout_ms = 500U;
}
return timeout_ms;
}
static UBaseType_t queue_waiting(QueueHandle_t queue)
{
return queue ? uxQueueMessagesWaiting(queue) : 0;
}
static void log_tx_message(const char *prefix, const dali_bus_ctx_t *bus,
const Dali_msg_t *msg, uint32_t timeout_ms)
{
if (bus == NULL || msg == NULL) {
return;
}
ESP_LOGW(TAG,
"%s bus=%u timeoutMs=%lu busState=%s txState=%s rxState=%s "
"txQ=%u replyQ=%u status=%u len=%u data=%02x %02x %02x %02x",
prefix, bus->bus_id, (unsigned long)timeout_ms,
bus_state_name(bus->bus_state), tx_state_name(bus->tx_state),
rx_state_name(bus->rx_state), (unsigned)queue_waiting(bus->tx_queue),
(unsigned)queue_waiting(bus->tx_reply_queue), msg->status, msg->length,
msg->data[0], msg->data[1], msg->data[2], msg->data[3]);
}
static void drain_tx_reply_queue(dali_bus_ctx_t *bus)
{
if (bus == NULL || bus->tx_reply_queue == NULL) {
return;
}
Dali_msg_t stale = {0};
UBaseType_t drained = 0;
while (xQueueReceive(bus->tx_reply_queue, &stale, 0) == pdTRUE) {
drained++;
}
if (drained > 0) {
ESP_LOGW(TAG,
"bus=%u dropped %u stale TX completion(s) status=%u len=%u data=%02x %02x %02x %02x",
bus->bus_id, (unsigned)drained, stale.status, stale.length, stale.data[0],
stale.data[1], stale.data[2], stale.data[3]);
}
}
static void recover_tx_timeout(dali_bus_ctx_t *bus)
{
if (bus == NULL) {
return;
}
if (bus->tx_queue) {
xQueueReset(bus->tx_queue);
}
if (bus->tx_reply_queue) {
xQueueReset(bus->tx_reply_queue);
}
bus->tx_data.status = DALI_FRAME_ERROR;
bus->tx_state = TX_STATE_IDLE;
bus->rx_state = RX_STATE_IDLE;
bus->tx_half_bit_counter = 0;
bus->tx_data_bit_counter = 0;
bus->rx_half_bit_counter = 0;
bus->rx_data_bit_counter = 0;
if (bus->bus_state == DALI_BUS_TRANSMITTING || bus->bus_state == DALI_BUS_TIME_BREAK ||
bus->bus_state == DALI_BUS_RECOVERY) {
bus->tx_last_edge_time = esp_timer_get_time();
DALI_SET_BUS_HIGH(bus);
bus->bus_state = DALI_BUS_READY;
}
ESP_LOGW(TAG, "bus=%u native TX queue recovered busState=%s txState=%s rxState=%s",
bus->bus_id, bus_state_name(bus->bus_state), tx_state_name(bus->tx_state),
rx_state_name(bus->rx_state));
}
static inline bool IRAM_ATTR interval_elapsed_us(uint64_t time_now, uint64_t last_time,
uint64_t interval_us)
{
return interval_us > 0 && (time_now - last_time) >= interval_us;
}
static void IRAM_ATTR publish_bus_abnormal_from_isr(dali_bus_ctx_t *bus, BaseType_t *yield)
{
if (bus == NULL || dali_raw_receive_queue == NULL || DALI_BUS_ABNORMAL_REPORT_INTERVAL_US == 0) {
return;
}
Dali_msg_t abnormal = {0};
abnormal.id = bus->bus_id;
abnormal.type = DALI_MSG_FORWARD;
abnormal.status = DALI_FRAME_OK;
abnormal.length = 16;
abnormal.data[0] = 0xFF;
abnormal.data[1] = 0xFD;
if (xQueueSendToBackFromISR(dali_raw_receive_queue, &abnormal, yield) != pdTRUE) {
Dali_msg_t dropped = {0};
xQueueReceiveFromISR(dali_raw_receive_queue, &dropped, yield);
xQueueSendToBackFromISR(dali_raw_receive_queue, &abnormal, yield);
}
}
static void IRAM_ATTR maybe_report_bus_abnormal_from_isr(dali_bus_ctx_t *bus, uint64_t time_now,
BaseType_t *yield)
{
if (bus == NULL || DALI_BUS_ABNORMAL_REPORT_INTERVAL_US == 0) {
return;
}
if (!interval_elapsed_us(time_now, bus->bus_abnormal_report_time,
DALI_BUS_ABNORMAL_REPORT_INTERVAL_US)) {
return;
}
publish_bus_abnormal_from_isr(bus, yield);
bus->bus_abnormal_report_time = time_now;
}
static void IRAM_ATTR poll_power_down_bus_from_isr(dali_bus_ctx_t *bus, uint64_t time_now,
BaseType_t *yield)
{
if (bus == NULL || bus->bus_state != DALI_BUS_POWER_DOWN) {
return;
}
if (interval_elapsed_us(time_now, bus->bus_level_check_time,
DALI_BUS_POWER_CHECK_INTERVAL_US)) {
const uint8_t current_level = DALI_GET_BUS_LEVEL(bus);
bus->bus_level_check_time = time_now;
if (current_level != bus->rx_level) {
bus->rx_level = current_level;
bus->rx_last_edge_time = time_now;
}
}
maybe_report_bus_abnormal_from_isr(bus, time_now, yield);
}
static inline void publish_rx_frame_from_isr(Dali_msg_t *msg, QueueHandle_t queue, BaseType_t *yield) static inline void publish_rx_frame_from_isr(Dali_msg_t *msg, QueueHandle_t queue, BaseType_t *yield)
{ {
if (msg == NULL) { if (msg == NULL) {
@@ -264,6 +537,38 @@ static inline void publish_rx_frame_from_isr(Dali_msg_t *msg, QueueHandle_t queu
} }
} }
static void IRAM_ATTR complete_tx_from_isr(dali_bus_ctx_t *bus, BaseType_t *yield)
{
if (bus == NULL) {
return;
}
bus->tx_data.status = DALI_FRAME_OK;
if (bus->tx_reply_queue) {
if (xQueueSendToBackFromISR(bus->tx_reply_queue, &bus->tx_data, yield) != pdTRUE) {
Dali_msg_t dropped = {0};
xQueueReceiveFromISR(bus->tx_reply_queue, &dropped, yield);
xQueueSendToBackFromISR(bus->tx_reply_queue, &bus->tx_data, yield);
}
}
bus->tx_state = TX_STATE_IDLE;
}
static void IRAM_ATTR start_tx_collision_recovery_from_isr(dali_bus_ctx_t *bus,
uint64_t time_now)
{
if (bus == NULL) {
return;
}
bus->rx_last_edge_time = time_now;
bus->tx_last_edge_time = time_now;
DALI_SET_BUS_LOW(bus);
bus->bus_state = DALI_BUS_TIME_BREAK;
bus->tx_data.status = DALI_FRAME_COLLISION;
}
// GPIO ISR handler // GPIO ISR handler
// define rx_gpio_isr_handler on any edge // define rx_gpio_isr_handler on any edge
static void IRAM_ATTR rx_gpio_isr_handler(void* arg) static void IRAM_ATTR rx_gpio_isr_handler(void* arg)
@@ -273,6 +578,7 @@ static void IRAM_ATTR rx_gpio_isr_handler(void* arg)
return; return;
} }
BaseType_t yield = false;
uint64_t rx_current_edge_time = esp_timer_get_time(); // get time in us uint64_t rx_current_edge_time = esp_timer_get_time(); // get time in us
uint8_t rx_previous_level = bus->rx_level; uint8_t rx_previous_level = bus->rx_level;
@@ -287,8 +593,16 @@ static void IRAM_ATTR rx_gpio_isr_handler(void* arg)
// always save time of last edge // always save time of last edge
bus->rx_last_edge_time = rx_current_edge_time; // get time in us bus->rx_last_edge_time = rx_current_edge_time; // get time in us
if(bus->bus_state == DALI_BUS_READY && bus->rx_level == 0) // found start bit bool tx_stop_released = bus->bus_state == DALI_BUS_TRANSMITTING &&
bus->tx_state == TX_STATE_STOP &&
DALI_GET_TX_LEVEL(bus) == 1;
if((bus->bus_state == DALI_BUS_READY || tx_stop_released) && bus->rx_level == 0) // found start bit
{ {
if (tx_stop_released) {
complete_tx_from_isr(bus, &yield);
}
// within range for backward frame // within range for backward frame
uint32_t time_ms = bus->rx_pulse_width / 1000; // 1ms = 1000us uint32_t time_ms = bus->rx_pulse_width / 1000; // 1ms = 1000us
if(time_ms>255) bus->rx_data.type = 255; if(time_ms>255) bus->rx_data.type = 255;
@@ -378,12 +692,13 @@ static void IRAM_ATTR rx_gpio_isr_handler(void* arg)
// if collision detected: we are too late after bit was transmitted // if collision detected: we are too late after bit was transmitted
else if (bus->bus_state == DALI_BUS_TRANSMITTING && bus->rx_tx_delta > s_timing.collision_txrx_delta) else if (bus->bus_state == DALI_BUS_TRANSMITTING && bus->tx_state != TX_STATE_STOP &&
bus->rx_tx_delta > s_timing.collision_txrx_delta)
{ {
// we need now to start collision recovery with time break: 101.9.2.4 // we need now to start collision recovery with time break: 101.9.2.4
bus->tx_last_edge_time = esp_timer_get_time(); // get time in us
DALI_SET_BUS_LOW(bus); // force TX low - active state, inform about collision, this also generate new GPIO ISR DALI_SET_BUS_LOW(bus); // force TX low - active state, inform about collision, this also generate new GPIO ISR
bus->tx_last_edge_time = esp_timer_get_time(); // get time in us
bus->bus_state = DALI_BUS_TIME_BREAK; // we are in time break state bus->bus_state = DALI_BUS_TIME_BREAK; // we are in time break state
bus->tx_data.status = DALI_FRAME_COLLISION; // collision detected bus->tx_data.status = DALI_FRAME_COLLISION; // collision detected
} }
@@ -399,7 +714,11 @@ static void IRAM_ATTR rx_gpio_isr_handler(void* arg)
dbg.rx_pulse_width = bus->rx_pulse_width; dbg.rx_pulse_width = bus->rx_pulse_width;
dbg.rx_tx_delta = bus->rx_tx_delta; dbg.rx_tx_delta = bus->rx_tx_delta;
dbg.bus_id = bus->bus_id; dbg.bus_id = bus->bus_id;
xQueueSendToBackFromISR(rx_dbg_queue, &dbg, NULL); // send data to queue xQueueSendToBackFromISR(rx_dbg_queue, &dbg, &yield); // send data to queue
}
if (yield) {
portYIELD_FROM_ISR();
} }
} }
@@ -423,6 +742,18 @@ static bool IRAM_ATTR handle_bus_timer(dali_bus_ctx_t *bus, uint64_t time_now)
bus->tx_last_edge_time = time_now - MAX_DELTA_RELOAD_TIME/2; // half of max time bus->tx_last_edge_time = time_now - MAX_DELTA_RELOAD_TIME/2; // half of max time
} }
poll_power_down_bus_from_isr(bus, time_now, &yield);
rx_delta = time_now - bus->rx_last_edge_time;
tx_delta = time_now - bus->tx_last_edge_time;
if (bus->bus_state == DALI_BUS_TRANSMITTING && bus->tx_state == TX_STATE_STOP &&
DALI_GET_TX_LEVEL(bus) == 1 &&
(bus->rx_state == RX_STATE_START || bus->rx_state == RX_STATE_DATA ||
bus->rx_state == RX_STATE_STOP)) {
complete_tx_from_isr(bus, &yield);
bus->bus_state = DALI_BUS_RECEIVING;
}
// recovery from different error states: UNKNOWN, ERROR, POWER_DOWN // recovery from different error states: UNKNOWN, ERROR, POWER_DOWN
if(bus->bus_state <= DALI_BUS_ERROR) if(bus->bus_state <= DALI_BUS_ERROR)
{ // 101.8.2.4 - startup BUS after 2.4ms { // 101.8.2.4 - startup BUS after 2.4ms
@@ -434,8 +765,13 @@ static bool IRAM_ATTR handle_bus_timer(dali_bus_ctx_t *bus, uint64_t time_now)
// if bus power down - if bus is low for more then 45ms // if bus power down - if bus is low for more then 45ms
if(bus->rx_level==0 && rx_delta > s_timing.time_bus_down) if(bus->rx_level==0 && rx_delta > s_timing.time_bus_down)
{ // power lost { // power lost
bool entered_power_down = bus->bus_state != DALI_BUS_POWER_DOWN;
bus->bus_state = DALI_BUS_POWER_DOWN; // bus is power down - recovery see previous if bus->bus_state = DALI_BUS_POWER_DOWN; // bus is power down - recovery see previous if
DALI_SET_BUS_HIGH(bus); // make sure TX is high DALI_SET_BUS_HIGH(bus); // make sure TX is high
if (entered_power_down) {
bus->bus_level_check_time = time_now;
bus->bus_abnormal_report_time = time_now;
}
} }
// recovery from collision detection // recovery from collision detection
@@ -444,9 +780,9 @@ static bool IRAM_ATTR handle_bus_timer(dali_bus_ctx_t *bus, uint64_t time_now)
// BUS: ACTIVE, LOW - BUS is busy, let caller to restart transmission // BUS: ACTIVE, LOW - BUS is busy, let caller to restart transmission
if(bus->bus_state == DALI_BUS_TIME_BREAK && rx_delta > s_timing.time_break_min) if(bus->bus_state == DALI_BUS_TIME_BREAK && rx_delta > s_timing.time_break_min)
{ {
bus->tx_last_edge_time = esp_timer_get_time(); // get time in us
DALI_SET_BUS_HIGH(bus); // TX high - idle state - generate ISR on RX pin DALI_SET_BUS_HIGH(bus); // TX high - idle state - generate ISR on RX pin
bus->tx_last_edge_time = esp_timer_get_time(); // get time in us
// read bus state // read bus state
if(DALI_GET_BUS_LEVEL(bus) == 0) // other device is keeping bus low if(DALI_GET_BUS_LEVEL(bus) == 0) // other device is keeping bus low
{ {
@@ -474,26 +810,31 @@ static bool IRAM_ATTR handle_bus_timer(dali_bus_ctx_t *bus, uint64_t time_now)
bus->tx_state = TX_STATE_START; // start transmitting bus->tx_state = TX_STATE_START; // start transmitting
bus->tx_half_bit_counter = 0; bus->tx_half_bit_counter = 0;
bus->tx_data_bit_counter = 0; // actually sent bits count bus->tx_data_bit_counter = 0; // actually sent bits count
DALI_SET_BUS_LOW(bus); // start bit first half
bus->tx_last_edge_time = esp_timer_get_time(); // get time in us bus->tx_last_edge_time = esp_timer_get_time(); // get time in us
DALI_SET_BUS_LOW(bus); // start bit first half
} }
else if(bus->bus_state == DALI_BUS_TRANSMITTING) else if(bus->bus_state == DALI_BUS_TRANSMITTING)
{ {
uint8_t bus_level = DALI_GET_BUS_LEVEL(bus);
if(bus->tx_state != TX_STATE_STOP && tx_delta > s_timing.collision_txrx_delta &&
bus_level != DALI_GET_TX_LEVEL(bus)) {
bus->rx_level = bus_level;
bus->rx_tx_delta = tx_delta;
start_tx_collision_recovery_from_isr(bus, time_now);
}
// transmit data // transmit data
if(bus->tx_state == TX_STATE_START) { else if(bus->tx_state == TX_STATE_START) {
bus->tx_state = TX_STATE_DATA; // start transmitting data bus->tx_state = TX_STATE_DATA; // start transmitting data
bus->tx_half_bit_counter++; bus->tx_half_bit_counter++;
DALI_SET_BUS_HIGH(bus); // start bit second half
bus->tx_last_edge_time = esp_timer_get_time(); // get time in us bus->tx_last_edge_time = esp_timer_get_time(); // get time in us
DALI_SET_BUS_HIGH(bus); // start bit second half
} }
else if(bus->tx_state == TX_STATE_DATA) { else if(bus->tx_state == TX_STATE_DATA) {
bool value = (bus->tx_data.data[bus->tx_data_bit_counter/8] >> ( 7 - (bus->tx_data_bit_counter % 8) )) & 0x01; bool value = (bus->tx_data.data[bus->tx_data_bit_counter/8] >> ( 7 - (bus->tx_data_bit_counter % 8) )) & 0x01;
value ^= bus->tx_half_bit_counter & 0x01; // xor=invert value for odd half bit 1:0->1 and 0:1->0 value ^= bus->tx_half_bit_counter & 0x01; // xor=invert value for odd half bit 1:0->1 and 0:1->0
bus->tx_last_edge_time = esp_timer_get_time(); // get time in us
DALI_SET_BUS_LEVEL(bus, value); DALI_SET_BUS_LEVEL(bus, value);
bus->tx_last_edge_time = esp_timer_get_time(); // get time in us
bus->tx_half_bit_counter++; // increment half bit counter before next test bus->tx_half_bit_counter++; // increment half bit counter before next test
if(bus->tx_half_bit_counter & 0x01) { // next bit if(bus->tx_half_bit_counter & 0x01) { // next bit
bus->tx_data_bit_counter++; bus->tx_data_bit_counter++;
@@ -506,15 +847,11 @@ static bool IRAM_ATTR handle_bus_timer(dali_bus_ctx_t *bus, uint64_t time_now)
// here we check TX (NOT RX) bit state // here we check TX (NOT RX) bit state
if(DALI_GET_TX_LEVEL(bus) == 0) // really ok - otherwise we will keep bus low forever if(DALI_GET_TX_LEVEL(bus) == 0) // really ok - otherwise we will keep bus low forever
{ {
DALI_SET_BUS_HIGH(bus);
bus->tx_last_edge_time = esp_timer_get_time(); // get time in us bus->tx_last_edge_time = esp_timer_get_time(); // get time in us
DALI_SET_BUS_HIGH(bus);
} }
else if(tx_delta > s_timing.tx_stop_cond) { else if(tx_delta > s_timing.tx_stop_cond) {
bus->tx_data.status = DALI_FRAME_OK; // frame is OK complete_tx_from_isr(bus, &yield);
if (bus->tx_reply_queue) {
xQueueSendToBackFromISR(bus->tx_reply_queue, &bus->tx_data, &yield); // send data to queue
}
bus->tx_state = TX_STATE_IDLE; // final state with transmitted data
bus->bus_state = DALI_BUS_READY; // bus is ready bus->bus_state = DALI_BUS_READY; // bus is ready
} }
} }
@@ -552,6 +889,10 @@ static bool IRAM_ATTR handle_bus_timer(dali_bus_ctx_t *bus, uint64_t time_now)
publish_rx_frame_from_isr(&bus->rx_data, bus->rx_queue, &yield); // send data to queue publish_rx_frame_from_isr(&bus->rx_data, bus->rx_queue, &yield); // send data to queue
} }
} }
else if(bus->rx_state == RX_STATE_START && rx_delta > s_timing.rx_hb_max) {
bus->rx_state = RX_STATE_ERROR;
bus->rx_data.status = DALI_FRAME_TIME_VIOLATION;
}
} }
return yield; return yield;
} }
@@ -588,7 +929,7 @@ static void debug_task(void *pvParameters)
else v = '0' + dbg.level; else v = '0' + dbg.level;
} }
else v=' '; else v=' ';
printf("bus[%u] rx: [%2d] pw=%lu v=%u rtd=%lu [%c]", ESP_LOGD(TAG, "bus[%u] rx: [%2d] pw=%lu v=%u rtd=%lu [%c]",
dbg.bus_id, i++, dbg.rx_pulse_width, dbg.level, dbg.rx_tx_delta, v); dbg.bus_id, i++, dbg.rx_pulse_width, dbg.level, dbg.rx_tx_delta, v);
if(dbg.rx_pulse_width < 1000) { if(dbg.rx_pulse_width < 1000) {
if(dbg.rx_pulse_width > 550) HB+=2; if(dbg.rx_pulse_width > 550) HB+=2;
@@ -659,7 +1000,7 @@ static esp_err_t ensure_timer_started(void)
.flags = { .flags = {
.intr_shared = true, .intr_shared = true,
}, },
.resolution_hz = 1 * 1000 * 1000, // 1MHz, 1 tick = 1us .resolution_hz = CONFIG_DALI_TIMER_RESOLUTION_HZ,
}; };
err = gptimer_new_timer(&timer_config, &gptimer); err = gptimer_new_timer(&timer_config, &gptimer);
if (err != ESP_OK) { if (err != ESP_OK) {
@@ -726,6 +1067,9 @@ static esp_err_t init_bus(uint8_t bus_id, uint8_t tx_pin, uint8_t rx_pin)
bus->bus_id = bus_id; bus->bus_id = bus_id;
bus->tx_pin = tx_pin; bus->tx_pin = tx_pin;
bus->rx_pin = rx_pin; bus->rx_pin = rx_pin;
bus->tx_level = 1;
gpio_set_level(bus->tx_pin, DALI_TX_HIGH);
gpio_config_t io_conf; gpio_config_t io_conf;
@@ -771,6 +1115,8 @@ static esp_err_t init_bus(uint8_t bus_id, uint8_t tx_pin, uint8_t rx_pin)
bus->rx_last_edge_time = esp_timer_get_time(); // get time in us - startup time bus->rx_last_edge_time = esp_timer_get_time(); // get time in us - startup time
bus->rx_level = DALI_GET_BUS_LEVEL(bus); // get level of RX pin bus->rx_level = DALI_GET_BUS_LEVEL(bus); // get level of RX pin
bus->tx_last_edge_time = bus->rx_last_edge_time; bus->tx_last_edge_time = bus->rx_last_edge_time;
bus->bus_level_check_time = bus->rx_last_edge_time;
bus->bus_abnormal_report_time = 0;
err = ensure_isr_service(); err = ensure_isr_service();
if (err != ESP_OK) { if (err != ESP_OK) {
@@ -805,17 +1151,45 @@ static int dali_tx_bus(dali_bus_ctx_t *bus, Dali_msg_t *dali_msg)
if (bus == NULL || !bus->inited) { if (bus == NULL || !bus->inited) {
return ESP_FAIL; return ESP_FAIL;
} }
if(xQueueSendToBack(bus->tx_queue, dali_msg, pdMS_TO_TICKS(50)) == pdFALSE) { if (bus->tx_queue == NULL || bus->tx_reply_queue == NULL || dali_msg == NULL) {
xQueueReset(bus->tx_queue); // clear queue
printf("dali_tx: Queue full\n");
return ESP_FAIL; return ESP_FAIL;
} }
if(xQueueReceive(bus->tx_reply_queue, dali_msg, pdMS_TO_TICKS(50)) == pdFALSE) {
xQueueReset(bus->tx_reply_queue); // clear queue const uint32_t timeout_ms = tx_completion_timeout_ms(dali_msg);
printf("dali_tx: No reply\n"); const TickType_t timeout_ticks = pdMS_TO_TICKS(timeout_ms);
drain_tx_reply_queue(bus);
if (bus->bus_state == DALI_BUS_POWER_DOWN) {
dali_msg->status = DALI_FRAME_ERROR;
log_tx_message("native TX skipped, bus power down", bus, dali_msg, timeout_ms);
return ESP_FAIL; return ESP_FAIL;
} }
return ESP_OK;
ESP_LOGD(TAG, "bus=%u queue TX len=%u data=%02x %02x %02x %02x timeoutMs=%lu",
bus->bus_id, dali_msg->length, dali_msg->data[0], dali_msg->data[1],
dali_msg->data[2], dali_msg->data[3], (unsigned long)timeout_ms);
if(xQueueSendToBack(bus->tx_queue, dali_msg, timeout_ticks) == pdFALSE) {
log_tx_message("native TX queue full", bus, dali_msg, timeout_ms);
if (bus->tx_state == TX_STATE_IDLE) {
xQueueReset(bus->tx_queue);
}
return ESP_FAIL;
}
if(xQueueReceive(bus->tx_reply_queue, dali_msg, timeout_ticks) == pdFALSE) {
if (bus->tx_state == TX_STATE_IDLE && queue_waiting(bus->tx_queue) == 0) {
*dali_msg = bus->tx_data;
log_tx_message("native TX completion queue missed", bus, dali_msg, timeout_ms);
return dali_msg->status == DALI_FRAME_OK ? ESP_OK : ESP_FAIL;
}
log_tx_message("native TX completion timeout", bus, dali_msg, timeout_ms);
recover_tx_timeout(bus);
return ESP_FAIL;
}
ESP_LOGD(TAG, "bus=%u TX complete status=%u len=%u data=%02x %02x %02x %02x",
bus->bus_id, dali_msg->status, dali_msg->length, dali_msg->data[0],
dali_msg->data[1], dali_msg->data[2], dali_msg->data[3]);
return dali_msg->status == DALI_FRAME_OK ? ESP_OK : ESP_FAIL;
} }
// dali_task - should run at highest priority // dali_task - should run at highest priority
@@ -843,6 +1217,7 @@ void dali_task(void *pvParameters)
esp_err_t dali_hal_init(uint8_t dali_id, uint8_t tx_pin, uint8_t rx_pin) esp_err_t dali_hal_init(uint8_t dali_id, uint8_t tx_pin, uint8_t rx_pin)
{ {
dali_hal_lock(); dali_hal_lock();
apply_dali_log_level();
esp_err_t err = ensure_timing_ready_locked(); esp_err_t err = ensure_timing_ready_locked();
if (err == ESP_OK) { if (err == ESP_OK) {
@@ -873,6 +1248,7 @@ esp_err_t dali_hal_init(uint8_t dali_id, uint8_t tx_pin, uint8_t rx_pin)
esp_err_t dali_hal_set_baudrate(uint32_t baudrate) esp_err_t dali_hal_set_baudrate(uint32_t baudrate)
{ {
dali_hal_lock(); dali_hal_lock();
apply_dali_log_level();
bool resume_timer = s_timer_started && gptimer; bool resume_timer = s_timer_started && gptimer;
if (resume_timer) { if (resume_timer) {
+8
View File
@@ -3,6 +3,10 @@
#include <stdint.h> #include <stdint.h>
#include "dali_hal.h" #include "dali_hal.h"
#ifdef __cplusplus
extern "C" {
#endif
/* /*
Addressing: 102.7.2.1 Addressing: 102.7.2.1
0AAA AAAx - short address AAAAAA 0-63 0AAA AAAx - short address AAAAAA 0-63
@@ -77,5 +81,9 @@ void dali_set_search_addr24(uint32_t addr24);
uint32_t dali_binary_search(); uint32_t dali_binary_search();
void dali_change_short_address(int addr1, int addr2); void dali_change_short_address(int addr1, int addr2);
#ifdef __cplusplus
}
#endif
+20 -3
View File
@@ -8,6 +8,10 @@
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/queue.h" #include "freertos/queue.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef CONFIG_DALI_PHY_COUNT #ifdef CONFIG_DALI_PHY_COUNT
#define DALI_PHY_COUNT CONFIG_DALI_PHY_COUNT #define DALI_PHY_COUNT CONFIG_DALI_PHY_COUNT
#else #else
@@ -182,13 +186,22 @@ typedef struct Dali_msg Dali_msg_t;
// define HW DALI for gpio functions // define HW DALI for gpio functions
#ifndef DALI_HW_PINS #ifndef DALI_HW_PINS
// define HW DALI for gpio functions // Physical GPIO levels for logical DALI idle/high and active/low bus states.
// - what we should write to pin to get HIGH/LOW #ifdef CONFIG_DALI_TX_ACTIVE_HIGH
#define DALI_TX_HIGH 0 // idle state
#define DALI_TX_LOW 1 // active state
#else
#define DALI_TX_HIGH 1 // idle state #define DALI_TX_HIGH 1 // idle state
#define DALI_TX_LOW 0 // active state #define DALI_TX_LOW 0 // active state
// - what we should read from pin to get HIGH/LOW #endif
#ifdef CONFIG_DALI_RX_ACTIVE_LOW
#define DALI_RX_HIGH 1 // idle state #define DALI_RX_HIGH 1 // idle state
#define DALI_RX_LOW 0 // active state #define DALI_RX_LOW 0 // active state
#else
#define DALI_RX_HIGH 0 // idle state
#define DALI_RX_LOW 1 // active state
#endif
#endif #endif
// LED onboard - debug // LED onboard - debug
@@ -228,3 +241,7 @@ esp_err_t dali_hal_get_bus_info(uint8_t bus_id, dali_hal_bus_info_t *info);
QueueHandle_t dali_hal_raw_receive_queue(void); QueueHandle_t dali_hal_raw_receive_queue(void);
void dali_task(void *pvParameters); void dali_task(void *pvParameters);
#ifdef __cplusplus
}
#endif
+22 -6
View File
@@ -64,6 +64,10 @@ struct SerialRxPacket {
uint8_t data[kSerialRxPacketMaxBytes]{}; uint8_t data[kSerialRxPacketMaxBytes]{};
}; };
std::vector<uint8_t> LegacyQueryResponse(uint8_t status, uint8_t value = 0x00) {
return {status, value};
}
bool SendHardwareFrame(uint8_t bus_id, const uint8_t* data, size_t len) { bool SendHardwareFrame(uint8_t bus_id, const uint8_t* data, size_t len) {
if (data == nullptr || len != 3) { if (data == nullptr || len != 3) {
return false; return false;
@@ -89,9 +93,12 @@ bool SendHardwareFrame(uint8_t bus_id, const uint8_t* data, size_t len) {
} }
std::vector<uint8_t> TransactHardwareFrame(uint8_t bus_id, const uint8_t* data, size_t len) { std::vector<uint8_t> TransactHardwareFrame(uint8_t bus_id, const uint8_t* data, size_t len) {
if (data == nullptr || len != 3) { if (data == nullptr) {
return {}; return {};
} }
if (len != 3) {
return len > 0 && data[0] == 0x12 ? LegacyQueryResponse(0xFD) : std::vector<uint8_t>{};
}
switch (data[0]) { switch (data[0]) {
case 0x00: case 0x00:
@@ -107,9 +114,12 @@ std::vector<uint8_t> TransactHardwareFrame(uint8_t bus_id, const uint8_t* data,
tx.id = bus_id; tx.id = bus_id;
Dali_msg_t rx = {}; Dali_msg_t rx = {};
if (dali_query(&tx, &rx) == pdTRUE) { if (dali_query(&tx, &rx) == pdTRUE) {
if (rx.status != DALI_FRAME_OK || rx.length != 8) {
return LegacyQueryResponse(0xFD);
}
return {0xFF, rx.data[0]}; return {0xFF, rx.data[0]};
} }
return {0xFE}; return LegacyQueryResponse(0xFE);
} }
default: default:
return {}; return {};
@@ -151,13 +161,19 @@ std::vector<uint8_t> ReadSerialFrame(QueueHandle_t queue, size_t len, uint32_t t
std::vector<uint8_t> TransactSerialFrame(int uart_port, QueueHandle_t queue, std::vector<uint8_t> TransactSerialFrame(int uart_port, QueueHandle_t queue,
uint32_t query_timeout_ms, const uint8_t* data, uint32_t query_timeout_ms, const uint8_t* data,
size_t len) { size_t len) {
if (data == nullptr || len == 0) {
return LegacyQueryResponse(0xFD);
}
if (data[0] == 0x12 && len != 3) {
return LegacyQueryResponse(0xFD);
}
if (data != nullptr && len > 0 && data[0] == 0x12) { if (data != nullptr && len > 0 && data[0] == 0x12) {
DrainSerialQueue(queue); DrainSerialQueue(queue);
} }
if (!WriteSerialFrame(uart_port, data, len)) { if (!WriteSerialFrame(uart_port, data, len)) {
return {0xFD}; return LegacyQueryResponse(0xFD);
} }
if (data == nullptr || len == 0 || data[0] != 0x12) { if (data[0] != 0x12) {
return {0xFF}; return {0xFF};
} }
@@ -173,10 +189,10 @@ std::vector<uint8_t> TransactSerialFrame(int uart_port, QueueHandle_t queue,
auto response = PacketToVector(packet, 2); auto response = PacketToVector(packet, 2);
if (!response.empty() && if (!response.empty() &&
(response[0] == 0xFF || response[0] == 0xFE || response[0] == 0xFD)) { (response[0] == 0xFF || response[0] == 0xFE || response[0] == 0xFD)) {
return response; return LegacyQueryResponse(response[0], response.size() > 1 ? response[1] : 0x00);
} }
} }
return {0xFE}; return LegacyQueryResponse(0xFE);
} }
} // namespace } // namespace
@@ -82,6 +82,19 @@ void GatewayUsbSetupBridge::handleBytes(const uint8_t* data, size_t len) {
} }
const uint8_t gateway_id = setupGatewayId(); const uint8_t gateway_id = setupGatewayId();
if (data[0] == 0x12) {
const auto response = dali_domain_.transactBridgeFrame(gateway_id, data, len);
if (!response.empty()) {
const int written = usb_serial_jtag_write_bytes(response.data(), response.size(),
pdMS_TO_TICKS(config_.write_timeout_ms));
if (written < 0 || static_cast<size_t>(written) != response.size()) {
ESP_LOGW(kTag, "failed to write USB raw query response channel=%u len=%u",
config_.channel_index, static_cast<unsigned>(response.size()));
}
}
return;
}
if (!dali_domain_.writeBridgeFrame(gateway_id, data, len)) { if (!dali_domain_.writeBridgeFrame(gateway_id, data, len)) {
ESP_LOGW(kTag, "failed to write USB raw setup frame channel=%u len=%u", config_.channel_index, ESP_LOGW(kTag, "failed to write USB raw setup frame channel=%u len=%u", config_.channel_index,
static_cast<unsigned>(len)); static_cast<unsigned>(len));