Commit b0d2b6d6c8a538a356068cf7d2d3b13005f396dd

Authored by qqqlab
Committed by GitHub
0 parents

.

Examples/Dimmer/Dimmer.ino 0 → 100644
  1 +++ a/Examples/Dimmer/Dimmer.ino
  1 +/*###########################################################################
  2 +DALI Interface Demo
  3 +
  4 +Dimms all lights connected to the DALI bus up and down
  5 +
  6 +Works with Arduino ATMEGA328 + Mikroe DALI Click
  7 +
  8 +----------------------------------------------------------------------------
  9 +Changelog:
  10 +2020-11-08 Created & tested on ATMega328 @ 8Mhz
  11 +----------------------------------------------------------------------------
  12 + Dimmer.ino - copyright qqqlab.com / github.com/qqqlab
  13 +
  14 + This program is free software: you can redistribute it and/or modify
  15 + it under the terms of the GNU General Public License as published by
  16 + the Free Software Foundation, either version 3 of the License, or
  17 + (at your option) any later version.
  18 +
  19 + This program is distributed in the hope that it will be useful,
  20 + but WITHOUT ANY WARRANTY; without even the implied warranty of
  21 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22 + GNU General Public License for more details.
  23 +
  24 + You should have received a copy of the GNU General Public License
  25 + along with this program. If not, see <http://www.gnu.org/licenses/>.
  26 +###########################################################################*/
  27 +
  28 +#define DALI_OUTPUT_PIN 3
  29 +#define DALI_INPUT_PIN 4
  30 +
  31 +#include "qqqDali.h"
  32 +
  33 +Dali dali;
  34 +
  35 +void setup() {
  36 + Serial.begin(115200);
  37 + Serial.println("DALI Dimmer Demo");
  38 +
  39 + //start the DALI interfaces
  40 + //arguments: tx_pin, rx_pin (negative values disable transmitter / receiver)
  41 + //Note: the receiver pins should be on different PCINT groups, e.g one
  42 + //receiver on pin0-7 (PCINT2) one on pin8-13 (PCINT0) and one on pin14-19 (PCINT1)
  43 + dali.begin(DALI_OUTPUT_PIN, DALI_INPUT_PIN);
  44 +}
  45 +
  46 +#define MIN_LEVEL 100 //most LED Drivers do not get much lower than this
  47 +int16_t level = 254; //254 is max level, 1 is min level (if driver supports it), 0 is off
  48 +int8_t level_step = 4;
  49 +
  50 +void loop() {
  51 + Serial.print("set level: ");
  52 + Serial.println(level);
  53 + dali.set_level(level);
  54 +
  55 + level+=level_step;
  56 + if(level>=254) {
  57 + level = 254;
  58 + level_step = -level_step;
  59 + }
  60 + if(level<MIN_LEVEL) {
  61 + level = MIN_LEVEL;
  62 + level_step = -level_step;
  63 + }
  64 +}
