Digital Addressable Lighting Interface (DALI) Bus Driver

[中文]

The DALI component provides an ESP-IDF based DALI (IEC 62386) master driver. It uses the ESP RMT peripheral to generate forward frames and decode backward frames, so applications can control and query DALI control gear directly.

Features

  • Physical Layer — RMT-based Manchester TX/RX (Te = 416.67 µs, ±10 % tolerance).

  • Addressing — Short address (0–63), group address (0–15), broadcast, and special commands.

  • Part 102 (Control Gear) — DAPC dimming, indirect/configuration commands, and queries for lamps.

  • Part 103 (Control Device) — Event reporting and device/instance-level commands for input devices.

  • Part 303/304 (Sensors) — Occupancy (303) and light (304) sensor support.

  • Part 209 (DT8 Color) — RGB, CCT (Tc), and XY chromaticity control.

  • Commissioning — Automatic short address assignment for Part 102 and Part 103 devices.

  • Send-twice — Built-in double transmission within 100 ms for configuration commands.

Glossary

Te

The DALI half-period unit. Nominal value: 416.67 µs (±10 % tolerance allowed by IEC 62386). All DALI timing is expressed as multiples of Te.

Forward Frame (FF)

A 16-bit frame transmitted by the DALI master to control gear. It consists of 1 start bit + 16 data bits + 2 stop bits = 38 Te total. The first byte encodes the address; the second byte carries the command or arc-power value.

Backward Frame (BF)

An 8-bit reply frame sent by a DALI slave in response to a query command. It consists of 1 start bit + 8 data bits + 2 stop bits = 22 Te total. The slave must respond within 7 Te-22 Te after the forward frame ends.

Short Address

A unique address assigned to a single DALI control gear, in the range 0-63. Encoded in the forward frame as 0AAAAAAS (A = address bits, S = selector bit). Short addresses for Part 102 and Part 103 devices are independent; no address conflicts during commissioning.

Group Address

An address shared by up to 16 control gear units, in the range 0-15. Encoded as 100AAAAS. Allows simultaneous control of multiple fixtures without individual addressing.

Supported Targets

DALI components support chips that include RMT peripherals; currently supported chips include:

  • ESP32

  • ESP32-S2

  • ESP32-S3

  • ESP32-C3

  • ESP32-C6

  • ESP32-P4

  • ESP32-H2

Quick Start

  1. Include headers:

    #include "dali.h"
    #include "dali_command.h"
    
  2. Initialize the driver:

    dali_master_handle_t dali;
    dali_master_config_t cfg = {
        .rx_gpio = GPIO_NUM_4,
        .tx_gpio = GPIO_NUM_5,
        .invert_tx = false,
        .invert_rx = false,
    };
    dali_master_rmt_config_t rmt_cfg = {
        .mem_block_symbols = 64,
    };
    ESP_ERROR_CHECK(dali_new_master_rmt(&cfg, &rmt_cfg, &dali));
    
  3. Send a command (no backward frame expected):

    /* The driver automatically inserts the minimum inter-frame gap
       (> 22 Te) after every transaction — no explicit delay needed. */
    dali_master_transaction_config_t tx_cfg = {
        .addr_type = DALI_ADDR_SHORT,
        .addr = 0,
        .is_cmd = true,
        .command = DALI_CMD_RECALL_MAX_LEVEL,
        .send_twice = false,
        .tx_timeout_ms = DALI_TX_TIMEOUT_MS,
    };
    ESP_ERROR_CHECK(dali_master_do_transaction(dali, &tx_cfg, NULL));
    
  4. Send a query (backward frame expected):

    int reply = DALI_RESULT_NO_REPLY;
    dali_master_transaction_config_t tx_cfg = {
        .addr_type = DALI_ADDR_SHORT,
        .addr = 0,
        .is_cmd = true,
        .command = DALI_CMD_QUERY_STATUS,
        .send_twice = false,
        .tx_timeout_ms = DALI_TX_TIMEOUT_MS,
    };
    ESP_ERROR_CHECK(dali_master_do_transaction(dali, &tx_cfg, &reply));
    if (DALI_RESULT_IS_VALID(reply)) {
        ESP_LOGI("dali", "QUERY_STATUS = 0x%02X", (unsigned)reply);
    }
    
  5. Commissioning (auto-assign short addresses):

    /* Part 102 — Control Gear (lamps) */
    uint8_t count102 = 0;
    esp_err_t err = dali_commission(dali, DALI_COMMISSION_ALL, 0, 64, &count102,
                                    DALI_TX_TIMEOUT_MS);
    if (err == ESP_OK) {
        ESP_LOGI("dali", "Part 102 commissioned: %u gear", count102);
    }
    
    /* Part 103 — Control Devices (sensors) */
    uint8_t count103 = 0;
    err = dali_103_commission(dali, DALI_COMMISSION_ALL, 10, 64, &count103,
                              DALI_TX_TIMEOUT_MS);
    if (err == ESP_OK) {
        ESP_LOGI("dali", "Part 103 commissioned: %u devices", count103);
    }
    
  6. Set DT8 color (Part 209):

    /* RGB mode — set address 4 to red */
    dali_color_val_t color = { .rgb = { .r = 254, .g = 0, .b = 0 } };
    ESP_ERROR_CHECK(dali_master_set_color(dali, DALI_ADDR_SHORT, 4,
                                           DALI_COLOR_RGB, color,
                                           DALI_TX_TIMEOUT_MS));
    
    /* CCT mode — set address 4 to 2700 K (370 Mirek) */
    dali_color_val_t cct = { .cct = { .mirek = 370 } };
    ESP_ERROR_CHECK(dali_master_set_color(dali, DALI_ADDR_SHORT, 4,
                                           DALI_COLOR_CCT, cct,
                                           DALI_TX_TIMEOUT_MS));
    

