blob: 5db3c090dfea2fb00d884152364a50450a76ce4f (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
#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);
}
|