... ...
qqqDali.cpp 0 → 100644
  1 +++ a/qqqDali.cpp
  1 +/*###########################################################################
  2 + qqqDali.cpp - 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-08 Created & tested on ATMega328 @ 8Mhz
  20 +###########################################################################*/
  21 +#include "qqqDali.h"
  22 +#include "arduino.h"
  23 +
  24 +//###########################################################################
  25 +// Helpers
  26 +//###########################################################################
  27 +#define DALI_BUS_LOW() digitalWrite(this->tx_pin,LOW); this->tx_bus_low=1
  28 +#define DALI_BUS_HIGH() digitalWrite(this->tx_pin,HIGH); this->tx_bus_low=0
  29 +#define DALI_IS_BUS_LOW() (digitalRead(this->rx_pin)==LOW)
  30 +#define DALI_BAUD 1200
  31 +#define DALI_TE ((1000000+(DALI_BAUD))/(2*(DALI_BAUD))) //417us
  32 +#define DALI_TE_MIN (80*DALI_TE)/100
  33 +#define DALI_TE_MAX (120*DALI_TE)/100
  34 +#define DALI_IS_TE(x) ((DALI_TE_MIN)<=(x) && (x)<=(DALI_TE_MAX))
  35 +#define DALI_IS_2TE(x) ((2*(DALI_TE_MIN))<=(x) && (x)<=(2*(DALI_TE_MAX)))
  36 +
  37 +//###########################################################################
  38 +// Transmitter ISR
  39 +//###########################################################################
  40 +static Dali *IsrTimerHooks[DALI_HOOK_COUNT+1];
  41 +
  42 +// timer compare interrupt service routine
  43 +ISR(TIMER1_COMPA_vect) {
  44 +
  45 + for(uint8_t i=0;i<DALI_HOOK_COUNT;i++) {
  46 + if(IsrTimerHooks[i]==NULL) {return;}
  47 + IsrTimerHooks[i]->ISR_timer();
  48 + }
  49 +}
  50 +
  51 +//called every Te period (417us)
  52 +void Dali::ISR_timer() {
  53 + if(this->bus_idle_te_cnt<0xff) this->bus_idle_te_cnt++;
  54 +
  55 + //send starbit, message bytes, 2 stop bits.
  56 + switch(this->tx_state) {
  57 + case TX_IDLE:
  58 + break;
  59 + case TX_START:
  60 + //wait for timeslot, then send start bit
  61 + if(this->bus_idle_te_cnt >= 22) {
  62 + DALI_BUS_LOW();
  63 + this->tx_state = TX_START_X;
  64 + }
  65 + break;
  66 + case TX_START_X:
  67 + DALI_BUS_HIGH();
  68 + this->tx_pos=0;
  69 + this->tx_state = TX_BIT;
  70 + break;
  71 + case TX_BIT:
  72 + if(this->tx_msg[this->tx_pos>>3] & 1<<(7-(this->tx_pos&0x7))) {DALI_BUS_LOW();} else {DALI_BUS_HIGH();}
  73 + this->tx_state = TX_BIT_X;
  74 + break;
  75 + case TX_BIT_X:
  76 + if(this->tx_msg[this->tx_pos>>3] & 1<<(7-(this->tx_pos&0x7))) {DALI_BUS_HIGH();} else {DALI_BUS_LOW();}
  77 + this->tx_pos++;
  78 + if(this->tx_pos < this->tx_len) {this->tx_state = TX_BIT;} else {this->tx_state = TX_STOP1;}
  79 + break;
  80 + case TX_STOP1:
  81 + DALI_BUS_HIGH();
  82 + this->tx_state = TX_STOP1_X;
  83 + break;
  84 + case TX_STOP1_X:
  85 + this->tx_state = TX_STOP2;
  86 + break;
  87 + case TX_STOP2:
  88 + this->tx_state = TX_STOP2_X;
  89 + break;
  90 + case TX_STOP2_X:
  91 + this->tx_state = TX_STOP3;
  92 + break;
  93 + case TX_STOP3:
  94 + this->bus_idle_te_cnt=0;
  95 + this->tx_state = TX_IDLE;
  96 + this->rx_state = RX_IDLE;
  97 + this->rx_len = 0;
  98 + break;
  99 + }
  100 +
  101 + //handle receiver stop bits
  102 + if(this->rx_state == RX_BIT && this->bus_idle_te_cnt>4) {
  103 + this->rx_state = RX_IDLE;
  104 + //received two stop bits, got message in rx_msg + rx_halfbitlen
  105 + uint8_t bitlen = (this->rx_halfbitlen+1)>>1;
  106 + if((bitlen & 0x7) == 0) {
  107 + this->rx_len = bitlen>>3;
  108 + if(this->EventHandlerReceivedData!=NULL) this->EventHandlerReceivedData(this, (uint8_t*)this->rx_msg, this->rx_len);
  109 + }else{
  110 + //invalid bitlen
  111 + //TODO handle this
  112 + }
  113 + }
  114 +}
  115 +
  116 +//###########################################################################
  117 +// Receiver ISR
  118 +//###########################################################################
  119 +//pin PCINT
  120 +//0-7 PCINT2_vect PCINT16-23
  121 +//8-13 PCINT0_vect PCINT0-5
  122 +//14-19 PCINT1_vect PCINT8-13
  123 +static Dali *IsrPCINT0Hook;
  124 +static Dali *IsrPCINT1Hook;
  125 +static Dali *IsrPCINT2Hook;
  126 +
  127 +ISR(PCINT0_vect) {
  128 + if(IsrPCINT0Hook!=NULL) IsrPCINT0Hook->ISR_pinchange();
  129 +}
  130 +ISR(PCINT1_vect) {
  131 + if(IsrPCINT1Hook!=NULL) IsrPCINT1Hook->ISR_pinchange();
  132 +}
  133 +ISR(PCINT2_vect) {
  134 + if(IsrPCINT2Hook!=NULL) IsrPCINT2Hook->ISR_pinchange();
  135 +}
  136 +
  137 +
  138 +void Dali::ISR_pinchange() {
  139 + uint32_t ts = micros(); //get timestamp of change
  140 + this->bus_idle_te_cnt=0; //reset idle counter
  141 + uint8_t bus_low = DALI_IS_BUS_LOW();
  142 +
  143 + //exit if transmitting
  144 + if(this->tx_state != TX_IDLE) {
  145 + //check tx collision
  146 + if(bus_low && !this->tx_bus_low) {
  147 + this->tx_state = TX_IDLE; //stop transmitter
  148 + this->tx_collision = 1; //mark collision
  149 + }
  150 + return;
  151 + }
  152 +
  153 + //no bus change, ignore
  154 + if(bus_low == this->rx_last_bus_low) return;
  155 +
  156 + //store values for next loop
  157 + uint32_t dt = ts - this->rx_last_change_ts;
  158 + this->rx_last_change_ts = ts;
  159 + this->rx_last_bus_low = bus_low;
  160 +
  161 + switch(this->rx_state) {
  162 + case RX_IDLE:
  163 + if(bus_low) {
  164 + this->rx_state = RX_START;
  165 + }
  166 + break;
  167 + case RX_START:
  168 + if(bus_low || !DALI_IS_TE(dt)) {
  169 + this->rx_state = RX_IDLE;
  170 + }else{
  171 + this->rx_halfbitlen=-1;
  172 + for(uint8_t i=0;i<7;i++) this->rx_msg[0]=0;
  173 + this->rx_state = RX_BIT;
  174 + }
  175 + break;
  176 + case RX_BIT:
  177 + if(DALI_IS_TE(dt)) {
  178 + //got a single Te pulse
  179 + this->push_halfbit(bus_low);
  180 + } else if(DALI_IS_2TE(dt)) {
  181 + //got a double Te pulse
  182 + this->push_halfbit(bus_low);
  183 + this->push_halfbit(bus_low);
  184 + } else {
  185 + //got something else -> no good
  186 + this->rx_state = RX_IDLE;
  187 + //TODO rx error
  188 + return;
  189 + }
  190 + break;
  191 + }
  192 +}
  193 +
  194 +void Dali::push_halfbit(uint8_t bit) {
  195 + bit = (~bit)&1;
  196 + if((this->rx_halfbitlen & 1)==0) {
  197 + uint8_t i = this->rx_halfbitlen>>4;
  198 + if(i<3) {
  199 + this->rx_msg[i] = (this->rx_msg[i]<<1) | bit;
  200 + }
  201 + }
  202 + this->rx_halfbitlen++;
  203 +}
  204 +
  205 +
  206 +//###########################################################################
  207 +// Dali Class
  208 +//###########################################################################
  209 +void Dali::begin(int8_t tx_pin, int8_t rx_pin) {
  210 + this->tx_pin = tx_pin;
  211 + this->rx_pin = rx_pin;
  212 + this->tx_state = TX_IDLE;
  213 + this->rx_state = RX_IDLE;
  214 +
  215 + //setup tx
  216 + if(this->tx_pin>=0) {
  217 + //setup tx pin
  218 + pinMode(this->tx_pin, OUTPUT);
  219 + DALI_BUS_HIGH();
  220 +
  221 + //setup tx timer interrupt
  222 + TCCR1A = 0;
  223 + TCCR1B = 0;
  224 + TCNT1 = 0;
  225 +
  226 + OCR1A = (F_CPU+(DALI_BAUD))/(2*(DALI_BAUD)); // compare match register 16MHz/256/2Hz
  227 + TCCR1B |= (1 << WGM12); // CTC mode
  228 + TCCR1B |= (1 << CS10); // 1:1 prescaler
  229 + TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
  230 +
  231 + //setup timer interrupt hooks
  232 + for(uint8_t i=0;i<DALI_HOOK_COUNT;i++) {
  233 + if(IsrTimerHooks[i] == NULL) {
  234 + IsrTimerHooks[i] = this;
  235 + break;
  236 + }
  237 + }
  238 + }
  239 +
  240 + //setup rx
  241 + if(this->rx_pin>=0) {
  242 + //setup rx pin
  243 + pinMode(this->rx_pin, INPUT);
  244 +
  245 + //setup rx pinchange interrupt
  246 + // 0- 7 PCINT2_vect PCINT16-23
  247 + // 8-13 PCINT0_vect PCINT0-5
  248 + //14-19 PCINT1_vect PCINT8-13
  249 + if(this->rx_pin<=7){
  250 + PCICR |= (1<<PCIE2);
  251 + PCMSK2 |= (1<< (this->rx_pin));
  252 + IsrPCINT2Hook = this; //setup pinchange interrupt hook
  253 + }else if(this->rx_pin<=13) {
  254 + PCICR |= (1<<PCIE0);
  255 + PCMSK0 |= (1<< (this->rx_pin-8));
  256 + IsrPCINT0Hook = this; //setup pinchange interrupt hook
  257 + }else if(this->rx_pin<=19) {
  258 + PCICR |= (1<<PCIE1);
  259 + PCMSK1 |= (1<< (this->rx_pin-14));
  260 + IsrPCINT1Hook = this; //setup pinchange interrupt hook
  261 + }
  262 + }
  263 +}
  264 +
  265 +
  266 +uint8_t Dali::send(uint8_t* tx_msg, uint8_t tx_len_bytes) {
  267 + if(tx_len_bytes>3) return -(DALI_RESULT_INVALID_TOO_LONG);
  268 + if(this->tx_state != TX_IDLE) return -(DALI_RESULT_TIMEOUT);
  269 + for(uint8_t i=0;i<tx_len_bytes;i++) this->tx_msg[i]=tx_msg[i];
  270 + this->tx_len = tx_len_bytes<<3;
  271 + this->tx_collision=0;
  272 + this->tx_state = TX_START;
  273 + return 0;
  274 +}
  275 +
  276 +uint8_t Dali::sendwait(uint8_t* tx_msg, uint8_t tx_len_bytes, uint32_t timeout_ms) {
  277 + if(tx_len_bytes>3) return -(DALI_RESULT_INVALID_TOO_LONG);
  278 + uint32_t ts = millis();
  279 + //wait for idle
  280 + while(this->tx_state != TX_IDLE) {
  281 + if(millis() - ts > timeout_ms) return -(DALI_RESULT_TIMEOUT);
  282 + }
  283 + //start transmit
  284 + uint8_t rv = this->send(tx_msg,tx_len_bytes);
  285 + if(rv) return rv;
  286 + //wait for completion
  287 + while(this->tx_state != TX_IDLE) {
  288 + if(millis() - ts > timeout_ms) return -(DALI_RESULT_TX_TIMEOUT);
  289 + }
  290 + return 0;
  291 +}
  292 +
  293 +//transmit 2 byte command, receive 1 byte reply
  294 +int16_t Dali::tx(uint8_t cmd0, uint8_t cmd1, uint32_t timeout_ms) {
  295 + uint8_t tx[2];
  296 + tx[0] = cmd0;
  297 + tx[1] = cmd1;
  298 + int16_t rv = this->sendwait(tx,2);
  299 + this->rx_halfbitlen = 0;
  300 + if(rv) return -rv;;
  301 +
  302 + //wait up to 10 ms for start of reply
  303 + uint32_t ts = millis();
  304 + while(this->rx_state == RX_IDLE) {
  305 + if(millis() - ts > 10) return DALI_RESULT_NO_REPLY;
  306 + }
  307 + //wait up to 15 ms for completion of reply
  308 + ts = millis();
  309 + while(this->rx_len == 0) {
  310 + if(millis() - ts > 15) return DALI_RESULT_NO_REPLY;
  311 + }
  312 + if(this->rx_len > 1) return DALI_RESULT_INVALID_REPLY;
  313 + return this->rx_msg[0];
  314 +}
  315 +
  316 +
  317 +
  318 +//=================================================================
  319 +// High level
  320 +//=================================================================
  321 +//check YAAAAAA: 0000 0000 to 0011 1111 adr, 0100 0000 to 0100 1111 group, x111 1111 broadcast
  322 +uint8_t Dali::check_yaaaaaa(uint8_t yaaaaaa) {
  323 + return (yaaaaaa<=0b01001111 || yaaaaaa==0b01111111 || yaaaaaa==0b11111111);
  324 +}
  325 +
  326 +void Dali::set_level(uint8_t level, uint8_t adr) {
  327 + if(this->check_yaaaaaa(adr)) this->tx(adr<<1,level);
  328 +}
  329 +
  330 +int16_t Dali::cmd(uint16_t cmd, uint8_t arg) {
  331 + //Serial.print("dali_cmd[");Serial.print(cmd,HEX);Serial.print(",");Serial.print(arg,HEX);Serial.print(")");
  332 + uint8_t cmd0,cmd1;
  333 + if(cmd&0x0100) {
  334 + //special commands: MUST NOT have YAAAAAAX pattern for cmd
  335 + //Serial.print(" SPC");
  336 + if(!this->check_yaaaaaa(cmd>>1)) {
  337 + cmd0 = cmd;
  338 + cmd1 = arg;
  339 + }else{
  340 + return DALI_RESULT_INVALID_CMD;
  341 + }
  342 + }else{
  343 + //regular commands: MUST have YAAAAAA pattern for arg
  344 +
  345 + //Serial.print(" REG");
  346 + if(this->check_yaaaaaa(arg)) {
  347 + cmd0 = arg<<1|1;
  348 + cmd1 = cmd;
  349 + }else{
  350 + return DALI_RESULT_INVALID_CMD;
  351 + }
  352 + }
  353 + if(cmd&0x0200) {
  354 + //Serial.print(" REPEAT");
  355 + this->tx(cmd0, cmd1);
  356 + }
  357 + int16_t rv = this->tx(cmd0, cmd1);
  358 + //Serial.print(" rv=");Serial.println(rv);
  359 + return rv;
  360 +}
  361 +
  362 +
  363 +uint8_t Dali::set_operating_mode(uint8_t v, uint8_t adr) {
  364 + return set_value(DALI_SET_OPERATING_MODE, DALI_QUERY_OPERATING_MODE, v, adr);
  365 +}
  366 +
  367 +uint8_t Dali::set_max_level(uint8_t v, uint8_t adr) {
  368 + return set_value(DALI_SET_MAX_LEVEL, DALI_QUERY_MAX_LEVEL, v, adr);
  369 +}
  370 +
  371 +uint8_t Dali::set_min_level(uint8_t v, uint8_t adr) {
  372 + return set_value(DALI_SET_MIN_LEVEL, DALI_QUERY_MIN_LEVEL, v, adr);
  373 +}
  374 +
  375 +
  376 +uint8_t Dali::set_system_failure_level(uint8_t v, uint8_t adr) {
  377 + return set_value(DALI_SET_SYSTEM_FAILURE_LEVEL, DALI_QUERY_SYSTEM_FAILURE_LEVEL, v, adr);
  378 +}
  379 +
  380 +uint8_t Dali::set_power_on_level(uint8_t v, uint8_t adr) {
  381 + return set_value(DALI_SET_POWER_ON_LEVEL, DALI_QUERY_POWER_ON_LEVEL, v, adr);
  382 +}
  383 +
  384 +//set a parameter value, returns 0 on success
  385 +uint8_t Dali::set_value(uint16_t setcmd, uint16_t getcmd, uint8_t v, uint8_t adr) {
  386 + int16_t current_v = this->cmd(getcmd,adr); //get current parameter value
  387 + if(current_v == v) return 0;
  388 + this->cmd(DALI_DATA_TRANSFER_REGISTER0,v); //store value in DTR
  389 + int16_t dtr = this->cmd(DALI_QUERY_CONTENT_DTR0,adr); //get DTR value
  390 + if(dtr != v) return 1;
  391 + this->cmd(setcmd,adr); //set parameter value = DTR
  392 + current_v = this->cmd(getcmd,adr); //get current parameter value
  393 + if(current_v != v) return 2;
  394 + return 0;
  395 +}
  396 +
  397 +