Configuration

All DALI driver configuration is done through the two configuration structures at runtime — no Kconfig options are required:

dali_master_config_t cfg = {
    .rx_gpio = GPIO_NUM_4,
    .tx_gpio = GPIO_NUM_5,
    .invert_tx = false,      /* By default, TX polarity is not inverted */
    .invert_rx = false,      /* By default, RX polarity is not inverted */
};
dali_master_rmt_config_t rmt_cfg = {
    .mem_block_symbols = 0, /* 0 = auto-detect per SOC capability */
};
ESP_ERROR_CHECK(dali_new_master_rmt(&cfg, &rmt_cfg, &dali));

Command Model

Use dali_master_do_transaction() as the single entry for all transaction types. Pass a dali_master_transaction_config_t to describe the transaction:

  • DAPC value write: config.is_cmd = false, config.command is arc power value.

  • Normal command/query: config.is_cmd = true, config.command from dali_command.h.

  • Commands requiring double transmission: set config.send_twice = true.

  • For queries, pass result != NULL and check DALI_RESULT_IS_VALID(*result). dali_master_do_transaction() automatically inserts the required inter-frame gap (> 22 Te) after every transaction, so no manual delay is needed between consecutive calls.

Timing Notes

  • DALI defines strict frame spacing and backward-frame response windows.

  • The driver automatically inserts the minimum inter-frame gap (> 22 Te) after every dali_master_do_transaction() call, satisfying the IEC 62386 requirement.

  • dali_master_do_transaction() is blocking — do not call it from an ISR or a time-critical task.

Example and Test

  • Example application: lighting/dali_basic

  • Component test app: components/dali/test_apps/main/dali_test.c

The example demonstrates:

  • Commissioning — Automatic short address assignment for Part 102 (lamps) and Part 103 (sensors)

  • Dynamic Device Detection — Scan and identify DT6 (dimming) vs DT8 (color) gear by device type

  • DAPC Dimming — Brightness control sequence on all discovered lamps

  • Part 103 Sensor — Occupancy polling and event-triggered actions

  • Simultaneous Blink — When occupied: DT6 lamps blink together, DT8 lamp alternates Red/Blue

  • Query Commands — Status, actual level, and device type queries

API Reference

DALI APIs are divided into the following parts:

DALI Definitions

This section contains common definitions, constants, and types used across DALI.

DALI Commands

Header File

Macros

DALI_DAPC_OFF

DAPC: Fade to minimum level then switch off.

DALI_DAPC_MASK

DAPC: Mask value — command is ignored; no change to output level.

DALI_CMD_OFF

Switch off lamp without fading.

DALI_CMD_UP

Dim up at the selected fade rate for 200 ms.

DALI_CMD_DOWN

Dim down at the selected fade rate for 200 ms.

DALI_CMD_STEP_UP

Increase light output by one step (no fade); lamp stays off if already off.

DALI_CMD_STEP_DOWN

Decrease light output by one step (no fade); lamp stays on at minimum.

DALI_CMD_RECALL_MAX_LEVEL

Set output to the stored maximum level.

DALI_CMD_RECALL_MIN_LEVEL

Set output to the stored minimum level.

DALI_CMD_STEP_DOWN_AND_OFF

Decrease light output by one step (no fade); switch off if already at minimum.

DALI_CMD_ON_AND_STEP_UP

Switch on (if off) and increase one step (no fade).

DALI_CMD_ENABLE_DAPC_SEQ

Enable DAPC sequence mode.

DALI_CMD_RESET

[2x] Reset all device parameters to their power-on defaults.

DALI_CMD_STORE_ACTUAL_LEVEL

[2x] Store the current actual level in the DTR.

DALI_CMD_STORE_DTR_AS_MAX_LEVEL

[2x] Set maximum level from DTR.

DALI_CMD_STORE_DTR_AS_MIN_LEVEL

[2x] Set minimum level from DTR.

DALI_CMD_STORE_DTR_AS_FAIL_LEVEL

[2x] Set system failure level from DTR.

DALI_CMD_STORE_DTR_AS_POWER_ON_LEVEL

[2x] Set power-on level from DTR.

DALI_CMD_STORE_DTR_AS_FADE_TIME

[2x] Set fade time from DTR.

DALI_CMD_STORE_DTR_AS_FADE_RATE

[2x] Set fade rate from DTR.

DALI_CMD_STORE_DTR_AS_SHORT_ADDR

[2x] Store DTR value as the device’s short address.

DALI_CMD_ENABLE_WRITE_MEMORY

[2x] Enable write to memory bank.

DALI_CMD_QUERY_STATUS

Query: device status byte (bit-field, see IEC 62386-102 §8.4.1).

DALI_CMD_QUERY_CONTROL_GEAR

Query: confirm that a control gear is present (returns 0xFF if yes).

DALI_CMD_QUERY_LAMP_FAILURE

Query: lamp failure flag (bit 1 of status byte).

DALI_CMD_QUERY_LAMP_POWER_ON

Query: lamp arc power on flag (bit 2 of status byte).

DALI_CMD_QUERY_LIMIT_ERROR

Query: limit error flag (bit 3 of status byte).

DALI_CMD_QUERY_RESET_STATE

Query: reset state flag (bit 4 of status byte).

DALI_CMD_QUERY_MISSING_SHORT_ADDR

Query: missing short address flag (bit 5 of status byte).

DALI_CMD_QUERY_VERSION

Query: DALI version number.

DALI_CMD_QUERY_CONTENT_DTR

Query: content of the Data Transfer Register (DTR).

DALI_CMD_QUERY_DEVICE_TYPE

Query: device type number (e.g., 0 = fluorescent, 6 = LED).

DALI_CMD_QUERY_PHY_MIN_LEVEL

Query: physical minimum arc-power level.

DALI_CMD_QUERY_POWER_FAILURE

