Introduce an adaptive inter packet delay.
On some systems a small delay is required between receiving the response of a packet and sending the request for the next packet. Without this delay, almost every request fails with either a NAK or a timeout. Retrying usually works, but also causes the download to slow down considerable. The root of the problem appears to be related to the FTDI low latency setting. On Windows and Mac OS X systems, the default setting for the latency is 16ms, while Linux defaults to a low latency setting of only 1ms. This higher latency on Windows and Mac automatically introduces a small delay while reading the packet, and that probably happens to be just enough to make the transfer succeed without any problems. But on Linux, due to the low latency setting, the next request is send almost immediately, and that causes the transfer to fail. I suspect the dive computer may still be busy with the previous request and needs a bit more time before it's ready to accept a new request. To mitigate this problem, we introduce a adaptive inter packet delay. Initially this adaptive delay is set to zero. This is to make sure we don't affect those systems that don't need a delay at all. Now, every time a packet fails, that's an indication the inter packet delay is too small, and we slightly increase the value. After a few attempts we'll automatically reach the minimal required value. To avoid that the delay grows out of control in the case of serious trouble, it's limited at 16ms. Note that the fixed 100ms delay before retrying a failed packet remains in place. That's on purpose, to make sure the next attempt will always be successful, regardless of whether the adaptive delay has already reached its minimal value or not.
This commit is contained in:
parent
bfeab10515
commit
f0faebb3a1
@ -35,6 +35,7 @@
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &oceanic_atom2_device_vtable)
|
||||
|
||||
#define MAXRETRIES 2
|
||||
#define MAXDELAY 16
|
||||
|
||||
#define EXITCODE(rc) \
|
||||
( \
|
||||
@ -47,6 +48,7 @@
|
||||
typedef struct oceanic_atom2_device_t {
|
||||
oceanic_common_device_t base;
|
||||
serial_t *port;
|
||||
unsigned int delay;
|
||||
} oceanic_atom2_device_t;
|
||||
|
||||
static dc_status_t oceanic_atom2_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size);
|
||||
@ -318,6 +320,10 @@ oceanic_atom2_send (oceanic_atom2_device_t *device, const unsigned char command[
|
||||
if (device_is_cancelled (abstract))
|
||||
return DC_STATUS_CANCELLED;
|
||||
|
||||
if (device->delay) {
|
||||
serial_sleep (device->port, device->delay);
|
||||
}
|
||||
|
||||
// Send the command to the dive computer.
|
||||
int n = serial_write (device->port, command, csize);
|
||||
if (n != csize) {
|
||||
@ -364,6 +370,10 @@ oceanic_atom2_transfer (oceanic_atom2_device_t *device, const unsigned char comm
|
||||
if (nretries++ >= MAXRETRIES)
|
||||
return rc;
|
||||
|
||||
// Increase the inter packet delay.
|
||||
if (device->delay < MAXDELAY)
|
||||
device->delay++;
|
||||
|
||||
// Delay the next attempt.
|
||||
serial_sleep (device->port, 100);
|
||||
serial_flush (device->port, SERIAL_QUEUE_INPUT);
|
||||
@ -421,6 +431,7 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, const char
|
||||
|
||||
// Set the default values.
|
||||
device->port = NULL;
|
||||
device->delay = 0;
|
||||
|
||||
// Open the device.
|
||||
int rc = serial_open (&device->port, context, name);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user