... ...
qqqDali.h 0 → 100644
  1 +++ a/qqqDali.h
  1 +/*###########################################################################
  2 + qqqDali.h - 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-08 Created & tested on ATMega328 @ 8Mhz
  20 +###########################################################################*/
  21 +#include <inttypes.h>
  22 +
  23 +
  24 +class Dali {
  25 +public:
  26 + void begin(int8_t tx_pin, int8_t rx_pin);
  27 +
  28 + //high level functions
  29 + void set_level(uint8_t level, uint8_t adr=0xFF); //set arc level
  30 + 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
  31 + uint8_t set_operating_mode(uint8_t v, uint8_t adr=0xFF); //returns 0 on success
  32 + uint8_t set_max_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success
  33 + uint8_t set_min_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success
  34 + uint8_t set_system_failure_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success
  35 + uint8_t set_power_on_level(uint8_t v, uint8_t adr=0xFF); //returns 0 on success
  36 +
  37 +
  38 +
  39 + //low level functions
  40 + typedef void (*EventHandlerReceivedDataFuncPtr)(Dali *sender, uint8_t *data, uint8_t len);
  41 + EventHandlerReceivedDataFuncPtr EventHandlerReceivedData;
  42 +
  43 + uint8_t send(uint8_t* tx_msg, uint8_t tx_len_bytes);
  44 + uint8_t sendwait(uint8_t* tx_msg, uint8_t tx_len_bytes, uint32_t timeout_ms=500);
  45 + int16_t tx(uint8_t cmd0, uint8_t cmd1, uint32_t timeout_ms=500);
  46 + void ISR_timer();
  47 + void ISR_pinchange();
  48 +
  49 + #define DALI_HOOK_COUNT 3
  50 +
  51 +
  52 +private:
  53 + //low level functions
  54 + 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};
  55 + uint8_t tx_pin; //transmitter pin
  56 + uint8_t tx_msg[3]; //message to transmit
  57 + uint8_t tx_len; //number of bits to transmit
  58 + volatile uint8_t tx_pos; //current bit transmit position
  59 + volatile tx_stateEnum tx_state; //current state
  60 + volatile uint8_t tx_collision; //collistion occured
  61 + volatile uint8_t tx_bus_low; //bus is low according to transmitter?
  62 +
  63 + enum rx_stateEnum { RX_IDLE,RX_START,RX_BIT};
  64 + uint8_t rx_pin; //receiver pin
  65 + volatile uint8_t rx_last_bus_low; //receiver as low at last pinchange
  66 + volatile uint32_t rx_last_change_ts; //timestamp last pinchange
  67 + volatile rx_stateEnum rx_state; //current state
  68 + volatile uint8_t rx_msg[3]; //message received
  69 + volatile uint8_t rx_len; //number of bytes received
  70 + volatile int8_t rx_halfbitlen; //number of half bits received
  71 + volatile uint8_t rx_last_halfbit; //last halfbit received
  72 +
  73 + volatile uint8_t bus_idle_te_cnt; //number of Te since start of idle bus
  74 +
  75 + void push_halfbit(uint8_t bit);
  76 +
  77 + //high level functions
  78 + uint8_t check_yaaaaaa(uint8_t yaaaaaa); //check for yaaaaaa pattern
  79 + uint8_t set_value(uint16_t setcmd, uint16_t getcmd, uint8_t v, uint8_t adr); //set a parameter value, returns 0 on success
  80 +};
  81 +
  82 +
  83 +#define DALI_RESULT_TIMEOUT -1 //Timeout waiting for DALI bus
  84 +#define DALI_RESULT_INVALID_TOO_LONG -2 //Trying to send too many bytes (max 3)
  85 +#define DALI_RESULT_TX_TIMEOUT -3 //Timeout during transmission
  86 +#define DALI_RESULT_NO_REPLY -4 //cmd() did not receive a reply (i.e. received a 'NO' Backward Frame)
  87 +#define DALI_RESULT_INVALID_CMD -5 //The cmd argument in the call to cmd() was invalid
  88 +#define DALI_RESULT_INVALID_REPLY -6 //cmd() received an invalid reply (too long)
  89 +
  90 +
  91 +//bit8=extended commands, bit9=repeat
  92 +#define DALI_OFF 0 //0 - Turns off lighting.
  93 +#define DALI_UP 1 //1 - Increases the lighting control level for 200 ms according to the Fade rate.
  94 +#define DALI_DOWN 2 //2 - Decreases the lighting control level for 200 ms according to the Fade rate.
  95 +#define DALI_STEP_UP 3 //3 - Increments the lighting control level (without fade).
  96 +#define DALI_STEP_DOWN 4 //4 - Decrements the lighting control level (without fade).
  97 +#define DALI_RECALL_MAX_LEVEL 5 //5 - Maximizes the lighting control level (without fade).
  98 +#define DALI_RECALL_MIN_LEVEL 6 //6 - Minimizes the lighting control level (without fade)
  99 +#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).
  100 +#define DALI_ON_AND_STEP_UP 8 //8 - Increments the lighting control level and turns on lighting if lighting is off (with fade).
  101 +#define DALI_ENABLE_DAPC_SEQUENCE 9 //9 - It shows the repeat start of the DAPC command.
  102 +#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)
  103 +#define DALI_RESERVED11 11 //11 - [Reserved]
  104 +#define DALI_RESERVED12 12 //12 - [Reserved]
  105 +#define DALI_RESERVED13 13 //13 - [Reserved]
  106 +#define DALI_RESERVED14 14 //14 - [Reserved]
  107 +#define DALI_RESERVED16 16 //16 - [Reserved]
  108 +#define DALI_GO_TO_SCENE0 16 //16 - Adjusts the lighting control level for Scene XXXX according to the fade time.
  109 +#define DALI_GO_TO_SCENE1 17 //17 - Adjusts the lighting control level for Scene XXXX according to the fade time.
  110 +#define DALI_GO_TO_SCENE2 18 //18 - Adjusts the lighting control level for Scene XXXX according to the fade time.
  111 +#define DALI_GO_TO_SCENE3 19 //19 - Adjusts the lighting control level for Scene XXXX according to the fade time.
  112 +#define DALI_GO_TO_SCENE4 20 //20 - Adjusts the lighting control level for Scene XXXX according to the fade time.
  113 +#define DALI_GO_TO_SCENE5 21 //21 - Adjusts the lighting control level for Scene XXXX according to the fade time.
  114 +#define DALI_GO_TO_SCENE6 22 //22 - Adjusts the lighting control level for Scene XXXX according to the fade time.
  115 +#define DALI_GO_TO_SCENE7 23 //23 - Adjusts the lighting control level for Scene XXXX according to the fade time.
  116 +#define DALI_GO_TO_SCENE8 24 //24 - Adjusts the lighting control level for Scene XXXX according to the fade time.
  117 +#define DALI_GO_TO_SCENE9 25 //25 - Adjusts the lighting control level for Scene XXXX according to the fade time.
  118 +#define DALI_GO_TO_SCENE10 26 //26 - Adjusts the lighting control level for Scene XXXX according to the fade time.
  119 +#define DALI_GO_TO_SCENE11 27 //27 - Adjusts the lighting control level for Scene XXXX according to the fade time.
  120 +#define DALI_GO_TO_SCENE12 28 //28 - Adjusts the lighting control level for Scene XXXX according to the fade time.
  121 +#define DALI_GO_TO_SCENE13 29 //29 - Adjusts the lighting control level for Scene XXXX according to the fade time.
  122 +#define DALI_GO_TO_SCENE14 30 //30 - Adjusts the lighting control level for Scene XXXX according to the fade time.
  123 +#define DALI_GO_TO_SCENE15 31 //31 - Adjusts the lighting control level for Scene XXXX according to the fade time.
  124 +#define DALI_RESET 544 //32 REPEAT - Makes a slave an RESET state.
  125 +#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)
  126 +#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)
  127 +#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)
  128 +#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)
  129 +#define DALI_IDENTIFY_DEVICE 549 //37 REPEAT DALI-2 - Starts the identification state of the device. (Command that exist only in IEC62386-102ed2.0)
  130 +#define DALI_RESERVED38 550 //38 REPEAT - [Reserved]
  131 +#define DALI_RESERVED39 551 //39 REPEAT - [Reserved]
  132 +#define DALI_RESERVED40 552 //40 REPEAT - [Reserved]
  133 +#define DALI_RESERVED41 553 //41 REPEAT - [Reserved]
  134 +#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)
  135 +#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)
  136 +#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)
  137 +#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)
  138 +#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)
  139 +#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)
  140 +#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)
  141 +#define DALI_RESERVED49 561 //49 REPEAT - [Reserved]
  142 +#define DALI_RESERVED50 562 //50 REPEAT - [Reserved]
  143 +#define DALI_RESERVED51 563 //51 REPEAT - [Reserved]
  144 +#define DALI_RESERVED52 564 //52 REPEAT - [Reserved]
  145 +#define DALI_RESERVED53 565 //53 REPEAT - [Reserved]
  146 +#define DALI_RESERVED54 566 //54 REPEAT - [Reserved]
  147 +#define DALI_RESERVED55 567 //55 REPEAT - [Reserved]
  148 +#define DALI_RESERVED56 568 //56 REPEAT - [Reserved]
  149 +#define DALI_RESERVED57 569 //57 REPEAT - [Reserved]
  150 +#define DALI_RESERVED58 570 //58 REPEAT - [Reserved]
  151 +#define DALI_RESERVED59 571 //59 REPEAT - [Reserved]
  152 +#define DALI_RESERVED60 572 //60 REPEAT - [Reserved]
  153 +#define DALI_RESERVED61 573 //61 REPEAT - [Reserved]
  154 +#define DALI_RESERVED62 574 //62 REPEAT - [Reserved]
  155 +#define DALI_RESERVED63 575 //63 REPEAT - [Reserved]
  156 +#define DALI_SET_SCENE0 576 //64 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0)
  157 +#define DALI_SET_SCENE1 577 //65 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0)
  158 +#define DALI_SET_SCENE2 578 //66 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0)
  159 +#define DALI_SET_SCENE3 579 //67 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0)
  160 +#define DALI_SET_SCENE4 580 //68 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0)
  161 +#define DALI_SET_SCENE5 581 //69 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0)
  162 +#define DALI_SET_SCENE6 582 //70 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0)
  163 +#define DALI_SET_SCENE7 583 //71 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0)
  164 +#define DALI_SET_SCENE8 584 //72 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0)
  165 +#define DALI_SET_SCENE9 585 //73 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0)
  166 +#define DALI_SET_SCENE10 586 //74 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0)
  167 +#define DALI_SET_SCENE11 587 //75 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0)
  168 +#define DALI_SET_SCENE12 588 //76 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0)
  169 +#define DALI_SET_SCENE13 589 //77 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0)
  170 +#define DALI_SET_SCENE14 590 //78 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0)
  171 +#define DALI_SET_SCENE15 591 //79 REPEAT - Specifies the DTR data as Scene XXXX. (In the parenthesis is a name in IEC62386-102ed2.0)
  172 +#define DALI_REMOVE_FROM_SCENE0 592 //80 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.)
  173 +#define DALI_REMOVE_FROM_SCENE1 593 //81 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.)
  174 +#define DALI_REMOVE_FROM_SCENE2 594 //82 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.)
  175 +#define DALI_REMOVE_FROM_SCENE3 595 //83 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.)
  176 +#define DALI_REMOVE_FROM_SCENE4 596 //84 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.)
  177 +#define DALI_REMOVE_FROM_SCENE5 597 //85 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.)
  178 +#define DALI_REMOVE_FROM_SCENE6 598 //86 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.)
  179 +#define DALI_REMOVE_FROM_SCENE7 599 //87 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.)
  180 +#define DALI_REMOVE_FROM_SCENE8 600 //88 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.)
  181 +#define DALI_REMOVE_FROM_SCENE9 601 //89 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.)
  182 +#define DALI_REMOVE_FROM_SCENE10 602 //90 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.)
  183 +#define DALI_REMOVE_FROM_SCENE11 603 //91 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.)
  184 +#define DALI_REMOVE_FROM_SCENE12 604 //92 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.)
  185 +#define DALI_REMOVE_FROM_SCENE13 605 //93 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.)
  186 +#define DALI_REMOVE_FROM_SCENE14 606 //94 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.)
  187 +#define DALI_REMOVE_FROM_SCENE15 607 //95 REPEAT - Deletes the Scene XXXX setting. (Specifies 1111 1111 for the scene register.)
  188 +#define DALI_ADD_TO_GROUP0 608 //96 REPEAT - Adds the slave to Group XXXX.
  189 +#define DALI_ADD_TO_GROUP1 609 //97 REPEAT - Adds the slave to Group XXXX.
  190 +#define DALI_ADD_TO_GROUP2 610 //98 REPEAT - Adds the slave to Group XXXX.
  191 +#define DALI_ADD_TO_GROUP3 611 //99 REPEAT - Adds the slave to Group XXXX.
  192 +#define DALI_ADD_TO_GROUP4 612 //100 REPEAT - Adds the slave to Group XXXX.
  193 +#define DALI_ADD_TO_GROUP5 613 //101 REPEAT - Adds the slave to Group XXXX.
  194 +#define DALI_ADD_TO_GROUP6 614 //102 REPEAT - Adds the slave to Group XXXX.
  195 +#define DALI_ADD_TO_GROUP7 615 //103 REPEAT - Adds the slave to Group XXXX.
  196 +#define DALI_ADD_TO_GROUP8 616 //104 REPEAT - Adds the slave to Group XXXX.
  197 +#define DALI_ADD_TO_GROUP9 617 //105 REPEAT - Adds the slave to Group XXXX.
  198 +#define DALI_ADD_TO_GROUP10 618 //106 REPEAT - Adds the slave to Group XXXX.
  199 +#define DALI_ADD_TO_GROUP11 619 //107 REPEAT - Adds the slave to Group XXXX.
  200 +#define DALI_ADD_TO_GROUP12 620 //108 REPEAT - Adds the slave to Group XXXX.
  201 +#define DALI_ADD_TO_GROUP13 621 //109 REPEAT - Adds the slave to Group XXXX.
  202 +#define DALI_ADD_TO_GROUP14 622 //110 REPEAT - Adds the slave to Group XXXX.
  203 +#define DALI_ADD_TO_GROUP15 623 //111 REPEAT - Adds the slave to Group XXXX.
  204 +#define DALI_REMOVE_FROM_GROUP0 624 //112 REPEAT - Deletes the slave from Group XXXX.
  205 +#define DALI_REMOVE_FROM_GROUP1 625 //113 REPEAT - Deletes the slave from Group XXXX.
  206 +#define DALI_REMOVE_FROM_GROUP2 626 //114 REPEAT - Deletes the slave from Group XXXX.
  207 +#define DALI_REMOVE_FROM_GROUP3 627 //115 REPEAT - Deletes the slave from Group XXXX.
  208 +#define DALI_REMOVE_FROM_GROUP4 628 //116 REPEAT - Deletes the slave from Group XXXX.
  209 +#define DALI_REMOVE_FROM_GROUP5 629 //117 REPEAT - Deletes the slave from Group XXXX.
  210 +#define DALI_REMOVE_FROM_GROUP6 630 //118 REPEAT - Deletes the slave from Group XXXX.
  211 +#define DALI_REMOVE_FROM_GROUP7 631 //119 REPEAT - Deletes the slave from Group XXXX.
  212 +#define DALI_REMOVE_FROM_GROUP8 632 //120 REPEAT - Deletes the slave from Group XXXX.
  213 +#define DALI_REMOVE_FROM_GROUP9 633 //121 REPEAT - Deletes the slave from Group XXXX.
  214 +#define DALI_REMOVE_FROM_GROUP10 634 //122 REPEAT - Deletes the slave from Group XXXX.
  215 +#define DALI_REMOVE_FROM_GROUP11 635 //123 REPEAT - Deletes the slave from Group XXXX.
  216 +#define DALI_REMOVE_FROM_GROUP12 636 //124 REPEAT - Deletes the slave from Group XXXX.
  217 +#define DALI_REMOVE_FROM_GROUP13 637 //125 REPEAT - Deletes the slave from Group XXXX.
  218 +#define DALI_REMOVE_FROM_GROUP14 638 //126 REPEAT - Deletes the slave from Group XXXX.
  219 +#define DALI_REMOVE_FROM_GROUP15 639 //127 REPEAT - Deletes the slave from Group XXXX.
  220 +#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)
  221 +#define DALI_ENABLE_WRITE_MEMORY 641 //129 REPEAT - Allows writing of the memory bank.
  222 +#define DALI_RESERVED130 642 //130 REPEAT - [Reserved]
  223 +#define DALI_RESERVED131 643 //131 REPEAT - [Reserved]
  224 +#define DALI_RESERVED132 644 //132 REPEAT - [Reserved]
  225 +#define DALI_RESERVED133 645 //133 REPEAT - [Reserved]
  226 +#define DALI_RESERVED134 646 //134 REPEAT - [Reserved]
  227 +#define DALI_RESERVED135 647 //135 REPEAT - [Reserved]
  228 +#define DALI_RESERVED136 648 //136 REPEAT - [Reserved]
  229 +#define DALI_RESERVED137 649 //137 REPEAT - [Reserved]
  230 +#define DALI_RESERVED138 650 //138 REPEAT - [Reserved]
  231 +#define DALI_RESERVED139 651 //139 REPEAT - [Reserved]
  232 +#define DALI_RESERVED140 652 //140 REPEAT - [Reserved]
  233 +#define DALI_RESERVED141 653 //141 REPEAT - [Reserved]
  234 +#define DALI_RESERVED142 654 //142 REPEAT - [Reserved]
  235 +#define DALI_RESERVED143 655 //143 REPEAT - [Reserved]
  236 +#define DALI_QUERY_STATUS 144 //144 - Returns "STATUS INFORMATION"
  237 +#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)
  238 +#define DALI_QUERY_LAMP_FAILURE 146 //146 - Is there a lamp problem?
  239 +#define DALI_QUERY_LAMP_POWER_ON 147 //147 - Is a lamp on?
  240 +#define DALI_QUERY_LIMIT_ERROR 148 //148 - Is the specified lighting control level out of the range from the minimum to the maximum values?
  241 +#define DALI_QUERY_RESET_STATE 149 //149 - Is the slave in 'RESET STATE'?
  242 +#define DALI_QUERY_MISSING_SHORT_ADDRESS 150 //150 - Does the slave not have a short address?
  243 +#define DALI_QUERY_VERSION_NUMBER 151 //151 - What is the corresponding IEC standard number?
  244 +#define DALI_QUERY_CONTENT_DTR0 152 //152 - What is the DTR content? (In the parenthesis is a name in IEC62386-102ed2.0)
  245 +#define DALI_QUERY_DEVICE_TYPE 153 //153 - What is the device type? (fluorescent lamp:0000 0000) (IEC62386-207 is 6 fixed)
  246 +#define DALI_QUERY_PHYSICAL_MINIMUM_LEVEL 154 //154 - What is the minimum lighting control level specified by the hardware?
  247 +#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?
  248 +#define DALI_QUERY_CONTENT_DTR1 156 //156 - What is the DTR1 content?
  249 +#define DALI_QUERY_CONTENT_DTR2 157 //157 - What is the DTR2 content?
  250 +#define DALI_QUERY_OPERATING_MODE 158 //158 DALI-2 - What is the Operating Mode? (Only IEC62386-102ed2.0 )
  251 +#define DALI_QUERY_LIGHT_SOURCE_TYPE 159 //159 DALI-2 - What is the Light source type? (Only IEC62386-102ed2.0 )
  252 +#define DALI_QUERY_ACTUAL_LEVEL 160 //160 - What is the "ACTUAL LEVEL" (the current lighting control level)?
  253 +#define DALI_QUERY_MAX_LEVEL 161 //161 - What is the maximum lighting control level?
  254 +#define DALI_QUERY_MIN_LEVEL 162 //162 - What is the minimum lighting control level?
  255 +#define DALI_QUERY_POWER_ON_LEVEL 163 //163 - What is the "POWER ON LEVEL" (the lighting control level when the power is turned on)?
  256 +#define DALI_QUERY_SYSTEM_FAILURE_LEVEL 164 //164 - What is the "SYSTEM FAILURE LEVEL" (the lighting control level when a failure occurs)?
  257 +#define DALI_QUERY_FADE_TIME_FADE_RATE 165 //165 - What are the Fade time and Fade rate?
  258 +#define DALI_QUERY_MANUFACTURER_SPECIFIC_MODE 166 //166 DALI-2 - What is the Specific Mode? (Command that exist only in IEC62386-102ed2.0)
  259 +#define DALI_QUERY_NEXT_DEVICE_TYPE 167 //167 DALI-2 - What is the next Device Type? (Command that exist only in IEC62386-102ed2.0)
  260 +#define DALI_QUERY_EXTENDED_FADE_TIME 168 //168 DALI-2 - What is the Extended Fade Time? (Command that exist only in IEC62386-102ed2.0)
  261 +#define DALI_QUERY_CONTROL_GEAR_FAILURE 169 //169 DALI-2 - Does a slave have the abnormality? (Command that exist only in IEC62386-102ed2.0)
  262 +#define DALI_RESERVED170 170 //170 - [Reserved]
  263 +#define DALI_RESERVED171 171 //171 - [Reserved]
  264 +#define DALI_RESERVED172 172 //172 - [Reserved]
  265 +#define DALI_RESERVED173 173 //173 - [Reserved]
  266 +#define DALI_RESERVED174 174 //174 - [Reserved]
  267 +#define DALI_RESERVED175 175 //175 - [Reserved]
  268 +#define DALI_QUERY_SCENE0_LEVEL 176 //176 - What is the lighting control level for SCENE XXXX?
  269 +#define DALI_QUERY_SCENE1_LEVEL 177 //177 - What is the lighting control level for SCENE XXXX?
  270 +#define DALI_QUERY_SCENE2_LEVEL 178 //178 - What is the lighting control level for SCENE XXXX?
  271 +#define DALI_QUERY_SCENE3_LEVEL 179 //179 - What is the lighting control level for SCENE XXXX?
  272 +#define DALI_QUERY_SCENE4_LEVEL 180 //180 - What is the lighting control level for SCENE XXXX?
  273 +#define DALI_QUERY_SCENE5_LEVEL 181 //181 - What is the lighting control level for SCENE XXXX?
  274 +#define DALI_QUERY_SCENE6_LEVEL 182 //182 - What is the lighting control level for SCENE XXXX?
  275 +#define DALI_QUERY_SCENE7_LEVEL 183 //183 - What is the lighting control level for SCENE XXXX?
  276 +#define DALI_QUERY_SCENE8_LEVEL 184 //184 - What is the lighting control level for SCENE XXXX?
  277 +#define DALI_QUERY_SCENE9_LEVEL 185 //185 - What is the lighting control level for SCENE XXXX?
  278 +#define DALI_QUERY_SCENE10_LEVEL 186 //186 - What is the lighting control level for SCENE XXXX?
  279 +#define DALI_QUERY_SCENE11_LEVEL 187 //187 - What is the lighting control level for SCENE XXXX?
  280 +#define DALI_QUERY_SCENE12_LEVEL 188 //188 - What is the lighting control level for SCENE XXXX?
  281 +#define DALI_QUERY_SCENE13_LEVEL 189 //189 - What is the lighting control level for SCENE XXXX?
  282 +#define DALI_QUERY_SCENE14_LEVEL 190 //190 - What is the lighting control level for SCENE XXXX?
  283 +#define DALI_QUERY_SCENE15_LEVEL 191 //191 - What is the lighting control level for SCENE XXXX?
  284 +#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.)
  285 +#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.)
  286 +#define DALI_QUERY_RANDOM_ADDRESS_H 194 //194 - What are the higher 8 bits of the random address?
  287 +#define DALI_QUERY_RANDOM_ADDRESS_M 195 //195 - What are the middle 8 bits of the random address?
  288 +#define DALI_QUERY_RANDOM_ADDRESS_L 196 //196 - What are the lower 8 bits of the random address?
  289 +#define DALI_READ_MEMORY_LOCATION 197 //197 - What is the memory location content?
  290 +#define DALI_RESERVED198 198 //198 - [Reserved]
  291 +#define DALI_RESERVED199 199 //199 - [Reserved]
  292 +#define DALI_RESERVED200 200 //200 - [Reserved]
  293 +#define DALI_RESERVED201 201 //201 - [Reserved]
  294 +#define DALI_RESERVED202 202 //202 - [Reserved]
  295 +#define DALI_RESERVED203 203 //203 - [Reserved]
  296 +#define DALI_RESERVED204 204 //204 - [Reserved]
  297 +#define DALI_RESERVED205 205 //205 - [Reserved]
  298 +#define DALI_RESERVED206 206 //206 - [Reserved]
  299 +#define DALI_RESERVED207 207 //207 - [Reserved]
  300 +#define DALI_RESERVED208 208 //208 - [Reserved]
  301 +#define DALI_RESERVED209 209 //209 - [Reserved]
  302 +#define DALI_RESERVED210 210 //210 - [Reserved]
  303 +#define DALI_RESERVED211 211 //211 - [Reserved]
  304 +#define DALI_RESERVED212 212 //212 - [Reserved]
  305 +#define DALI_RESERVED213 213 //213 - [Reserved]
  306 +#define DALI_RESERVED214 214 //214 - [Reserved]
  307 +#define DALI_RESERVED215 215 //215 - [Reserved]
  308 +#define DALI_RESERVED216 216 //216 - [Reserved]
  309 +#define DALI_RESERVED217 217 //217 - [Reserved]
  310 +#define DALI_RESERVED218 218 //218 - [Reserved]
  311 +#define DALI_RESERVED219 219 //219 - [Reserved]
  312 +#define DALI_RESERVED220 220 //220 - [Reserved]
  313 +#define DALI_RESERVED221 221 //221 - [Reserved]
  314 +#define DALI_RESERVED222 222 //222 - [Reserved]
  315 +#define DALI_RESERVED223 223 //223 - [Reserved]
  316 +#define DALI_REFERENCE_SYSTEM_POWER 224 //224 IEC62386-207 - Starts power measurement. (Command that exist only in IEC62386-207)
  317 +#define DALI_ENABLE_CURRENT_PROTECTOR 225 //225 IEC62386-207 - Enables the current protection. (Command that exist only in IEC62386-207)
  318 +#define DALI_DISABLE_CURRENT_PROTECTOR 226 //226 IEC62386-207 - Disables the current protection. (Command that exist only in IEC62386-207)
  319 +#define DALI_SELECT_DIMMING_CURVE 227 //227 IEC62386-207 - Selects Dimming curve. (Command that exist only in IEC62386-207)
  320 +#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)
  321 +#define DALI_RESERVED229 229 //229 - [Reserved]
  322 +#define DALI_RESERVED230 230 //230 - [Reserved]
  323 +#define DALI_RESERVED231 231 //231 - [Reserved]
  324 +#define DALI_RESERVED232 232 //232 - [Reserved]
  325 +#define DALI_RESERVED233 233 //233 - [Reserved]
  326 +#define DALI_RESERVED234 234 //234 - [Reserved]
  327 +#define DALI_RESERVED235 235 //235 - [Reserved]
  328 +#define DALI_RESERVED236 236 //236 - [Reserved]
  329 +#define DALI_QUERY_GEAR_TYPE 237 //237 IEC62386-207 - Returns ‘GEAR TYPE’ (Command that exist only in IEC62386-207)
  330 +#define DALI_QUERY_DIMMING_CURVE 238 //238 IEC62386-207 - Returns ’Dimming curve’in use (Command that exist only in IEC62386-207)
  331 +#define DALI_QUERY_POSSIBLE_OPERATING_MODE 239 //239 IEC62386-207 - Returns ‘POSSIBLEG OPERATING MODE’ (Command that exist only in IEC62386-207)
  332 +#define DALI_QUERY_FEATURES 240 //240 IEC62386-207 - Returns ‘FEATURES’ (Command that exist only in IEC62386-207)
  333 +#define DALI_QUERY_FAILURE_STATUS 241 //241 IEC62386-207 - Returns ‘FAILURE STATUS’ (Command that exist only in IEC62386-207)
  334 +#define DALI_QUERY_SHORT_CIRCUIT 242 //242 IEC62386-207 - Returns bit0 short circuit of ‘FAILURE STATUS’ (Command that exist only in IEC62386-207)
  335 +#define DALI_QUERY_OPEN_CIRCUIT 243 //243 IEC62386-207 - Returns bit1 open circuit of ‘FAILURE STATUS’ (Command that exist only in IEC62386-207)
  336 +#define DALI_QUERY_LOAD_DECREASE 244 //244 IEC62386-207 - Returns bit2 load decrease of ‘FAILURE STATUS’ (Command that exist only in IEC62386-207)
  337 +#define DALI_QUERY_LOAD_INDREASE 245 //245 IEC62386-207 - Returns bit3 load increase of‘FAILURE STATUS’ (Command that exist only in IEC62386-207)
  338 +#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)
  339 +#define DALI_QUERY_THERMAL_SHUTDOWN 247 //247 IEC62386-207 - Returns bit5 thermal shut down of ‘FAILURE STATUS’ (Command that exist only in IEC62386-207)
  340 +#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)
  341 +#define DALI_QUERY_REFARENCE_RUNNING 249 //249 IEC62386-207 - Returns whetherReference System Power is in operation. (Command that exist only in IEC62386-207)
  342 +#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)
  343 +#define DALI_QUERY_CURRENT_PROTECTOR_ENABLE 251 //251 IEC62386-207 - Returns state of Curent protector (Command that exist only in IEC62386-207)
  344 +#define DALI_QUERY_OPERATING_MODE 252 //252 IEC62386-207 - Returns ‘OPERATING MODE’ (Command that exist only in IEC62386-207)
  345 +#define DALI_QUERY_FAST_FADE_TIME 253 //253 IEC62386-207 - Returns set Fast fade time. (Command that exist only in IEC62386-207)
  346 +#define DALI_QUERY_MIN_FAST_FADE_TIME 254 //254 IEC62386-207 - Returns set Minimum fast fade time (Command that exist only in IEC62386-207)
  347 +#define DALI_QUERY_EXTENDED_VERSION_NUMBER 255 //255 IEC62386-207 - The version number of the extended support? IEC62386-207: 1, Other: NO(no response)
  348 +#define DALI_TERMINATE 0x01A1 //256 - Releases the INITIALISE state.
  349 +#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)
  350 +#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.
  351 +#define DALI_RANDOMISE 0x03A7 //259 REPEAT - Generates a random address.
  352 +#define DALI_COMPARE 0x01A9 //260 - Is the random address smaller or equal to the search address?
  353 +#define DALI_WITHDRAW 0x01AB //261 - Excludes slaves for which the random address and search address match from the Compare process.
  354 +#define DALI_RESERVED262 0x01AD //262 - [Reserved]
  355 +#define DALI_PING 0x01AF //263 DALI-2 - Ignores in the slave. (Command that exist only in IEC62386-102ed2.0)
  356 +#define DALI_SEARCHADDRH 0x01B1 //264 - Specifies the higher 8 bits of the search address.
  357 +#define DALI_SEARCHADDRM 0x01B3 //265 - Specifies the middle 8 bits of the search address.
  358 +#define DALI_SEARCHADDRL 0x01B5 //266 - Specifies the lower 8 bits of the search address.
  359 +#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.
  360 +#define DALI_VERIFY_SHORT_ADDRESS 0x01B9 //268 - Is the short address AAA AAA?
  361 +#define DALI_QUERY_SHORT_ADDRESS 0x01BB //269 - What is the short address of the slaveNote 2being selected?
  362 +#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)
  363 +#define DALI_RESERVED271 0x01BF //271 - [Reserved]
  364 +#define DALI_ENABLE_DEVICE_TYPE_X 0x01C1 //272 - Adds the device XXXX (a special device).
  365 +#define DALI_DATA_TRANSFER_REGISTER1 0x01C3 //273 - Stores data XXXX into DTR1.
  366 +#define DALI_DATA_TRANSFER_REGISTER2 0x01C5 //274 - Stores data XXXX into DTR2.
  367 +#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)
  368 +#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)
  369 +#define DALI_RESERVED277 0x01CB //277 - [Reserved]
  370 +#define DALI_RESERVED278 0x01CD //278 - [Reserved]
  371 +#define DALI_RESERVED279 0x01CF //279 - [Reserved]
  372 +#define DALI_RESERVED280 0x01D1 //280 - [Reserved]
  373 +#define DALI_RESERVED281 0x01D3 //281 - [Reserved]
  374 +#define DALI_RESERVED282 0x01D5 //282 - [Reserved]
  375 +#define DALI_RESERVED283 0x01D7 //283 - [Reserved]
  376 +#define DALI_RESERVED284 0x01D9 //284 - [Reserved]
  377 +#define DALI_RESERVED285 0x01DB //285 - [Reserved]
  378 +#define DALI_RESERVED286 0x01DD //286 - [Reserved]
  379 +#define DALI_RESERVED287 0x01DF //287 - [Reserved]
  380 +#define DALI_RESERVED288 0x01E1 //288 - [Reserved]
  381 +#define DALI_RESERVED289 0x01E3 //289 - [Reserved]
  382 +#define DALI_RESERVED290 0x01E5 //290 - [Reserved]
  383 +#define DALI_RESERVED291 0x01E7 //291 - [Reserved]
  384 +#define DALI_RESERVED292 0x01E9 //292 - [Reserved]
  385 +#define DALI_RESERVED293 0x01EB //293 - [Reserved]
  386 +#define DALI_RESERVED294 0x01ED //294 - [Reserved]
  387 +#define DALI_RESERVED295 0x01DF //295 - [Reserved]
  388 +#define DALI_RESERVED296 0x01F1 //296 - [Reserved]
  389 +#define DALI_RESERVED297 0x01F3 //297 - [Reserved]
  390 +#define DALI_RESERVED298 0x01F5 //298 - [Reserved]
  391 +#define DALI_RESERVED299 0x01F7 //299 - [Reserved]
  392 +#define DALI_RESERVED300 0x01F9 //300 - [Reserved]
  393 +#define DALI_RESERVED301 0x01FB //301 - [Reserved]
  394 +#define DALI_RESERVED302 0x01FD //302 - [Reserved]
  395 +
  396 +
  397 +
  398 +
  399 +/*
  400 +SIGNAL CHARACTERISTICS
  401 +High Level: 9.5 to 22.5 V (Typical 16 V)
  402 +Low Level: -6.5 to + 6.5 V (Typical 0 V)
  403 +Te = half cycle = 416.67 us +/- 10 %
  404 +10 us <= tfall <= 100 us
  405 +10 us <= trise <= 100 us
  406 +
  407 +BIT TIMING
  408 +msb send first
  409 + logical 1 = 1Te Low 1Te High
  410 + logical 0 = 1Te High 1Te Low
  411 + Start bit = logical 1
  412 + Stop bit = 2Te High
  413 +
  414 +FRAME TIMING
  415 +FF: TX Forward Frame 2 bytes (38Te) = 2*(1start+16bits+2stop)
  416 +BF: RX Backward Frame 1 byte (22Te) = 2*(1start+8bits+2stop)
  417 +no reply: FF >22Te pause FF
  418 +with reply: FF >7Te <22Te pause BF >22Te pause FF
  419 +
  420 +
  421 +DALI commands
  422 +=============
  423 +In accordance with the DIN EN 60929 standard, addresses and commands are transmitted as numbers with a length of two bytes.
  424 +
  425 +These commands take the form YAAA AAAS xxXXxx. Each letter here stands for one bit.
  426 +
  427 +Y: type of address
  428 + 0bin: short address
  429 + 1bin: group address or collective call
  430 +
  431 +A: significant address bit
  432 +
  433 +S: selection bit (specifies the significance of the following eight bits):
  434 + 0bin: the 8 xxXXxx bits contain a value for direct control of the lamp power
  435 + 1bin: the 8 xxXXxx bits contain a command number.
  436 +
  437 +x: a bit in the lamp power or in the command number
  438 +
  439 +
  440 +Type of Addresses
  441 +=================
  442 +Type of Addresses Byte Description
  443 +Short address 0AAAAAAS (AAAAAA = 0 to 63, S = 0/1)
  444 +Group address 100AAAAS (AAAA = 0 to 15, S = 0/1)
  445 +Broadcast address 1111111S (S = 0/1)
  446 +Special command 101CCCC1 (CCCC = command number)
  447 +
  448 +
  449 +Direct DALI commands for lamp power
  450 +===================================
  451 +These commands take the form YAAA AAA0 xxXXxx.
  452 +
  453 +xxXXxx: the value representing the lamp power is transmitted in these 8 bits. It is calculated according to this formula:
  454 +
  455 +Pvalue = 10 ^ ((value-1) / (253/3)) * Pmax / 1000
  456 +
  457 +253 values from 1dec to 254dec are available for transmission in accordance with this formula.
  458 +
  459 +There are also 2 direct DALI commands with special meanings:
  460 +
  461 +Command; Command No; Description; Answer
  462 +00hex; 0dec; The DALI device dims using the current fade time down to the parameterised MIN value, and then switches off.; -
  463 +FFhex; 254dec; Mask (no change): this value is ignored in what follows, and is therefore not loaded into memory.; -
  464 +
  465 +
  466 +Indirect DALI commands for lamp power
  467 +=====================================
  468 +These commands take the form YAAA AAA1 xxXXxx.
  469 +
  470 +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.
  471 +
  472 +Command; Command No; Description; Answer
  473 +00hex 0dez Extinguish the lamp (without fading) -
  474 +01hex 1dez Dim up 200 ms using the selected fade rate -
  475 +02hex 2dez Dim down 200 ms using the selected fade rate -
  476 +03hex 3dez Set the actual arc power level one step higher without fading. If the lamp is off, it will be not ignited. -
  477 +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. -
  478 +05hex 5dez Set the actual arc power level to the maximum value. If the lamp is off, it will be ignited. -
  479 +06hex 6dez Set the actual arc power level to the minimum value. If the lamp is off, it will be ignited. -
  480 +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. -
  481 +08hex 8dez Set the actual arc power level one step higher without fading. If the lamp is off, it will be ignited. -
  482 +09hex ... 0Fhex 9dez ... 15dez reserved -
  483 +1nhex
  484 +(n: 0hex ... Fhex) 16dez ... 31dez Set the light level to the value stored for the selected scene (n) -
  485 +
  486 +
  487 +Configuration commands
  488 +======================
  489 +Command; Command No; Description; Answer
  490 +20hex 32dez Reset the parameters to default settings -
  491 +21hex 33dez Store the current light level in the DTR (Data Transfer Register) -
  492 +22hex ... 29hex 34dez ... 41dez reserved -
  493 +2Ahex 42dez Store the value in the DTR as the maximum level -
  494 +2Bhex 43dez Store the value in the DTR as the minimum level -
  495 +2Chex 44dez Store the value in the DTR as the system failure level -
  496 +2Dhex 45dez Store the value in the DTR as the power on level -
  497 +2Ehex 46dez Store the value in the DTR as the fade time -
  498 +2Fhex 47dez Store the value in the DTR as the fade rate -
  499 +30hex ... 3Fhex 48dez ... 63dez reserved -
  500 +4nhex
  501 +(n: 0hex ... Fhex) 64dez ... 79dez Store the value in the DTR as the selected scene (n) -
  502 +5nhex
  503 +(n: 0hex ... Fhex) 80dez ... 95dez Remove the selected scene (n) from the DALI slave -
  504 +6nhex
  505 +(n: 0hex ... Fhex) 96dez ... 111dez Add the DALI slave unit to the selected group (n) -
  506 +7nhex
  507 +(n: 0hex ... Fhex) 112dez ... 127dez Remove the DALI slave unit from the selected group (n) -
  508 +80hex 128dez Store the value in the DTR as a short address -
  509 +81hex ... 8Fhex 129dez ... 143dez reserved -
  510 +90hex 144dez Returns the status (XX) of the DALI slave XX
  511 +91hex 145dez Check if the DALI slave is working yes/no
  512 +92hex 146dez Check if there is a lamp failure yes/no
  513 +93hex 147dez Check if the lamp is operating yes/no
  514 +94hex 148dez Check if the slave has received a level out of limit yes/no
  515 +95hex 149dez Check if the DALI slave is in reset state yes/no
  516 +96hex 150dez Check if the DALI slave is missing a short address XX
  517 +97hex 151dez Returns the version number as XX
  518 +98hex 152dez Returns the content of the DTR as XX
  519 +99hex 153dez Returns the device type as XX
  520 +9Ahex 154dez Returns the physical minimum level as XX
  521 +9Bhex 155dez Check if the DALI slave is in power failure mode yes/no
  522 +9Chex ... 9Fhex 156dez ... 159dez reserved -
  523 +A0hex 160dez Returns the current light level as XX
  524 +A1hex 161dez Returns the maximum allowed light level as XX
  525 +A2hex 162dez Returns the minimum allowed light level as XX
  526 +A3hex 163dez Return the power up level as XX
  527 +A4hex 164dez Returns the system failure level as XX
  528 +A5hex 165dez Returns the fade time as X and the fade rate as Y XY
  529 +A6hex ... AFhex 166dez ... 175dez reserved -
  530 +Bnhex
  531 +(n: 0hex ... Fhex) 176dez ... 191dez Returns the light level XX for the selected scene (n) XX
  532 +C0hex 192dez Returns a bit pattern XX indicating which group (0-7) the DALI slave belongs to XX
  533 +C1hex 193dez Returns a bit pattern XX indicating which group (8-15) the DALI slave belongs to XX
  534 +C2hex 194dez Returns the high bits of the random address as HH
  535 +C3hex 195dez Return the middle bit of the random address as MM
  536 +C4hex 196dez Returns the lower bits of the random address as LL
  537 +C5hex ... DFhex 197dez ... 223dez reserved -
  538 +E0hex ... FFhex 224dez ... 255dez Returns application specific extension commands
  539 +
  540 +
  541 +Note Repeat of DALI commands
  542 +============================
  543 +According to IEC 60929, a DALI Master has to repeat several commands within 100 ms, so that DALI-Slaves will execute them.
  544 +
  545 +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.
  546 +
  547 +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.
  548 +
  549 +
  550 +DALI Control Device Type List
  551 +=============================
  552 +Type DEC Type HEX Name Comments
  553 +128 0x80 Unknown Device. If one of the devices below don't apply
  554 +129 0x81 Switch Device A Wall-Switch based Controller including, but not limited to ON/OFF devices, Scene switches, dimming device.
  555 +130 0x82 Slide Dimmer An analog/positional dimming controller
  556 +131 0x83 Motion/Occupancy Sensor. A device that indicates the presence of people within a control area.
  557 +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.
  558 +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.
  559 +134 0x86 Scheduler. A device that establishes the building mode based on time of day, or which provides control outputs.
  560 +135 0x87 Gateway. An interface to other control systems or communication busses
  561 +136 0x88 Sequencer. A device which sequences lights based on a triggering event
  562 +137 0x89 Power Supply *). A DALI Power Supply device which supplies power for the communication loop
  563 +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.
  564 +139 0x8b Analog input unit. A general device with analog input.
  565 +140 0x8c Data Logger. A unit logging data (can be digital or analog data)
  566 +
  567 +
  568 +Flash Variables and Offset in Information
  569 +=========================================
  570 +Memory Name Offset
  571 +Power On Level [0]
  572 +System Failure Level [1]
  573 +Minimum Level [2]
  574 +Maximum Level [3]
  575 +Fade Rate [4]
  576 +Fade Time [5]
  577 +Short Address [6]
  578 +Group 0 through 7 [7]
  579 +Group 8 through 15 [8]
  580 +Scene 0 through 15 [9-24]
  581 +Random Address [25-27]
  582 +Fast Fade Time [28]
  583 +Failure Status [29]
  584 +Operating Mode [30]
  585 +Dimming Curve [31]
  586 +*/
... ...