Query: power failure flag (bit 7 of status byte).

DALI_CMD_QUERY_CONTENT_DTR1

Query: content of Data Transfer Register 1 (DTR1).

DALI_CMD_QUERY_CONTENT_DTR2

Query: content of Data Transfer Register 2 (DTR2).

DALI_CMD_QUERY_ACTUAL_LEVEL

Query: current actual arc-power output level (0x00–0xFF).

DALI_CMD_QUERY_MAX_LEVEL

Query: stored maximum arc-power level.

DALI_CMD_QUERY_MIN_LEVEL

Query: stored minimum arc-power level.

DALI_CMD_QUERY_POWER_ON_LEVEL

Query: stored power-on arc-power level.

DALI_CMD_QUERY_SYSTEM_FAILURE_LEVEL

Query: stored system-failure arc-power level.

DALI_CMD_QUERY_FADE_TIME_RATE

Query: fade time and fade rate (high nibble = fade time, low nibble = fade rate).

DALI_CMD_QUERY_GROUPS_0_7

Query: group membership mask for groups 0–7 (bit n = member of group n).

DALI_CMD_QUERY_GROUPS_8_15

Query: group membership mask for groups 8–15.

DALI_CMD_QUERY_RANDOM_ADDR_H

Query: high byte of the 24-bit random address.

DALI_CMD_QUERY_RANDOM_ADDR_M

Query: middle byte of the 24-bit random address.

DALI_CMD_QUERY_RANDOM_ADDR_L

Query: low byte of the 24-bit random address.

DALI_CMD_READ_MEMORY_LOCATION

Query: read a byte from the memory bank at the current address pointer.

DALI_CMD_QUERY_EXTENDED_VERSION

Query: extended version number for a specific device type.

DALI_SPECIAL_TERMINATE

Terminate an ongoing initialize or commission sequence.

DALI_SPECIAL_DATA_TRANSFER_REG

Load a value into the Data Transfer Register (DTR); data in second byte.

DALI_SPECIAL_INITIALIZE

[2x] Enter addressing mode; second byte: 0x00 = all, 0xFF = unaddressed.

DALI_SPECIAL_RANDOMIZE

[2x] Generate a new 24-bit random address for all devices in INIT mode.

DALI_SPECIAL_COMPARE

Query: return YES (0xFF) if any device random address ≤ search address.

DALI_SPECIAL_WITHDRAW

[2x] Withdraw the selected device from the addressing process.

DALI_SPECIAL_SEARCH_ADDR_H

Set the high byte of the search address; data in second byte.

DALI_SPECIAL_SEARCH_ADDR_M

Set the middle byte of the search address; data in second byte.

DALI_SPECIAL_SEARCH_ADDR_L

Set the low byte of the search address; data in second byte.

DALI_SPECIAL_PROGRAM_SHORT_ADDR

[2x] Program a short address into the device matching the search address.

DALI_SPECIAL_VERIFY_SHORT_ADDR

Verify that the selected device has the given short address.

DALI_SPECIAL_QUERY_SHORT_ADDR

Query: return the short address of the device matching the search address.

DALI_SPECIAL_PHYSICAL_SELECTION

Select a device via physical means (e.g., pressing a button on the gear).

DALI_SPECIAL_ENABLE_DEVICE_TYPE

Enable a device-type-specific extension; device type in second byte.

DALI_SPECIAL_DATA_TRANSFER_REG1

Load a value into DTR1; data in second byte.

DALI_SPECIAL_DATA_TRANSFER_REG2

Load a value into DTR2; data in second byte.

DALI_SPECIAL_WRITE_MEMORY_LOCATION

[2x] Write a byte to the memory bank at the current address pointer.

DALI_209_SET_TEMPORARY_X_COORDINATE

Set temporary X coordinate from DTR0 (low byte) and DTR1 (high byte). Call DALI_209_ACTIVATE afterwards to latch the new XY value.

DALI_209_SET_TEMPORARY_Y_COORDINATE

Set temporary Y coordinate from DTR0 (low byte) and DTR1 (high byte). Call DALI_209_ACTIVATE afterwards to latch the new XY value.

DALI_209_ACTIVATE

Activate the color value previously loaded into the temporary registers. Must be sent after pre-loading DTRs for any color mode.

DALI_209_X_COORD_STEP_UP

Increase X-coordinate by one step (no DTR pre-load needed).

DALI_209_X_COORD_STEP_DOWN

Decrease X-coordinate by one step.

DALI_209_Y_COORD_STEP_UP

Increase Y-coordinate by one step.

DALI_209_Y_COORD_STEP_DOWN

Decrease Y-coordinate by one step.

DALI_209_SET_COLOR_TEMPERATURE

Set temporary color temperature from DTR0 (low byte) and DTR1 (high byte). Unit: Mirek (= 1 000 000 / Kelvin). Range: 1–65534 (0x0000 and 0xFFFF reserved). Call DALI_209_ACTIVATE afterwards to latch the new Tc.

DALI_209_COLOR_TEMPERATURE_STEP_COOLER

Increase color temperature (Tc) by one step toward cooler (lower Mirek).

DALI_209_COLOR_TEMPERATURE_STEP_WARMER

Increase color temperature (Tc) by one step toward warmer (higher Mirek).

DALI_209_SET_PRIMARY_N_DIMLEVEL

Set temporary primary-N dimlevel for primary channel N (0–5). DTR0 = dimlevel (0x00–0xFE), DTR1 = primary index N. Call DALI_209_ACTIVATE afterwards.

DALI_209_SET_TEMPORARY_RGB_DIMLEVEL

Set temporary RGB dimlevel. Load: DTR0 = R, DTR1 = G, DTR2 = B (each 0x00–0xFE, 0xFF = no change). Call DALI_209_ACTIVATE afterwards.

