diff --git a/src/ebusd/bushandler.cpp b/src/ebusd/bushandler.cpp index 3f770c12..d8fad1ef 100644 --- a/src/ebusd/bushandler.cpp +++ b/src/ebusd/bushandler.cpp @@ -215,7 +215,7 @@ result_t BusHandler::handleSymbol() switch (m_state) { case bs_noSignal: - timeout = SIGNAL_TIMEOUT; + timeout = m_generateSynInterval>0 ? m_generateSynInterval : SIGNAL_TIMEOUT; break; case bs_skip: @@ -315,7 +315,7 @@ result_t BusHandler::handleSymbol() timeout = SEND_TIMEOUT; else { sending = false; - timeout = 0; + timeout = SYN_TIMEOUT; setState(bs_skip, result); } } @@ -324,10 +324,31 @@ result_t BusHandler::handleSymbol() unsigned char recvSymbol; result = m_device->recv(timeout, recvSymbol); + if (!sending && result == RESULT_ERR_TIMEOUT && m_generateSynInterval > 0 && timeout >= m_generateSynInterval && (m_state == bs_noSignal || m_state == bs_skip)) { + // check if acting as AUTO-SYN generator is required + result = m_device->send(SYN); + if (result == RESULT_OK) { + recvSymbol = ESC; + result = m_device->recv(SEND_TIMEOUT, recvSymbol); + if (result == RESULT_ERR_TIMEOUT) { + return setState(bs_noSignal, result); + } + if (result != RESULT_OK) + logError(lf_bus, "unable to receive sent AUTO-SYN symbol: %s", getResultCode(result)); + else if (recvSymbol != SYN) { + logError(lf_bus, "received %2.2x instead of AUTO-SYN symbol", recvSymbol); + } else if (m_generateSynInterval != SYN_TIMEOUT) { + // received own AUTO-SYN symbol back again: act as AUTO-SYN generator now + m_generateSynInterval = SYN_TIMEOUT; + logNotice(lf_bus, "acting as AUTO-SYN generator"); + } + } + return setState(bs_skip, result); + } time_t now; time(&now); if (result != RESULT_OK) { - if (difftime(now, m_lastReceive) > 1 // at least one full second has passed since last received symbol + if ((m_generateSynInterval != SYN_TIMEOUT && difftime(now, m_lastReceive) > 1) // at least one full second has passed since last received symbol || m_state == bs_noSignal) return setState(bs_noSignal, result); diff --git a/src/ebusd/bushandler.h b/src/ebusd/bushandler.h index fa6f0d2c..021ef1ad 100644 --- a/src/ebusd/bushandler.h +++ b/src/ebusd/bushandler.h @@ -259,18 +259,21 @@ public: * @param slaveRecvTimeout the maximum time in microseconds an addressed slave is expected to acknowledge. * @param busAcquireTimeout the maximum time in microseconds for bus acquisition. * @param lockCount the number of AUTO-SYN symbols before sending is allowed after lost arbitration, or 0 for auto detection. + * @param generateSyn whether to enable AUTO-SYN symbol generation. * @param pollInterval the interval in seconds in which poll messages are cycled, or 0 if disabled. */ BusHandler(Device* device, MessageMap* messages, const unsigned char ownAddress, const bool answer, const unsigned int busLostRetries, const unsigned int failedSendRetries, const unsigned int busAcquireTimeout, const unsigned int slaveRecvTimeout, - const unsigned int lockCount, const unsigned int pollInterval) + const unsigned int lockCount, const bool generateSyn, + const unsigned int pollInterval) : m_device(device), m_messages(messages), m_ownMasterAddress(ownAddress), m_ownSlaveAddress((unsigned char)(ownAddress+5)), m_answer(answer), m_busLostRetries(busLostRetries), m_failedSendRetries(failedSendRetries), m_busAcquireTimeout(busAcquireTimeout), m_slaveRecvTimeout(slaveRecvTimeout), m_masterCount(1), m_autoLockCount(lockCount==0), m_lockCount(lockCount<=3 ? 3 : lockCount), m_remainLockCount(m_autoLockCount), + m_generateSynInterval(generateSyn ? SYN_TIMEOUT*getMasterNumber(ownAddress)+SYMBOL_DURATION : 0), m_pollInterval(pollInterval), m_lastReceive(0), m_lastPoll(0), m_currentRequest(NULL), m_nextSendPos(0), m_symPerSec(0), m_maxSymPerSec(0), @@ -400,6 +403,9 @@ private: /** the remaining number of AUTO-SYN symbols before sending is allowed again. */ unsigned int m_remainLockCount; + /** the interval in microseconds after which to generate an AUTO-SYN symbol, or 0 if disabled. */ + unsigned int m_generateSynInterval; + /** the interval in seconds in which poll messages are cycled, or 0 if disabled. */ const unsigned int m_pollInterval; diff --git a/src/ebusd/main.cpp b/src/ebusd/main.cpp index b0f7aa14..e60f4d43 100644 --- a/src/ebusd/main.cpp +++ b/src/ebusd/main.cpp @@ -74,6 +74,7 @@ static struct options opt = { 2, // sendRetries SLAVE_RECV_TIMEOUT, // receiveTimeout 0, // masterCount + false, // generateSyn false, // foreground 8888, // port false, // localOnly @@ -106,12 +107,13 @@ static const char argpdoc[] = #define O_SNDRET 7 #define O_RCVTIM 8 #define O_MASCNT 9 -#define O_LOCAL 10 -#define O_LOGARE 11 -#define O_LOGLEV 12 -#define O_LOGRAW 13 -#define O_DMPFIL 14 -#define O_DMPSIZ 15 +#define O_GENSYN 10 +#define O_LOCAL 11 +#define O_LOGARE 12 +#define O_LOGLEV 13 +#define O_LOGRAW 14 +#define O_DMPFIL 15 +#define O_DMPSIZ 16 /** the definition of the known program arguments. */ static const struct argp_option argpoptions[] = { @@ -133,6 +135,7 @@ static const struct argp_option argpoptions[] = { {"sendretries", O_SNDRET, "COUNT", 0, "Repeat failed sends COUNT times [2]", 0 }, {"receivetimeout", O_RCVTIM, "USEC", 0, "Expect a slave to answer within USEC us [15000]", 0 }, {"numbermasters", O_MASCNT, "COUNT", 0, "Expect COUNT masters on the bus, 0 for auto detection [0]", 0 }, + {"generatesyn", O_GENSYN, NULL, 0, "Enable AUTO-SYN symbol generation", 0 }, {NULL, 0, NULL, 0, "Daemon options:", 4 }, {"foreground", 'f', NULL, 0, "Run in foreground", 0 }, @@ -245,6 +248,9 @@ error_t parse_opt(int key, char *arg, struct argp_state *state) return EINVAL; } break; + case O_GENSYN: // --generatesyn + opt->generateSyn = true; + break; // Daemon options: case 'f': // --foreground diff --git a/src/ebusd/main.h b/src/ebusd/main.h index 7046aaa2..1bd5a7f5 100644 --- a/src/ebusd/main.h +++ b/src/ebusd/main.h @@ -43,6 +43,7 @@ struct options int sendRetries; //!< number of retries for failed sends [2] int receiveTimeout; //!< timeout for receiving answer from slave in us [15000] int masterCount; //!< expected number of masters for arbitration [5] + bool generateSyn; //!< enable AUTO-SYN symbol generation bool foreground; //!< run in foreground int port; //!< port to listen for client connections [8888]