mirror of https://github.com/arendst/Tasmota.git
Dali add better receive error detection
This commit is contained in:
parent
6bc2e50d9c
commit
1a5e6db02d
|
@ -19,6 +19,7 @@
|
||||||
--------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------
|
||||||
Version yyyymmdd Action Description
|
Version yyyymmdd Action Description
|
||||||
--------------------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------------------
|
||||||
|
0.1.0.2 20241008 update - Better receive error detection
|
||||||
0.1.0.1 20241007 update - To stablizie communication send Dali datagram twice like Busch-Jaeger does
|
0.1.0.1 20241007 update - To stablizie communication send Dali datagram twice like Busch-Jaeger does
|
||||||
- Change DaliPower 0..2 to act like Tasmota Power (Off, On, Toggle)
|
- Change DaliPower 0..2 to act like Tasmota Power (Off, On, Toggle)
|
||||||
- Keep last Dimmer value as default power on
|
- Keep last Dimmer value as default power on
|
||||||
|
@ -26,7 +27,6 @@
|
||||||
- Fix decoding of received Dali 1 data
|
- Fix decoding of received Dali 1 data
|
||||||
- Refactor command `DaliPower 0..254` controlling Broadcast devices
|
- Refactor command `DaliPower 0..254` controlling Broadcast devices
|
||||||
- Add command `DaliDimmer 0..254` controlling Broadcast devices
|
- Add command `DaliDimmer 0..254` controlling Broadcast devices
|
||||||
|
|
||||||
0.0.0.1 20221027 publish - Initial version
|
0.0.0.1 20221027 publish - Initial version
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
|
|
||||||
//#define DALI_DEBUG
|
//#define DALI_DEBUG
|
||||||
#ifndef DALI_DEBUG_PIN
|
#ifndef DALI_DEBUG_PIN
|
||||||
#define DALI_DEBUG_PIN 27
|
#define DALI_DEBUG_PIN 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define BROADCAST_DP 0b11111110 // 0xFE = 254
|
#define BROADCAST_DP 0b11111110 // 0xFE = 254
|
||||||
|
@ -90,85 +90,58 @@ void DaliDisableRxInterrupt(void) {
|
||||||
|
|
||||||
/*************** R E C E I V E * P R O C E D U R E *********/
|
/*************** R E C E I V E * P R O C E D U R E *********/
|
||||||
|
|
||||||
#define DALI_WAIT_RCV { while (ESP.getCycleCount() < (wait + start)); wait += bit_time; }
|
void IRAM_ATTR DaliReceiveData(void); // Fix ESP8266 ISR not in IRAM! exception
|
||||||
|
|
||||||
void IRAM_ATTR DaliReceiveData(void);
|
|
||||||
void DaliReceiveData(void) {
|
void DaliReceiveData(void) {
|
||||||
if (Dali->input_ready) { return; }
|
if (Dali->input_ready) { return; } // Skip if last input is not yet handled
|
||||||
uint32_t start = ESP.getCycleCount();
|
uint32_t wait = ESP.getCycleCount() + (Dali->bit_time / 2);
|
||||||
uint32_t bit_time = Dali->bit_time;
|
|
||||||
// Advance the starting point for the samples but compensate for the
|
|
||||||
// initial delay which occurs before the interrupt is delivered
|
|
||||||
uint32_t wait = bit_time / 2;
|
|
||||||
int bit_state = 0;
|
int bit_state = 0;
|
||||||
bool dali_read;
|
bool dali_read;
|
||||||
uint32_t received_dali_data = 0;
|
uint32_t received_dali_data = 0;
|
||||||
|
uint32_t bit_pos = 15;
|
||||||
DALI_WAIT_RCV;
|
for (uint32_t i = 0; i < 36; i++) { // (1 Start bit, 16 data bits, 1 stop bit) * 2 bits/bit (manchester encoding)
|
||||||
DALI_WAIT_RCV; // Start bit
|
while (ESP.getCycleCount() < wait);
|
||||||
for (uint32_t i = 0; i < 32; i++) {
|
wait += Dali->bit_time; // Auto roll-over
|
||||||
DALI_WAIT_RCV;
|
if (abs(bit_state) <= 2) { // Manchester encoding max 2 consecutive equal bits
|
||||||
if (abs(bit_state) <= 2) { // Manchester encoding max 2 consequtive equal bits
|
|
||||||
dali_read = digitalRead(Dali->pin_rx);
|
dali_read = digitalRead(Dali->pin_rx);
|
||||||
#ifdef DALI_DEBUG
|
#ifdef DALI_DEBUG
|
||||||
digitalWrite(DALI_DEBUG_PIN, i&1); // Add LogicAnalyzer poll indication
|
digitalWrite(DALI_DEBUG_PIN, i&1); // Add LogicAnalyzer poll indication
|
||||||
#endif // DALI_DEBUG
|
#endif // DALI_DEBUG
|
||||||
bit_state += (dali_read) ? 1 : -1;
|
bit_state += (dali_read) ? 1 : -1;
|
||||||
if (i &1) {
|
if ((i >= 2) && (i <= 34)) { // 32 manchester encoded data bits
|
||||||
uint32_t j = i >>1;
|
if (i &1) { // 16 data bits
|
||||||
received_dali_data |= ((DALI_IN_INVERT) ? !dali_read : dali_read << (15 -j));
|
received_dali_data |= ((DALI_IN_INVERT) ? !dali_read : dali_read << bit_pos--);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DALI_WAIT_RCV;
|
if (abs(bit_state) <= 2) { // Valid Manchester encoding including start and stop bits
|
||||||
DALI_WAIT_RCV; // Stop bit
|
if (Dali->received_dali_data != received_dali_data) { // Skip duplicates
|
||||||
|
Dali->received_dali_data = received_dali_data;
|
||||||
if (abs(bit_state) <= 2) { // Valid Manchester encoding
|
Dali->input_ready = true; // Valid data received
|
||||||
Dali->received_dali_data = received_dali_data;
|
}
|
||||||
Dali->input_ready = true; // Valid data received
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ESP8266
|
|
||||||
// Must clear this bit in the interrupt register,
|
|
||||||
// it gets set even when interrupts are disabled
|
|
||||||
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << Dali->pin_rx);
|
|
||||||
#endif // ESP8266
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************** S E N D * P R O C E D U R E ***************/
|
/*************** S E N D * P R O C E D U R E ***************/
|
||||||
|
|
||||||
#define DALI_WAIT_SND { while (ESP.getCycleCount() < (wait + start)) optimistic_yield(1); wait += bit_time; } // Watchdog timeouts
|
|
||||||
|
|
||||||
void DaliDigitalWrite(bool pin_value) {
|
|
||||||
digitalWrite(Dali->pin_tx, (pin_value == DALI_OUT_INVERT) ? LOW : HIGH);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DaliSendDataOnce(uint16_t send_dali_data) {
|
void DaliSendDataOnce(uint16_t send_dali_data) {
|
||||||
uint32_t bit_time = Dali->bit_time;
|
bool bit_value;
|
||||||
uint32_t wait = bit_time;
|
uint32_t bit_pos = 15;
|
||||||
// digitalWrite(Dali->pin_tx, HIGH); // Already in HIGH mode
|
uint32_t wait = ESP.getCycleCount();
|
||||||
uint32_t start = ESP.getCycleCount();
|
for (uint32_t i = 0; i < 35; i++) {
|
||||||
|
if (0 == (i &1)) { // Even bit
|
||||||
// Settling time between forward and backward frame
|
// Start bit, Stop bit, Data bits
|
||||||
for (uint32_t i = 0; i < 8; i++) {
|
bit_value = (0 == i) ? 1 : (34 == i) ? 0 : (bool)((send_dali_data >> bit_pos--) &1); // MSB first
|
||||||
DALI_WAIT_SND;
|
} else { // Odd bit
|
||||||
|
bit_value = !bit_value; // Complement bit
|
||||||
|
}
|
||||||
|
bool pin_value = bit_value ? LOW : HIGH; // Invert bit
|
||||||
|
digitalWrite(Dali->pin_tx, (pin_value == DALI_OUT_INVERT) ? LOW : HIGH);
|
||||||
|
wait += Dali->bit_time; // Auto roll-over
|
||||||
|
while (ESP.getCycleCount() < wait) {
|
||||||
|
optimistic_yield(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Start bit;
|
|
||||||
DaliDigitalWrite(LOW);
|
|
||||||
DALI_WAIT_SND;
|
|
||||||
DaliDigitalWrite(HIGH);
|
|
||||||
DALI_WAIT_SND;
|
|
||||||
for (uint32_t i = 0; i < 16; i++) {
|
|
||||||
// Bit value (edge) selection
|
|
||||||
bool bit_value = (bool)((send_dali_data >> (15 - i)) & 0x01); // MSB first
|
|
||||||
// Every half bit -> Manchester coding
|
|
||||||
DaliDigitalWrite(bit_value ? LOW : HIGH); // Manchester
|
|
||||||
DALI_WAIT_SND;
|
|
||||||
DaliDigitalWrite(bit_value ? HIGH : LOW); // Value
|
|
||||||
DALI_WAIT_SND;
|
|
||||||
}
|
|
||||||
// Stop bit
|
|
||||||
DaliDigitalWrite(HIGH);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DaliSendData(uint8_t firstByte, uint8_t secondByte) {
|
void DaliSendData(uint8_t firstByte, uint8_t secondByte) {
|
||||||
|
@ -184,10 +157,11 @@ void DaliSendData(uint8_t firstByte, uint8_t secondByte) {
|
||||||
send_dali_data += secondByte & 0xff;
|
send_dali_data += secondByte & 0xff;
|
||||||
|
|
||||||
DaliDisableRxInterrupt();
|
DaliDisableRxInterrupt();
|
||||||
|
delay(3); // Settling time between forward and backward frame
|
||||||
DaliSendDataOnce(send_dali_data); // Takes 14.5 ms
|
DaliSendDataOnce(send_dali_data); // Takes 14.5 ms
|
||||||
delay(15); // As used by Busch-Jaeger
|
delay(14); // As used by Busch-Jaeger
|
||||||
DaliSendDataOnce(send_dali_data); // Takes 14.5 ms
|
DaliSendDataOnce(send_dali_data); // Takes 14.5 ms
|
||||||
delay(1); // Block response
|
delay(3); // Block response
|
||||||
DaliEnableRxInterrupt();
|
DaliEnableRxInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,7 +221,7 @@ void DaliInit(void) {
|
||||||
#endif // DALI_DEBUG
|
#endif // DALI_DEBUG
|
||||||
|
|
||||||
Dali->dimmer = DALI_INIT_STATE;
|
Dali->dimmer = DALI_INIT_STATE;
|
||||||
Dali->bit_time = ESP.getCpuFreqMHz() * 1000000 / 2400; // Manchester twice 1200 bps
|
Dali->bit_time = ESP.getCpuFreqMHz() * 1000000 / 2400; // Manchester twice 1200 bps = 2400 bps = 417 ms
|
||||||
|
|
||||||
DaliEnableRxInterrupt();
|
DaliEnableRxInterrupt();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue