susisstrolch's Tx "take two" mod

This commit is contained in:
proddy
2019-05-23 14:52:34 +02:00
parent 57442db11c
commit 66ec810ea1

View File

@@ -200,7 +200,7 @@ static inline void ICACHE_FLASH_ATTR emsuart_loopback(bool enable) {
void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) { void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) {
uint32_t tmp; uint32_t tmp;
// backward compatibility // backwards compatibility
if (EMS_Sys_Status.emsTxDelay < 2) { if (EMS_Sys_Status.emsTxDelay < 2) {
for (uint8_t i = 0; i < len; i++) { for (uint8_t i = 0; i < len; i++) {
USF(EMSUART_UART) = buf[i]; USF(EMSUART_UART) = buf[i];
@@ -213,46 +213,43 @@ void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) {
} }
emsuart_tx_brk(); // send <BRK> emsuart_tx_brk(); // send <BRK>
} else { } else {
// smart Tx /* smart Tx - take two - https://github.com/proddy/EMS-ESP/issues/103 by @susisstrolch
* changed logic...
* we emit the whole telegram, with Rx interrupt disabled, collecting busmaster response in FIFO.
* after sending the last char we poll the Rx status until either
* - size(Rx FIFO) == size(Tx-Telegram)
* - <BRK> is detected
* At end of receive we re-enable Rx-INT and send a Tx-BRK in loopback mode.
*/
ETS_UART_INTR_DISABLE(); // disable rx interrupt ETS_UART_INTR_DISABLE(); // disable rx interrupt
emsuart_flush_fifos(); emsuart_flush_fifos();
emsuart_loopback(true); // reset FIFOs & enable loopback
for (uint8_t i = 0; i < len; i++) { // throw out the telegram...
for (uint8_t i = 0; i < len; i++)
USF(EMSUART_UART) = buf[i]; // send byte USF(EMSUART_UART) = buf[i]; // send byte
delayMicroseconds(10 * EMSUART_BIT_TIME); // wait until we received sizeof(telegram) or RxBRK (== collision detect)
while ((((USS(EMSUART_UART) >> USRXC) & 0xFF) < len) || (U0IS & (1 << UIBD)))
delayMicroseconds(11 * EMSUART_BIT_TIME); // burn CPU cycles...
/* wait until // we got the whole telegram in Rx buffer
* ° loopback char is received // on Rx-BRK (bus collision), we simply enable Rx and leave
* ° Rx-FIFO full (unlikely) // otherwise, we send the final Tx-BRK in loopback and enable Rx-INT.
* ° Rx-TimeOut (unlikely) // worst case, we'll see an additional Rx-BRK...
* ° Break detected (bus collision) - not handled now... if (!(U0IS & (1 << UIBD))) {
*/ // no bus collision - send terminating BRK signal
for (uint8_t l = 0; l < 13; l++) { emsuart_loopback(true);
if (((USS(EMSUART_UART) >> USRXC) & 0xFF) || (U0IS & ((1 << UIFF) | (1 << UITO) | (1 << UIBD)))) USC0(EMSUART_UART) |= (1 << UCBRK); // set <BRK>
break;
while (!(U0IS & (1 << UIBD))) // wait until BRK detected...
delayMicroseconds(EMSUART_BIT_TIME / 8); // ~13µs delayMicroseconds(EMSUART_BIT_TIME / 8); // ~13µs
} USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear <BRK>
uint32_t break_detect = (U0IS & (1 << UIBD)); // keep break detect interrupt U0IC = (1 << UIBD); // clear BRK detect IRQ
(void)(USF(EMSUART_UART)); // read out fifo, also clears FIFO counter emsuart_loopback(false); // disable loopback mode
U0IC = (1 << UIFF) | (1 << UITO) | (1 << UIBD); // clear pending interrupts
if (break_detect)
break; // collision / abort from master
} }
ETS_UART_INTR_ENABLE(); // receive anything from FIFO...
// send <BRK> - wait until <BRK> detect
USC0(EMSUART_UART) |= (1 << UCBRK); // send <BRK>
while (!(U0IS & (1 << UIBD)))
delayMicroseconds(EMSUART_BIT_TIME / 8); // ~13µs
USC0(EMSUART_UART) &= ~(1 << UCBRK); // clear <BRK>
U0IC = (1 << UIFF) | (1 << UITO) | (1 << UIBD); // clear pending interrupts
emsuart_flush_fifos();
emsuart_loopback(false); // disable loopback mode
ETS_UART_INTR_ENABLE(); // enable rx interrupt
} }
} }