Commit ae5cef79cc8d9f42bef16f29a47d59027cf7f244
Committed by
GitHub
1 parent
81a81f13
.
Showing
5 changed files
with
1867 additions
and
0 deletions
examples/Commissioning/Commissioning.ino
0 → 100644
| 1 | +/*########################################################################### | |
| 2 | + copyright qqqlab.com / github.com/qqqlab | |
| 3 | + | |
| 4 | + This program is free software: you can redistribute it and/or modify | |
| 5 | + it under the terms of the GNU General Public License as published by | |
| 6 | + the Free Software Foundation, either version 3 of the License, or | |
| 7 | + (at your option) any later version. | |
| 8 | + | |
| 9 | + This program is distributed in the hope that it will be useful, | |
| 10 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | + GNU General Public License for more details. | |
| 13 | + | |
| 14 | + You should have received a copy of the GNU General Public License | |
| 15 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 16 | +###########################################################################*/ | |
| 17 | +#include "qqqDALI.h" | |
| 18 | + | |
| 19 | +Dali dali; | |
| 20 | + | |
| 21 | +//ATMEGA328 specific | |
| 22 | +#define TX_PIN 3 | |
| 23 | +#define RX_PIN 4 | |
| 24 | + | |
| 25 | +//is bus asserted | |
| 26 | +uint8_t bus_is_high() { | |
| 27 | + return digitalRead(RX_PIN); //slow version | |
| 28 | + //return PIND & (1 << 4); //fast version | |
| 29 | +} | |
| 30 | + | |
| 31 | +//assert bus | |
| 32 | +void bus_set_low() { | |
| 33 | + digitalWrite(TX_PIN,HIGH); //opto slow version | |
| 34 | + //PORTD |= (1 << 3); //opto fast version | |
| 35 | + | |
| 36 | + //digitalWrite(TX_PIN,LOW); //diy slow version | |
| 37 | + //PORTD &= ~(1 << 3); //diy fast version | |
| 38 | +} | |
| 39 | + | |
| 40 | +//release bus | |
| 41 | +void bus_set_high() { | |
| 42 | + digitalWrite(TX_PIN,LOW); //opto slow version | |
| 43 | + //PORTD &= ~(1 << 3); //opto fast version | |
| 44 | + | |
| 45 | + //digitalWrite(TX_PIN,HIGH); //diy slow version | |
| 46 | + //PORTD |= (1 << 3); //diy fast version | |
| 47 | +} | |
| 48 | + | |
| 49 | +void bus_init() { | |
| 50 | + //setup rx pin | |
| 51 | + pinMode(4, INPUT); | |
| 52 | + | |
| 53 | + //setup tx pin | |
| 54 | + pinMode(3, OUTPUT); | |
| 55 | + | |
| 56 | + //setup tx timer interrupt | |
| 57 | + TCCR1A = 0; | |
| 58 | + TCCR1B = 0; | |
| 59 | + TCNT1 = 0; | |
| 60 | + OCR1A = (F_CPU + 8 * DALI_BAUD / 2) / (8 * DALI_BAUD); // compare match register at baud rate * 8 | |
| 61 | + TCCR1B |= (1 << WGM12); // CTC mode | |
| 62 | + TCCR1B |= (1 << CS10); // 1:1 prescaler | |
| 63 | + TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt | |
| 64 | +} | |
| 65 | + | |
| 66 | +ISR(TIMER1_COMPA_vect) { | |
| 67 | + dali.timer(); | |
| 68 | +} | |
| 69 | + | |
| 70 | +void setup() { | |
| 71 | + Serial.begin(115200); | |
| 72 | + Serial.println("DALI Commissioning Demo"); | |
| 73 | + | |
| 74 | + dali.begin(bus_is_high, bus_set_high, bus_set_low); | |
| 75 | + bus_init(); | |
| 76 | + | |
| 77 | + menu(); | |
| 78 | +} | |
| 79 | + | |
| 80 | +void loop() { | |
| 81 | + while (Serial.available() > 0) { | |
| 82 | + int incomingByte = Serial.read(); | |
| 83 | + switch(incomingByte) { | |
| 84 | + case '1': menu_blink(); menu(); break; | |
| 85 | + case '2': menu_scan_short_addr(); menu(); break; | |
| 86 | + case '3': menu_commission(); menu(); break; | |
| 87 | + case '4': menu_commission_debug(); menu(); break; | |
| 88 | + case '5': menu_delete_short_addr(); menu(); break; | |
| 89 | + case '6': menu_read_memory(); menu(); break; | |
| 90 | + } | |
| 91 | + } | |
| 92 | +} | |
| 93 | + | |
| 94 | +void menu() { | |
| 95 | + Serial.println("----------------------------"); | |
| 96 | + Serial.println("1 Blink all lamps"); | |
| 97 | + Serial.println("2 Scan short addresses"); | |
| 98 | + Serial.println("3 Commission short addresses"); | |
| 99 | + Serial.println("4 Commission short addresses (VERBOSE)"); | |
| 100 | + Serial.println("5 Delete short addresses"); | |
| 101 | + Serial.println("6 Read memory bank"); | |
| 102 | + Serial.println("----------------------------"); | |
| 103 | +} | |
| 104 | + | |
| 105 | +void menu_blink() { | |
| 106 | + Serial.println("Running: Blinking all lamps"); | |
| 107 | + for(uint8_t i=0;i<5;i++) { | |
| 108 | + dali.set_level(254); | |
| 109 | + Serial.print("."); | |
| 110 | + delay(500); | |
| 111 | + dali.set_level(0); | |
| 112 | + Serial.print("."); | |
| 113 | + delay(500); | |
| 114 | + } | |
| 115 | + Serial.println(); | |
| 116 | +} | |
| 117 | + | |
| 118 | +void menu_scan_short_addr() { | |
| 119 | + Serial.println("Running: Scan all short addresses"); | |
| 120 | + uint8_t sa; | |
| 121 | + uint8_t cnt = 0; | |
| 122 | + for(sa = 0; sa<64; sa++) { | |
| 123 | + int16_t rv = dali.cmd(DALI_QUERY_STATUS,sa); | |
| 124 | + if(rv>=0) { | |
| 125 | + cnt++; | |
| 126 | + Serial.print("short address="); | |
| 127 | + Serial.print(sa); | |
| 128 | + Serial.print(" status=0x"); | |
| 129 | + Serial.print(rv,HEX); | |
| 130 | + Serial.print(" minLevel="); | |
| 131 | + Serial.print(dali.cmd(DALI_QUERY_MIN_LEVEL,sa)); | |
| 132 | + Serial.print(" flashing"); | |
| 133 | + for(uint8_t i=0;i<5;i++) { | |
| 134 | + dali.set_level(254,sa); | |
| 135 | + Serial.print("."); | |
| 136 | + delay(500); | |
| 137 | + dali.set_level(0,sa); | |
| 138 | + Serial.print("."); | |
| 139 | + delay(500); | |
| 140 | + } | |
| 141 | + Serial.println(); | |
| 142 | + }else if (-rv != DALI_RESULT_NO_REPLY) { | |
| 143 | + Serial.print("short address="); | |
| 144 | + Serial.print(sa); | |
| 145 | + Serial.print(" ERROR="); | |
| 146 | + Serial.println(-rv); | |
| 147 | + } | |
| 148 | + } | |
| 149 | + Serial.print("DONE, found ");Serial.print(cnt);Serial.println(" short addresses"); | |
| 150 | +} | |
| 151 | + | |
| 152 | +//might need a couple of calls to find everything... | |
| 153 | +void menu_commission(){ | |
| 154 | + Serial.println("Running: Commission"); | |
| 155 | + Serial.println("Might need a couple of runs to find all lamps ..."); | |
| 156 | + Serial.println("Be patient, this takes a while ..."); | |
| 157 | + uint8_t cnt = dali.commission(0xff); //init_arg=0b11111111 : all without short address | |
| 158 | + Serial.print("DONE, assigned ");Serial.print(cnt);Serial.println(" new short addresses"); | |
| 159 | +} | |
| 160 | + | |
| 161 | +//might need a couple of calls to find everything... | |
| 162 | +void menu_commission_debug(){ | |
| 163 | + Serial.println("Running: Commission (VERBOSE)"); | |
| 164 | + Serial.println("Might need a couple of runs to find all lamps ..."); | |
| 165 | + Serial.println("Be patient, this takes a while ..."); | |
| 166 | + uint8_t cnt = debug_commission(0xff); //init_arg=0b11111111 : all without short address | |
| 167 | + Serial.print("DONE, assigned ");Serial.print(cnt);Serial.println(" new short addresses"); | |
| 168 | +} | |
| 169 | + | |
| 170 | +void menu_delete_short_addr() { | |
| 171 | + Serial.println("Running: Delete all short addresses"); | |
| 172 | + //remove all short addresses | |
| 173 | + dali.cmd(DALI_DATA_TRANSFER_REGISTER0,0xFF); | |
| 174 | + dali.cmd(DALI_SET_SHORT_ADDRESS, 0xFF); | |
| 175 | + Serial.println("DONE delete"); | |
| 176 | +} | |
| 177 | + | |
| 178 | +//init_arg=11111111 : all without short address | |
| 179 | +//init_arg=00000000 : all | |
| 180 | +//init_arg=0AAAAAA1 : only for this shortadr | |
| 181 | +//returns number of new short addresses assigned | |
| 182 | +uint8_t debug_commission(uint8_t init_arg) { | |
| 183 | + uint8_t cnt = 0; | |
| 184 | + uint8_t arr[64]; | |
| 185 | + uint8_t sa; | |
| 186 | + for(sa=0; sa<64; sa++) arr[sa]=0; | |
| 187 | + | |
| 188 | + dali.cmd(DALI_INITIALISE,init_arg); | |
| 189 | + dali.cmd(DALI_RANDOMISE,0x00); | |
| 190 | + //need 100ms pause after RANDOMISE, scan takes care of this... | |
| 191 | + | |
| 192 | + //find used short addresses (run always, seems to work better than without...) | |
| 193 | + Serial.println("Find existing short adr"); | |
| 194 | + for(sa = 0; sa<64; sa++) { | |
| 195 | + int16_t rv = dali.cmd(DALI_QUERY_STATUS,sa); | |
| 196 | + if(rv>=0) { | |
| 197 | + if(init_arg!=0b00000000) arr[sa]=1; //remove address from list if not in "all" mode | |
| 198 | + Serial.print("sortadr="); | |
| 199 | + Serial.print(sa); | |
| 200 | + Serial.print(" status=0x"); | |
| 201 | + Serial.print(rv,HEX); | |
| 202 | + Serial.print(" minLevel="); | |
| 203 | + Serial.println(dali.cmd(DALI_QUERY_MIN_LEVEL,sa)); | |
| 204 | + } | |
| 205 | + } | |
| 206 | + | |
| 207 | +// dali.set_searchaddr(0x000000); | |
| 208 | +// dali.set_searchaddr(0xFFFFFF); | |
| 209 | +//while(1) { | |
| 210 | +// dali.compare(); | |
| 211 | +// delay(200); | |
| 212 | +//} | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + Serial.println("Find random adr"); | |
| 217 | + while(1) { | |
| 218 | + uint32_t adr = dali.find_addr(); | |
| 219 | + if(adr>0xffffff) break; | |
| 220 | + Serial.print("found="); | |
| 221 | + Serial.println(adr,HEX); | |
| 222 | + | |
| 223 | + //find available address | |
| 224 | + for(sa=0; sa<64; sa++) { | |
| 225 | + if(arr[sa]==0) break; | |
| 226 | + } | |
| 227 | + if(sa>=64) break; | |
| 228 | + arr[sa] = 1; | |
| 229 | + cnt++; | |
| 230 | + | |
| 231 | + Serial.print("program short adr="); | |
| 232 | + Serial.println(sa); | |
| 233 | + dali.program_short_address(sa); | |
| 234 | + Serial.print("read short adr="); | |
| 235 | + Serial.println(dali.query_short_address()); | |
| 236 | + | |
| 237 | + dali.cmd(DALI_WITHDRAW,0x00); | |
| 238 | + } | |
| 239 | + | |
| 240 | + dali.cmd(DALI_TERMINATE,0x00); | |
| 241 | + return cnt; | |
| 242 | +} | |
| 243 | + | |
| 244 | +void menu_read_memory() { | |
| 245 | +/* | |
| 246 | + uint8_t v = 123; | |
| 247 | + uint8_t adr = 0xff; | |
| 248 | + | |
| 249 | + while(1) { | |
| 250 | + int16_t rv = dali.cmd(DALI_DATA_TRANSFER_REGISTER0, v); //store value in DTR | |
| 251 | + Serial.print("rv="); | |
| 252 | + Serial.print(rv); | |
| 253 | + | |
| 254 | + int16_t dtr = dali.cmd(DALI_QUERY_CONTENT_DTR0, adr); //get DTR value | |
| 255 | + Serial.print(" dtr="); | |
| 256 | + Serial.println(dtr); | |
| 257 | + delay(13); | |
| 258 | + } | |
| 259 | +*/ | |
| 260 | + | |
| 261 | + Serial.println("Running: Scan all short addresses"); | |
| 262 | + uint8_t sa; | |
| 263 | + uint8_t cnt = 0; | |
| 264 | + for(sa = 0; sa<64; sa++) { | |
| 265 | + int16_t rv = dali.cmd(DALI_QUERY_STATUS,sa); | |
| 266 | + if(rv>=0) { | |
| 267 | + cnt++; | |
| 268 | + Serial.print("\nshort address "); | |
| 269 | + Serial.println(sa); | |
| 270 | + Serial.print("status=0x"); | |
| 271 | + Serial.println(rv,HEX); | |
| 272 | + Serial.print("minLevel="); | |
| 273 | + Serial.println(dali.cmd(DALI_QUERY_MIN_LEVEL,sa)); | |
| 274 | + | |
| 275 | + dali_read_memory_bank_verbose(0,sa); | |
| 276 | + | |
| 277 | + }else if (-rv != DALI_RESULT_NO_REPLY) { | |
| 278 | + Serial.print("short address="); | |
| 279 | + Serial.print(sa); | |
| 280 | + Serial.print(" ERROR="); | |
| 281 | + Serial.println(-rv); | |
| 282 | + } | |
| 283 | + } | |
| 284 | + Serial.print("DONE, found ");Serial.print(cnt);Serial.println(" short addresses"); | |
| 285 | +} | |
| 286 | + | |
| 287 | +uint8_t dali_read_memory_bank_verbose(uint8_t bank, uint8_t adr) { | |
| 288 | + uint16_t rv; | |
| 289 | + | |
| 290 | + if(dali.set_dtr0(0, adr)) return 1; | |
| 291 | + if(dali.set_dtr1(bank, adr)) return 2; | |
| 292 | + | |
| 293 | + //uint8_t data[255]; | |
| 294 | + uint16_t len = dali.cmd(DALI_READ_MEMORY_LOCATION, adr); | |
| 295 | + Serial.print("memlen="); | |
| 296 | + Serial.println(len); | |
| 297 | + for(uint8_t i=0;i<len;i++) { | |
| 298 | + int16_t mem = dali.cmd(DALI_READ_MEMORY_LOCATION, adr); | |
| 299 | + if(mem>=0) { | |
| 300 | + //data[i] = mem; | |
| 301 | + Serial.print(i,HEX); | |
| 302 | + Serial.print(":"); | |
| 303 | + Serial.print(mem); | |
| 304 | + Serial.print(" 0x"); | |
| 305 | + Serial.print(mem,HEX); | |
| 306 | + Serial.print(" "); | |
| 307 | + if(mem>=32 && mem <127) Serial.print((char)mem); | |
| 308 | + Serial.println(); | |
| 309 | + }else if(mem!=-DALI_RESULT_NO_REPLY) { | |
| 310 | + Serial.print(i,HEX); | |
| 311 | + Serial.print(":err="); | |
| 312 | + Serial.println(mem); | |
| 313 | + } | |
| 314 | + } | |
| 315 | + | |
| 316 | + uint16_t dtr0 = dali.cmd(DALI_QUERY_CONTENT_DTR0,adr); //get DTR value | |
| 317 | + if(dtr0 != 255) return 4; | |
| 318 | +} | |
| 0 | 319 | \ No newline at end of file | ... | ... |
examples/Dimmer/Dimmer.ino
0 → 100644
| 1 | +/*########################################################################### | |
| 2 | + copyright qqqlab.com / github.com/qqqlab | |
| 3 | + | |
| 4 | + This program is free software: you can redistribute it and/or modify | |
| 5 | + it under the terms of the GNU General Public License as published by | |
| 6 | + the Free Software Foundation, either version 3 of the License, or | |
| 7 | + (at your option) any later version. | |
| 8 | + | |
| 9 | + This program is distributed in the hope that it will be useful, | |
| 10 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | + GNU General Public License for more details. | |
| 13 | + | |
| 14 | + You should have received a copy of the GNU General Public License | |
| 15 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 16 | +###########################################################################*/ | |
| 17 | +#include "qqqDALI.h" | |
| 18 | + | |
| 19 | +Dali dali; | |
| 20 | + | |
| 21 | +//ATMEGA328 specific | |
| 22 | +#define TX_PIN 3 | |
| 23 | +#define RX_PIN 4 | |
| 24 | + | |
| 25 | +//is bus asserted | |
| 26 | +uint8_t bus_is_high() { | |
| 27 | + return digitalRead(RX_PIN); //slow version | |
| 28 | + //return PIND & (1 << 4); //fast version | |
| 29 | +} | |
| 30 | + | |
| 31 | +//assert bus | |
| 32 | +void bus_set_low() { | |
| 33 | + digitalWrite(TX_PIN,HIGH); //opto slow version | |
| 34 | + //PORTD |= (1 << 3); //opto fast version | |
| 35 | + | |
| 36 | + //digitalWrite(TX_PIN,LOW); //diy slow version | |
| 37 | + //PORTD &= ~(1 << 3); //diy fast version | |
| 38 | +} | |
| 39 | + | |
| 40 | +//release bus | |
| 41 | +void bus_set_high() { | |
| 42 | + digitalWrite(TX_PIN,LOW); //opto slow version | |
| 43 | + //PORTD &= ~(1 << 3); //opto fast version | |
| 44 | + | |
| 45 | + //digitalWrite(TX_PIN,HIGH); //diy slow version | |
| 46 | + //PORTD |= (1 << 3); //diy fast version | |
| 47 | +} | |
| 48 | + | |
| 49 | +void bus_init() { | |
| 50 | + //setup rx pin | |
| 51 | + pinMode(4, INPUT); | |
| 52 | + | |
| 53 | + //setup tx pin | |
| 54 | + pinMode(3, OUTPUT); | |
| 55 | + | |
| 56 | + //setup tx timer interrupt | |
| 57 | + TCCR1A = 0; | |
| 58 | + TCCR1B = 0; | |
| 59 | + TCNT1 = 0; | |
| 60 | + OCR1A = (F_CPU + 8 * DALI_BAUD / 2) / (8 * DALI_BAUD); // compare match register at baud rate * 8 | |
| 61 | + TCCR1B |= (1 << WGM12); // CTC mode | |
| 62 | + TCCR1B |= (1 << CS10); // 1:1 prescaler | |
| 63 | + TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt | |
| 64 | +} | |
| 65 | + | |
| 66 | +ISR(TIMER1_COMPA_vect) { | |
| 67 | + dali.timer(); | |
| 68 | +} | |
| 69 | + | |
| 70 | +void setup() { | |
| 71 | + Serial.begin(115200); | |
| 72 | + Serial.println("DALI Dimmer Demo"); | |
| 73 | + | |
| 74 | + dali.begin(bus_is_high, bus_set_high, bus_set_low); | |
| 75 | + bus_init(); | |
| 76 | +} | |
| 77 | + | |
| 78 | +#define MIN_LEVEL 100 //most LED Drivers do not get much lower than this | |
| 79 | +int16_t level = 254; //254 is max level, 1 is min level (if driver supports it), 0 is off | |
| 80 | +int8_t level_step = 4; | |
| 81 | + | |
| 82 | +void loop() { | |
| 83 | + Serial.print("set level: "); | |
| 84 | + Serial.println(level); | |
| 85 | + dali.set_level(level); | |
| 86 | + | |
| 87 | + level+=level_step; | |
| 88 | + if(level>=254) { | |
| 89 | + level = 254; | |
| 90 | + level_step = -level_step; | |
| 91 | + } | |
| 92 | + if(level<MIN_LEVEL) { | |
| 93 | + level = MIN_LEVEL; | |
| 94 | + level_step = -level_step; | |
| 95 | + } | |
| 96 | +} | |
| 0 | 97 | \ No newline at end of file | ... | ... |
examples/Monitor/Monitor.ino
0 → 100644
| 1 | +/*########################################################################### | |
| 2 | + copyright qqqlab.com / github.com/qqqlab | |
| 3 | + | |
| 4 | + This program is free software: you can redistribute it and/or modify | |
| 5 | + it under the terms of the GNU General Public License as published by | |
| 6 | + the Free Software Foundation, either version 3 of the License, or | |
| 7 | + (at your option) any later version. | |
| 8 | + | |
| 9 | + This program is distributed in the hope that it will be useful, | |
| 10 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | + GNU General Public License for more details. | |
| 13 | + | |
| 14 | + You should have received a copy of the GNU General Public License | |
| 15 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 16 | +###########################################################################*/ | |
| 17 | +#include "qqqDALI.h" | |
| 18 | + | |
| 19 | +Dali dali; | |
| 20 | + | |
| 21 | +//ATMEGA328 specific | |
| 22 | +#define TX_PIN 3 | |
| 23 | +#define RX_PIN 4 | |
| 24 | + | |
| 25 | +//is bus asserted | |
| 26 | +uint8_t bus_is_high() { | |
| 27 | + return digitalRead(RX_PIN); //slow version | |
| 28 | + //return PIND & (1 << 4); //fast version | |
| 29 | +} | |
| 30 | + | |
| 31 | +//assert bus | |
| 32 | +void bus_set_low() { | |
| 33 | + digitalWrite(TX_PIN,HIGH); //opto slow version | |
| 34 | + //PORTD |= (1 << 3); //opto fast version | |
| 35 | + | |
| 36 | + //digitalWrite(TX_PIN,LOW); //diy slow version | |
| 37 | + //PORTD &= ~(1 << 3); //diy fast version | |
| 38 | +} | |
| 39 | + | |
| 40 | +//release bus | |
| 41 | +void bus_set_high() { | |
| 42 | + digitalWrite(TX_PIN,LOW); //opto slow version | |
| 43 | + //PORTD &= ~(1 << 3); //opto fast version | |
| 44 | + | |
| 45 | + //digitalWrite(TX_PIN,HIGH); //diy slow version | |
| 46 | + //PORTD |= (1 << 3); //diy fast version | |
| 47 | +} | |
| 48 | + | |
| 49 | +void bus_init() { | |
| 50 | + //setup rx pin | |
| 51 | + pinMode(4, INPUT); | |
| 52 | + | |
| 53 | + //setup tx pin | |
| 54 | + pinMode(3, OUTPUT); | |
| 55 | + | |
| 56 | + //setup tx timer interrupt | |
| 57 | + TCCR1A = 0; | |
| 58 | + TCCR1B = 0; | |
| 59 | + TCNT1 = 0; | |
| 60 | + OCR1A = (F_CPU + 8 * DALI_BAUD / 2) / (8 * DALI_BAUD); // compare match register at baud rate * 8 | |
| 61 | + TCCR1B |= (1 << WGM12); // CTC mode | |
| 62 | + TCCR1B |= (1 << CS10); // 1:1 prescaler | |
| 63 | + TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt | |
| 64 | +} | |
| 65 | + | |
| 66 | +ISR(TIMER1_COMPA_vect) { | |
| 67 | + dali.timer(); | |
| 68 | +} | |
| 69 | + | |
| 70 | +void setup() { | |
| 71 | + Serial.begin(115200); | |
| 72 | + Serial.println("DALI Monitor Demo"); | |
| 73 | + | |
| 74 | + dali.begin(bus_is_high, bus_set_high, bus_set_low); | |
| 75 | + bus_init(); | |
| 76 | +} | |
| 77 | + | |
| 78 | +void loop() { | |
| 79 | + uint8_t data[4]; | |
| 80 | + uint8_t bitcnt = dali.rx(data); | |
| 81 | + if(bitcnt>=8) { | |
| 82 | + for(uint8_t i=0;i<=(bitcnt-1)>>3;i++) { | |
| 83 | + Serial.print(data[i],HEX); | |
| 84 | + Serial.print(' '); | |
| 85 | + } | |
| 86 | + Serial.println(); | |
| 87 | + } | |
| 88 | +} | |
| 0 | 89 | \ No newline at end of file | ... | ... |
qqqDALI.cpp
0 → 100644
| 1 | +/*########################################################################### | |
| 2 | + copyright qqqlab.com / github.com/qqqlab | |
| 3 | + | |
| 4 | + This program is free software: you can redistribute it and/or modify | |
| 5 | + it under the terms of the GNU General Public License as published by | |
| 6 | + the Free Software Foundation, either version 3 of the License, or | |
| 7 | + (at your option) any later version. | |
| 8 | + | |
| 9 | + This program is distributed in the hope that it will be useful, | |
| 10 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | + GNU General Public License for more details. | |
| 13 | + | |
| 14 | + You should have received a copy of the GNU General Public License | |
| 15 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 16 | + | |
| 17 | +---------------------------------------------------------------------------- | |
| 18 | +Changelog: | |
| 19 | +2020-11-14 Rewrite with sampling instead of pinchange | |
| 20 | +2020-11-10 Split off hardware specific code into separate class | |
| 21 | +2020-11-08 Created & tested on ATMega328 @ 8Mhz | |
| 22 | +###########################################################################*/ | |
| 23 | + | |
| 24 | +//#define DALI_DEBUG | |
| 25 | + | |
| 26 | +//================================================================= | |
| 27 | +// LOW LEVEL DRIVER | |
| 28 | +//================================================================= | |
| 29 | +#include "qqqDALI.h" | |
| 30 | + | |
| 31 | +#ifdef DALI_DEBUG | |
| 32 | +#include "arduino.h" | |
| 33 | +#endif | |
| 34 | + | |
| 35 | +//timing | |
| 36 | +#define BEFORE_CMD_IDLE_MS 13 //require 13ms idle time before sending a cmd() | |
| 37 | + | |
| 38 | +//busstate | |
| 39 | +#define IDLE 0 | |
| 40 | +#define RX 1 | |
| 41 | +#define COLLISION_RX 2 | |
| 42 | +#define TX 3 | |
| 43 | +#define COLLISION_TX 4 | |
| 44 | + | |
| 45 | +void Dali::begin(uint8_t (*bus_is_high)(), void (*bus_set_low)(), void (*bus_set_high)()) | |
| 46 | +{ | |
| 47 | + this->bus_is_high = bus_is_high; | |
| 48 | + this->bus_set_low = bus_set_low; | |
| 49 | + this->bus_set_high = bus_set_high; | |
| 50 | + _init(); | |
| 51 | +} | |
| 52 | + | |
| 53 | +void Dali::_set_busstate_idle() { | |
| 54 | + bus_set_high(); | |
| 55 | + idlecnt = 0; | |
| 56 | + busstate = IDLE; | |
| 57 | +} | |
| 58 | + | |
| 59 | +void Dali::_init() { | |
| 60 | + _set_busstate_idle(); | |
| 61 | + rxstate = EMPTY; | |
| 62 | + txcollision = 0; | |
| 63 | +} | |
| 64 | + | |
| 65 | +uint16_t Dali::milli() { | |
| 66 | + while(ticks==0xFF); //wait for _millis update to finish | |
| 67 | + return _milli; | |
| 68 | +} | |
| 69 | + | |
| 70 | +// timer interrupt service routine, called 9600 times per second | |
| 71 | +void Dali::timer() { | |
| 72 | + //get bus sample | |
| 73 | + uint8_t busishigh = (bus_is_high() ? 1 : 0); //bus_high is 1 on high (non-asserted), 0 on low (asserted) | |
| 74 | + | |
| 75 | + //millis update | |
| 76 | + ticks++; | |
| 77 | + if(ticks==10) { | |
| 78 | + ticks = 0xff; //signal _millis is updating | |
| 79 | + _milli++; | |
| 80 | + ticks = 0; | |
| 81 | + } | |
| 82 | + | |
| 83 | + switch(busstate) { | |
| 84 | + case IDLE: | |
| 85 | + if(busishigh) { | |
| 86 | + if(idlecnt != 0xff) idlecnt++; | |
| 87 | + break; | |
| 88 | + } | |
| 89 | + //set busstate = RX | |
| 90 | + rxpos = 0; | |
| 91 | + rxbitcnt = 0; | |
| 92 | + rxidle = 0; | |
| 93 | + rxstate = RECEIVING; | |
| 94 | + busstate = RX; | |
| 95 | + //fall-thru to RX | |
| 96 | + case RX: | |
| 97 | + //store sample | |
| 98 | + rxbyte = (rxbyte << 1) | busishigh; | |
| 99 | + rxbitcnt++; | |
| 100 | + if(rxbitcnt == 8) { | |
| 101 | + rxdata[rxpos] = rxbyte; | |
| 102 | + rxpos++; | |
| 103 | + if(rxpos > DALI_RX_BUF_SIZE - 1) rxpos = DALI_RX_BUF_SIZE - 1; | |
| 104 | + rxbitcnt = 0; | |
| 105 | + } | |
| 106 | + //check for reception of 2 stop bits | |
| 107 | + if(busishigh) { | |
| 108 | + rxidle++; | |
| 109 | + if(rxidle >= 16) { | |
| 110 | + rxdata[rxpos] = 0xFF; | |
| 111 | + rxpos++; | |
| 112 | + rxstate = COMPLETED; | |
| 113 | + _set_busstate_idle(); | |
| 114 | + break; | |
| 115 | + } | |
| 116 | + }else{ | |
| 117 | + rxidle = 0; | |
| 118 | + } | |
| 119 | + break; | |
| 120 | + case TX: | |
| 121 | + if(txhbcnt >= txhblen) { | |
| 122 | + //all bits transmitted, go back to IDLE | |
| 123 | + _set_busstate_idle(); | |
| 124 | + }else{ | |
| 125 | + //check for collisions (transmitting high but bus is low) | |
| 126 | + if( ( | |
| 127 | + txcollisionhandling == DALI_TX_COLLISSION_ON //handle all | |
| 128 | + || (txcollisionhandling == DALI_TX_COLLISSION_AUTO && txhblen != 2+8+4) //handle only if not transmitting 8 bits (2+8+4 half bits) | |
| 129 | + ) && (txhigh && !busishigh) //transmitting high, but bus is low | |
| 130 | + && (txspcnt==1 || txspcnt==2) ) // in middle of transmitting low period | |
| 131 | + { | |
| 132 | + if(txcollision != 0xFF) txcollision++; | |
| 133 | + txspcnt = 0; | |
| 134 | + busstate = COLLISION_TX; | |
| 135 | + return; | |
| 136 | + } | |
| 137 | + | |
| 138 | + //send data bits (MSB first) to bus every 4th sample time | |
| 139 | + if(txspcnt == 0) { | |
| 140 | + //send bit | |
| 141 | + uint8_t pos = txhbcnt >> 3; | |
| 142 | + uint8_t bitmask = 1 << (7 - (txhbcnt & 0x7)); | |
| 143 | + if( txhbdata[pos] & bitmask ) { | |
| 144 | + bus_set_low(); | |
| 145 | + txhigh = 0; | |
| 146 | + }else{ | |
| 147 | + bus_set_high(); | |
| 148 | + txhigh = 1; | |
| 149 | + } | |
| 150 | + //update half bit counter | |
| 151 | + txhbcnt++; | |
| 152 | + //next transmit in 4 sample times | |
| 153 | + txspcnt = 4; | |
| 154 | + } | |
| 155 | + txspcnt--; | |
| 156 | + } | |
| 157 | + break; | |
| 158 | + case COLLISION_TX: | |
| 159 | + //keep bus low for 16 samples = 4 TE | |
| 160 | + bus_set_low(); | |
| 161 | + txspcnt++; | |
| 162 | + if(txspcnt >= 16) _set_busstate_idle(); | |
| 163 | + break; | |
| 164 | + } | |
| 165 | +} | |
| 166 | + | |
| 167 | +//push 2 half bits into the half bit transmit buffer, MSB first, 0x0=stop, 0x1= bit value 0, 0x2= bit value 1/start | |
| 168 | +void Dali::_tx_push_2hb(uint8_t hb) { | |
| 169 | + uint8_t pos = txhblen>>3; | |
| 170 | + uint8_t shift = 6 - (txhblen & 0x7); | |
| 171 | + txhbdata[pos] |= hb << shift; | |
| 172 | + txhblen += 2; | |
| 173 | +} | |
| 174 | + | |
| 175 | +//non-blocking transmit | |
| 176 | +//transmit if bus is IDLE, without checking hold off times, sends start+stop bits | |
| 177 | +uint8_t Dali::tx(uint8_t *data, uint8_t bitlen) { | |
| 178 | + if(bitlen > 32) return DALI_RESULT_FRAME_TOO_LONG; | |
| 179 | + if(busstate != IDLE) return DALI_RESULT_BUS_NOT_IDLE; | |
| 180 | + | |
| 181 | + //clear data | |
| 182 | + for(uint8_t i=0; i<9; i++) txhbdata[i]=0; | |
| 183 | + | |
| 184 | + //push data in transmit buffer | |
| 185 | + txhblen = 0; | |
| 186 | + _tx_push_2hb(0x2); //start bit | |
| 187 | + //data bits MSB first | |
| 188 | + for(uint8_t i=0; i<bitlen; i++) { | |
| 189 | + uint8_t pos = i>>3; | |
| 190 | + uint8_t mask = 1 << (7 - (i & 0x7)); | |
| 191 | + _tx_push_2hb( data[pos] & mask ? 0x2 : 0x1 ); | |
| 192 | + } | |
| 193 | + _tx_push_2hb(0x0); //stop bit | |
| 194 | + _tx_push_2hb(0x0); //stop bit | |
| 195 | + | |
| 196 | + //setup tx vars | |
| 197 | + txhbcnt = 0; | |
| 198 | + txspcnt = 0; | |
| 199 | + txcollision = 0; | |
| 200 | + rxstate = EMPTY; | |
| 201 | + busstate = TX; | |
| 202 | + return DALI_OK; | |
| 203 | +} | |
| 204 | + | |
| 205 | +uint8_t Dali::tx_state() { | |
| 206 | + if(txcollision) { | |
| 207 | + txcollision = 0; | |
| 208 | + return DALI_RESULT_COLLISION; | |
| 209 | + } | |
| 210 | + if(busstate == TX) return DALI_RESULT_TRANSMITTING; | |
| 211 | + return DALI_OK; | |
| 212 | +} | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | +//------------------------------------------------------------------- | |
| 218 | +//manchester decode | |
| 219 | +/* | |
| 220 | + | |
| 221 | +Prefectly matched transmitter and sampling: 8 samples per bit | |
| 222 | +---------+ +---+ +-------+ +-------+ +------------------------ | |
| 223 | + | | | | | | | | | |
| 224 | + +---+ +---+ +-------+ +---+ | |
| 225 | +sample-> 012345670123456701234567012345670123456701234567012345670 | |
| 226 | +sync-> ^ ^ ^ ^ ^ ^ ^ ^ | |
| 227 | +decode-> start 1 1 0 1 0 stop stop | |
| 228 | + | |
| 229 | + | |
| 230 | +slow transmitter: 9 samples per bit | |
| 231 | +---------+ +----+ +--------+ +--------+ +------------------------ | |
| 232 | + | | | | | | | | | |
| 233 | + +---+ +----+ +--------+ +---+ | |
| 234 | +sample-> 0123456780123456780123456780123456780123456780123456780123456780 | |
| 235 | +sync-> ^ ^ ^ ^ ^ ^ ^ ^ | |
| 236 | +decode-> start 1 1 0 1 0 stop stop | |
| 237 | + | |
| 238 | +*/ | |
| 239 | + | |
| 240 | +//compute weight for a 8 bit sample i | |
| 241 | +uint8_t Dali::_man_weight(uint8_t i) { | |
| 242 | + int8_t w = 0; | |
| 243 | + w += ((i>>7) & 1) ? 1 : -1; | |
| 244 | + w += ((i>>6) & 1) ? 2 : -2; //put more weight in middle | |
| 245 | + w += ((i>>5) & 1) ? 2 : -2; //put more weight in middle | |
| 246 | + w += ((i>>4) & 1) ? 1 : -1; | |
| 247 | + w -= ((i>>3) & 1) ? 1 : -1; | |
| 248 | + w -= ((i>>2) & 1) ? 2 : -2; //put more weight in middle | |
| 249 | + w -= ((i>>1) & 1) ? 2 : -2; //put more weight in middle | |
| 250 | + w -= ((i>>0) & 1) ? 1 : -1; | |
| 251 | + //w at this point: | |
| 252 | + //w = -12 perfect manchester encoded value 1 | |
| 253 | + //... | |
| 254 | + //w = -2 very weak value 1 | |
| 255 | + //w = 0 unknown (all samples high or low) | |
| 256 | + //... | |
| 257 | + //w = 12 perfect manchester encoded value 0 | |
| 258 | + | |
| 259 | + w *= 2; | |
| 260 | + if(w<0) w = -w + 1; | |
| 261 | + return w; | |
| 262 | +} | |
| 263 | + | |
| 264 | +//call with bitpos <= DALI_RX_BUF_SIZE*8-8; | |
| 265 | +uint8_t Dali::_man_sample(uint8_t *edata, uint16_t bitpos, uint8_t *stop_coll) { | |
| 266 | + uint8_t pos = bitpos>>3; | |
| 267 | + uint8_t shift = bitpos & 0x7; | |
| 268 | + uint8_t sample = (edata[pos] << shift) | (edata[pos+1] >> (8-shift)); | |
| 269 | + | |
| 270 | + //stop bit: received high (non-asserted) bus for last 8 samples | |
| 271 | + if(sample == 0xFF) *stop_coll = 1; | |
| 272 | + | |
| 273 | + //collision: received low (asserted) bus for last 8 samples | |
| 274 | + if(sample == 0x00) *stop_coll = 2; | |
| 275 | + | |
| 276 | + return sample; | |
| 277 | +} | |
| 278 | + | |
| 279 | + | |
| 280 | +//decode 8 times oversampled encoded data | |
| 281 | +//returns bitlen of decoded data, or 0 on collision | |
| 282 | +uint8_t Dali::_man_decode(uint8_t *edata, uint8_t ebitlen, uint8_t *ddata) { | |
| 283 | + uint8_t dbitlen = 0; | |
| 284 | + uint16_t ebitpos = 1; | |
| 285 | + while(ebitpos+1<ebitlen) { | |
| 286 | + uint8_t stop_coll = 0; | |
| 287 | + //weight at nominal oversample rate | |
| 288 | + uint8_t sample = _man_sample(edata, ebitpos, &stop_coll); | |
| 289 | + uint8_t weightmax = _man_weight(sample); //weight of maximum | |
| 290 | + uint8_t pmax = 8; //position of maximum | |
| 291 | + | |
| 292 | + //weight at nominal oversample rate - 1 | |
| 293 | + sample = _man_sample(edata, ebitpos - 1, &stop_coll); | |
| 294 | + uint8_t w = _man_weight(sample); | |
| 295 | + if( weightmax < w) { //when equal keep pmax=8, the nominal oversample baud rate | |
| 296 | + weightmax = w; | |
| 297 | + pmax = 7; | |
| 298 | + } | |
| 299 | + | |
| 300 | + //weight at nominal oversample rate + 1 | |
| 301 | + sample = _man_sample(edata, ebitpos + 1, &stop_coll); | |
| 302 | + w = _man_weight(sample); | |
| 303 | + if( weightmax < w ) { //when equal keep previous value | |
| 304 | + weightmax = w; | |
| 305 | + pmax = 9; | |
| 306 | + } | |
| 307 | + | |
| 308 | + //handle stop/collision | |
| 309 | + if(stop_coll==1) break; //stop | |
| 310 | + if(stop_coll==2) return 0; //collison | |
| 311 | + | |
| 312 | + //store mancheter bit | |
| 313 | + if(dbitlen > 0) { //ignore start bit | |
| 314 | + uint8_t bytepos = (dbitlen - 1) >> 3; | |
| 315 | + uint8_t bitpos = (dbitlen - 1) & 0x7; | |
| 316 | + if(bitpos == 0) ddata[bytepos] = 0; //empty data before storing first bit | |
| 317 | + ddata[bytepos] = (ddata[bytepos] << 1) | (weightmax & 1); //get databit from bit0 of weight | |
| 318 | + } | |
| 319 | + dbitlen++; | |
| 320 | + ebitpos += pmax; //jump to next mancheter bit, skipping over number of samples with max weight | |
| 321 | + } | |
| 322 | + if(dbitlen>1) dbitlen--; | |
| 323 | + return dbitlen; | |
| 324 | +} | |
| 325 | + | |
| 326 | +//non-blocking receive, | |
| 327 | +//returns 0 empty, 1 if busy receiving, 2 decode error, >2 number of bits received | |
| 328 | +uint8_t Dali::rx(uint8_t *ddata) { | |
| 329 | + switch(rxstate) { | |
| 330 | + case EMPTY: return 0; | |
| 331 | + case RECEIVING: return 1; | |
| 332 | + case COMPLETED: | |
| 333 | + rxstate = EMPTY; | |
| 334 | + uint8_t dlen = _man_decode(rxdata,rxpos*8,ddata); | |
| 335 | + | |
| 336 | + | |
| 337 | +#ifdef DALI_DEBUG | |
| 338 | + if(dlen!=8){ | |
| 339 | + //print received samples | |
| 340 | + Serial.print("RX: len="); | |
| 341 | + Serial.print(rxpos*8); | |
| 342 | + Serial.print(" "); | |
| 343 | + for(uint8_t i=0;i<rxpos;i++) { | |
| 344 | + for(uint8_t m=0x80;m!=0x00;m>>=1) { | |
| 345 | + if(rxdata[i]&m) Serial.print("1"); else Serial.print("0"); | |
| 346 | + } | |
| 347 | + Serial.print(" "); | |
| 348 | + } | |
| 349 | + | |
| 350 | + //print decoded data | |
| 351 | + Serial.print("decoded: len="); | |
| 352 | + Serial.print(dlen); | |
| 353 | + Serial.print(" "); | |
| 354 | + for(uint8_t i=0;i<dlen;i++) { | |
| 355 | + if( ddata[i>>3] & (1 << (7 - (i & 0x7))) ) Serial.print("1"); else Serial.print("0"); | |
| 356 | + } | |
| 357 | + Serial.println(); | |
| 358 | + } | |
| 359 | +#endif | |
| 360 | + | |
| 361 | + if(dlen<3) return 2; | |
| 362 | + return dlen; | |
| 363 | + } | |
| 364 | + return 0; //should not get here | |
| 365 | +} | |
| 366 | + | |
| 367 | + | |
| 368 | +//================================================================= | |
| 369 | +// HIGH LEVEL FUNCTIONS | |
| 370 | +//================================================================= | |
| 371 | + | |
| 372 | +//blocking send - wait until successful send or timeout | |
| 373 | +uint8_t Dali::tx_wait(uint8_t* data, uint8_t bitlen, uint16_t timeout_ms) { | |
| 374 | + if(bitlen>32) return DALI_RESULT_DATA_TOO_LONG; | |
| 375 | + uint16_t start_ms = milli(); | |
| 376 | + while(1) { | |
| 377 | + //wait for 10ms idle | |
| 378 | + while(idlecnt < BEFORE_CMD_IDLE_MS){ | |
| 379 | + //Serial.print('w'); | |
| 380 | + if(milli() - start_ms > timeout_ms) return DALI_RESULT_TIMEOUT; | |
| 381 | + } | |
| 382 | + //try transmit | |
| 383 | + while(tx(data,bitlen) != DALI_OK){ | |
| 384 | + //Serial.print('w'); | |
| 385 | + if(milli() - start_ms > timeout_ms) return DALI_RESULT_TIMEOUT; | |
| 386 | + } | |
| 387 | + //wait for completion | |
| 388 | + uint8_t rv; | |
| 389 | + while(1) { | |
| 390 | + rv = tx_state(); | |
| 391 | + if(rv != DALI_RESULT_TRANSMITTING) break; | |
| 392 | + if(milli() - start_ms > timeout_ms) return DALI_RESULT_TIMEOUT; | |
| 393 | + } | |
| 394 | + //exit if transmit was ok | |
| 395 | + if(rv == DALI_OK) return DALI_OK; | |
| 396 | + //not ok (for example collision) - retry until timeout | |
| 397 | + } | |
| 398 | + return DALI_RESULT_TIMEOUT; | |
| 399 | +} | |
| 400 | + | |
| 401 | +//blocking transmit 2 byte command, receive 1 byte reply (if a reply was sent) | |
| 402 | +//returns >=0 with reply byte | |
| 403 | +//returns <0 with negative result code | |
| 404 | +int16_t Dali::tx_wait_rx(uint8_t cmd0, uint8_t cmd1, uint16_t timeout_ms) { | |
| 405 | +#ifdef DALI_DEBUG | |
| 406 | + Serial.print("TX"); | |
| 407 | + Serial.print(cmd0>>4,HEX); | |
| 408 | + Serial.print(cmd0&0xF,HEX); | |
| 409 | + Serial.print(cmd1>>4,HEX); | |
| 410 | + Serial.print(cmd1&0xF,HEX); | |
| 411 | + Serial.print(" "); | |
| 412 | +#endif | |
| 413 | + uint8_t data[4]; | |
| 414 | + data[0] = cmd0; | |
| 415 | + data[1] = cmd1; | |
| 416 | + int16_t rv = tx_wait(data, 16, timeout_ms); | |
| 417 | + if(rv) return -rv;; | |
| 418 | + | |
| 419 | + //wait up to 10 ms for start of reply, additional 15ms for receive to complete | |
| 420 | + uint16_t rx_start_ms = milli(); | |
| 421 | + uint16_t rx_timeout_ms = 10; | |
| 422 | + while(1) { | |
| 423 | + rv = rx(data); | |
| 424 | + switch( rv ) { | |
| 425 | + case 0: break; //nothing received yet, wait | |
| 426 | + case 1: rx_timeout_ms = 25; break; //extend timeout, wait for RX completion | |
| 427 | + case 2: return -DALI_RESULT_COLLISION; //report collision | |
| 428 | + default: | |
| 429 | + if(rv==8) | |
| 430 | + return data[0]; | |
| 431 | + else | |
| 432 | + return -DALI_RESULT_INVALID_REPLY; | |
| 433 | + } | |
| 434 | + if(milli() - rx_start_ms > rx_timeout_ms) return -DALI_RESULT_NO_REPLY; | |
| 435 | + } | |
| 436 | + return -DALI_RESULT_NO_REPLY; //should not get here | |
| 437 | +} | |
| 438 | + | |
| 439 | + | |
| 440 | +//check YAAAAAA: 0000 0000 to 0011 1111 adr, 0100 0000 to 0100 1111 group, x111 1111 broadcast | |
| 441 | +uint8_t Dali::_check_yaaaaaa(uint8_t yaaaaaa) { | |
| 442 | + return (yaaaaaa<=0b01001111 || yaaaaaa==0b01111111 || yaaaaaa==0b11111111); | |
| 443 | +} | |
| 444 | + | |
| 445 | +void Dali::set_level(uint8_t level, uint8_t adr) { | |
| 446 | + if(_check_yaaaaaa(adr)) tx_wait_rx(adr<<1,level); | |
| 447 | +} | |
| 448 | + | |
| 449 | +int16_t Dali::cmd(uint16_t cmd, uint8_t arg) { | |
| 450 | + //Serial.print("dali_cmd[");Serial.print(cmd,HEX);Serial.print(",");Serial.print(arg,HEX);Serial.print(")"); | |
| 451 | + uint8_t cmd0,cmd1; | |
| 452 | + if(cmd & 0x0100) { | |
| 453 | + //special commands: MUST NOT have YAAAAAAX pattern for cmd | |
| 454 | + //Serial.print(" SPC"); | |
| 455 | + if(!_check_yaaaaaa(cmd>>1)) { | |
| 456 | + cmd0 = cmd; | |
| 457 | + cmd1 = arg; | |
| 458 | + }else{ | |
| 459 | + return DALI_RESULT_INVALID_CMD; | |
| 460 | + } | |
| 461 | + }else{ | |
| 462 | + //regular commands: MUST have YAAAAAA pattern for arg | |
| 463 | + | |
| 464 | + //Serial.print(" REG"); | |
| 465 | + if(_check_yaaaaaa(arg)) { | |
| 466 | + cmd0 = arg<<1|1; | |
| 467 | + cmd1 = cmd; | |
| 468 | + }else{ | |
| 469 | + return DALI_RESULT_INVALID_CMD; | |
| 470 | + } | |
| 471 | + } | |
| 472 | + if(cmd & 0x0200) { | |
| 473 | + //Serial.print(" REPEAT"); | |
| 474 | + tx_wait_rx(cmd0, cmd1); | |
| 475 | + } | |
| 476 | + int16_t rv = tx_wait_rx(cmd0, cmd1); | |
| 477 | + //Serial.print(" rv=");Serial.println(rv); | |
| 478 | + return rv; | |
| 479 | +} | |
| 480 | + | |
| 481 | + | |
| 482 | +uint8_t Dali::set_operating_mode(uint8_t v, uint8_t adr) { | |
| 483 | + return _set_value(DALI_SET_OPERATING_MODE, DALI_QUERY_OPERATING_MODE, v, adr); | |
| 484 | +} | |
| 485 | + | |
| 486 | +uint8_t Dali::set_max_level(uint8_t v, uint8_t adr) { | |
| 487 | + return _set_value(DALI_SET_MAX_LEVEL, DALI_QUERY_MAX_LEVEL, v, adr); | |
| 488 | +} | |
| 489 | + | |
| 490 | +uint8_t Dali::set_min_level(uint8_t v, uint8_t adr) { | |
| 491 | + return _set_value(DALI_SET_MIN_LEVEL, DALI_QUERY_MIN_LEVEL, v, adr); | |
| 492 | +} | |
| 493 | + | |
| 494 | + | |
| 495 | +uint8_t Dali::set_system_failure_level(uint8_t v, uint8_t adr) { | |
| 496 | + return _set_value(DALI_SET_SYSTEM_FAILURE_LEVEL, DALI_QUERY_SYSTEM_FAILURE_LEVEL, v, adr); | |
| 497 | +} | |
| 498 | + | |
| 499 | +uint8_t Dali::set_power_on_level(uint8_t v, uint8_t adr) { | |
| 500 | + return _set_value(DALI_SET_POWER_ON_LEVEL, DALI_QUERY_POWER_ON_LEVEL, v, adr); | |
| 501 | +} | |
| 502 | + | |
| 503 | +//set a parameter value, returns 0 on success | |
| 504 | +uint8_t Dali::_set_value(uint16_t setcmd, uint16_t getcmd, uint8_t v, uint8_t adr) { | |
| 505 | + int16_t current_v = cmd(getcmd,adr); //get current parameter value | |
| 506 | + if(current_v == v) return 0; | |
| 507 | + cmd(DALI_DATA_TRANSFER_REGISTER0,v); //store value in DTR | |
| 508 | + int16_t dtr = cmd(DALI_QUERY_CONTENT_DTR0,adr); //get DTR value | |
| 509 | + if(dtr != v) return 1; | |
| 510 | + cmd(setcmd,adr); //set parameter value = DTR | |
| 511 | + current_v = cmd(getcmd,adr); //get current parameter value | |
| 512 | + if(current_v != v) return 2; | |
| 513 | + return 0; | |
| 514 | +} | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | +//====================================================================== | |
| 520 | +// Commissioning short addresses | |
| 521 | +//====================================================================== | |
| 522 | + | |
| 523 | +//Sets the slave Note 1 to the INITIALISE status for15 minutes. | |
| 524 | +//Commands 259 to 270 are enabled only for a slave in this | |
| 525 | +//status. | |
| 526 | + | |
| 527 | +//set search address | |
| 528 | +void Dali::set_searchaddr(uint32_t adr) { | |
| 529 | + cmd(DALI_SEARCHADDRH,adr>>16); | |
| 530 | + cmd(DALI_SEARCHADDRM,adr>>8); | |
| 531 | + cmd(DALI_SEARCHADDRL,adr); | |
| 532 | +} | |
| 533 | + | |
| 534 | +//set search address, but set only changed bytes (takes less time) | |
| 535 | +void Dali::set_searchaddr_diff(uint32_t adr_new,uint32_t adr_current) { | |
| 536 | + if( (uint8_t)(adr_new>>16) != (uint8_t)(adr_current>>16) ) cmd(DALI_SEARCHADDRH,adr_new>>16); | |
| 537 | + if( (uint8_t)(adr_new>>8) != (uint8_t)(adr_current>>8) ) cmd(DALI_SEARCHADDRM,adr_new>>8); | |
| 538 | + if( (uint8_t)(adr_new) != (uint8_t)(adr_current) ) cmd(DALI_SEARCHADDRL,adr_new); | |
| 539 | +} | |
| 540 | + | |
| 541 | +//Is the random address smaller or equal to the search address? | |
| 542 | +//as more than one device can reply, the reply gets garbled | |
| 543 | +uint8_t Dali::compare() { | |
| 544 | + uint8_t retry = 2; | |
| 545 | + while(retry>0) { | |
| 546 | + //compare is true if we received any activity on the bus as reply. | |
| 547 | + //sometimes the reply is not registered... so only accept retry times 'no reply' as a real false compare | |
| 548 | + int16_t rv = cmd(DALI_COMPARE,0x00); | |
| 549 | + if(rv == -DALI_RESULT_COLLISION) return 1; | |
| 550 | + if(rv == -DALI_RESULT_INVALID_REPLY) return 1; | |
| 551 | + if(rv == 0xFF) return 1; | |
| 552 | + | |
| 553 | + retry--; | |
| 554 | + } | |
| 555 | + return 0; | |
| 556 | +} | |
| 557 | + | |
| 558 | +//The slave shall store the received 6-bit address (AAAAAA) as a short address if it is selected. | |
| 559 | +void Dali::program_short_address(uint8_t shortadr) { | |
| 560 | + cmd(DALI_PROGRAM_SHORT_ADDRESS, (shortadr << 1) | 0x01); | |
| 561 | +} | |
| 562 | + | |
| 563 | +//What is the short address of the slave being selected? | |
| 564 | +uint8_t Dali::query_short_address() { | |
| 565 | + return cmd(DALI_QUERY_SHORT_ADDRESS, 0x00) >> 1; | |
| 566 | +} | |
| 567 | + | |
| 568 | +//find addr with binary search | |
| 569 | +uint32_t Dali::find_addr() { | |
| 570 | + uint32_t adr = 0x800000; | |
| 571 | + uint32_t addsub = 0x400000; | |
| 572 | + uint32_t adr_last = adr; | |
| 573 | + set_searchaddr(adr); | |
| 574 | + | |
| 575 | + while(addsub) { | |
| 576 | + set_searchaddr_diff(adr,adr_last); | |
| 577 | + adr_last = adr; | |
| 578 | + //Serial.print("cmpadr="); | |
| 579 | + //Serial.print(adr,HEX); | |
| 580 | + uint8_t cmp = compare(); //returns 1 if searchadr > adr | |
| 581 | + //Serial.print("cmp "); | |
| 582 | + //Serial.print(adr,HEX); | |
| 583 | + //Serial.print(" = "); | |
| 584 | + //Serial.println(cmp); | |
| 585 | + if(cmp) adr-=addsub; else adr+=addsub; | |
| 586 | + addsub >>= 1; | |
| 587 | + } | |
| 588 | + set_searchaddr_diff(adr,adr_last); | |
| 589 | + adr_last = adr; | |
| 590 | + if(!compare()) { | |
| 591 | + adr++; | |
| 592 | + set_searchaddr_diff(adr,adr_last); | |
| 593 | + } | |
| 594 | + return adr; | |
| 595 | +} | |
| 596 | + | |
| 597 | +//init_arg=11111111 : all without short address | |
| 598 | +//init_arg=00000000 : all | |
| 599 | +//init_arg=0AAAAAA1 : only for this shortadr | |
| 600 | +//returns number of new short addresses assigned | |
| 601 | +uint8_t Dali::commission(uint8_t init_arg) { | |
| 602 | + uint8_t cnt = 0; | |
| 603 | + uint8_t arr[64]; | |
| 604 | + uint8_t sa; | |
| 605 | + for(sa=0; sa<64; sa++) arr[sa]=0; | |
| 606 | + | |
| 607 | + //start commissioning | |
| 608 | + cmd(DALI_INITIALISE,init_arg); | |
| 609 | + cmd(DALI_RANDOMISE,0x00); | |
| 610 | + //need 100ms pause after RANDOMISE, scan takes care of this... | |
| 611 | + | |
| 612 | + //find used short addresses (run always, seems to work better than without...) | |
| 613 | + for(sa = 0; sa<64; sa++) { | |
| 614 | + int16_t rv = cmd(DALI_QUERY_STATUS,sa); | |
| 615 | + if(rv>=0) { | |
| 616 | + if(init_arg!=0b00000000) arr[sa]=1; //remove address from list if not in "all" mode | |
| 617 | + } | |
| 618 | + } | |
| 619 | + | |
| 620 | + //find random addresses and assign unused short addresses | |
| 621 | + while(1) { | |
| 622 | + uint32_t adr = find_addr(); | |
| 623 | + if(adr>0xffffff) break; //no more random addresses found -> exit | |
| 624 | + | |
| 625 | + //find first unused short address | |
| 626 | + for(sa=0; sa<64; sa++) { | |
| 627 | + if(arr[sa]==0) break; | |
| 628 | + } | |
| 629 | + if(sa>=64) break; //all 64 short addresses assigned -> exit | |
| 630 | + | |
| 631 | + //mark short address as used | |
| 632 | + arr[sa] = 1; | |
| 633 | + cnt++; | |
| 634 | + | |
| 635 | + //assign short address | |
| 636 | + program_short_address(sa); | |
| 637 | + | |
| 638 | + //Serial.println(query_short_address()); //TODO check read adr, handle if not the same... | |
| 639 | + | |
| 640 | + //remove the device from the search | |
| 641 | + cmd(DALI_WITHDRAW,0x00); | |
| 642 | + } | |
| 643 | + | |
| 644 | + //terminate the DALI_INITIALISE command | |
| 645 | + cmd(DALI_TERMINATE,0x00); | |
| 646 | + return cnt; | |
| 647 | +} | |
| 648 | + | |
| 649 | +//====================================================================== | |
| 650 | +// Memory | |
| 651 | +//====================================================================== | |
| 652 | +uint8_t Dali::set_dtr0(uint8_t value, uint8_t adr) { | |
| 653 | + uint8_t retry=3; | |
| 654 | + while(retry) { | |
| 655 | + cmd(DALI_DATA_TRANSFER_REGISTER0,value); //store value in DTR | |
| 656 | + int16_t dtr = cmd(DALI_QUERY_CONTENT_DTR0,adr); //get DTR value | |
| 657 | + if(dtr == value) return 0; | |
| 658 | + retry--; | |
| 659 | + } | |
| 660 | + return 1; | |
| 661 | +} | |
| 662 | + | |
| 663 | +uint8_t Dali::set_dtr1(uint8_t value, uint8_t adr) { | |
| 664 | + uint8_t retry=3; | |
| 665 | + while(retry) { | |
| 666 | + cmd(DALI_DATA_TRANSFER_REGISTER1,value); //store value in DTR | |
| 667 | + int16_t dtr = cmd(DALI_QUERY_CONTENT_DTR1,adr); //get DTR value | |
| 668 | + if(dtr == value) return 0; | |
| 669 | + retry--; | |
| 670 | + } | |
| 671 | + return 1; | |
| 672 | +} | |
| 673 | + | |
| 674 | +uint8_t Dali::set_dtr2(uint8_t value, uint8_t adr) { | |
| 675 | + uint8_t retry=3; | |
| 676 | + while(retry) { | |
| 677 | + cmd(DALI_DATA_TRANSFER_REGISTER2,value); //store value in DTR | |
| 678 | + int16_t dtr = cmd(DALI_QUERY_CONTENT_DTR2,adr); //get DTR value | |
| 679 | + if(dtr == value) return 0; | |
| 680 | + retry--; | |
| 681 | + } | |
| 682 | + return 1; | |
| 683 | +} | |
| 684 | + | |
| 685 | +uint8_t Dali::read_memory_bank(uint8_t bank, uint8_t adr) { | |
| 686 | + uint16_t rv; | |
| 687 | + | |
| 688 | + if(set_dtr0(0, adr)) return 1; | |
| 689 | + if(set_dtr1(bank, adr)) return 2; | |
| 690 | + | |
| 691 | + //uint8_t data[255]; | |
| 692 | + uint16_t len = cmd(DALI_READ_MEMORY_LOCATION, adr); | |
| 693 | +#ifdef DALI_DEBUG | |
| 694 | + Serial.print("memlen="); | |
| 695 | + Serial.println(len); | |
| 696 | + for(uint8_t i=0;i<len;i++) { | |
| 697 | + int16_t mem = cmd(DALI_READ_MEMORY_LOCATION, adr); | |
| 698 | + if(mem>=0) { | |
| 699 | + //data[i] = mem; | |
| 700 | + Serial.print(i,HEX); | |
| 701 | + Serial.print(":"); | |
| 702 | + Serial.print(mem); | |
| 703 | + Serial.print(" 0x"); | |
| 704 | + Serial.print(mem,HEX); | |
| 705 | + Serial.print(" "); | |
| 706 | + if(mem>=32 && mem <127) Serial.print((char)mem); | |
| 707 | + Serial.println(); | |
| 708 | + }else if(mem!=-DALI_RESULT_NO_REPLY) { | |
| 709 | + Serial.print(i,HEX); | |
| 710 | + Serial.print(":err="); | |
| 711 | + Serial.println(mem); | |
| 712 | + } | |
| 713 | + //delay(10); | |
| 714 | + } | |
| 715 | +#endif | |
| 716 | + | |
| 717 | + uint16_t dtr0 = cmd(DALI_QUERY_CONTENT_DTR0,adr); //get DTR value | |
| 718 | + if(dtr0 != 255) return 4; | |
| 719 | +} | |
| 720 | + | |
| 721 | + | |
| 722 | +//====================================================================== | ... | ... |
qqqDALI.h
0 → 100644
| 1 | +/*########################################################################### | |
| 2 | + copyright qqqlab.com / github.com/qqqlab | |
| 3 | + | |
| 4 | + This program is free software: you can redistribute it and/or modify | |
| 5 | + it under the terms of the GNU General Public License as published by | |
| 6 | + the Free Software Foundation, either version 3 of the License, or | |
| 7 | + (at your option) any later version. | |
| 8 | + | |
| 9 | + This program is distributed in the hope that it will be useful, | |
| 10 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | + GNU General Public License for more details. | |
| 13 | + | |
| 14 | + You should have received a copy of the GNU General Public License | |
| 15 | + along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| 16 | + | |
| 17 | +---------------------------------------------------------------------------- | |
| 18 | +Changelog: | |
| 19 | +2020-11-14 Rewrite with sampling instead of pinchange | |
| 20 | +2020-11-10 Split off hardware specific code into separate class | |
| 21 | +2020-11-08 Created & tested on ATMega328 @ 8Mhz | |
| 22 | +###########################################################################*/ | |
| 23 | +#include <inttypes.h> | |
| 24 | + | |
| 25 | +//------------------------------------------------- | |
| 26 | +//LOW LEVEL DRIVER DEFINES | |
| 27 | +#define DALI_BAUD 1200 | |
| 28 | + | |
| 29 | +//low level | |
| 30 | +#define DALI_OK 0 | |
| 31 | +#define DALI_RESULT_BUS_NOT_IDLE 1 //can't transmit, bus is not idle | |
| 32 | +#define DALI_RESULT_FRAME_TOO_LONG 2 //can't transmit, attempting to send more than 32 bits | |
| 33 | +#define DALI_RESULT_COLLISION 3 //bus collision occured | |
| 34 | +#define DALI_RESULT_TRANSMITTING 4 //currently transmitting | |
| 35 | +#define DALI_RESULT_RECEIVING 5 //currently receiving | |
| 36 | + | |
| 37 | +//high level | |
| 38 | +#define DALI_RESULT_NO_REPLY 101 //cmd() did not receive a reply (i.e. received a 'NO' Backward Frame) | |
| 39 | +#define DALI_RESULT_TIMEOUT 102 //Timeout waiting for DALI bus | |
| 40 | +#define DALI_RESULT_DATA_TOO_LONG 103 //Trying to send too many bytes (max 3) | |
| 41 | +#define DALI_RESULT_INVALID_CMD 104 //The cmd argument in the call to cmd() was invalid | |
| 42 | +#define DALI_RESULT_INVALID_REPLY 105 //cmd() received an invalid reply (not 8 bits) | |
| 43 | + | |
| 44 | + | |
| 45 | +//tx collision handling | |
| 46 | +#define DALI_TX_COLLISSION_AUTO 0 //handle tx collisions for non 8 bit frames | |
| 47 | +#define DALI_TX_COLLISSION_OFF 1 //don't handle tx collisions | |
| 48 | +#define DALI_TX_COLLISSION_ON 2 //handle all tx collisions | |
| 49 | + | |
| 50 | +#define DALI_RX_BUF_SIZE 40 | |
| 51 | + | |
| 52 | +class Dali { | |
| 53 | +public: | |
| 54 | + //------------------------------------------------- | |
| 55 | + //LOW LEVEL DRIVER PUBLIC | |
| 56 | + void begin(uint8_t (*bus_is_high)(), void (*bus_set_low)(), void (*bus_set_high)()); | |
| 57 | + void timer(); //call this function every 104.167 us (1200 baud 8x oversampled) | |
| 58 | + uint8_t tx(uint8_t *data, uint8_t bitlen); //low level non-blocking transmit | |
| 59 | + uint8_t rx(uint8_t *data); //low level non-blocking receive | |
| 60 | + uint8_t tx_state(); //low level tx state, returns DALI_RESULT_COLLISION, DALI_RESULT_TRANSMITTING or DALI_OK | |
| 61 | + uint8_t txcollisionhandling; //collision handling DALI_TX_COLLISSION_AUTO,DALI_TX_COLLISSION_OFF,DALI_TX_COLLISSION_ON | |
| 62 | + uint16_t milli(); //millis() implementation, 1 milli is 1.04167 ms (10 timer ticks), rollover 65 seconds | |
| 63 | + Dali() : busstate(0), ticks(0), _milli(0), idlecnt(0), txcollisionhandling(DALI_TX_COLLISSION_AUTO) {}; //initialize variables | |
| 64 | + | |
| 65 | + //------------------------------------------------- | |
| 66 | + //HIGH LEVEL PUBLIC | |
| 67 | + void set_level(uint8_t level, uint8_t adr=0xFF); //set arc level | |
| 68 | + int16_t cmd(uint16_t cmd, uint8_t arg); //execute DALI command, use a DALI_xxx command define as cmd argument, returns negative DALI_RESULT_xxx or reply byte | |
| 69 | + uint8_t set_operating_mode(uint8_t v, uint8_t adr=0xFF); //returns 0 on success | |
| 70 | + uint8_t set_max_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success | |
| 71 | + uint8_t set_min_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success | |
| 72 | + uint8_t set_system_failure_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success | |
| 73 | + uint8_t set_power_on_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success | |
| 74 | + uint8_t tx_wait(uint8_t* data, uint8_t bitlen, uint16_t timeout_ms=500); //blocking transmit bytes | |
| 75 | + int16_t tx_wait_rx(uint8_t cmd0, uint8_t cmd1, uint16_t timeout_ms=500); //blocking transmit and receive | |
| 76 | + | |
| 77 | + uint8_t read_memory_bank(uint8_t bank, uint8_t adr); | |
| 78 | + uint8_t set_dtr0(uint8_t value, uint8_t adr); | |
| 79 | + uint8_t set_dtr1(uint8_t value, uint8_t adr); | |
| 80 | + uint8_t set_dtr2(uint8_t value, uint8_t adr); | |
| 81 | + | |
| 82 | + //commissioning | |
| 83 | + uint8_t commission(uint8_t init_arg=0xff); | |
| 84 | + void set_searchaddr(uint32_t adr); | |
| 85 | + void set_searchaddr_diff(uint32_t adr_new,uint32_t adr_current); | |
| 86 | + uint8_t compare(); | |
| 87 | + void program_short_address(uint8_t shortadr); | |
| 88 | + uint8_t query_short_address(); | |
| 89 | + uint32_t find_addr(); | |
| 90 | + | |
| 91 | +private: | |
| 92 | + //------------------------------------------------- | |
| 93 | + //LOW LEVEL DRIVER PRIVATE | |
| 94 | + | |
| 95 | + //BUS | |
| 96 | + volatile uint8_t busstate; //current bus state IDLE,TX,RX,COLLISION_RX,COLLISION_TX | |
| 97 | + volatile uint8_t ticks; //sample counter, wraps around. 1 tick is approx 0.1 ms, overflow 6.5 seconds | |
| 98 | + volatile uint16_t _milli; //millisecond counter, wraps around, overflow 256 ms | |
| 99 | + volatile uint8_t idlecnt; //number of idle samples (capped at 255) | |
| 100 | + | |
| 101 | + //RECEIVER | |
| 102 | + enum rx_stateEnum { EMPTY, RECEIVING, COMPLETED}; | |
| 103 | + volatile rx_stateEnum rxstate; //state of receiver | |
| 104 | + volatile uint8_t rxdata[DALI_RX_BUF_SIZE]; //received samples | |
| 105 | + volatile uint8_t rxpos; //pos in rxdata | |
| 106 | + volatile uint8_t rxbyte; //last 8 samples, MSB is oldest | |
| 107 | + volatile uint8_t rxbitcnt; //bitcnt in rxbyte | |
| 108 | + volatile uint8_t rxidle; //idle tick counter during RX | |
| 109 | + | |
| 110 | + | |
| 111 | + //TRANSMITTER | |
| 112 | + volatile uint8_t txhbdata[9]; //half bit data to transmit (max 32 bits = 2+64+4 half bits = 9 bytes) | |
| 113 | + volatile uint8_t txhblen; //number of half bits to transmit, incl start + stop bits | |
| 114 | + volatile uint8_t txhbcnt; //number of transmitted half bits, incl start + stop bits | |
| 115 | + volatile uint8_t txspcnt; //sample count since last transmitted bit | |
| 116 | + volatile uint8_t txhigh; //currently bus is high | |
| 117 | + volatile uint8_t txcollision; //collision count (capped at 255) | |
| 118 | + | |
| 119 | + //hardware abstraction layer | |
| 120 | + uint8_t (*bus_is_high)(); //returns !=0 if DALI bus is in high (non-asserted) state | |
| 121 | + void (*bus_set_low)(); //set DALI bus in low (asserted) state | |
| 122 | + void (*bus_set_high)(); //set DALI bus in high (released) state | |
| 123 | + | |
| 124 | + void _init(); | |
| 125 | + void _set_busstate_idle(); | |
| 126 | + void _tx_push_2hb(uint8_t hb); | |
| 127 | + | |
| 128 | + | |
| 129 | + uint8_t _man_weight(uint8_t i); | |
| 130 | + uint8_t _man_sample(uint8_t *edata, uint16_t bitpos, uint8_t *stop_coll); | |
| 131 | + uint8_t _man_decode(uint8_t *edata, uint8_t ebitlen, uint8_t *ddata); | |
| 132 | + | |
| 133 | + //------------------------------------------------- | |
| 134 | + //HIGH LEVEL PRIVATE | |
| 135 | + uint8_t _check_yaaaaaa(uint8_t yaaaaaa); //check for yaaaaaa pattern | |
| 136 | + uint8_t _set_value(uint16_t setcmd, uint16_t getcmd, uint8_t v, uint8_t adr); //set a parameter value, returns 0 on success | |
| 137 | + | |
| 138 | +}; | |
| 139 | + | |
| 140 | + | |
| 141 | +//------------------------------------------------- | |
| 142 | +//HIGH LEVEL DEFINES | |
| 143 | + | |
| 144 | +#define DALI_BAUD 1200 | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | +//bit8=extended commands, bit9=repeat | |
| 149 | +#define DALI_OFF 0 //0 - Turns off lighting. | |
| 150 | +#define DALI_UP 1 //1 - Increases the lighting control level for 200 ms according to the Fade rate. | |
| 151 | +#define DALI_DOWN 2 //2 - Decreases the lighting control level for 200 ms according to the Fade rate. | |
| 152 | +#define DALI_STEP_UP 3 //3 - Increments the lighting control level (without fade). | |
| 153 | +#define DALI_STEP_DOWN 4 //4 - Decrements the lighting control level (without fade). | |
| 154 | +#define DALI_RECALL_MAX_LEVEL 5 //5 - Maximizes the lighting control level (without fade). | |
| 155 | +#define DALI_RECALL_MIN_LEVEL 6 //6 - Minimizes the lighting control level (without fade) | |
| 156 | +#define DALI_STEP_DOWN_AND_OFF 7 //7 - Decrements the lighting control level and turns off lighting if the level is at the minimum (without fade). | |
| 157 | +#define DALI_ON_AND_STEP_UP 8 //8 - Increments the lighting control level and turns on lighting if lighting is off (with fade). | |
| 158 | +#define DALI_ENABLE_DAPC_SEQUENCE 9 //9 - It shows the repeat start of the DAPC command. | |
| 159 | +#define DALI_GO_TO_LAST_ACTIVE_LEVEL 10 //10 DALI-2 - Adjusts the lighting control level to the last light control level according to the Fade time. (Command that exist only in IEC62386-102ed2.0) | |
| 160 | +#define DALI_RESERVED11 11 //11 - [Reserved] | |
| 161 | +#define DALI_RESERVED12 12 //12 - [Reserved] | |
| 162 | +#define DALI_RESERVED13 13 //13 - [Reserved] | |
| 163 | +#define DALI_RESERVED14 14 //14 - [Reserved] | |
| 164 | +#define DALI_RESERVED16 16 //16 - [Reserved] | |
| 165 | +#define DALI_GO_TO_SCENE0 16 //16 - Adjusts the lighting control level for Scene XXXX according to the fade time. | |
| 166 | +#define DALI_GO_TO_SCENE1 17 //17 - Adjusts the lighting control level for Scene XXXX according to the fade time. | |
| 167 | +#define DALI_GO_TO_SCENE2 18 //18 - Adjusts the lighting control level for Scene XXXX according to the fade time. | |
| 168 | +#define DALI_GO_TO_SCENE3 19 //19 - Adjusts the lighting control level for Scene XXXX according to the fade time. | |
| 169 | +#define DALI_GO_TO_SCENE4 20 //20 - Adjusts the lighting control level for Scene XXXX according to the fade time. | |
| 170 | +#define DALI_GO_TO_SCENE5 21 //21 - Adjusts the lighting control level for Scene XXXX according to the fade time. | |
| 171 | +#define DALI_GO_TO_SCENE6 22 //22 - Adjusts the lighting control level for Scene XXXX according to the fade time. | |
| 172 | +#define DALI_GO_TO_SCENE7 23 //23 - Adjusts the lighting control level for Scene XXXX according to the fade time. | |
| 173 | +#define DALI_GO_TO_SCENE8 24 //24 - Adjusts the lighting control level for Scene XXXX according to the fade time. | |
| 174 | +#define DALI_GO_TO_SCENE9 25 //25 - Adjusts the lighting control level for Scene XXXX according to the fade time. | |
| 175 | +#define DALI_GO_TO_SCENE10 26 //26 - Adjusts the lighting control level for Scene XXXX according to the fade time. | |
| 176 | +#define DALI_GO_TO_SCENE11 27 //27 - Adjusts the lighting control level for Scene XXXX according to the fade time. | |
| 177 | +#define DALI_GO_TO_SCENE12 28 //28 - Adjusts the lighting control level for Scene XXXX according to the fade time. | |
| 178 | +#define DALI_GO_TO_SCENE13 29 //29 - Adjusts the lighting control level for Scene XXXX according to the fade time. | |
| 179 | +#define DALI_GO_TO_SCENE14 30 //30 - Adjusts the lighting control level for Scene XXXX according to the fade time. | |
| 180 | +#define DALI_GO_TO_SCENE15 31 //31 - Adjusts the lighting control level for Scene XXXX according to the fade time. | |
| 181 | +#define DALI_RESET 544 //32 REPEAT - Makes a slave an RESET state. | |
| 182 | +#define DALI_STORE_ACTUAL_LEVEL_IN_THE_DTR0 545 //33 REPEAT - Saves the current lighting control level to the DTR (DTR0). (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 183 | +#define DALI_SAVE_PERSISTENT_VARIABLES 546 //34 REPEAT DALI-2 - Saves a variable in nonvolatile memory (NVM). (Command that exist only in IEC62386-102ed2.0) | |
| 184 | +#define DALI_SET_OPERATING_MODE 547 //35 REPEAT DALI-2 - Sets data of DTR0 as an operating mode. (Command that exist only in IEC62386-102ed2.0) | |
| 185 | +#define DALI_RESET_MEMORY_BANK 548 //36 REPEAT DALI-2 - Changes to the reset value the specified memory bank in DTR0. (Command that exist only in IEC62386-102ed2.0) | |
| 186 | +#define DALI_IDENTIFY_DEVICE 549 //37 REPEAT DALI-2 - Starts the identification state of the device. (Command that exist only in IEC62386-102ed2.0) | |
| 187 | +#define DALI_RESERVED38 550 //38 REPEAT - [Reserved] | |
| 188 | +#define DALI_RESERVED39 551 //39 REPEAT - [Reserved] | |
| 189 | +#define DALI_RESERVED40 552 //40 REPEAT - [Reserved] | |
| 190 | +#define DALI_RESERVED41 553 //41 REPEAT - [Reserved] | |
| 191 | +#define DALI_SET_MAX_LEVEL 554 //42 REPEAT - Specifies the DTR data as the maximum lighting control level. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 192 | +#define DALI_SET_MIN_LEVEL 555 //43 REPEAT - Specifies the DTR data as the minimum lighting control level. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 193 | +#define DALI_SET_SYSTEM_FAILURE_LEVEL 556 //44 REPEAT - Specifies the DTR data as the "FAILURELEVEL". (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 194 | +#define DALI_SET_POWER_ON_LEVEL 557 //45 REPEAT - Specifies the DTR data as the "POWER ONLEVEL". (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 195 | +#define DALI_SET_FADE_TIME 558 //46 REPEAT - Specifies the DTR data as the Fade time. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 196 | +#define DALI_SET_FADE_RATE 559 //47 REPEAT - Specifies the DTR data as the Fade rate. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 197 | +#define DALI_SET_EXTENDED_FADE_TIME 560 //48 REPEAT DALI-2 - Specifies the DTR data as the Extended Fade Time. (Command that exist only in IEC62386-102ed2.0) | |
| 198 | +#define DALI_RESERVED49 561 //49 REPEAT - [Reserved] | |
| 199 | +#define DALI_RESERVED50 562 //50 REPEAT - [Reserved] | |
| 200 | +#define DALI_RESERVED51 563 //51 REPEAT - [Reserved] | |
| 201 | +#define DALI_RESERVED52 564 //52 REPEAT - [Reserved] | |
| 202 | +#define DALI_RESERVED53 565 //53 REPEAT - [Reserved] | |
| 203 | +#define DALI_RESERVED54 566 //54 REPEAT - [Reserved] | |
| 204 | +#define DALI_RESERVED55 567 //55 REPEAT - [Reserved] | |
| 205 | +#define DALI_RESERVED56 568 //56 REPEAT - [Reserved] | |
| 206 | +#define DALI_RESERVED57 569 //57 REPEAT - [Reserved] | |
| 207 | +#define DALI_RESERVED58 570 //58 REPEAT - [Reserved] | |
| 208 | +#define DALI_RESERVED59 571 //59 REPEAT - [Reserved] | |
| 209 | +#define DALI_RESERVED60 572 //60 REPEAT - [Reserved] | |
| 210 | +#define DALI_RESERVED61 573 //61 REPEAT - [Reserved] | |
| 211 | +#define DALI_RESERVED62 574 //62 REPEAT - [Reserved] | |
| 212 | +#define DALI_RESERVED63 575 //63 REPEAT - [Reserved] | |
| 213 | +#define DALI_SET_SCENE0 576 //64 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 214 | +#define DALI_SET_SCENE1 577 //65 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 215 | +#define DALI_SET_SCENE2 578 //66 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 216 | +#define DALI_SET_SCENE3 579 //67 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 217 | +#define DALI_SET_SCENE4 580 //68 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 218 | +#define DALI_SET_SCENE5 581 //69 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 219 | +#define DALI_SET_SCENE6 582 //70 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 220 | +#define DALI_SET_SCENE7 583 //71 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 221 | +#define DALI_SET_SCENE8 584 //72 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 222 | +#define DALI_SET_SCENE9 585 //73 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 223 | +#define DALI_SET_SCENE10 586 //74 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 224 | +#define DALI_SET_SCENE11 587 //75 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 225 | +#define DALI_SET_SCENE12 588 //76 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 226 | +#define DALI_SET_SCENE13 589 //77 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 227 | +#define DALI_SET_SCENE14 590 //78 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 228 | +#define DALI_SET_SCENE15 591 //79 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 229 | +#define DALI_REMOVE_FROM_SCENE0 592 //80 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.) | |
| 230 | +#define DALI_REMOVE_FROM_SCENE1 593 //81 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.) | |
| 231 | +#define DALI_REMOVE_FROM_SCENE2 594 //82 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.) | |
| 232 | +#define DALI_REMOVE_FROM_SCENE3 595 //83 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.) | |
| 233 | +#define DALI_REMOVE_FROM_SCENE4 596 //84 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.) | |
| 234 | +#define DALI_REMOVE_FROM_SCENE5 597 //85 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.) | |
| 235 | +#define DALI_REMOVE_FROM_SCENE6 598 //86 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.) | |
| 236 | +#define DALI_REMOVE_FROM_SCENE7 599 //87 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.) | |
| 237 | +#define DALI_REMOVE_FROM_SCENE8 600 //88 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.) | |
| 238 | +#define DALI_REMOVE_FROM_SCENE9 601 //89 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.) | |
| 239 | +#define DALI_REMOVE_FROM_SCENE10 602 //90 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.) | |
| 240 | +#define DALI_REMOVE_FROM_SCENE11 603 //91 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.) | |
| 241 | +#define DALI_REMOVE_FROM_SCENE12 604 //92 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.) | |
| 242 | +#define DALI_REMOVE_FROM_SCENE13 605 //93 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.) | |
| 243 | +#define DALI_REMOVE_FROM_SCENE14 606 //94 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.) | |
| 244 | +#define DALI_REMOVE_FROM_SCENE15 607 //95 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.) | |
| 245 | +#define DALI_ADD_TO_GROUP0 608 //96 REPEAT - Adds the slave to Group XXXX. | |
| 246 | +#define DALI_ADD_TO_GROUP1 609 //97 REPEAT - Adds the slave to Group XXXX. | |
| 247 | +#define DALI_ADD_TO_GROUP2 610 //98 REPEAT - Adds the slave to Group XXXX. | |
| 248 | +#define DALI_ADD_TO_GROUP3 611 //99 REPEAT - Adds the slave to Group XXXX. | |
| 249 | +#define DALI_ADD_TO_GROUP4 612 //100 REPEAT - Adds the slave to Group XXXX. | |
| 250 | +#define DALI_ADD_TO_GROUP5 613 //101 REPEAT - Adds the slave to Group XXXX. | |
| 251 | +#define DALI_ADD_TO_GROUP6 614 //102 REPEAT - Adds the slave to Group XXXX. | |
| 252 | +#define DALI_ADD_TO_GROUP7 615 //103 REPEAT - Adds the slave to Group XXXX. | |
| 253 | +#define DALI_ADD_TO_GROUP8 616 //104 REPEAT - Adds the slave to Group XXXX. | |
| 254 | +#define DALI_ADD_TO_GROUP9 617 //105 REPEAT - Adds the slave to Group XXXX. | |
| 255 | +#define DALI_ADD_TO_GROUP10 618 //106 REPEAT - Adds the slave to Group XXXX. | |
| 256 | +#define DALI_ADD_TO_GROUP11 619 //107 REPEAT - Adds the slave to Group XXXX. | |
| 257 | +#define DALI_ADD_TO_GROUP12 620 //108 REPEAT - Adds the slave to Group XXXX. | |
| 258 | +#define DALI_ADD_TO_GROUP13 621 //109 REPEAT - Adds the slave to Group XXXX. | |
| 259 | +#define DALI_ADD_TO_GROUP14 622 //110 REPEAT - Adds the slave to Group XXXX. | |
| 260 | +#define DALI_ADD_TO_GROUP15 623 //111 REPEAT - Adds the slave to Group XXXX. | |
| 261 | +#define DALI_REMOVE_FROM_GROUP0 624 //112 REPEAT - Deletes the slave from Group XXXX. | |
| 262 | +#define DALI_REMOVE_FROM_GROUP1 625 //113 REPEAT - Deletes the slave from Group XXXX. | |
| 263 | +#define DALI_REMOVE_FROM_GROUP2 626 //114 REPEAT - Deletes the slave from Group XXXX. | |
| 264 | +#define DALI_REMOVE_FROM_GROUP3 627 //115 REPEAT - Deletes the slave from Group XXXX. | |
| 265 | +#define DALI_REMOVE_FROM_GROUP4 628 //116 REPEAT - Deletes the slave from Group XXXX. | |
| 266 | +#define DALI_REMOVE_FROM_GROUP5 629 //117 REPEAT - Deletes the slave from Group XXXX. | |
| 267 | +#define DALI_REMOVE_FROM_GROUP6 630 //118 REPEAT - Deletes the slave from Group XXXX. | |
| 268 | +#define DALI_REMOVE_FROM_GROUP7 631 //119 REPEAT - Deletes the slave from Group XXXX. | |
| 269 | +#define DALI_REMOVE_FROM_GROUP8 632 //120 REPEAT - Deletes the slave from Group XXXX. | |
| 270 | +#define DALI_REMOVE_FROM_GROUP9 633 //121 REPEAT - Deletes the slave from Group XXXX. | |
| 271 | +#define DALI_REMOVE_FROM_GROUP10 634 //122 REPEAT - Deletes the slave from Group XXXX. | |
| 272 | +#define DALI_REMOVE_FROM_GROUP11 635 //123 REPEAT - Deletes the slave from Group XXXX. | |
| 273 | +#define DALI_REMOVE_FROM_GROUP12 636 //124 REPEAT - Deletes the slave from Group XXXX. | |
| 274 | +#define DALI_REMOVE_FROM_GROUP13 637 //125 REPEAT - Deletes the slave from Group XXXX. | |
| 275 | +#define DALI_REMOVE_FROM_GROUP14 638 //126 REPEAT - Deletes the slave from Group XXXX. | |
| 276 | +#define DALI_REMOVE_FROM_GROUP15 639 //127 REPEAT - Deletes the slave from Group XXXX. | |
| 277 | +#define DALI_SET_SHORT_ADDRESS 640 //128 REPEAT - Specifies the DTR data as a Short Address. (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 278 | +#define DALI_ENABLE_WRITE_MEMORY 641 //129 REPEAT - Allows writing of the memory bank. | |
| 279 | +#define DALI_RESERVED130 642 //130 REPEAT - [Reserved] | |
| 280 | +#define DALI_RESERVED131 643 //131 REPEAT - [Reserved] | |
| 281 | +#define DALI_RESERVED132 644 //132 REPEAT - [Reserved] | |
| 282 | +#define DALI_RESERVED133 645 //133 REPEAT - [Reserved] | |
| 283 | +#define DALI_RESERVED134 646 //134 REPEAT - [Reserved] | |
| 284 | +#define DALI_RESERVED135 647 //135 REPEAT - [Reserved] | |
| 285 | +#define DALI_RESERVED136 648 //136 REPEAT - [Reserved] | |
| 286 | +#define DALI_RESERVED137 649 //137 REPEAT - [Reserved] | |
| 287 | +#define DALI_RESERVED138 650 //138 REPEAT - [Reserved] | |
| 288 | +#define DALI_RESERVED139 651 //139 REPEAT - [Reserved] | |
| 289 | +#define DALI_RESERVED140 652 //140 REPEAT - [Reserved] | |
| 290 | +#define DALI_RESERVED141 653 //141 REPEAT - [Reserved] | |
| 291 | +#define DALI_RESERVED142 654 //142 REPEAT - [Reserved] | |
| 292 | +#define DALI_RESERVED143 655 //143 REPEAT - [Reserved] | |
| 293 | +#define DALI_QUERY_STATUS 144 //144 - Returns "STATUS INFORMATION" | |
| 294 | +#define DALI_QUERY_CONTROL_GEAR_PRESENT 145 //145 - Is there a slave that can communicate? (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 295 | +#define DALI_QUERY_LAMP_FAILURE 146 //146 - Is there a lamp problem? | |
| 296 | +#define DALI_QUERY_LAMP_POWER_ON 147 //147 - Is a lamp on? | |
| 297 | +#define DALI_QUERY_LIMIT_ERROR 148 //148 - Is the specified lighting control level out of the range from the minimum to the maximum values? | |
| 298 | +#define DALI_QUERY_RESET_STATE 149 //149 - Is the slave in 'RESET STATE'? | |
| 299 | +#define DALI_QUERY_MISSING_SHORT_ADDRESS 150 //150 - Does the slave not have a short address? | |
| 300 | +#define DALI_QUERY_VERSION_NUMBER 151 //151 - What is the corresponding IEC standard number? | |
| 301 | +#define DALI_QUERY_CONTENT_DTR0 152 //152 - What is the DTR content? (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 302 | +#define DALI_QUERY_DEVICE_TYPE 153 //153 - What is the device type? (fluorescent lamp:0000 0000) (IEC62386-207 is 6 fixed) | |
| 303 | +#define DALI_QUERY_PHYSICAL_MINIMUM_LEVEL 154 //154 - What is the minimum lighting control level specified by the hardware? | |
| 304 | +#define DALI_QUERY_POWER_FAILURE 155 //155 - Has the slave operated without the execution of reset-command or the adjustment of the lighting control level? | |
| 305 | +#define DALI_QUERY_CONTENT_DTR1 156 //156 - What is the DTR1 content? | |
| 306 | +#define DALI_QUERY_CONTENT_DTR2 157 //157 - What is the DTR2 content? | |
| 307 | +#define DALI_QUERY_OPERATING_MODE 158 //158 DALI-2 - What is the Operating Mode? (Only IEC62386-102ed2.0 ) | |
| 308 | +#define DALI_QUERY_LIGHT_SOURCE_TYPE 159 //159 DALI-2 - What is the Light source type? (Only IEC62386-102ed2.0 ) | |
| 309 | +#define DALI_QUERY_ACTUAL_LEVEL 160 //160 - What is the "ACTUAL LEVEL" (the current lighting control level)? | |
| 310 | +#define DALI_QUERY_MAX_LEVEL 161 //161 - What is the maximum lighting control level? | |
| 311 | +#define DALI_QUERY_MIN_LEVEL 162 //162 - What is the minimum lighting control level? | |
| 312 | +#define DALI_QUERY_POWER_ON_LEVEL 163 //163 - What is the "POWER ON LEVEL" (the lighting control level when the power is turned on)? | |
| 313 | +#define DALI_QUERY_SYSTEM_FAILURE_LEVEL 164 //164 - What is the "SYSTEM FAILURE LEVEL" (the lighting control level when a failure occurs)? | |
| 314 | +#define DALI_QUERY_FADE_TIME_FADE_RATE 165 //165 - What are the Fade time and Fade rate? | |
| 315 | +#define DALI_QUERY_MANUFACTURER_SPECIFIC_MODE 166 //166 DALI-2 - What is the Specific Mode? (Command that exist only in IEC62386-102ed2.0) | |
| 316 | +#define DALI_QUERY_NEXT_DEVICE_TYPE 167 //167 DALI-2 - What is the next Device Type? (Command that exist only in IEC62386-102ed2.0) | |
| 317 | +#define DALI_QUERY_EXTENDED_FADE_TIME 168 //168 DALI-2 - What is the Extended Fade Time? (Command that exist only in IEC62386-102ed2.0) | |
| 318 | +#define DALI_QUERY_CONTROL_GEAR_FAILURE 169 //169 DALI-2 - Does a slave have the abnormality? (Command that exist only in IEC62386-102ed2.0) | |
| 319 | +#define DALI_RESERVED170 170 //170 - [Reserved] | |
| 320 | +#define DALI_RESERVED171 171 //171 - [Reserved] | |
| 321 | +#define DALI_RESERVED172 172 //172 - [Reserved] | |
| 322 | +#define DALI_RESERVED173 173 //173 - [Reserved] | |
| 323 | +#define DALI_RESERVED174 174 //174 - [Reserved] | |
| 324 | +#define DALI_RESERVED175 175 //175 - [Reserved] | |
| 325 | +#define DALI_QUERY_SCENE0_LEVEL 176 //176 - What is the lighting control level for SCENE XXXX? | |
| 326 | +#define DALI_QUERY_SCENE1_LEVEL 177 //177 - What is the lighting control level for SCENE XXXX? | |
| 327 | +#define DALI_QUERY_SCENE2_LEVEL 178 //178 - What is the lighting control level for SCENE XXXX? | |
| 328 | +#define DALI_QUERY_SCENE3_LEVEL 179 //179 - What is the lighting control level for SCENE XXXX? | |
| 329 | +#define DALI_QUERY_SCENE4_LEVEL 180 //180 - What is the lighting control level for SCENE XXXX? | |
| 330 | +#define DALI_QUERY_SCENE5_LEVEL 181 //181 - What is the lighting control level for SCENE XXXX? | |
| 331 | +#define DALI_QUERY_SCENE6_LEVEL 182 //182 - What is the lighting control level for SCENE XXXX? | |
| 332 | +#define DALI_QUERY_SCENE7_LEVEL 183 //183 - What is the lighting control level for SCENE XXXX? | |
| 333 | +#define DALI_QUERY_SCENE8_LEVEL 184 //184 - What is the lighting control level for SCENE XXXX? | |
| 334 | +#define DALI_QUERY_SCENE9_LEVEL 185 //185 - What is the lighting control level for SCENE XXXX? | |
| 335 | +#define DALI_QUERY_SCENE10_LEVEL 186 //186 - What is the lighting control level for SCENE XXXX? | |
| 336 | +#define DALI_QUERY_SCENE11_LEVEL 187 //187 - What is the lighting control level for SCENE XXXX? | |
| 337 | +#define DALI_QUERY_SCENE12_LEVEL 188 //188 - What is the lighting control level for SCENE XXXX? | |
| 338 | +#define DALI_QUERY_SCENE13_LEVEL 189 //189 - What is the lighting control level for SCENE XXXX? | |
| 339 | +#define DALI_QUERY_SCENE14_LEVEL 190 //190 - What is the lighting control level for SCENE XXXX? | |
| 340 | +#define DALI_QUERY_SCENE15_LEVEL 191 //191 - What is the lighting control level for SCENE XXXX? | |
| 341 | +#define DALI_QUERY_GROUPS_0_7 192 //192 - Does the slave belong to a group among groups 0 to 7? (Each bit corresponds to agroup.) | |
| 342 | +#define DALI_QUERY_GROUPS_8_15 193 //193 - Does the slave belong to a group among groups 8 to 15? (Each bit corresponds to agroup.) | |
| 343 | +#define DALI_QUERY_RANDOM_ADDRESS_H 194 //194 - What are the higher 8 bits of the random address? | |
| 344 | +#define DALI_QUERY_RANDOM_ADDRESS_M 195 //195 - What are the middle 8 bits of the random address? | |
| 345 | +#define DALI_QUERY_RANDOM_ADDRESS_L 196 //196 - What are the lower 8 bits of the random address? | |
| 346 | +#define DALI_READ_MEMORY_LOCATION 197 //197 - What is the memory location content? | |
| 347 | +#define DALI_RESERVED198 198 //198 - [Reserved] | |
| 348 | +#define DALI_RESERVED199 199 //199 - [Reserved] | |
| 349 | +#define DALI_RESERVED200 200 //200 - [Reserved] | |
| 350 | +#define DALI_RESERVED201 201 //201 - [Reserved] | |
| 351 | +#define DALI_RESERVED202 202 //202 - [Reserved] | |
| 352 | +#define DALI_RESERVED203 203 //203 - [Reserved] | |
| 353 | +#define DALI_RESERVED204 204 //204 - [Reserved] | |
| 354 | +#define DALI_RESERVED205 205 //205 - [Reserved] | |
| 355 | +#define DALI_RESERVED206 206 //206 - [Reserved] | |
| 356 | +#define DALI_RESERVED207 207 //207 - [Reserved] | |
| 357 | +#define DALI_RESERVED208 208 //208 - [Reserved] | |
| 358 | +#define DALI_RESERVED209 209 //209 - [Reserved] | |
| 359 | +#define DALI_RESERVED210 210 //210 - [Reserved] | |
| 360 | +#define DALI_RESERVED211 211 //211 - [Reserved] | |
| 361 | +#define DALI_RESERVED212 212 //212 - [Reserved] | |
| 362 | +#define DALI_RESERVED213 213 //213 - [Reserved] | |
| 363 | +#define DALI_RESERVED214 214 //214 - [Reserved] | |
| 364 | +#define DALI_RESERVED215 215 //215 - [Reserved] | |
| 365 | +#define DALI_RESERVED216 216 //216 - [Reserved] | |
| 366 | +#define DALI_RESERVED217 217 //217 - [Reserved] | |
| 367 | +#define DALI_RESERVED218 218 //218 - [Reserved] | |
| 368 | +#define DALI_RESERVED219 219 //219 - [Reserved] | |
| 369 | +#define DALI_RESERVED220 220 //220 - [Reserved] | |
| 370 | +#define DALI_RESERVED221 221 //221 - [Reserved] | |
| 371 | +#define DALI_RESERVED222 222 //222 - [Reserved] | |
| 372 | +#define DALI_RESERVED223 223 //223 - [Reserved] | |
| 373 | +#define DALI_REFERENCE_SYSTEM_POWER 224 //224 IEC62386-207 - Starts power measurement. (Command that exist only in IEC62386-207) | |
| 374 | +#define DALI_ENABLE_CURRENT_PROTECTOR 225 //225 IEC62386-207 - Enables the current protection. (Command that exist only in IEC62386-207) | |
| 375 | +#define DALI_DISABLE_CURRENT_PROTECTOR 226 //226 IEC62386-207 - Disables the current protection. (Command that exist only in IEC62386-207) | |
| 376 | +#define DALI_SELECT_DIMMING_CURVE 227 //227 IEC62386-207 - Selects Dimming curve. (Command that exist only in IEC62386-207) | |
| 377 | +#define DALI_STORE_DTR_AS_FAST_FADE_TIME 228 //228 IEC62386-207 - Sets the DTR of the data as Fast Fade Time.(Command that exist only in IEC62386-207) | |
| 378 | +#define DALI_RESERVED229 229 //229 - [Reserved] | |
| 379 | +#define DALI_RESERVED230 230 //230 - [Reserved] | |
| 380 | +#define DALI_RESERVED231 231 //231 - [Reserved] | |
| 381 | +#define DALI_RESERVED232 232 //232 - [Reserved] | |
| 382 | +#define DALI_RESERVED233 233 //233 - [Reserved] | |
| 383 | +#define DALI_RESERVED234 234 //234 - [Reserved] | |
| 384 | +#define DALI_RESERVED235 235 //235 - [Reserved] | |
| 385 | +#define DALI_RESERVED236 236 //236 - [Reserved] | |
| 386 | +#define DALI_QUERY_GEAR_TYPE 237 //237 IEC62386-207 - Returns ‘GEAR TYPE’ (Command that exist only in IEC62386-207) | |
| 387 | +#define DALI_QUERY_DIMMING_CURVE 238 //238 IEC62386-207 - Returns ’Dimming curve’in use (Command that exist only in IEC62386-207) | |
| 388 | +#define DALI_QUERY_POSSIBLE_OPERATING_MODE 239 //239 IEC62386-207 - Returns ‘POSSIBLEG OPERATING MODE’ (Command that exist only in IEC62386-207) | |
| 389 | +#define DALI_QUERY_FEATURES 240 //240 IEC62386-207 - Returns ‘FEATURES’ (Command that exist only in IEC62386-207) | |
| 390 | +#define DALI_QUERY_FAILURE_STATUS 241 //241 IEC62386-207 - Returns ‘FAILURE STATUS’ (Command that exist only in IEC62386-207) | |
| 391 | +#define DALI_QUERY_SHORT_CIRCUIT 242 //242 IEC62386-207 - Returns bit0 short circuit of ‘FAILURE STATUS’ (Command that exist only in IEC62386-207) | |
| 392 | +#define DALI_QUERY_OPEN_CIRCUIT 243 //243 IEC62386-207 - Returns bit1 open circuit of ‘FAILURE STATUS’ (Command that exist only in IEC62386-207) | |
| 393 | +#define DALI_QUERY_LOAD_DECREASE 244 //244 IEC62386-207 - Returns bit2 load decrease of ‘FAILURE STATUS’ (Command that exist only in IEC62386-207) | |
| 394 | +#define DALI_QUERY_LOAD_INDREASE 245 //245 IEC62386-207 - Returns bit3 load increase of‘FAILURE STATUS’ (Command that exist only in IEC62386-207) | |
| 395 | +#define DALI_QUERY_CURRENT_PROTECTOR_ACTIVE 246 //246 IEC62386-207 - Returns bit4 current protector active of ‘FAILURE STATUS’ (Command that exist only in IEC62386-207) | |
| 396 | +#define DALI_QUERY_THERMAL_SHUTDOWN 247 //247 IEC62386-207 - Returns bit5 thermal shut down of ‘FAILURE STATUS’ (Command that exist only in IEC62386-207) | |
| 397 | +#define DALI_QUERY_THERMAL_OVERLOAD 248 //248 IEC62386-207 - Returns bit6 thermal overload with light level reduction of ‘FAILURE STATUS’ (Command that exist only in IEC62386-207) | |
| 398 | +#define DALI_QUERY_REFARENCE_RUNNING 249 //249 IEC62386-207 - Returns whetherReference System Power is in operation. (Command that exist only in IEC62386-207) | |
| 399 | +#define DALI_QUERY_REFERENCE_MEASURMENT_FAILED 250 //250 IEC62386-207 - Returns bit7 reference measurement failed of ‘FAILURE STATUS’ (Command that exist only in IEC62386-207) | |
| 400 | +#define DALI_QUERY_CURRENT_PROTECTOR_ENABLE 251 //251 IEC62386-207 - Returns state of Curent protector (Command that exist only in IEC62386-207) | |
| 401 | +#define DALI_QUERY_OPERATING_MODE 252 //252 IEC62386-207 - Returns ‘OPERATING MODE’ (Command that exist only in IEC62386-207) | |
| 402 | +#define DALI_QUERY_FAST_FADE_TIME 253 //253 IEC62386-207 - Returns set Fast fade time. (Command that exist only in IEC62386-207) | |
| 403 | +#define DALI_QUERY_MIN_FAST_FADE_TIME 254 //254 IEC62386-207 - Returns set Minimum fast fade time (Command that exist only in IEC62386-207) | |
| 404 | +#define DALI_QUERY_EXTENDED_VERSION_NUMBER 255 //255 IEC62386-207 - The version number of the extended support? IEC62386-207: 1, Other: NO(no response) | |
| 405 | +#define DALI_TERMINATE 0x01A1 //256 - Releases the INITIALISE state. | |
| 406 | +#define DALI_DATA_TRANSFER_REGISTER0 0x01A3 //257 - Stores the data XXXX XXXX to the DTR(DTR0). (In the parenthesis is a name in IEC62386-102ed2.0) | |
| 407 | +#define DALI_INITIALISE 0x03A5 //258 REPEAT - Sets the slave to the INITIALISE status for15 minutes. Commands 259 to 270 are enabled only for a slave in this status. | |
| 408 | +#define DALI_RANDOMISE 0x03A7 //259 REPEAT - Generates a random address. | |
| 409 | +#define DALI_COMPARE 0x01A9 //260 - Is the random address smaller or equal to the search address? | |
| 410 | +#define DALI_WITHDRAW 0x01AB //261 - Excludes slaves for which the random address and search address match from the Compare process. | |
| 411 | +#define DALI_RESERVED262 0x01AD //262 - [Reserved] | |
| 412 | +#define DALI_PING 0x01AF //263 DALI-2 - Ignores in the slave. (Command that exist only in IEC62386-102ed2.0) | |
| 413 | +#define DALI_SEARCHADDRH 0x01B1 //264 - Specifies the higher 8 bits of the search address. | |
| 414 | +#define DALI_SEARCHADDRM 0x01B3 //265 - Specifies the middle 8 bits of the search address. | |
| 415 | +#define DALI_SEARCHADDRL 0x01B5 //266 - Specifies the lower 8 bits of the search address. | |
| 416 | +#define DALI_PROGRAM_SHORT_ADDRESS 0x01B7 //267 - The slave shall store the received 6-bit address (AAA AAA) as a short address if it is selected. | |
| 417 | +#define DALI_VERIFY_SHORT_ADDRESS 0x01B9 //268 - Is the short address AAA AAA? | |
| 418 | +#define DALI_QUERY_SHORT_ADDRESS 0x01BB //269 - What is the short address of the slaveNote 2being selected? | |
| 419 | +#define DALI_PHYSICAL_SELECTION 0x01BD //270 not DALI-2 - Sets the slave to Physical Selection Mode and excludes the slave from the Compare process. (Excluding IEC62386-102ed2.0) (Command that exist only in IEC62386-102ed1.0, -207ed1.0) | |
| 420 | +#define DALI_RESERVED271 0x01BF //271 - [Reserved] | |
| 421 | +#define DALI_ENABLE_DEVICE_TYPE_X 0x01C1 //272 - Adds the device XXXX (a special device). | |
| 422 | +#define DALI_DATA_TRANSFER_REGISTER1 0x01C3 //273 - Stores data XXXX into DTR1. | |
| 423 | +#define DALI_DATA_TRANSFER_REGISTER2 0x01C5 //274 - Stores data XXXX into DTR2. | |
| 424 | +#define DALI_WRITE_MEMORY_LOCATION 0x01C7 //275 - Write data into the specified address of the specified memory bank. (There is BW) (DTR(DTR0):address, DTR1:memory bank number) | |
| 425 | +#define DALI_WRITE_MEMORY_LOCATION_NO_REPLY 0x01C9 //276 DALI-2 - Write data into the specified address of the specified memory bank. (There is no BW) (DTR(DTR0):address, TR1:memory bank number) (Command that exist only in IEC62386-102ed2.0) | |
| 426 | +#define DALI_RESERVED277 0x01CB //277 - [Reserved] | |
| 427 | +#define DALI_RESERVED278 0x01CD //278 - [Reserved] | |
| 428 | +#define DALI_RESERVED279 0x01CF //279 - [Reserved] | |
| 429 | +#define DALI_RESERVED280 0x01D1 //280 - [Reserved] | |
| 430 | +#define DALI_RESERVED281 0x01D3 //281 - [Reserved] | |
| 431 | +#define DALI_RESERVED282 0x01D5 //282 - [Reserved] | |
| 432 | +#define DALI_RESERVED283 0x01D7 //283 - [Reserved] | |
| 433 | +#define DALI_RESERVED284 0x01D9 //284 - [Reserved] | |
| 434 | +#define DALI_RESERVED285 0x01DB //285 - [Reserved] | |
| 435 | +#define DALI_RESERVED286 0x01DD //286 - [Reserved] | |
| 436 | +#define DALI_RESERVED287 0x01DF //287 - [Reserved] | |
| 437 | +#define DALI_RESERVED288 0x01E1 //288 - [Reserved] | |
| 438 | +#define DALI_RESERVED289 0x01E3 //289 - [Reserved] | |
| 439 | +#define DALI_RESERVED290 0x01E5 //290 - [Reserved] | |
| 440 | +#define DALI_RESERVED291 0x01E7 //291 - [Reserved] | |
| 441 | +#define DALI_RESERVED292 0x01E9 //292 - [Reserved] | |
| 442 | +#define DALI_RESERVED293 0x01EB //293 - [Reserved] | |
| 443 | +#define DALI_RESERVED294 0x01ED //294 - [Reserved] | |
| 444 | +#define DALI_RESERVED295 0x01DF //295 - [Reserved] | |
| 445 | +#define DALI_RESERVED296 0x01F1 //296 - [Reserved] | |
| 446 | +#define DALI_RESERVED297 0x01F3 //297 - [Reserved] | |
| 447 | +#define DALI_RESERVED298 0x01F5 //298 - [Reserved] | |
| 448 | +#define DALI_RESERVED299 0x01F7 //299 - [Reserved] | |
| 449 | +#define DALI_RESERVED300 0x01F9 //300 - [Reserved] | |
| 450 | +#define DALI_RESERVED301 0x01FB //301 - [Reserved] | |
| 451 | +#define DALI_RESERVED302 0x01FD //302 - [Reserved] | |
| 452 | + | |
| 453 | + | |
| 454 | + | |
| 455 | + | |
| 456 | +/* | |
| 457 | +SIGNAL CHARACTERISTICS | |
| 458 | +High Level: 9.5 to 22.5 V (Typical 16 V) | |
| 459 | +Low Level: -6.5 to + 6.5 V (Typical 0 V) | |
| 460 | +Te = half cycle = 416.67 us +/- 10 % | |
| 461 | +10 us <= tfall <= 100 us | |
| 462 | +10 us <= trise <= 100 us | |
| 463 | + | |
| 464 | +BIT TIMING | |
| 465 | +msb send first | |
| 466 | + logical 1 = 1Te Low 1Te High | |
| 467 | + logical 0 = 1Te High 1Te Low | |
| 468 | + Start bit = logical 1 | |
| 469 | + Stop bit = 2Te High | |
| 470 | + | |
| 471 | +FRAME TIMING | |
| 472 | +FF: TX Forward Frame 2 bytes (38Te) = 2*(1start+16bits+2stop) | |
| 473 | +BF: RX Backward Frame 1 byte (22Te) = 2*(1start+8bits+2stop) | |
| 474 | +no reply: FF >22Te pause FF | |
| 475 | +with reply: FF >7Te <22Te pause BF >22Te pause FF | |
| 476 | + | |
| 477 | + | |
| 478 | +DALI commands | |
| 479 | +============= | |
| 480 | +In accordance with the DIN EN 60929 standard, addresses and commands are transmitted as numbers with a length of two bytes. | |
| 481 | + | |
| 482 | +These commands take the form YAAA AAAS xxXXxx. Each letter here stands for one bit. | |
| 483 | + | |
| 484 | +Y: type of address | |
| 485 | + 0bin: short address | |
| 486 | + 1bin: group address or collective call | |
| 487 | + | |
| 488 | +A: significant address bit | |
| 489 | + | |
| 490 | +S: selection bit (specifies the significance of the following eight bits): | |
| 491 | + 0bin: the 8 xxXXxx bits contain a value for direct control of the lamp power | |
| 492 | + 1bin: the 8 xxXXxx bits contain a command number. | |
| 493 | + | |
| 494 | +x: a bit in the lamp power or in the command number | |
| 495 | + | |
| 496 | + | |
| 497 | +Type of Addresses | |
| 498 | +================= | |
| 499 | +Type of Addresses Byte Description | |
| 500 | +Short address 0AAAAAAS (AAAAAA = 0 to 63, S = 0/1) | |
| 501 | +Group address 100AAAAS (AAAA = 0 to 15, S = 0/1) | |
| 502 | +Broadcast address 1111111S (S = 0/1) | |
| 503 | +Special command 101CCCC1 (CCCC = command number) | |
| 504 | + | |
| 505 | + | |
| 506 | +Direct DALI commands for lamp power | |
| 507 | +=================================== | |
| 508 | +These commands take the form YAAA AAA0 xxXXxx. | |
| 509 | + | |
| 510 | +xxXXxx: the value representing the lamp power is transmitted in these 8 bits. It is calculated according to this formula: | |
| 511 | + | |
| 512 | +Pvalue = 10 ^ ((value-1) / (253/3)) * Pmax / 1000 | |
| 513 | + | |
| 514 | +253 values from 1dec to 254dec are available for transmission in accordance with this formula. | |
| 515 | + | |
| 516 | +There are also 2 direct DALI commands with special meanings: | |
| 517 | + | |
| 518 | +Command; Command No; Description; Answer | |
| 519 | +00hex; 0dec; The DALI device dims using the current fade time down to the parameterised MIN value, and then switches off.; - | |
| 520 | +FFhex; 254dec; Mask (no change): this value is ignored in what follows, and is therefore not loaded into memory.; - | |
| 521 | + | |
| 522 | + | |
| 523 | +Indirect DALI commands for lamp power | |
| 524 | +===================================== | |
| 525 | +These commands take the form YAAA AAA1 xxXXxx. | |
| 526 | + | |
| 527 | +xxXXxx: These 8 bits transfer the command number. The available command numbers are listed and explained in the following tables in hexadecimal and decimal formats. | |
| 528 | + | |
| 529 | +Command; Command No; Description; Answer | |
| 530 | +00hex 0dez Extinguish the lamp (without fading) - | |
| 531 | +01hex 1dez Dim up 200 ms using the selected fade rate - | |
| 532 | +02hex 2dez Dim down 200 ms using the selected fade rate - | |
| 533 | +03hex 3dez Set the actual arc power level one step higher without fading. If the lamp is off, it will be not ignited. - | |
| 534 | +04hex 4dez Set the actual arc power level one step lower without fading. If the lamp has already it's minimum value, it is not switched off. - | |
| 535 | +05hex 5dez Set the actual arc power level to the maximum value. If the lamp is off, it will be ignited. - | |
| 536 | +06hex 6dez Set the actual arc power level to the minimum value. If the lamp is off, it will be ignited. - | |
| 537 | +07hex 7dez Set the actual arc power level one step lower without fading. If the lamp has already it's minimum value, it is switched off. - | |
| 538 | +08hex 8dez Set the actual arc power level one step higher without fading. If the lamp is off, it will be ignited. - | |
| 539 | +09hex ... 0Fhex 9dez ... 15dez reserved - | |
| 540 | +1nhex | |
| 541 | +(n: 0hex ... Fhex) 16dez ... 31dez Set the light level to the value stored for the selected scene (n) - | |
| 542 | + | |
| 543 | + | |
| 544 | +Configuration commands | |
| 545 | +====================== | |
| 546 | +Command; Command No; Description; Answer | |
| 547 | +20hex 32dez Reset the parameters to default settings - | |
| 548 | +21hex 33dez Store the current light level in the DTR (Data Transfer Register) - | |
| 549 | +22hex ... 29hex 34dez ... 41dez reserved - | |
| 550 | +2Ahex 42dez Store the value in the DTR as the maximum level - | |
| 551 | +2Bhex 43dez Store the value in the DTR as the minimum level - | |
| 552 | +2Chex 44dez Store the value in the DTR as the system failure level - | |
| 553 | +2Dhex 45dez Store the value in the DTR as the power on level - | |
| 554 | +2Ehex 46dez Store the value in the DTR as the fade time - | |
| 555 | +2Fhex 47dez Store the value in the DTR as the fade rate - | |
| 556 | +30hex ... 3Fhex 48dez ... 63dez reserved - | |
| 557 | +4nhex | |
| 558 | +(n: 0hex ... Fhex) 64dez ... 79dez Store the value in the DTR as the selected scene (n) - | |
| 559 | +5nhex | |
| 560 | +(n: 0hex ... Fhex) 80dez ... 95dez Remove the selected scene (n) from the DALI slave - | |
| 561 | +6nhex | |
| 562 | +(n: 0hex ... Fhex) 96dez ... 111dez Add the DALI slave unit to the selected group (n) - | |
| 563 | +7nhex | |
| 564 | +(n: 0hex ... Fhex) 112dez ... 127dez Remove the DALI slave unit from the selected group (n) - | |
| 565 | +80hex 128dez Store the value in the DTR as a short address - | |
| 566 | +81hex ... 8Fhex 129dez ... 143dez reserved - | |
| 567 | +90hex 144dez Returns the status (XX) of the DALI slave XX | |
| 568 | +91hex 145dez Check if the DALI slave is working yes/no | |
| 569 | +92hex 146dez Check if there is a lamp failure yes/no | |
| 570 | +93hex 147dez Check if the lamp is operating yes/no | |
| 571 | +94hex 148dez Check if the slave has received a level out of limit yes/no | |
| 572 | +95hex 149dez Check if the DALI slave is in reset state yes/no | |
| 573 | +96hex 150dez Check if the DALI slave is missing a short address XX | |
| 574 | +97hex 151dez Returns the version number as XX | |
| 575 | +98hex 152dez Returns the content of the DTR as XX | |
| 576 | +99hex 153dez Returns the device type as XX | |
| 577 | +9Ahex 154dez Returns the physical minimum level as XX | |
| 578 | +9Bhex 155dez Check if the DALI slave is in power failure mode yes/no | |
| 579 | +9Chex ... 9Fhex 156dez ... 159dez reserved - | |
| 580 | +A0hex 160dez Returns the current light level as XX | |
| 581 | +A1hex 161dez Returns the maximum allowed light level as XX | |
| 582 | +A2hex 162dez Returns the minimum allowed light level as XX | |
| 583 | +A3hex 163dez Return the power up level as XX | |
| 584 | +A4hex 164dez Returns the system failure level as XX | |
| 585 | +A5hex 165dez Returns the fade time as X and the fade rate as Y XY | |
| 586 | +A6hex ... AFhex 166dez ... 175dez reserved - | |
| 587 | +Bnhex | |
| 588 | +(n: 0hex ... Fhex) 176dez ... 191dez Returns the light level XX for the selected scene (n) XX | |
| 589 | +C0hex 192dez Returns a bit pattern XX indicating which group (0-7) the DALI slave belongs to XX | |
| 590 | +C1hex 193dez Returns a bit pattern XX indicating which group (8-15) the DALI slave belongs to XX | |
| 591 | +C2hex 194dez Returns the high bits of the random address as HH | |
| 592 | +C3hex 195dez Return the middle bit of the random address as MM | |
| 593 | +C4hex 196dez Returns the lower bits of the random address as LL | |
| 594 | +C5hex ... DFhex 197dez ... 223dez reserved - | |
| 595 | +E0hex ... FFhex 224dez ... 255dez Returns application specific extension commands | |
| 596 | + | |
| 597 | + | |
| 598 | +Note Repeat of DALI commands | |
| 599 | +============================ | |
| 600 | +According to IEC 60929, a DALI Master has to repeat several commands within 100 ms, so that DALI-Slaves will execute them. | |
| 601 | + | |
| 602 | +The DALI Master Terminal KL6811 repeats the commands 32dez to 128dez, 258dez and 259dez (bold marked) automatically to make the the double call from the user program unnecessary. | |
| 603 | + | |
| 604 | +The DALI Master Terminal KL6811 repeats also the commands 224dez to 255dez, if you have activated this with Bit 1 of the Control-Byte (CB.1) before. | |
| 605 | + | |
| 606 | + | |
| 607 | +DALI Control Device Type List | |
| 608 | +============================= | |
| 609 | +Type DEC Type HEX Name Comments | |
| 610 | +128 0x80 Unknown Device. If one of the devices below don't apply | |
| 611 | +129 0x81 Switch Device A Wall-Switch based Controller including, but not limited to ON/OFF devices, Scene switches, dimming device. | |
| 612 | +130 0x82 Slide Dimmer An analog/positional dimming controller | |
| 613 | +131 0x83 Motion/Occupancy Sensor. A device that indicates the presence of people within a control area. | |
| 614 | +132 0x84 Open-loop daylight Controller. A device that outputs current light level and/or sends control messages to actuators based on light passing a threshold. | |
| 615 | +133 0x85 Closed-loop daylight controller. A device that outputs current light level and/or sends control messages to actuators based on a change in light level. | |
| 616 | +134 0x86 Scheduler. A device that establishes the building mode based on time of day, or which provides control outputs. | |
| 617 | +135 0x87 Gateway. An interface to other control systems or communication busses | |
| 618 | +136 0x88 Sequencer. A device which sequences lights based on a triggering event | |
| 619 | +137 0x89 Power Supply *). A DALI Power Supply device which supplies power for the communication loop | |
| 620 | +138 0x8a Emergency Lighting Controller. A device, which is certified for use in control of emergency lighting, or, if not certified, for noncritical backup lighting. | |
| 621 | +139 0x8b Analog input unit. A general device with analog input. | |
| 622 | +140 0x8c Data Logger. A unit logging data (can be digital or analog data) | |
| 623 | + | |
| 624 | + | |
| 625 | +Flash Variables and Offset in Information | |
| 626 | +========================================= | |
| 627 | +Memory Name Offset | |
| 628 | +Power On Level [0] | |
| 629 | +System Failure Level [1] | |
| 630 | +Minimum Level [2] | |
| 631 | +Maximum Level [3] | |
| 632 | +Fade Rate [4] | |
| 633 | +Fade Time [5] | |
| 634 | +Short Address [6] | |
| 635 | +Group 0 through 7 [7] | |
| 636 | +Group 8 through 15 [8] | |
| 637 | +Scene 0 through 15 [9-24] | |
| 638 | +Random Address [25-27] | |
| 639 | +Fast Fade Time [28] | |
| 640 | +Failure Status [29] | |
| 641 | +Operating Mode [30] | |
| 642 | +Dimming Curve [31] | |
| 643 | +*/ | ... | ... |