#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; /* [0] bit 0 => addr 0, [0] bit 1 => addr 1, etc. */ static uint8_t dali_map[8]; 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); } 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) { 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 { dali_search_single(); 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) { uint8_t addr = 0xff; if ((dali_rx & 0x81) == 0x01) { addr = dali_rx >> 1; uart_puts(" current: "); uart_puthex(addr); } if (addr == 0x00 || (dali_map[addr >> 3] & (1 << (addr & 0x07)))) { 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) dali_map[addr >> 3] |= 1 << (addr & 0x7); } else uart_puts(" error\n"); wdt_reset(); dali_send(DALI_C_WITHDRAW); } } 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); }