DALI_209_SET_TEMPORARY_WAF_DIMLEVEL

Set temporary WAF dimlevel. Load: DTR0 = W, DTR1 = A, DTR2 = F (each 0x00–0xFE, 0xFF = no change). Call DALI_209_ACTIVATE afterwards.

DALI_209_SET_TEMPORARY_RGBWAF_CONTROL

Select which RGBWAF channels are controlled by the RGB/WAF temporary values.

DALI_209_COPY_REPORT_TO_TEMPORARY

Copy the reported color value into the temporary color registers.

DALI_209_STORE_COLOR_TEMPERATURE_LIMIT_COOL

[2x] Store DTR0/DTR1 as the physical cool-white color temperature limit (Tc_coolest).

DALI_209_STORE_COLOR_TEMPERATURE_LIMIT_WARM

[2x] Store DTR0/DTR1 as the physical warm-white color temperature limit (Tc_warmest).

DALI_209_QUERY_COLOR_STATUS

Query the device color status byte (IEC 62386-209 §8.3.1). Bit fields: [0] Color mode active (1 = active) [1] Color temperature free running [2] Automatic activation enabled [3] Color temperature step active [4] XY-coordinate supported [5] Color temperature supported [6] Primary N supported [7] RGBWAF supported

DALI_209_QUERY_COLOR_CAPABILITIES

Query the color capabilities bitmask. Indicates which color modes the device supports (same bit layout as status byte [4:7]).

DALI_209_QUERY_COLOR_VALUE

Query a color value by index (placed in DTR0 before issuing this command). Returns the low byte; repeat with incremented index for high byte.

DTR0 index map (IEC 62386-209 Table 4): 0x00 = X-coordinate (lo byte) 0x01 = X-coordinate (hi byte) 0x02 = Y-coordinate (lo byte) 0x03 = Y-coordinate (hi byte) 0x04 = Tc (lo byte) 0x05 = Tc (hi byte) 0x06 = primary-0 dimlevel … 0x10 = R dimlevel 0x11 = G dimlevel 0x12 = B dimlevel 0x13 = W dimlevel 0x14 = A dimlevel 0x15 = F dimlevel

To read color temperature (Tc):

  1. SET DTR0 = 0x04 (DALI_SPECIAL_DATA_TRANSFER_REG, data=0x04)

  2. Issue DALI_209_QUERY_COLOR_VALUE → returns Tc low byte

  3. SET DTR0 = 0x05

  4. Issue DALI_209_QUERY_COLOR_VALUE → returns Tc high byte Tc_mirek = (hi << 8) | lo

DALI_209_QUERY_COLOR_TEMPERATURE_LIMIT_COOL

Query the cool-white color temperature limit (Tc_coolest) low byte (pre-load DTR0=index).

DALI_209_QUERY_COLOR_TEMPERATURE_LIMIT_WARM

Query the warm-white color temperature limit (Tc_warmest) low byte.

DALI_209_QUERY_EXTENDED_VERSION

Query the extended version number for Part 209.

DALI_103_START_QUIESCENT_MODE

[2x] Start quiescent mode: suppress input-device/application-controller activity.

DALI_103_STOP_QUIESCENT_MODE

[2x] Stop quiescent mode.

DALI_103_RESET

[2x] Reset all device parameters to factory defaults (Part 103).

DALI_103_SET_SHORT_ADDRESS

[2x] Set input device short address from DTR0.

DALI_103_ENABLE_WRITE_MEMORY

[2x] Enable write to memory bank.

DALI_103_SET_EVENT_PRIORITY

[2x] Set event priority: DTR0 = priority.

DALI_103_ENABLE_INSTANCE

[2x] Enable instance.

DALI_103_DISABLE_INSTANCE

[2x] Disable instance.

DALI_103_SET_PRIMARY_INSTANCE_GROUP

[2x] Set primary instance group.

DALI_103_SET_INSTANCE_GROUP_1

[2x] Set instance group 1.

DALI_103_SET_INSTANCE_GROUP_2

[2x] Set instance group 2.

DALI_103_SET_EVENT_SCHEME

[2x] Set event scheme.

DALI_103_SET_EVENT_FILTER

[2x] Set event filter.

DALI_103_QUERY_DEVICE_STATUS

Query: input device status byte.

DALI_103_QUERY_APPLICATION_CONTROLLER_ERROR

Query: application controller error.

DALI_103_QUERY_INPUT_DEVICE_ERROR

Query: input device error.

DALI_103_QUERY_MISSING_SHORT_ADDRESS

Query: missing short address.

DALI_103_QUERY_VERSION_NUMBER

Query: version number.

DALI_103_QUERY_NUMBER_OF_INSTANCES

Query: number of instances.

DALI_103_QUERY_CONTENT_DTR0

Query: content of DTR0.

DALI_103_QUERY_CONTENT_DTR1

Query: content of DTR1.

DALI_103_QUERY_CONTENT_DTR2

Query: content of DTR2.

DALI_103_QUERY_RANDOM_ADDRESS_H

Query: high byte of the device random address.

DALI_103_QUERY_RANDOM_ADDRESS_M

Query: middle byte of the device random address.

DALI_103_QUERY_RANDOM_ADDRESS_L

Query: low byte of the device random address.

DALI_103_QUERY_GROUPS_0_7

Query: device groups 0–7 membership mask.

DALI_103_QUERY_GROUPS_8_15

Query: device groups 8–15 membership mask.

DALI_103_QUERY_GROUPS_16_23

Query: device groups 16–23 membership mask.

DALI_103_QUERY_GROUPS_24_31

Query: device groups 24–31 membership mask.

DALI_103_QUERY_INPUT_DEVICE_CAPABILITIES

Query: input device capabilities.

DALI_103_QUERY_SHORT_ADDRESS

Query: short address is not a standard device-level command; use special QUERY_SHORT_ADDRESS during commissioning.

