Commit e44ea54cde229bd447cc03a99697a16bc2b32450

Authored by qqqlab
Committed by GitHub
1 parent 14e13c2c

.

Documentation/DALI Commands.xlsx 0 → 100644
No preview for this file type
Documentation/Renesas DALI Applicaton Note.pdf 0 → 100644
No preview for this file type
Examples/Commissioning/Commissioning.ino
@@ -50,26 +50,28 @@ void loop() { @@ -50,26 +50,28 @@ void loop() {
50 while (Serial.available() > 0) { 50 while (Serial.available() > 0) {
51 int incomingByte = Serial.read(); 51 int incomingByte = Serial.read();
52 switch(incomingByte) { 52 switch(incomingByte) {
53 - case '1': menu_flash(); menu(); break; 53 + case '1': menu_blink(); menu(); break;
54 case '2': menu_scan_short_addr(); menu(); break; 54 case '2': menu_scan_short_addr(); menu(); break;
55 case '3': menu_commission(); menu(); break; 55 case '3': menu_commission(); menu(); break;
56 - case '4': menu_delete_short_addr(); menu(); break; 56 + case '4': menu_commission_debug(); menu(); break;
  57 + case '5': menu_delete_short_addr(); menu(); break;
57 } 58 }
58 } 59 }
59 } 60 }
60 61
61 void menu() { 62 void menu() {
62 Serial.println("----------------------------"); 63 Serial.println("----------------------------");
63 - Serial.println("1 Flash all lights"); 64 + Serial.println("1 Blink all lamps");
64 Serial.println("2 Scan short addresses"); 65 Serial.println("2 Scan short addresses");
65 Serial.println("3 Commission short addresses"); 66 Serial.println("3 Commission short addresses");
66 - Serial.println("4 Delete short addresses"); 67 + Serial.println("4 Commission short addresses (VERBOSE)");
  68 + Serial.println("5 Delete short addresses");
67 Serial.println("----------------------------"); 69 Serial.println("----------------------------");
68 } 70 }
69 71
70 72
71 -void menu_flash() {  
72 - Serial.println("Running: Flash all"); 73 +void menu_blink() {
  74 + Serial.println("Running: Blinking all lamps");
73 for(uint8_t i=0;i<5;i++) { 75 for(uint8_t i=0;i<5;i++) {
74 dali.set_level(254); 76 dali.set_level(254);
75 Serial.print("."); 77 Serial.print(".");
@@ -117,8 +119,18 @@ void menu_scan_short_addr() { @@ -117,8 +119,18 @@ void menu_scan_short_addr() {
117 119
118 //might need a couple of calls to find everything... 120 //might need a couple of calls to find everything...
119 void menu_commission(){ 121 void menu_commission(){
120 - Serial.println("Running: Commission - be patient, this takes a while ....");  
121 -// uint8_t cnt = dali.commission(0xff); //init_arg=0b11111111 : all without short address 122 + Serial.println("Running: Commission");
  123 + Serial.println("Might need a couple of runs to find all lamps ...");
  124 + Serial.println("Be patient, this takes a while ...");
  125 + uint8_t cnt = dali.commission(0xff); //init_arg=0b11111111 : all without short address
  126 + Serial.print("DONE, assigned ");Serial.print(cnt);Serial.println(" new short addresses");
  127 +}
  128 +
  129 +//might need a couple of calls to find everything...
  130 +void menu_commission_debug(){
  131 + Serial.println("Running: Commission (VERBOSE)");
  132 + Serial.println("Might need a couple of runs to find all lamps ...");
  133 + Serial.println("Be patient, this takes a while ...");
122 uint8_t cnt = debug_commission(0xff); //init_arg=0b11111111 : all without short address 134 uint8_t cnt = debug_commission(0xff); //init_arg=0b11111111 : all without short address
123 Serial.print("DONE, assigned ");Serial.print(cnt);Serial.println(" new short addresses"); 135 Serial.print("DONE, assigned ");Serial.print(cnt);Serial.println(" new short addresses");
124 } 136 }
@@ -140,26 +152,25 @@ uint8_t debug_commission(uint8_t init_arg) { @@ -140,26 +152,25 @@ uint8_t debug_commission(uint8_t init_arg) {
140 uint8_t arr[64]; 152 uint8_t arr[64];
141 uint8_t sa; 153 uint8_t sa;
142 for(sa=0; sa<64; sa++) arr[sa]=0; 154 for(sa=0; sa<64; sa++) arr[sa]=0;
143 -  
144 - //find existing short addresses when not assigning all  
145 - if(init_arg!=0b00000000) {  
146 - Serial.println("Find existing short adr");  
147 - for(sa = 0; sa<64; sa++) {  
148 - int16_t rv = dali.cmd(DALI_QUERY_STATUS,sa);  
149 - if(rv!=DALI_RESULT_NO_REPLY) {  
150 - arr[sa]=1;  
151 - Serial.print("sortadr=");  
152 - Serial.print(sa);  
153 - Serial.print(" status=0x");  
154 - Serial.print(rv,HEX);  
155 - Serial.print(" minLevel=");  
156 - Serial.println(dali.cmd(DALI_QUERY_MIN_LEVEL,sa));  
157 - }  
158 - }  
159 - }  
160 155
  156 + dali.cmd(DALI_RESET,0x00);
161 dali.cmd(DALI_INITIALISE,init_arg); 157 dali.cmd(DALI_INITIALISE,init_arg);
162 dali.cmd(DALI_RANDOMISE,0x00); 158 dali.cmd(DALI_RANDOMISE,0x00);
  159 +
  160 + //find used short addresses (run always, seems to work better than without...)
  161 + Serial.println("Find existing short adr");
  162 + for(sa = 0; sa<64; sa++) {
  163 + int16_t rv = dali.cmd(DALI_QUERY_STATUS,sa);
  164 + if(rv!=DALI_RESULT_NO_REPLY) {
  165 + if(init_arg!=0b00000000) arr[sa]=1; //remove address from list if not in "all" mode
  166 + Serial.print("sortadr=");
  167 + Serial.print(sa);
  168 + Serial.print(" status=0x");
  169 + Serial.print(rv,HEX);
  170 + Serial.print(" minLevel=");
  171 + Serial.println(dali.cmd(DALI_QUERY_MIN_LEVEL,sa));
  172 + }
  173 + }
163 174
164 Serial.println("Find random adr"); 175 Serial.println("Find random adr");
165 while(1) { 176 while(1) {
Examples/Monitor/Monitor.ino 0 → 100644
  1 +/*###########################################################################
  2 +DALI Interface Demo
  3 +
  4 +Monitors all messages on the DALI bus
  5 +
  6 +----------------------------------------------------------------------------
  7 +Changelog:
  8 +2020-11-10 Created & tested on ATMega328 @ 8Mhz
  9 +----------------------------------------------------------------------------
  10 + Monitor.ino - copyright qqqlab.com / github.com/qqqlab
  11 +
  12 + This program is free software: you can redistribute it and/or modify
  13 + it under the terms of the GNU General Public License as published by
  14 + the Free Software Foundation, either version 3 of the License, or
  15 + (at your option) any later version.
  16 +
  17 + This program is distributed in the hope that it will be useful,
  18 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20 + GNU General Public License for more details.
  21 +
  22 + You should have received a copy of the GNU General Public License
  23 + along with this program. If not, see <http://www.gnu.org/licenses/>.
  24 +###########################################################################*/
  25 +
  26 +#define DALI_OUTPUT_PIN 3
  27 +#define DALI_INPUT_PIN 4
  28 +
  29 +#include "qqqDali_ATMega328.h"
  30 +
  31 +Dali_ATMega328 dali;
  32 +
  33 +uint8_t rx_out=0;
  34 +volatile uint8_t rx_in=0;
  35 +uint8_t rx_data[256];
  36 +
  37 +//callback to handle received data on dali2 interface - executes in interrupt context, store data in buffer and display in loop()
  38 +void dali_receiver(Dali *d, uint8_t *data, uint8_t len) {
  39 + //push data in buffer
  40 + int16_t freebuf = (int16_t)256 + rx_in - rx_out - len - 2;
  41 + if(freebuf<=1) return; //buffer full
  42 + uint8_t j = rx_in;
  43 + rx_data[j++] = len; //push length
  44 + for(uint8_t i=0;i<len;i++) rx_data[j++]=data[i]; //push data
  45 + rx_in = j; //increment in pointer upon completion
  46 +}
  47 +
  48 +
  49 +void setup() {
  50 + Serial.begin(115200);
  51 + Serial.println("DALI Monitor Demo");
  52 +
  53 + //start the DALI interfaces
  54 + //arguments: tx_pin, rx_pin (negative values disable transmitter / receiver)
  55 + //Note: the receiver pins should be on different PCINT groups, e.g one
  56 + //receiver on pin0-7 (PCINT2) one on pin8-13 (PCINT0) and one on pin14-19 (PCINT1)
  57 + dali.begin(DALI_OUTPUT_PIN, DALI_INPUT_PIN);
  58 +
  59 + //attach a received data handler
  60 + dali.EventHandlerReceivedData = dali_receiver;
  61 +}
  62 +
  63 +#define MIN_LEVEL 100 //most LED Drivers do not get much lower than this
  64 +int16_t level = 254; //254 is max level, 1 is min level (if driver supports it), 0 is off
  65 +int8_t level_step = 4;
  66 +
  67 +void loop() {
  68 + if(rx_out!=rx_in) {
  69 + //Serial.print("RX:");
  70 + uint8_t len = rx_data[rx_out++];
  71 + for(uint8_t i=0;i<len;i++) {
  72 + Serial.print(rx_data[rx_out++],HEX);
  73 + Serial.print(' ');
  74 + }
  75 + Serial.println();
  76 + }
  77 +}
qqqDali.cpp
@@ -24,7 +24,7 @@ Changelog: @@ -24,7 +24,7 @@ Changelog:
24 //########################################################################### 24 //###########################################################################
25 // Helpers 25 // Helpers
26 //########################################################################### 26 //###########################################################################
27 -#define DALI_TOL 15 //allow for 15% tolerance on timing (DALI spec calls for 10%, add 5% for uc clock tolerance) 27 +#define DALI_TOL 25 //percentage tolerance on timing. DALI specs call for 10%, but use higher value to allow for implementation micros() jitter. NOTE: Max value is 50% to differentiate between TE and 2TE.
28 #define DALI_TE ((1000000+(DALI_BAUD))/(2*(DALI_BAUD))) //417us 28 #define DALI_TE ((1000000+(DALI_BAUD))/(2*(DALI_BAUD))) //417us
29 #define DALI_TE_MIN ((100-DALI_TOL)*DALI_TE)/100 29 #define DALI_TE_MIN ((100-DALI_TOL)*DALI_TE)/100
30 #define DALI_TE_MAX ((100+DALI_TOL)*DALI_TE)/100 30 #define DALI_TE_MAX ((100+DALI_TOL)*DALI_TE)/100
@@ -157,7 +157,7 @@ void Dali::ISR_pinchange() { @@ -157,7 +157,7 @@ void Dali::ISR_pinchange() {
157 this->rx_state = RX_IDLE; 157 this->rx_state = RX_IDLE;
158 //TODO rx error 158 //TODO rx error
159 return; 159 return;
160 - } 160 + }
161 break; 161 break;
162 } 162 }
163 } 163 }
@@ -177,34 +177,42 @@ void Dali::push_halfbit(uint8_t bit) { @@ -177,34 +177,42 @@ void Dali::push_halfbit(uint8_t bit) {
177 //########################################################################### 177 //###########################################################################
178 // Dali Class 178 // Dali Class
179 //########################################################################### 179 //###########################################################################
  180 +
  181 +//non blocking send - check tx_state for completion, check tx_collision for collision errors
180 uint8_t Dali::send(uint8_t* tx_msg, uint8_t tx_len_bytes) { 182 uint8_t Dali::send(uint8_t* tx_msg, uint8_t tx_len_bytes) {
181 - if(tx_len_bytes>3) return -(DALI_RESULT_INVALID_TOO_LONG); 183 + if(tx_len_bytes>3) return -(DALI_RESULT_DATA_TOO_LONG);
182 if(this->tx_state != TX_IDLE) return -(DALI_RESULT_TIMEOUT); 184 if(this->tx_state != TX_IDLE) return -(DALI_RESULT_TIMEOUT);
183 for(uint8_t i=0;i<tx_len_bytes;i++) this->tx_msg[i]=tx_msg[i]; 185 for(uint8_t i=0;i<tx_len_bytes;i++) this->tx_msg[i]=tx_msg[i];
184 this->tx_len = tx_len_bytes<<3; 186 this->tx_len = tx_len_bytes<<3;
185 this->tx_collision=0; 187 this->tx_collision=0;
186 - this->tx_state = TX_START; 188 + this->tx_state = TX_START; //start transmission
187 return 0; 189 return 0;
188 } 190 }
189 191
  192 +//blocking send - wait until successful send or timeout
190 uint8_t Dali::sendwait(uint8_t* tx_msg, uint8_t tx_len_bytes, uint32_t timeout_us) { 193 uint8_t Dali::sendwait(uint8_t* tx_msg, uint8_t tx_len_bytes, uint32_t timeout_us) {
191 - if(tx_len_bytes>3) return -(DALI_RESULT_INVALID_TOO_LONG); 194 + if(tx_len_bytes>3) return -(DALI_RESULT_DATA_TOO_LONG);
192 uint32_t ts = HAL_micros(); 195 uint32_t ts = HAL_micros();
193 - //wait for idle  
194 - while(this->tx_state != TX_IDLE) {  
195 - if(HAL_micros() - ts > timeout_us) return -(DALI_RESULT_TIMEOUT);  
196 - }  
197 - //start transmit  
198 - uint8_t rv = this->send(tx_msg,tx_len_bytes);  
199 - if(rv) return rv;  
200 - //wait for completion  
201 - while(this->tx_state != TX_IDLE) {  
202 - if(HAL_micros() - ts > timeout_us) return -(DALI_RESULT_TX_TIMEOUT); 196 +
  197 + while(1) {
  198 + //wait for idle
  199 + while(this->tx_state != TX_IDLE) {
  200 + if(HAL_micros() - ts > timeout_us) return -(DALI_RESULT_TIMEOUT);
  201 + }
  202 + //start transmit
  203 + uint8_t rv = this->send(tx_msg,tx_len_bytes);
  204 + if(rv) return rv;
  205 + //wait for completion
  206 + while(this->tx_state != TX_IDLE) {
  207 + if(HAL_micros() - ts > timeout_us) return -(DALI_RESULT_TX_TIMEOUT);
  208 + }
  209 + //check for collisions
  210 + if(this->tx_collision==0) return 0;
203 } 211 }
204 - return 0; 212 + return -(DALI_RESULT_TIMEOUT);
205 } 213 }
206 214
207 -//transmit 2 byte command, receive 1 byte reply 215 +//blocking transmit 2 byte command, receive 1 byte reply (if reply was sent)
208 int16_t Dali::tx(uint8_t cmd0, uint8_t cmd1, uint32_t timeout_us) { 216 int16_t Dali::tx(uint8_t cmd0, uint8_t cmd1, uint32_t timeout_us) {
209 uint8_t tx[2]; 217 uint8_t tx[2];
210 tx[0] = cmd0; 218 tx[0] = cmd0;
@@ -227,8 +235,6 @@ int16_t Dali::tx(uint8_t cmd0, uint8_t cmd1, uint32_t timeout_us) { @@ -227,8 +235,6 @@ int16_t Dali::tx(uint8_t cmd0, uint8_t cmd1, uint32_t timeout_us) {
227 return this->rx_msg[0]; 235 return this->rx_msg[0];
228 } 236 }
229 237
230 -  
231 -  
232 //================================================================= 238 //=================================================================
233 // High level 239 // High level
234 //================================================================= 240 //=================================================================
@@ -324,7 +330,7 @@ void Dali::set_searchaddr(uint32_t adr) { @@ -324,7 +330,7 @@ void Dali::set_searchaddr(uint32_t adr) {
324 this->cmd(DALI_SEARCHADDRL,adr); 330 this->cmd(DALI_SEARCHADDRL,adr);
325 } 331 }
326 332
327 -//set search address, but set only changed bytes 333 +//set search address, but set only changed bytes (takes less time)
328 void Dali::set_searchaddr_diff(uint32_t adr_new,uint32_t adr_current) { 334 void Dali::set_searchaddr_diff(uint32_t adr_new,uint32_t adr_current) {
329 if( (uint8_t)(adr_new>>16) != (uint8_t)(adr_current>>16) ) this->cmd(DALI_SEARCHADDRH,adr_new>>16); 335 if( (uint8_t)(adr_new>>16) != (uint8_t)(adr_current>>16) ) this->cmd(DALI_SEARCHADDRH,adr_new>>16);
330 if( (uint8_t)(adr_new>>8) != (uint8_t)(adr_current>>8) ) this->cmd(DALI_SEARCHADDRM,adr_new>>8); 336 if( (uint8_t)(adr_new>>8) != (uint8_t)(adr_current>>8) ) this->cmd(DALI_SEARCHADDRM,adr_new>>8);
@@ -336,8 +342,6 @@ uint8_t Dali::compare() { @@ -336,8 +342,6 @@ uint8_t Dali::compare() {
336 return (0xff == this->cmd(DALI_COMPARE,0x00)); 342 return (0xff == this->cmd(DALI_COMPARE,0x00));
337 } 343 }
338 344
339 -  
340 -  
341 //The slave shall store the received 6-bit address (AAAAAA) as a short address if it is selected. 345 //The slave shall store the received 6-bit address (AAAAAA) as a short address if it is selected.
342 void Dali::program_short_address(uint8_t shortadr) { 346 void Dali::program_short_address(uint8_t shortadr) {
343 this->cmd(DALI_PROGRAM_SHORT_ADDRESS, (shortadr << 1) | 0x01); 347 this->cmd(DALI_PROGRAM_SHORT_ADDRESS, (shortadr << 1) | 0x01);
@@ -384,57 +388,45 @@ uint8_t Dali::commission(uint8_t init_arg) { @@ -384,57 +388,45 @@ uint8_t Dali::commission(uint8_t init_arg) {
384 uint8_t arr[64]; 388 uint8_t arr[64];
385 uint8_t sa; 389 uint8_t sa;
386 for(sa=0; sa<64; sa++) arr[sa]=0; 390 for(sa=0; sa<64; sa++) arr[sa]=0;
387 -  
388 - //find existing short addresses when not assigning all  
389 - if(init_arg!=0b00000000) {  
390 - //Serial.println("Short adr");  
391 - for(sa = 0; sa<64; sa++) {  
392 - int16_t rv = this->cmd(DALI_QUERY_STATUS,sa);  
393 - if(rv!=DALI_RESULT_NO_REPLY) {  
394 - arr[sa]=1;  
395 - //Serial.print(sa);  
396 - //Serial.print(" status=0x");  
397 - //Serial.print(rv,HEX);  
398 - //Serial.print(" minLevel=");  
399 - //Serial.println(this->cmd(DALI_QUERY_MIN_LEVEL,sa));  
400 - }  
401 - }  
402 - }  
403 391
  392 + //start commissioning
  393 + this->cmd(DALI_RESET,0x00);
404 this->cmd(DALI_INITIALISE,init_arg); 394 this->cmd(DALI_INITIALISE,init_arg);
405 this->cmd(DALI_RANDOMISE,0x00); 395 this->cmd(DALI_RANDOMISE,0x00);
  396 +
  397 + //find used short addresses (run always, seems to work better than without...)
  398 + for(sa = 0; sa<64; sa++) {
  399 + int16_t rv = this->cmd(DALI_QUERY_STATUS,sa);
  400 + if(rv!=DALI_RESULT_NO_REPLY) {
  401 + if(init_arg!=0b00000000) arr[sa]=1; //remove address from list if not in "all" mode
  402 + }
  403 + }
406 404
  405 + //find random addresses and assign unused short addresses
407 while(1) { 406 while(1) {
408 - //Serial.print("addr=");  
409 - //Serial.println(this->get_random_address(0xff),HEX);  
410 -  
411 uint32_t adr = this->find_addr(); 407 uint32_t adr = this->find_addr();
412 if(adr>0xffffff) break; //no more random addresses found -> exit 408 if(adr>0xffffff) break; //no more random addresses found -> exit
413 - //Serial.print("found adr=");  
414 - //Serial.println(adr,HEX);  
415 409
416 - //Serial.print("short adr=");  
417 - //Serial.println(dali_query_short_address());  
418 -  
419 - //find available address 410 + //find first unused short address
420 for(sa=0; sa<64; sa++) { 411 for(sa=0; sa<64; sa++) {
421 if(arr[sa]==0) break; 412 if(arr[sa]==0) break;
422 } 413 }
423 if(sa>=64) break; //all 64 short addresses assigned -> exit 414 if(sa>=64) break; //all 64 short addresses assigned -> exit
  415 +
  416 + //mark short address as used
424 arr[sa] = 1; 417 arr[sa] = 1;
425 cnt++; 418 cnt++;
426 419
427 - //Serial.print("program short adr=");  
428 - //Serial.println(sa); 420 + //assign short address
429 this->program_short_address(sa); 421 this->program_short_address(sa);
430 - //dali_program_short_address(0xff);  
431 -  
432 - //Serial.print("read short adr="); 422 +
433 //Serial.println(this->query_short_address()); //TODO check read adr, handle if not the same... 423 //Serial.println(this->query_short_address()); //TODO check read adr, handle if not the same...
434 424
  425 + //remove the device from the search
435 this->cmd(DALI_WITHDRAW,0x00); 426 this->cmd(DALI_WITHDRAW,0x00);
436 } 427 }
437 - 428 +
  429 + //terminate the DALI_INITIALISE command
438 this->cmd(DALI_TERMINATE,0x00); 430 this->cmd(DALI_TERMINATE,0x00);
439 return cnt; 431 return cnt;
440 } 432 }
qqqDali.h
@@ -60,7 +60,7 @@ public: @@ -60,7 +60,7 @@ public:
60 60
61 //initialize variables 61 //initialize variables
62 Dali() : tx_state(TX_IDLE), rx_state(RX_IDLE), tx_bus_low(0), tx_len(0), EventHandlerReceivedData(0) {}; 62 Dali() : tx_state(TX_IDLE), rx_state(RX_IDLE), tx_bus_low(0), tx_len(0), EventHandlerReceivedData(0) {};
63 - 63 +
64 protected: 64 protected:
65 //low level functions 65 //low level functions
66 enum tx_stateEnum { TX_IDLE=0,TX_START,TX_START_X,TX_BIT,TX_BIT_X,TX_STOP1,TX_STOP1_X,TX_STOP2,TX_STOP2_X,TX_STOP3}; 66 enum tx_stateEnum { TX_IDLE=0,TX_START,TX_START_X,TX_BIT,TX_BIT_X,TX_STOP1,TX_STOP1_X,TX_STOP2,TX_STOP2_X,TX_STOP3};
@@ -79,6 +79,8 @@ protected: @@ -79,6 +79,8 @@ protected:
79 volatile uint8_t rx_len; //number of bytes received 79 volatile uint8_t rx_len; //number of bytes received
80 volatile int8_t rx_halfbitlen; //number of half bits received 80 volatile int8_t rx_halfbitlen; //number of half bits received
81 volatile uint8_t rx_last_halfbit; //last halfbit received 81 volatile uint8_t rx_last_halfbit; //last halfbit received
  82 +
  83 +
82 84
83 volatile uint8_t bus_idle_te_cnt; //number of Te since start of idle bus 85 volatile uint8_t bus_idle_te_cnt; //number of Te since start of idle bus
84 86
@@ -94,13 +96,12 @@ protected: @@ -94,13 +96,12 @@ protected:
94 96
95 #define DALI_BAUD 1200 97 #define DALI_BAUD 1200
96 98
97 -#define DALI_RESULT_TIMEOUT -1 //Timeout waiting for DALI bus  
98 -#define DALI_RESULT_INVALID_TOO_LONG -2 //Trying to send too many bytes (max 3)  
99 -#define DALI_RESULT_TX_TIMEOUT -3 //Timeout during transmission  
100 -#define DALI_RESULT_NO_REPLY -4 //cmd() did not receive a reply (i.e. received a 'NO' Backward Frame)  
101 -#define DALI_RESULT_INVALID_CMD -5 //The cmd argument in the call to cmd() was invalid  
102 -#define DALI_RESULT_INVALID_REPLY -6 //cmd() received an invalid reply (too long)  
103 - 99 +#define DALI_RESULT_TIMEOUT -1 //Timeout waiting for DALI bus
  100 +#define DALI_RESULT_DATA_TOO_LONG -2 //Trying to send too many bytes (max 3)
  101 +#define DALI_RESULT_TX_TIMEOUT -3 //Timeout during transmission
  102 +#define DALI_RESULT_NO_REPLY -4 //cmd() did not receive a reply (i.e. received a 'NO' Backward Frame)
  103 +#define DALI_RESULT_INVALID_CMD -5 //The cmd argument in the call to cmd() was invalid
  104 +#define DALI_RESULT_INVALID_REPLY -6 //cmd() received an invalid reply (too long)
104 105
105 //bit8=extended commands, bit9=repeat 106 //bit8=extended commands, bit9=repeat
106 #define DALI_OFF 0 //0 - Turns off lighting. 107 #define DALI_OFF 0 //0 - Turns off lighting.