At least one Oceanic Geo is unable to download the last memory page.
However, another device with an older firmware version (version 1D
instead of 2B), does not have this problem. So in theory the correct
layout depends on the firmware version.
But since the profile ringbuffer also appears to end at the address
0xFE00 instead of 0x10000, we'll never need to download that last page
in practice. Thus we can be lazy and simply use a single layout for all
firmware versions. The only drawback is that the last page might be
missing when downloading a full memory dump.
The Oceanic VTX is very similar to the Aeris A300 CS. The main
difference is the higher baudrate (115200 vs 38400). This is annoying
because without the correct baudrate, no communication is possible and
thus the existing autodetection based on the version packet doesn't
work. As a workaround, we now rely on the model number from the device
descriptor. The consequence is that the user must select the correct
model now (or at least a model with the same baudrate).
This change will be necessary for the Oceanic VTX, because it uses a
higher baudrate.
To maintain backwards compatibility, the existing function remains
unchanged and a new function is introduced instead.
At the moment, there is only retry logic for the ACK/NAK byte. Corrupt
data packets (e.g. wrong checksum, unexpected length, etc) are treated
as a fatal error. By reading the entire packet inside the retry loop,
all non-fatal errors are automatically taken care off.
This change is necessary for the Oceanic VTX. For some unknown reason,
the device always responds with an invalid data packet when sending the
version command for the first time:
W: 84 00
R: 5A 4F ?? 45 41 4E 56 54 58 20 31 42 20 32 30 34 38 E9
There is always one byte missing (marked with question marks), resulting
in a timeout. However, when re-sending the command again, we receive a
valid data packet:
W: 84 00
R: 5A 4F 43 45 41 4E 56 54 58 20 31 42 20 32 30 34 38 E9
This might be a firmware bug, because we're observing the exact same
behaviour with the official Oceanlog application.
Most of the changes needed for the F11 are the standard model specific
tweaks. But the F11 also has another interesting "feature". If you try
to download a full memory dump using the standard B1 read command, then
the data starts to repeat after the first 64K. It seems that somehow,
the B1 command can only address the first 64K of the memory. To avoid
this problem, the newer B4 read command needs to be used instead.
This might be a firmware bug, or maybe internally they store the address
in a 12bit variable, which causes the upper bits to get lost? That would
explain the repeating data.
In bigpage mode, we always read large pages, regardless of the amount of
bytes requested by the caller. Excess bytes are simply discarded. This
is inefficient because the same large page will be downloaded multiple
times, when requesting more than one 16 byte page from the same large
page. By caching the pages internally, we can greatly reduce the amount
of I/O operations.
In practice, applications and also libdivecomputer's internal algorithm
for downloading the dives will typically request contiguous pages, so we
only need to cache the last page.
This implementation is based on ideas and code contributed by Dirk
Hohndel.
This is ignoring a ton of data that the dive computer provides. But it
gives profile, tank pressure and temperatures - so it's a start.
This patch adds a set_dtr and set_rts call to the serial interface prior
to interacting with the device. This change is required for the A300CS to
talk to the computer.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Some new Oceanic dive computers like the Aeris A300CS support a new read
command that always reads 256 byte pages instead of 16 byte pages, other
versions support reading 128 byte pages.
This patch adds a field to the oceanic_atom2_device_t structure to
indicate which type of device this is. If bigpage mode is enabled, the
algorithm will always request larger, aligned reads and fall back to
standard 16 byte reads otherwise.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The Hollis TX1 has several new features compared to the other models. It
supports trimix and up to 6 different gas mixes can be configured. It
also has twice the amount of memory, which requires an extra bit for the
ringbuffer pointers.
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.
The VT4.x memory layout appears to be slightly different from the Atom
3.x memory layout. The logbook ringbuffer does start at offset 0x420
instead of 0x400.
The new Oceanic OCi appears to be almost identical to the already
supported Oceanic OC1. The most important change is the different
location for the logbook ringbuffer.
The logbook ringbuffer appears to start at offset 0x400 instead of
0x240. Since these ringbuffer boundaries have to be taken taken into
account only once the ringbuffer has been filled completely, this bug
affects users with more than 200 dives only. Thus, no surprise it didn't
get noticed earlier.
The Aeris XR-1 NX has very limited memory and doesn't have a
logbook and profile ringbuffer. Hence downloading dives isn't
really supported, but even this limited amount of data might be
useful for someone.
The React Pro White appears to be a newer variant of the React Pro. For
the communication it uses the newer atom2 protocol, but the data format
remains (almost) the same as the older React Pro.
Currently, each backend has it's own function to verify whether the
object vtable pointer is the expected one. All these functions can be
removed in favor of a single isintance function in the base class,
which takes the expected vtable pointer as a parameter.
Functions which are called through the vtable, don't need to verify the
vtable pointer, and those checks are removed.
The term "backend" can be confusing because it can refer to both the
virtual function table and the device/parser backends. The use of the
term "vtable" avoids this.
The hardcoded version strings are now grouped into arrays, according to
their corresponding layout descriptor. The main advantage of using
arrays is that new versions strings can now easily be added, without
having to modify any code.
The version function requires device specific knowledge to use it (at
least the required buffer size), it is already called internally when
necessary, and only a few backends support it. Thus there is no good
reason to keep it in the high-level public api.
These macros are used internally and don't need to be exposed. In some
cases, the actual values are not even constant, but dependant on the
model and/or the firmware version.
I forgot to update the device and parser initialization functions to
store the context pointer into the objects. As a result, the internal
context pointers were always NULL.
The public api is changed to require a context object for all
operations. Because other library objects store the context pointer
internally, only the constructor functions need an explicit context
object as a parameter.
Adding the "dc_" namespace prefix (which is of course an abbreviation
for libdivecomputer) should avoid conflicts with other libraries. For
the time being, only the high-level device and parser layers are
changed.
The public header files are moved to a new subdirectory, to separate
the definition of the public interface from the actual implementation.
Using an identical directory layout as the final installation has the
advantage that the example code can be build outside the project tree
without any modifications to the #include statements.
The Veo 1.0 has very limited memory and doesn't have a logbook and
profile ringbuffer. Hence downloading dives isn't really supported, but
even this limited amount of data might be useful for someone.