#define DALI_C_QBALLAST 0x0191 #define DALI_C_TERMINATE 0xa100 #define DALI_C_DTR 0xa300 #define DALI_C_INITIALISE 0xa500 #define DALI_C_RANDOMISE 0xa700 #define DALI_C_COMPARE 0xa900 #define DALI_C_WITHDRAW 0xab00 #define DALI_C_SADDR_H 0xb100 #define DALI_C_SADDR_M 0xb300 #define DALI_C_SADDR_L 0xb500 #define DALI_C_PROGSHORT 0xb701 #define DALI_C_VRFYSHORT 0xb901 #define DALI_C_QURYSHORT 0xbb00 static uint8_t dali_s_byte, dali_sh, dali_sm, dali_sl; static bool dali_s_notfound; EEMEM uint8_t dali_nextaddr = 0x02; static uint8_t dali_assign; static bool dali_compare(void) { uint16_t manchester = dalistat.manchester, falsestart = dalistat.falsestart, noise = dalistat.noise; dali_send(DALI_C_COMPARE); asm volatile ("" ::: "memory"); return dali_rx_avail || (manchester != dalistat.manchester) || (falsestart != dalistat.falsestart) || (noise != dalistat.noise); } static void dali_search_byte(uint16_t cmd) { dali_s_byte = 0xff; uint8_t bit = 0x80; while (bit) { wdt_reset(); dali_twice(cmd | (dali_s_byte & ~bit)); if (dali_compare()) { _delay_ms(1); if (dali_compare()) dali_s_byte &= ~bit; } bit >>= 1; } dali_twice(cmd | dali_s_byte); uart_puthex(dali_s_byte); } static void dali_search_single(void) { dali_twice(DALI_C_SADDR_H | 0xff); dali_twice(DALI_C_SADDR_M | 0xff); dali_twice(DALI_C_SADDR_L | 0xff); if (!dali_compare()) { dali_s_notfound = 1; return; } dali_search_byte(DALI_C_SADDR_H); if (dali_s_notfound) return; dali_sh = dali_s_byte; dali_search_byte(DALI_C_SADDR_M); if (dali_s_notfound) return; dali_sm = dali_s_byte; dali_search_byte(DALI_C_SADDR_L); if (dali_s_notfound) return; dali_sl = dali_s_byte; } static void dali_search(void) { uint8_t errtries = 0; dali_twice(DALI_C_INITIALISE); /* _some_ EVGs keep the long address in nonvolatile memory, * among them the OSRAM one we have lying around. however, * this doesn't seem to work with Tridonic EVGs. */ dali_twice(DALI_C_RANDOMISE); dali_assign = eeprom_read_byte(&dali_nextaddr); do { uint8_t ph = dali_sh, pm = dali_sm, pl = dali_sl; uart_puttick(); uart_puts("dali search... "); dali_search_single(); uart_puts("\n"); if (!dali_s_notfound) { wdt_reset(); uart_puttick(); uart_puts("dali scan found\t\t"); uart_puthex(dali_sh); uart_puthex(dali_sm); uart_puthex(dali_sl); dali_send(DALI_C_QURYSHORT); if (!dali_rx_avail) dali_send(DALI_C_QURYSHORT); wdt_reset(); if (dali_rx_avail) { uint8_t addr = 0xff; errtries = 0; if ((dali_rx & 0x81) == 0x01) { addr = dali_rx >> 1; uart_puts(" current: "); uart_puthex(addr); } if (addr == 0x00 || target_present(addr)) { uart_puts(" reprog"); addr = 0xff; } if (addr == 0xff) { dali_send(DALI_C_PROGSHORT | (dali_assign << 1)); dali_send(DALI_C_VRFYSHORT | (dali_assign << 1)); if (dali_rx_avail) { uart_puts("prog "); uart_puthex(dali_assign); } else uart_puts("progfail"); addr = dali_assign; dali_assign++; } uart_puts("\n"); if (addr < 64) target_set_present(addr); wdt_reset(); dali_send(DALI_C_WITHDRAW); } else { uart_puts(" error\n"); if (errtries < 3) { dali_sh = ph; dali_sm = pm; dali_sl = pl; errtries++; } else errtries = 0; } } } while (!dali_s_notfound); wdt_reset(); dali_twice(DALI_C_TERMINATE); uart_puttick(); uart_puts("dali scan end\n"); eeprom_write_byte(&dali_nextaddr, dali_assign); }