DALI_103_QUERY_INSTANCE_TYPE

Query: input value of the addressed instance.

DALI_103_QUERY_RESOLUTION

Query: resolution of the instance sensor value.

DALI_103_QUERY_INPUT_INST_VALUE

Query: current input value.

DALI_103_QUERY_INPUT_INST_VALUE_LATCH

Query: latched input value.

DALI_103_QUERY_INSTANCE_ENABLED

Query: whether the instance is enabled.

DALI_103_QUERY_PRIMARY_INSTANCE_GROUP

Query: primary instance group.

DALI_103_QUERY_INSTANCE_SCHEME

Query: event scheme for this instance.

DALI_103_QUERY_EVENT_FILTER_ZERO_TO_SEVEN

Query event filter bits 0-7

DALI_103_QUERY_EVENT_FILTER_EIGHT_TO_FIFTEEN

Query event filter bits 8-15

DALI_103_QUERY_EVENT_FILTER_SIXTEEN_TO_TWENTYTHREE

Query event filter bits 16-23

DALI_103_SPECIAL_ADDR

< Special address for Part 103

DALI_103_SPECIAL_TERMINATE

Terminate an ongoing input device commissioning sequence.

DALI_103_SPECIAL_INITIALIZE

[2x] Enter input device addressing mode; 0xFF = all, 0x00 = unaddressed.

DALI_103_SPECIAL_RANDOMIZE

[2x] Generate new 24-bit random address for all input devices in INIT mode.

DALI_103_SPECIAL_COMPARE

Query: return YES (0xFF) if any device random address ≤ search address.

DALI_103_SPECIAL_WITHDRAW

Withdraw the selected input device from the addressing process.

DALI_103_SPECIAL_SEARCH_ADDR_H

Set the high byte of the search address.

DALI_103_SPECIAL_SEARCH_ADDR_M

Set the middle byte of the search address.

DALI_103_SPECIAL_SEARCH_ADDR_L

Set the low byte of the search address.

DALI_103_SPECIAL_PROGRAM_SHORT_ADDR

[2x] Program a raw 6-bit short address (0..63) into the selected input device.

DALI_103_SPECIAL_VERIFY_SHORT_ADDR

Verify that the device matching the search address has the given short address.

DALI_103_SPECIAL_QUERY_SHORT_ADDR

Query: return the short address of the device matching the search address.

DALI_103_SPECIAL_WRITE_MEMORY_LOCATION

Write enable for instance configuration commands.

DALI_103_SPECIAL_DTR0

Load a value into DTR0.

DALI_103_SPECIAL_DTR1

Load a value into DTR1.

DALI_103_SPECIAL_DTR2

Load a value into DTR2.

DALI_303_SET_HOLD_TIMER

[2x] Set hold timer: DTR0 = value (unit: 10 s).

DALI_303_SET_REPORT_TIMER

[2x] Set report timer: DTR0 = timer value.

DALI_303_SET_DEADTIME_TIMER

[2x] Set deadtime timer: DTR0 = value.

DALI_303_CANCEL_HOLD_TIMER

Cancel hold timer.

DALI_303_QUERY_DEADTIME_TIMER

Query: current deadtime timer value.

DALI_303_QUERY_HOLD_TIMER

Query: current hold timer value.

DALI_303_QUERY_REPORT_TIMER

Query: current report timer value.

DALI_303_QUERY_CATCHING

Query: whether movement catching is enabled.

DALI_303_QUERY_OCCUPANCY

Query: occupancy state. Returns 0xFF = occupied, 0x00 = unoccupied (no reply = device absent).

DALI_303_QUERY_OCCUPANCY_LATCH

Query: occupancy state latch (reads and clears the latched occupancy event). Returns 0xFF if an occupancy event was latched since the last read.

DALI_304_SET_REPORT_TIMER

[2x] Set report timer: DTR0 = value.

DALI_304_SET_HYSTERESIS

[2x] Set hysteresis: DTR0 = value.

DALI_304_SET_DEADTIME_TIMER

[2x] Set deadtime timer: DTR0 = value.

DALI_304_SET_HYSTERESIS_MIN

[2x] Set minimum hysteresis: DTR0 = value.

DALI_304_QUERY_HYSTERESIS_MIN

Query: minimum hysteresis value.

DALI_304_QUERY_DEADTIME_TIMER

Query: deadtime timer value.

DALI_304_QUERY_REPORT_TIMER

Query: report timer value.

DALI_304_QUERY_HYSTERESIS

Query: hysteresis value.

DALI API

The following sections are generated from the public headers under components/dali/include/.

DALI Part 101 — Physical Layer & RMT Driver Core

Header File

Functions

esp_err_t dali_new_master_rmt(const dali_master_config_t *config, const dali_master_rmt_config_t *rmt_config, dali_master_handle_t *handle)

Create and initialise a DALI master backed by RMT.

Parameters
  • config[in] Configuration for the DALI master.

  • rmt_config[in] RMT configuration.

  • handle[out] Handle to the DALI master instance.

Returns

esp_err_t An error code indicating the success or failure of the operation.

esp_err_t dali_del_master(dali_master_handle_t handle)

De-initialise and free a DALI master instance.

Parameters

handle[in] Handle to the DALI master instance.

Returns

esp_err_t An error code indicating the success or failure of the operation.

esp_err_t dali_master_do_transaction(dali_master_handle_t handle, const dali_master_transaction_config_t *config, int *result)

Execute a 2-byte DALI forward frame and optionally receive a backward frame.

Parameters
  • handle[in] Handle to the DALI master instance.

  • config[in] Configuration for the transaction.

  • result[out] Result of the transaction.

Returns

esp_err_t An error code indicating the success or failure of the operation.

esp_err_t dali_master_do_raw_transaction(dali_master_handle_t handle, const uint8_t *tx_buf, size_t tx_len, bool send_twice, int tx_timeout_ms, int *result)

