move transfer latency to device
This commit is contained in:
@@ -433,7 +433,7 @@ result_t BusHandler::handleSymbol() {
|
||||
// check if another symbol has to be sent and determine timeout for receive
|
||||
switch (m_state) {
|
||||
case bs_noSignal:
|
||||
timeout = m_generateSynInterval > 0 ? m_generateSynInterval+m_transferLatency : SIGNAL_TIMEOUT;
|
||||
timeout = m_generateSynInterval > 0 ? m_generateSynInterval : SIGNAL_TIMEOUT;
|
||||
break;
|
||||
|
||||
case bs_skip:
|
||||
@@ -485,7 +485,7 @@ result_t BusHandler::handleSymbol() {
|
||||
break;
|
||||
|
||||
case bs_recvCmdAck:
|
||||
timeout = m_slaveRecvTimeout+(m_currentRequest ? m_transferLatency : 0);
|
||||
timeout = m_slaveRecvTimeout;
|
||||
break;
|
||||
|
||||
case bs_recvRes:
|
||||
@@ -498,7 +498,7 @@ result_t BusHandler::handleSymbol() {
|
||||
break;
|
||||
|
||||
case bs_recvResAck:
|
||||
timeout = m_slaveRecvTimeout+m_transferLatency;
|
||||
timeout = m_slaveRecvTimeout;
|
||||
break;
|
||||
|
||||
case bs_sendCmd:
|
||||
@@ -565,9 +565,9 @@ result_t BusHandler::handleSymbol() {
|
||||
clockGettime(&sentTime);
|
||||
if (result == RESULT_OK) {
|
||||
if (m_state == bs_ready) {
|
||||
timeout = m_transferLatency+m_busAcquireTimeout;
|
||||
timeout = m_busAcquireTimeout;
|
||||
} else {
|
||||
timeout = m_transferLatency+SEND_TIMEOUT;
|
||||
timeout = SEND_TIMEOUT;
|
||||
}
|
||||
} else {
|
||||
sending = false;
|
||||
@@ -579,7 +579,7 @@ result_t BusHandler::handleSymbol() {
|
||||
// receive next symbol (optionally check reception of sent symbol)
|
||||
symbol_t recvSymbol;
|
||||
ArbitrationState arbitrationState = as_none;
|
||||
result = m_device->recv(timeout+m_transferLatency, &recvSymbol, &arbitrationState);
|
||||
result = m_device->recv(timeout, &recvSymbol, &arbitrationState);
|
||||
if (sending) {
|
||||
clockGettime(&recvTime);
|
||||
}
|
||||
@@ -593,7 +593,7 @@ result_t BusHandler::handleSymbol() {
|
||||
}
|
||||
clockGettime(&sentTime);
|
||||
recvSymbol = ESC;
|
||||
result = m_device->recv(SEND_TIMEOUT+m_transferLatency, &recvSymbol, &arbitrationState);
|
||||
result = m_device->recv(SEND_TIMEOUT, &recvSymbol, &arbitrationState);
|
||||
clockGettime(&recvTime);
|
||||
if (result != RESULT_OK) {
|
||||
logError(lf_bus, "unable to receive sent AUTO-SYN symbol: %s", getResultCode(result));
|
||||
|
||||
@@ -378,14 +378,14 @@ class BusHandler : public WaitThread {
|
||||
BusHandler(Device* device, MessageMap* messages,
|
||||
symbol_t ownAddress, bool answer,
|
||||
unsigned int busLostRetries, unsigned int failedSendRetries,
|
||||
unsigned int transferLatency, unsigned int busAcquireTimeout, unsigned int slaveRecvTimeout,
|
||||
unsigned int busAcquireTimeout, unsigned int slaveRecvTimeout,
|
||||
unsigned int lockCount, bool generateSyn,
|
||||
unsigned int pollInterval)
|
||||
: WaitThread(), m_device(device), m_reconnect(false), m_messages(messages),
|
||||
m_ownMasterAddress(ownAddress), m_ownSlaveAddress(getSlaveAddress(ownAddress)),
|
||||
m_answer(answer), m_addressConflict(false),
|
||||
m_busLostRetries(busLostRetries), m_failedSendRetries(failedSendRetries),
|
||||
m_transferLatency(transferLatency), m_busAcquireTimeout(busAcquireTimeout), m_slaveRecvTimeout(slaveRecvTimeout),
|
||||
m_busAcquireTimeout(busAcquireTimeout), m_slaveRecvTimeout(slaveRecvTimeout),
|
||||
m_masterCount(device->isReadOnly()?0:1), m_autoLockCount(lockCount == 0),
|
||||
m_lockCount(lockCount <= 3 ? 3 : lockCount), m_remainLockCount(m_autoLockCount ? 1 : 0),
|
||||
m_generateSynInterval(generateSyn ? SYN_TIMEOUT*getMasterNumber(ownAddress)+SYMBOL_DURATION : 0),
|
||||
@@ -686,9 +686,6 @@ class BusHandler : public WaitThread {
|
||||
/** the number of times a failed send is repeated (other than lost arbitration). */
|
||||
const unsigned int m_failedSendRetries;
|
||||
|
||||
/** the bus transfer latency in microseconds. */
|
||||
const unsigned int m_transferLatency;
|
||||
|
||||
/** the maximum time in microseconds for bus acquisition. */
|
||||
const unsigned int m_busAcquireTimeout;
|
||||
|
||||
|
||||
+5
-1
@@ -1306,7 +1306,11 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
// open the device
|
||||
Device *device = Device::create(opt.device, !opt.noDeviceCheck, opt.readOnly, opt.initialSend);
|
||||
unsigned int latency = 0;
|
||||
if (opt.latency >= 0) {
|
||||
latency = (unsigned int)opt.latency;
|
||||
}
|
||||
Device *device = Device::create(opt.device, latency, !opt.noDeviceCheck, opt.readOnly, opt.initialSend);
|
||||
if (device == nullptr) {
|
||||
logError(lf_main, "unable to create device %s", opt.device);
|
||||
return EINVAL;
|
||||
|
||||
@@ -141,16 +141,10 @@ MainLoop::MainLoop(const struct options& opt, Device *device, MessageMap* messag
|
||||
}
|
||||
}
|
||||
// create BusHandler
|
||||
unsigned int latency;
|
||||
if (opt.latency < 0) {
|
||||
latency = device->getLatency();
|
||||
} else {
|
||||
latency = (unsigned int)opt.latency;
|
||||
}
|
||||
m_busHandler = new BusHandler(m_device, m_messages,
|
||||
m_address, opt.answer,
|
||||
opt.acquireRetries, opt.sendRetries,
|
||||
latency, opt.acquireTimeout, opt.receiveTimeout,
|
||||
opt.acquireTimeout, opt.receiveTimeout,
|
||||
opt.masterCount, opt.generateSyn,
|
||||
opt.pollInterval);
|
||||
m_busHandler->start("bushandler");
|
||||
|
||||
+8
-15
@@ -73,17 +73,9 @@ namespace ebusd {
|
||||
#define ENH_BYTE2 ((uint8_t)0x80)
|
||||
#define makeEnhancedSequence(cmd, data) {(uint8_t)(ENH_BYTE1 | ((cmd)<<2) | (((data)&0xc0)>>6)), (uint8_t)(ENH_BYTE2 | ((data)&0x3f))}
|
||||
|
||||
/**
|
||||
* Construct a new instance.
|
||||
* @param name the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network).
|
||||
* @param address the socket address of the device.
|
||||
* @param readOnly whether to allow read access to the device only.
|
||||
* @param initialSend whether to send an initial @a ESC symbol in @a open().
|
||||
* @param udp true for UDP, false to TCP.
|
||||
* @param enhancedProto whether to use the ebusd enhanced protocol.
|
||||
*/
|
||||
Device::Device(const char* name, bool checkDevice, bool readOnly, bool initialSend, bool enhancedProto)
|
||||
: m_name(name), m_checkDevice(checkDevice), m_readOnly(readOnly), m_initialSend(initialSend),
|
||||
Device::Device(const char* name, bool checkDevice, unsigned int latency, bool readOnly, bool initialSend,
|
||||
bool enhancedProto)
|
||||
: m_name(name), m_checkDevice(checkDevice), m_latency(latency), m_readOnly(readOnly), m_initialSend(initialSend),
|
||||
m_enhancedProto(enhancedProto), m_fd(-1), m_listener(nullptr), m_arbitrationMaster(SYN),
|
||||
m_arbitrationCheck(false), m_bufSize(((MAX_LEN+1+3)/4)*4), m_bufLen(0), m_bufPos(0) {
|
||||
m_buffer = reinterpret_cast<symbol_t*>(malloc(m_bufSize));
|
||||
@@ -99,7 +91,7 @@ Device::~Device() {
|
||||
}
|
||||
}
|
||||
|
||||
Device* Device::create(const char* name, bool checkDevice, bool readOnly, bool initialSend) {
|
||||
Device* Device::create(const char* name, unsigned int extraLatency, bool checkDevice, bool readOnly, bool initialSend) {
|
||||
bool enhanced = strncmp(name, "enh:", 4) == 0;
|
||||
if (enhanced) {
|
||||
name += 4;
|
||||
@@ -134,10 +126,10 @@ Device* Device::create(const char* name, bool checkDevice, bool readOnly, bool i
|
||||
*portpos = 0;
|
||||
char* hostOrIp = strdup(addrpos);
|
||||
free(in);
|
||||
return new NetworkDevice(name, hostOrIp, port, readOnly, initialSend, udp, enhanced);
|
||||
return new NetworkDevice(name, hostOrIp, port, extraLatency, readOnly, initialSend, udp, enhanced);
|
||||
}
|
||||
// support enh:/dev/<device>
|
||||
return new SerialDevice(name, checkDevice, readOnly, initialSend, enhanced);
|
||||
return new SerialDevice(name, checkDevice, extraLatency, readOnly, initialSend, enhanced);
|
||||
}
|
||||
|
||||
result_t Device::open() {
|
||||
@@ -205,6 +197,7 @@ result_t Device::recv(unsigned int timeout, symbol_t* value, ArbitrationState* a
|
||||
}
|
||||
bool repeat = false;
|
||||
bool repeated = false;
|
||||
timeout += m_latency;
|
||||
do {
|
||||
repeat = false;
|
||||
bool isAvailable = available();
|
||||
@@ -263,7 +256,7 @@ result_t Device::recv(unsigned int timeout, symbol_t* value, ArbitrationState* a
|
||||
// for a two-byte transfer another poll is needed
|
||||
repeat = true;
|
||||
repeated = true;
|
||||
timeout = ENHANCED_COMPLETE_WAIT_DURATION;
|
||||
timeout = m_latency+ENHANCED_COMPLETE_WAIT_DURATION;
|
||||
continue;
|
||||
}
|
||||
return RESULT_ERR_TIMEOUT;
|
||||
|
||||
+24
-13
@@ -40,6 +40,9 @@ namespace ebusd {
|
||||
* to a file and/or forwarding it to a logging function.
|
||||
*/
|
||||
|
||||
/** the transfer latency of the network device [ms]. */
|
||||
#define NETWORK_LATENCY_MS 10
|
||||
|
||||
/** the arbitration state handled by @a Device. */
|
||||
enum ArbitrationState {
|
||||
as_none, //!< no arbitration in process
|
||||
@@ -80,17 +83,20 @@ class DeviceListener {
|
||||
* The base class for accessing an eBUS.
|
||||
*/
|
||||
class Device {
|
||||
public:
|
||||
protected:
|
||||
/**
|
||||
* Construct a new instance.
|
||||
* @param name the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network).
|
||||
* @param checkDevice whether to regularly check the device availability.
|
||||
* @param latency the bus transfer latency in milliseconds.
|
||||
* @param readOnly whether to allow read access to the device only.
|
||||
* @param initialSend whether to send an initial @a ESC symbol in @a open().
|
||||
* @param enhancedProto whether to use the ebusd enhanced protocol.
|
||||
*/
|
||||
Device(const char* name, bool checkDevice, bool readOnly, bool initialSend, bool enhancedProto=false);
|
||||
Device(const char* name, bool checkDevice, unsigned int latency, bool readOnly, bool initialSend,
|
||||
bool enhancedProto=false);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
@@ -99,20 +105,21 @@ class Device {
|
||||
/**
|
||||
* Factory method for creating a new instance.
|
||||
* @param name the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network).
|
||||
* @param extraLatency the extra bus transfer latency in milliseconds.
|
||||
* @param checkDevice whether to regularly check the device availability (only for serial devices).
|
||||
* @param readOnly whether to allow read access to the device only.
|
||||
* @param initialSend whether to send an initial @a ESC symbol in @a open().
|
||||
* @return the new @a Device, or nullptr on error.
|
||||
* Note: the caller needs to free the created instance.
|
||||
*/
|
||||
static Device* create(const char* name, bool checkDevice = true, bool readOnly = false,
|
||||
bool initialSend = false);
|
||||
static Device* create(const char* name, unsigned int extraLatency = 0, bool checkDevice = true,
|
||||
bool readOnly = false, bool initialSend = false);
|
||||
|
||||
/**
|
||||
* Get the transfer latency of this device.
|
||||
* @return the transfer latency in microseconds.
|
||||
*/
|
||||
virtual unsigned int getLatency() const { return 0; }
|
||||
virtual unsigned int getLatency() const { return m_latency; }
|
||||
|
||||
/**
|
||||
* Open the file descriptor.
|
||||
@@ -223,6 +230,9 @@ class Device {
|
||||
/** whether to regularly check the device availability. */
|
||||
const bool m_checkDevice;
|
||||
|
||||
/** the bus transfer latency in milliseconds. */
|
||||
const unsigned int m_latency;
|
||||
|
||||
/** whether to allow read access to the device only. */
|
||||
const bool m_readOnly;
|
||||
|
||||
@@ -269,12 +279,14 @@ class SerialDevice : public Device {
|
||||
* Construct a new instance.
|
||||
* @param name the device name (e.g. "/dev/ttyUSB0" for serial, "127.0.0.1:1234" for network).
|
||||
* @param checkDevice whether to regularly check the device availability.
|
||||
* @param extraLatency the extra bus transfer latency in milliseconds.
|
||||
* @param readOnly whether to allow read access to the device only.
|
||||
* @param initialSend whether to send an initial @a ESC symbol in @a open().
|
||||
* @param enhancedProto whether to use the ebusd enhanced protocol.
|
||||
*/
|
||||
SerialDevice(const char* name, bool checkDevice, bool readOnly, bool initialSend, bool enhancedProto=false)
|
||||
: Device(name, checkDevice, readOnly, initialSend, enhancedProto) {}
|
||||
SerialDevice(const char* name, bool checkDevice, unsigned int extraLatency, bool readOnly, bool initialSend,
|
||||
bool enhancedProto=false)
|
||||
: Device(name, checkDevice, extraLatency, readOnly, initialSend, enhancedProto) {}
|
||||
|
||||
// @copydoc
|
||||
result_t open() override;
|
||||
@@ -304,14 +316,16 @@ class NetworkDevice : public Device {
|
||||
* @param address the socket address of the device.
|
||||
* @param hostOrIp the host name or IP address of the device.
|
||||
* @param port the TCP or UDP port of the device.
|
||||
* @param extraLatency the extra bus transfer latency in milliseconds.
|
||||
* @param readOnly whether to allow read access to the device only.
|
||||
* @param initialSend whether to send an initial @a ESC symbol in @a open().
|
||||
* @param udp true for UDP, false to TCP.
|
||||
* @param enhancedProto whether to use the ebusd enhanced protocol.
|
||||
*/
|
||||
NetworkDevice(const char* name, const char* hostOrIp, uint16_t port, bool readOnly, bool initialSend,
|
||||
bool udp, bool enhancedProto=false)
|
||||
: Device(name, true, readOnly, initialSend, enhancedProto), m_hostOrIp(hostOrIp), m_port(port), m_udp(udp) {}
|
||||
NetworkDevice(const char* name, const char* hostOrIp, uint16_t port, unsigned int extraLatency, bool readOnly,
|
||||
bool initialSend, bool udp, bool enhancedProto=false)
|
||||
: Device(name, true, NETWORK_LATENCY_MS+extraLatency, readOnly, initialSend, enhancedProto),
|
||||
m_hostOrIp(hostOrIp), m_port(port), m_udp(udp) {}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
@@ -322,9 +336,6 @@ class NetworkDevice : public Device {
|
||||
}
|
||||
}
|
||||
|
||||
// @copydoc
|
||||
unsigned int getLatency() const override { return 10000; }
|
||||
|
||||
// @copydoc
|
||||
result_t open() override;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user