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:
+31
-13
@@ -603,15 +603,13 @@ CONFIG_GATEWAY_CHANNEL_COUNT=1
|
||||
#
|
||||
CONFIG_GATEWAY_CHANNEL1_GW_ID=3
|
||||
# CONFIG_GATEWAY_CHANNEL1_PHY_DISABLED is not set
|
||||
# CONFIG_GATEWAY_CHANNEL1_PHY_NATIVE is not set
|
||||
CONFIG_GATEWAY_CHANNEL1_PHY_UART1=y
|
||||
CONFIG_GATEWAY_CHANNEL1_PHY_NATIVE=y
|
||||
# CONFIG_GATEWAY_CHANNEL1_PHY_UART1 is not set
|
||||
# CONFIG_GATEWAY_CHANNEL1_PHY_UART2 is not set
|
||||
CONFIG_GATEWAY_CHANNEL1_SERIAL_TX_PIN=1
|
||||
CONFIG_GATEWAY_CHANNEL1_SERIAL_RX_PIN=2
|
||||
CONFIG_GATEWAY_CHANNEL1_SERIAL_BAUDRATE=9600
|
||||
CONFIG_GATEWAY_CHANNEL1_SERIAL_RX_BUFFER=512
|
||||
CONFIG_GATEWAY_CHANNEL1_SERIAL_TX_BUFFER=512
|
||||
CONFIG_GATEWAY_CHANNEL1_SERIAL_QUERY_TIMEOUT_MS=100
|
||||
CONFIG_GATEWAY_CHANNEL1_NATIVE_BUS_ID=0
|
||||
CONFIG_GATEWAY_CHANNEL1_NATIVE_TX_PIN=2
|
||||
CONFIG_GATEWAY_CHANNEL1_NATIVE_RX_PIN=1
|
||||
CONFIG_GATEWAY_CHANNEL1_NATIVE_BAUDRATE=1200
|
||||
# end of Gateway Channel 1
|
||||
|
||||
#
|
||||
@@ -626,7 +624,7 @@ CONFIG_GATEWAY_CACHE_SUPPORTED=y
|
||||
CONFIG_GATEWAY_CACHE_START_ENABLED=y
|
||||
CONFIG_GATEWAY_CACHE_RECONCILIATION_ENABLED=y
|
||||
# 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_LOCAL_GATEWAY_FIRST is not set
|
||||
# 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_RX_PIN=-1
|
||||
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_PRIORITY=5
|
||||
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_DEFAULT_BAUDRATE=1200
|
||||
CONFIG_DALI_API_QUEUE_LEN=10
|
||||
CONFIG_DALI_TX_QUEUE_LEN=1
|
||||
CONFIG_DALI_TIMER_RESOLUTION_HZ=3000000
|
||||
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_RX_QUEUE_LEN=50
|
||||
CONFIG_DALI_DEBUG_QUEUE_LEN=100
|
||||
# CONFIG_DALI_ENABLE_DEBUG_TASK is not set
|
||||
CONFIG_DALI_DALI_TASK_STACK_SIZE=2048
|
||||
CONFIG_DALI_ENABLE_DEBUG_TASK=y
|
||||
CONFIG_DALI_DALI_TASK_STACK_SIZE=8192
|
||||
CONFIG_DALI_DALI_TASK_PRIORITY=2
|
||||
CONFIG_DALI_DEBUG_TASK_STACK_SIZE=2048
|
||||
CONFIG_DALI_DEBUG_TASK_PRIORITY=1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+33
-26
@@ -596,38 +596,25 @@ CONFIG_PARTITION_TABLE_MD5=y
|
||||
#
|
||||
# Gateway App
|
||||
#
|
||||
CONFIG_GATEWAY_CHANNEL_COUNT=2
|
||||
CONFIG_GATEWAY_CHANNEL_COUNT=1
|
||||
|
||||
#
|
||||
# Gateway Channel 1
|
||||
#
|
||||
CONFIG_GATEWAY_CHANNEL1_GW_ID=3
|
||||
# CONFIG_GATEWAY_CHANNEL1_PHY_DISABLED is not set
|
||||
# CONFIG_GATEWAY_CHANNEL1_PHY_NATIVE is not set
|
||||
CONFIG_GATEWAY_CHANNEL1_PHY_UART1=y
|
||||
CONFIG_GATEWAY_CHANNEL1_PHY_NATIVE=y
|
||||
# CONFIG_GATEWAY_CHANNEL1_PHY_UART1 is not set
|
||||
# CONFIG_GATEWAY_CHANNEL1_PHY_UART2 is not set
|
||||
CONFIG_GATEWAY_CHANNEL1_SERIAL_TX_PIN=1
|
||||
CONFIG_GATEWAY_CHANNEL1_SERIAL_RX_PIN=2
|
||||
CONFIG_GATEWAY_CHANNEL1_SERIAL_BAUDRATE=9600
|
||||
CONFIG_GATEWAY_CHANNEL1_SERIAL_RX_BUFFER=512
|
||||
CONFIG_GATEWAY_CHANNEL1_SERIAL_TX_BUFFER=512
|
||||
CONFIG_GATEWAY_CHANNEL1_SERIAL_QUERY_TIMEOUT_MS=100
|
||||
CONFIG_GATEWAY_CHANNEL1_NATIVE_BUS_ID=0
|
||||
CONFIG_GATEWAY_CHANNEL1_NATIVE_TX_PIN=2
|
||||
CONFIG_GATEWAY_CHANNEL1_NATIVE_RX_PIN=1
|
||||
CONFIG_GATEWAY_CHANNEL1_NATIVE_BAUDRATE=1200
|
||||
# end of Gateway Channel 1
|
||||
|
||||
#
|
||||
# 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
|
||||
|
||||
#
|
||||
@@ -637,7 +624,7 @@ CONFIG_GATEWAY_CACHE_SUPPORTED=y
|
||||
CONFIG_GATEWAY_CACHE_START_ENABLED=y
|
||||
CONFIG_GATEWAY_CACHE_RECONCILIATION_ENABLED=y
|
||||
# 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_LOCAL_GATEWAY_FIRST is not set
|
||||
# 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_RX_PIN=-1
|
||||
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_CLOUD_BRIDGE_SUPPORTED=y
|
||||
# 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_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_CPU1 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_DEFAULT_BAUDRATE=1200
|
||||
CONFIG_DALI_API_QUEUE_LEN=10
|
||||
CONFIG_DALI_TX_QUEUE_LEN=1
|
||||
CONFIG_DALI_TIMER_RESOLUTION_HZ=3000000
|
||||
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_RX_QUEUE_LEN=50
|
||||
CONFIG_DALI_DEBUG_QUEUE_LEN=100
|
||||
# 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_DEBUG_TASK_STACK_SIZE=2048
|
||||
CONFIG_DALI_DEBUG_TASK_PRIORITY=1
|
||||
|
||||
+135
-1
@@ -14,6 +14,140 @@ config DALI_DEFAULT_BAUDRATE
|
||||
help
|
||||
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
|
||||
int "Global API queue length"
|
||||
range 1 64
|
||||
@@ -48,7 +182,7 @@ config DALI_ENABLE_DEBUG_TASK
|
||||
config DALI_DALI_TASK_STACK_SIZE
|
||||
int "DALI task stack size"
|
||||
range 1024 8192
|
||||
default 2048
|
||||
default 4096
|
||||
|
||||
config DALI_DALI_TASK_PRIORITY
|
||||
int "DALI task priority"
|
||||
|
||||
@@ -41,10 +41,26 @@ void app_main(void) {
|
||||
Use `menuconfig` under `DALI Component` to configure:
|
||||
|
||||
- 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.
|
||||
- Task stack sizes and priorities.
|
||||
- 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
|
||||
|
||||
The global TX response queue symbol was renamed:
|
||||
|
||||
@@ -6,6 +6,14 @@
|
||||
#include <memory.h> // for memset
|
||||
#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 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;
|
||||
dali_msg.id = 0;
|
||||
@@ -90,7 +112,7 @@ void dali_send_double(Dali_msg_t *dali_msg) {
|
||||
dali_send_locked(dali_msg);
|
||||
// TODO check status
|
||||
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);
|
||||
// TODO check status
|
||||
dali_core_unlock();
|
||||
@@ -110,17 +132,16 @@ int dali_query(Dali_msg_t *tx_msg, Dali_msg_t *rx_msg) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// TODO check empty queue
|
||||
if(xQueueReceive(rx_q, rx_msg, 0) == pdTRUE) {
|
||||
printf("Queue not empty\n");
|
||||
return -1;
|
||||
dali_core_lock();
|
||||
UBaseType_t drained = drain_rx_queue(rx_q);
|
||||
if (drained > 0) {
|
||||
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]);
|
||||
|
||||
dali_core_lock();
|
||||
dali_send_locked(tx_msg);
|
||||
// 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();
|
||||
// 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;
|
||||
|
||||
@@ -4,6 +4,15 @@
|
||||
//ESP-IDF HAL
|
||||
#ifdef CONFIG_IDF_TARGET
|
||||
#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/task.h"
|
||||
#include "freertos/queue.h"
|
||||
@@ -39,7 +48,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DALI_DALI_TASK_STACK_SIZE
|
||||
#define CONFIG_DALI_DALI_TASK_STACK_SIZE 2048
|
||||
#define CONFIG_DALI_DALI_TASK_STACK_SIZE 4096
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DALI_DALI_TASK_PRIORITY
|
||||
@@ -54,14 +63,41 @@
|
||||
#define CONFIG_DALI_DEBUG_TASK_PRIORITY 1
|
||||
#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 MAX_DELTA_RELOAD_TIME 600000000 // 600s - max u32: 4,294,967,295~4,294s
|
||||
|
||||
#define DALI_BAUDRATE_MIN 400U
|
||||
#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 {
|
||||
uint32_t hb;
|
||||
uint32_t timer_alarm_ticks;
|
||||
uint32_t rx_hb_min;
|
||||
uint32_t rx_hb_max;
|
||||
uint32_t rx_2hb_min;
|
||||
@@ -76,6 +112,11 @@ typedef struct {
|
||||
|
||||
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 {
|
||||
uint8_t bus_id;
|
||||
uint8_t tx_pin;
|
||||
@@ -91,6 +132,10 @@ typedef struct {
|
||||
uint32_t rx_tx_delta;
|
||||
uint32_t rx_pulse_width;
|
||||
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 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) {
|
||||
return 0;
|
||||
}
|
||||
uint64_t hb = 500000ULL + (baudrate / 2U); // round to nearest
|
||||
hb /= baudrate;
|
||||
if (hb == 0 || hb > 2000000ULL) { // should never happen with checked bounds
|
||||
uint64_t hb_x100 = 50000000ULL + (baudrate / 2U); // round to nearest 0.01 us
|
||||
hb_x100 /= baudrate;
|
||||
if (hb_x100 == 0 || hb_x100 > 200000000ULL) { // should never happen with checked bounds
|
||||
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)
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
uint32_t hb = dali_half_bit_from_baud(baudrate);
|
||||
if (hb == 0) {
|
||||
ESP_LOGE(TAG, "invalid baudrate: %u", baudrate);
|
||||
uint32_t hb_x100 = CONFIG_DALI_CUSTOM_HALF_BIT_TIME_X100_US;
|
||||
if (hb_x100 == 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
dali_timing_t new_timing = {
|
||||
.hb = hb,
|
||||
.timer_alarm_ticks = timer_alarm_ticks,
|
||||
.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_2hb_min = scale_time_by_hb(DALI_RX_2HB_MIN, 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_break_min = scale_time_by_hb(DALI_TIME_BREAK_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),
|
||||
};
|
||||
|
||||
@@ -199,7 +273,7 @@ static esp_err_t apply_timer_alarm_locked(void)
|
||||
return ESP_OK;
|
||||
}
|
||||
gptimer_alarm_config_t timer_alarm_config = {
|
||||
.alarm_count = s_timing.hb,
|
||||
.alarm_count = s_timing.timer_alarm_ticks,
|
||||
.reload_count = 0,
|
||||
.flags = {
|
||||
.auto_reload_on_alarm = true,
|
||||
@@ -235,22 +309,221 @@ static bool s_debug_task_created = false;
|
||||
#endif
|
||||
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_LOW(bus) gpio_set_level((bus)->tx_pin, DALI_TX_LOW) // set bus level
|
||||
#define DALI_SET_BUS_LEVEL(bus, x) gpio_set_level((bus)->tx_pin, ((x)==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) do { gpio_set_level((bus)->tx_pin, DALI_TX_LOW); (bus)->tx_level = 0; } while (0)
|
||||
#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
|
||||
// return: 0 - bus level low, active 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
|
||||
// return: 0 - tx pin drive bus low, active state
|
||||
// 1 - tx pin drive bus high, idle state
|
||||
#define DALI_GET_TX_LEVEL(bus) (gpio_get_level((bus)->tx_pin) == (DALI_TX_HIGH)) // get TX pin level
|
||||
// return: 0 - TX drives bus low, active state
|
||||
// 1 - TX releases/drives bus high, idle state
|
||||
#define DALI_GET_TX_LEVEL(bus) ((bus)->tx_level)
|
||||
|
||||
static inline bool bus_valid(uint8_t bus_id) {
|
||||
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)
|
||||
{
|
||||
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
|
||||
// define rx_gpio_isr_handler on any edge
|
||||
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;
|
||||
}
|
||||
|
||||
BaseType_t yield = false;
|
||||
uint64_t rx_current_edge_time = esp_timer_get_time(); // get time in us
|
||||
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
|
||||
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
|
||||
uint32_t time_ms = bus->rx_pulse_width / 1000; // 1ms = 1000us
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
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->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_tx_delta = bus->rx_tx_delta;
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
if(bus->bus_state <= DALI_BUS_ERROR)
|
||||
{ // 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->rx_level==0 && rx_delta > s_timing.time_bus_down)
|
||||
{ // 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
|
||||
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
|
||||
@@ -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
|
||||
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
|
||||
|
||||
bus->tx_last_edge_time = esp_timer_get_time(); // get time in us
|
||||
// read bus state
|
||||
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_half_bit_counter = 0;
|
||||
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
|
||||
DALI_SET_BUS_LOW(bus); // start bit first half
|
||||
}
|
||||
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
|
||||
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_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
|
||||
DALI_SET_BUS_HIGH(bus); // start bit second half
|
||||
}
|
||||
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;
|
||||
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);
|
||||
|
||||
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
|
||||
if(bus->tx_half_bit_counter & 0x01) { // next bit
|
||||
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
|
||||
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
|
||||
DALI_SET_BUS_HIGH(bus);
|
||||
}
|
||||
else if(tx_delta > s_timing.tx_stop_cond) {
|
||||
bus->tx_data.status = DALI_FRAME_OK; // frame is OK
|
||||
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
|
||||
complete_tx_from_isr(bus, &yield);
|
||||
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
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
@@ -588,7 +929,7 @@ static void debug_task(void *pvParameters)
|
||||
else v = '0' + dbg.level;
|
||||
}
|
||||
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);
|
||||
if(dbg.rx_pulse_width < 1000) {
|
||||
if(dbg.rx_pulse_width > 550) HB+=2;
|
||||
@@ -659,7 +1000,7 @@ static esp_err_t ensure_timer_started(void)
|
||||
.flags = {
|
||||
.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);
|
||||
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->tx_pin = tx_pin;
|
||||
bus->rx_pin = rx_pin;
|
||||
bus->tx_level = 1;
|
||||
|
||||
gpio_set_level(bus->tx_pin, DALI_TX_HIGH);
|
||||
|
||||
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_level = DALI_GET_BUS_LEVEL(bus); // get level of RX pin
|
||||
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();
|
||||
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) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if(xQueueSendToBack(bus->tx_queue, dali_msg, pdMS_TO_TICKS(50)) == pdFALSE) {
|
||||
xQueueReset(bus->tx_queue); // clear queue
|
||||
printf("dali_tx: Queue full\n");
|
||||
if (bus->tx_queue == NULL || bus->tx_reply_queue == NULL || dali_msg == NULL) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if(xQueueReceive(bus->tx_reply_queue, dali_msg, pdMS_TO_TICKS(50)) == pdFALSE) {
|
||||
xQueueReset(bus->tx_reply_queue); // clear queue
|
||||
printf("dali_tx: No reply\n");
|
||||
|
||||
const uint32_t timeout_ms = tx_completion_timeout_ms(dali_msg);
|
||||
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_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
|
||||
@@ -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)
|
||||
{
|
||||
dali_hal_lock();
|
||||
apply_dali_log_level();
|
||||
|
||||
esp_err_t err = ensure_timing_ready_locked();
|
||||
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)
|
||||
{
|
||||
dali_hal_lock();
|
||||
apply_dali_log_level();
|
||||
|
||||
bool resume_timer = s_timer_started && gptimer;
|
||||
if (resume_timer) {
|
||||
|
||||
@@ -3,6 +3,10 @@
|
||||
#include <stdint.h>
|
||||
#include "dali_hal.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
Addressing: 102.7.2.1
|
||||
0AAA AAAx - short address AAAAAA 0-63
|
||||
@@ -77,5 +81,9 @@ void dali_set_search_addr24(uint32_t addr24);
|
||||
uint32_t dali_binary_search();
|
||||
void dali_change_short_address(int addr1, int addr2);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DALI_PHY_COUNT
|
||||
#define DALI_PHY_COUNT CONFIG_DALI_PHY_COUNT
|
||||
#else
|
||||
@@ -182,13 +186,22 @@ typedef struct Dali_msg Dali_msg_t;
|
||||
|
||||
// define HW DALI for gpio functions
|
||||
#ifndef DALI_HW_PINS
|
||||
// define HW DALI for gpio functions
|
||||
// - what we should write to pin to get HIGH/LOW
|
||||
#define DALI_TX_HIGH 1 // idle state
|
||||
#define DALI_TX_LOW 0 // active state
|
||||
// - what we should read from pin to get HIGH/LOW
|
||||
#define DALI_RX_HIGH 1 // idle state
|
||||
#define DALI_RX_LOW 0 // active state
|
||||
// Physical GPIO levels for logical DALI idle/high and active/low bus states.
|
||||
#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_LOW 0 // active state
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DALI_RX_ACTIVE_LOW
|
||||
#define DALI_RX_HIGH 1 // idle 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
|
||||
|
||||
// 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);
|
||||
void dali_task(void *pvParameters);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -64,6 +64,10 @@ struct SerialRxPacket {
|
||||
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) {
|
||||
if (data == nullptr || len != 3) {
|
||||
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) {
|
||||
if (data == nullptr || len != 3) {
|
||||
if (data == nullptr) {
|
||||
return {};
|
||||
}
|
||||
if (len != 3) {
|
||||
return len > 0 && data[0] == 0x12 ? LegacyQueryResponse(0xFD) : std::vector<uint8_t>{};
|
||||
}
|
||||
|
||||
switch (data[0]) {
|
||||
case 0x00:
|
||||
@@ -107,9 +114,12 @@ std::vector<uint8_t> TransactHardwareFrame(uint8_t bus_id, const uint8_t* data,
|
||||
tx.id = bus_id;
|
||||
Dali_msg_t rx = {};
|
||||
if (dali_query(&tx, &rx) == pdTRUE) {
|
||||
if (rx.status != DALI_FRAME_OK || rx.length != 8) {
|
||||
return LegacyQueryResponse(0xFD);
|
||||
}
|
||||
return {0xFF, rx.data[0]};
|
||||
}
|
||||
return {0xFE};
|
||||
return LegacyQueryResponse(0xFE);
|
||||
}
|
||||
default:
|
||||
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,
|
||||
uint32_t query_timeout_ms, const uint8_t* data,
|
||||
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) {
|
||||
DrainSerialQueue(queue);
|
||||
}
|
||||
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};
|
||||
}
|
||||
|
||||
@@ -173,10 +189,10 @@ std::vector<uint8_t> TransactSerialFrame(int uart_port, QueueHandle_t queue,
|
||||
auto response = PacketToVector(packet, 2);
|
||||
if (!response.empty() &&
|
||||
(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
|
||||
|
||||
@@ -82,6 +82,19 @@ void GatewayUsbSetupBridge::handleBytes(const uint8_t* data, size_t len) {
|
||||
}
|
||||
|
||||
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)) {
|
||||
ESP_LOGW(kTag, "failed to write USB raw setup frame channel=%u len=%u", config_.channel_index,
|
||||
static_cast<unsigned>(len));
|
||||
|
||||
Reference in New Issue
Block a user