Send a raw N-byte DALI frame (low-level physical layer API).

This is the underlying frame transmission primitive used by both:

Most applications should use the higher-level APIs (dali_master_do_transaction or dali_103_do_device_command) instead of calling this directly.

Parameters
  • handle[in] Handle from dali_new_master_rmt().

  • tx_buf[in] Raw bytes to send (Manchester-encoded by RMT).

  • tx_len[in] Number of bytes in tx_buf (2 for Part 102, 3 for Part 103).

  • send_twice[in] If true, sends the frame twice within 100 ms.

  • tx_timeout_ms[in] TX timeout per frame (ms).

  • result[out] Received backward frame byte, or DALI_RESULT_NO_REPLY.

Returns

esp_err_t An error code indicating the success or failure of the operation.

Structures

struct dali_master_config_t

Bus-level configuration for a DALI master instance.

Public Members

gpio_num_t rx_gpio

GPIO for DALI bus RX

gpio_num_t tx_gpio

GPIO for DALI bus TX

bool invert_tx

Invert TX signal polarity

bool invert_rx

Invert RX signal polarity

struct dali_master_rmt_config_t

RMT-backend specific configuration.

Public Members

uint32_t mem_block_symbols

0 = auto-detect from SOC

struct dali_master_transaction_config_t

Transaction configuration for dali_master_do_transaction().

Public Members

dali_addr_type_t addr_type

Address type

uint8_t addr

Address

bool is_cmd

Is command

uint8_t command

Command

bool send_twice

Send twice

int tx_timeout_ms

TX timeout (ms)

Macros

DALI_TX_TIMEOUT_MS

Default TX transmission timeout in milliseconds.

DALI_RESULT_NO_REPLY

Sentinel value returned in *result when no backward frame was received.

DALI_RESULT_IS_VALID(r)

Test whether a query result contains a valid backward-frame byte.

Type Definitions

typedef struct dali_master_t *dali_master_handle_t

Opaque handle for a DALI driver instance.

Enumerations

enum dali_addr_type_t

DALI address types.

Values:

enumerator DALI_ADDR_SHORT

Short address (0–63)

enumerator DALI_ADDR_GROUP

Group address (0–15)

enumerator DALI_ADDR_BROADCAST

Broadcast

enumerator DALI_ADDR_SPECIAL

Special command byte

enum dali_commission_mode_t

Commissioning mode selector (used by both Part 102 and Part 103).

Values:

enumerator DALI_COMMISSION_ALL

All gear/devices (Part 102: init byte = 0x00; Part 103: init byte = 0xFF)

enumerator DALI_COMMISSION_UNADDRESSED

Unaddressed gear/devices only (Part 102: init byte = 0xFF; Part 103: init byte = 0x00)

DALI Part 102 — Control Gear commissioning and addressing

Header File

Functions

esp_err_t dali_commission(dali_master_handle_t handle, dali_commission_mode_t mode, uint8_t start_addr, uint8_t max_devices, uint8_t *count, int tx_timeout_ms)

Assign short addresses to Part 102 control gear (IEC 62386-102).

Executes TERMINATE → INITIALISE → RANDOMISE → binary-search loop (COMPARE / PROGRAM_SHORT_ADDR / WITHDRAW) → TERMINATE.

Before starting the Part 102 sequence the function broadcasts Part 103 START_QUIESCENT_MODE so that input devices do not emit frames during the COMPARE windows. On completion the bus is left in quiescent mode; call STOP_QUIESCENT_MODE explicitly when you are ready for sensors to push event frames.

Parameters
  • handle[in] Handle from dali_new_master_rmt().

  • mode[in] DALI_COMMISSION_ALL or DALI_COMMISSION_UNADDRESSED.

  • start_addr[in] First short address to assign (0–63).

  • max_devices[in] Maximum addresses to assign (1–64).

  • count[out] Devices actually found and addressed (may be NULL).

  • tx_timeout_ms[in] Per-frame TX timeout (ms).

Returns

ESP_OK on success, or an ESP_ERR code.

DALI Part 103 — Input Device commissioning and general

Header File

Functions

esp_err_t dali_103_send_special(dali_master_handle_t handle, uint8_t special_cmd, uint8_t data, bool send_twice, int tx_timeout_ms, int *result)

Send a Part 103 special command (3-byte frame: 0xC1, cmd, data).

Parameters
  • handle – Handle from dali_new_master_rmt().

  • special_cmd – Special command to send.

  • data – Data to send.

  • send_twice – Whether to send twice.

  • tx_timeout_ms – Per-frame TX timeout (ms).

  • result – Result of the command (0 = success, 1 = failure).

Returns

esp_err_t An error code indicating the success or failure of the operation.

esp_err_t dali_103_do_device_command(dali_master_handle_t handle, dali_addr_type_t addr_type, uint8_t addr, uint8_t command, bool send_twice, int tx_timeout_ms, int *result)

Send a Part 103 device-level command (3-byte frame).

Parameters
  • handle – Handle from dali_new_master_rmt().

  • addr_type – DALI_ADDR_SHORT or DALI_ADDR_BROADCAST.

  • addr – Short address (0–63) for DALI_ADDR_SHORT.

  • command – Command to send.

  • send_twice – Whether to send twice.

  • tx_timeout_ms – Per-frame TX timeout (ms).

  • result – Result of the command (0 = success, 1 = failure).

Returns

esp_err_t An error code indicating the success or failure of the operation.

esp_err_t dali_103_do_instance_command(dali_master_handle_t handle, dali_addr_type_t addr_type, uint8_t addr, uint8_t instance, uint8_t command, bool send_twice, int tx_timeout_ms, int *result)

Send a Part 103 instance-level command (3-byte frame).

Parameters
  • handle – Handle from dali_new_master_rmt().

  • addr_type – DALI_ADDR_SHORT or DALI_ADDR_BROADCAST.

  • addr – Short address (0–63) for DALI_ADDR_SHORT.

  • instance – Instance number (0–31); encoded directly in byte 2.

  • command – Command to send.

  • send_twice – Whether to send twice.

  • tx_timeout_ms – Per-frame TX timeout (ms).

  • result – Result of the command (0 = success, 1 = failure).

Returns

esp_err_t An error code indicating the success or failure of the operation.

esp_err_t dali_103_commission(dali_master_handle_t handle, dali_commission_mode_t mode, uint8_t start_addr, uint8_t max_devices, uint8_t *count, int tx_timeout_ms)

Assign short addresses to Part 103 input devices (IEC 62386-103).

Mirrors dali_commission() but uses the Part 103 special-command set.

Parameters
  • handle[in] Handle from dali_new_master_rmt().

  • mode[in] DALI_COMMISSION_ALL or DALI_COMMISSION_UNADDRESSED.

  • start_addr[in] First short address to assign (0–63).

  • max_devices[in] Maximum addresses to assign (1–64).

  • count[out] Devices found and addressed (may be NULL).

  • tx_timeout_ms[in] Per-frame TX timeout (ms).

Returns

esp_err_t An error code indicating the success or failure of the operation.

esp_err_t dali_103_query_device_status(dali_master_handle_t handle, dali_addr_type_t addr_type, uint8_t addr, uint8_t *status, int tx_timeout_ms)

Query Part 103 input device status byte.

Parameters
  • handle – Handle from dali_new_master_rmt().

  • addr_type – DALI_ADDR_SHORT or DALI_ADDR_BROADCAST.

  • addr – Short address (0–63) for DALI_ADDR_SHORT.

  • status – Status byte to read.

  • tx_timeout_ms – Per-frame TX timeout (ms).

Returns

esp_err_t An error code indicating the success or failure of the operation.

esp_err_t dali_103_reset_device(dali_master_handle_t handle, dali_addr_type_t addr_type, uint8_t addr, int tx_timeout_ms)

Send a Part 103 RESET command (send-twice).

Parameters
  • handle – Handle from dali_new_master_rmt().

  • addr_type – DALI_ADDR_SHORT or DALI_ADDR_BROADCAST.

  • addr – Short address (0–63) for DALI_ADDR_SHORT.

  • tx_timeout_ms – Per-frame TX timeout (ms).

Returns

esp_err_t An error code indicating the success or failure of the operation.

esp_err_t dali_103_query_instance_type(dali_master_handle_t handle, dali_addr_type_t addr_type, uint8_t addr, uint8_t instance, uint8_t *type, int tx_timeout_ms)

Query the type of a Part 103 instance.

Parameters
  • handle – Handle from dali_new_master_rmt().

  • addr_type – DALI_ADDR_SHORT or DALI_ADDR_BROADCAST.

  • addr – Short address (0–63) for DALI_ADDR_SHORT.

  • instance – Instance number (0–31); encoded directly in byte 2.

  • type – Type of the instance.

  • tx_timeout_ms – Per-frame TX timeout (ms).

Returns

esp_err_t An error code indicating the success or failure of the operation.

esp_err_t dali_103_query_number_of_instances(dali_master_handle_t handle, dali_addr_type_t addr_type, uint8_t addr, uint8_t *num_instances, int tx_timeout_ms)

Query the number of instances on a Part 103 input device.

Parameters
  • handle – Handle from dali_new_master_rmt().

  • addr_type – DALI_ADDR_SHORT or DALI_ADDR_BROADCAST.

  • addr – Short address (0–63) for DALI_ADDR_SHORT.

  • num_instances – Number of instances.

  • tx_timeout_ms – Per-frame TX timeout (ms).

Returns

esp_err_t An error code indicating the success or failure of the operation.

DALI Part 209 — Color Control (DT8)

Header File

Functions

esp_err_t dali_enable_device_type(dali_master_handle_t handle, uint8_t device_type, int tx_timeout_ms)

Send ENABLE_DEVICE_TYPE to unlock the next application-extended command.

Must be called immediately before any Part 209 command. DTR pre-loads must be sent before this function so the timing window is not consumed.

Parameters
  • handle[in] Handle from dali_new_master_rmt().

  • device_type[in] Device-type number (8 for DT8).

  • tx_timeout_ms[in] TX timeout (ms).

Returns

esp_err_t An error code indicating the success or failure of the operation.

esp_err_t dali_master_set_color(dali_master_handle_t handle, dali_addr_type_t addr_type, uint8_t addr, dali_color_mode_t mode, dali_color_val_t val, int tx_timeout_ms)

Set the color of a DALI Part 209 color-control gear.

Executes the full DTR pre-load → SET_COLOR → ACTIVATE sequence.

Parameters
  • handle[in] Handle from dali_new_master_rmt().

  • addr_type[in] Address type for color/activate commands.

  • addr[in] Device address.

  • mode[in] Color mode.

  • val[in] Color value (mirek / r,g,b / r,g,b,w,a,f).

  • tx_timeout_ms[in] TX timeout per frame (ms).

Returns

esp_err_t An error code indicating the success or failure of the operation.

Unions

union dali_color_val_t
#include <dali_color_control_dt8.h>

Color value union for dali_master_set_color().

Public Members

uint16_t mirek

CCT in Mirek (153 ≈ 6500 K … 370 ≈ 2700 K)

struct dali_color_val_t::[anonymous] cct

CCT color mode

uint8_t r

Red channel (0–254, 0xFF = no change)

uint8_t g

Green channel (0–254, 0xFF = no change)

uint8_t b

Blue channel (0–254, 0xFF = no change)

struct dali_color_val_t::[anonymous] rgb

RGB color mode

uint8_t w

White channel (0–254, 0xFF = no change)

uint8_t a

Amber channel (0–254, 0xFF = no change)

uint8_t f

Free channel (0–254, 0xFF = no change)

struct dali_color_val_t::[anonymous] rgbwaf

RGBWAF 6-channel color (IEC 62386-209)

Enumerations

enum dali_color_mode_t

Color mode selector passed to dali_master_set_color().

Values:

enumerator DALI_COLOR_CCT

Correlated color temperature (Mirek)

enumerator DALI_COLOR_RGB

RGB dimlevels (r, g, b each 0–254)

enumerator DALI_COLOR_RGBWAF

Full 6-channel RGBWAF (0xFF = no change per IEC 62386-209 §8.6.19-20)

DALI Part 303 (Occupancy Sensor) & Part 304 (Light Sensor)

Header File

Functions

esp_err_t dali_303_query_occupancy(dali_master_handle_t handle, dali_addr_type_t addr_type, uint8_t addr, uint8_t instance, bool *occupied, int tx_timeout_ms)

Query the occupancy state of a Part 303 input device.

Parameters
  • handle[in] Handle from dali_new_master_rmt().

  • addr_type[in] Address type.

  • addr[in] Device short address.

  • instance[in] Occupancy instance number (typically 0).

  • occupied[out] true if occupied, false if unoccupied/no reply.

  • tx_timeout_ms[in] TX timeout (ms).

Returns

esp_err_t An error code indicating the success or failure of the operation.

esp_err_t dali_303_query_hold_timer(dali_master_handle_t handle, dali_addr_type_t addr_type, uint8_t addr, uint8_t instance, uint8_t *hold_timer, int tx_timeout_ms)

Query the hold timer on a Part 303 occupancy sensor instance.

Parameters
  • handle[in] Handle from dali_new_master_rmt().

  • addr_type[in] Address type.

  • addr[in] Device short address.

  • instance[in] Occupancy instance number (typically 0).

  • hold_timer[out] Hold timer value.

  • tx_timeout_ms[in] TX timeout (ms).

Returns

esp_err_t An error code indicating the success or failure of the operation.

esp_err_t dali_303_query_deadtime_timer(dali_master_handle_t handle, dali_addr_type_t addr_type, uint8_t addr, uint8_t instance, uint8_t *deadtime_timer, int tx_timeout_ms)

Query the deadtime timer on a Part 303 occupancy sensor instance.

Parameters
  • handle[in] Handle from dali_new_master_rmt().

  • addr_type[in] Address type.

  • addr[in] Device short address.

  • instance[in] Occupancy instance number (typically 0).

  • deadtime_timer[out] Deadtime timer value.

  • tx_timeout_ms[in] TX timeout (ms).

Returns

esp_err_t An error code indicating the success or failure of the operation.

esp_err_t dali_303_set_hold_timer(dali_master_handle_t handle, dali_addr_type_t addr_type, uint8_t addr, uint8_t instance, uint8_t hold_time_s, int tx_timeout_ms)

Set the hold timer on a Part 303 occupancy sensor instance.

Loads hold_time_s into Part 103 DTR0 via a special command, then issues DALI_303_SET_HOLD_TIMER (send-twice) to the addressed instance.

Parameters
  • handle[in] Handle from dali_new_master_rmt().

  • addr_type[in] Address type.

  • addr[in] Device short address.

  • instance[in] Occupancy instance number (typically 0).

  • hold_time_s[in] Raw DTR0 value (see IEC 62386-303 for encoding).

  • tx_timeout_ms[in] TX timeout (ms).

Returns

esp_err_t An error code indicating the success or failure of the operation.

esp_err_t dali_304_query_hysteresis(dali_master_handle_t handle, dali_addr_type_t addr_type, uint8_t addr, uint8_t instance, uint8_t *hysteresis, int tx_timeout_ms)

Query the hysteresis setting of a Part 304 light sensor instance.

Parameters
  • handle[in] Handle from dali_new_master_rmt().

  • addr_type[in] Address type.

  • addr[in] Device short address.

  • instance[in] Light sensor instance number (typically 0).

  • hysteresis[out] Hysteresis value.

  • tx_timeout_ms[in] TX timeout (ms).

Returns

esp_err_t An error code indicating the success or failure of the operation.

esp_err_t dali_304_query_report_timer(dali_master_handle_t handle, dali_addr_type_t addr_type, uint8_t addr, uint8_t instance, uint8_t *report_timer, int tx_timeout_ms)

Query the report timer of a Part 304 light sensor instance.

Parameters
  • handle[in] Handle from dali_new_master_rmt().

  • addr_type[in] Address type.

  • addr[in] Device short address.

  • instance[in] Light sensor instance number (typically 0).

  • report_timer[out] Report timer value.

  • tx_timeout_ms[in] TX timeout (ms).

Returns

esp_err_t An error code indicating the success or failure of the operation.

esp_err_t dali_304_query_deadtime_timer(dali_master_handle_t handle, dali_addr_type_t addr_type, uint8_t addr, uint8_t instance, uint8_t *deadtime_timer, int tx_timeout_ms)

Query the deadtime timer of a Part 304 light sensor instance.

Parameters
  • handle[in] Handle from dali_new_master_rmt().

  • addr_type[in] Address type.

  • addr[in] Device short address.

  • instance[in] Light sensor instance number (typically 0).

  • deadtime_timer[out] Deadtime timer value.

  • tx_timeout_ms[in] TX timeout (ms).

Returns

esp_err_t An error code indicating the success or failure of the operation.

Macros

DALI_304_RAW_TO_LUX_FP(raw)

Convert a raw Part 304 sensor value to approximate Lux (float).

IEC 62386-304 logarithmic encoding: lux = 10^((raw - 1) / 40). Returns 0.0f for raw == 0 (“no value available”).