If the gas model flag is set to air, the individual gas mix definitions
are ignored, and a single mix with air is returned instead. For non-air
dives, only the gas mixes marked as active are returned.
Sometimes there are garbage bytes present after opening the serial
port, which causes the communication to fail. Flushing the buffers
after a small delay is all it takes to get rid of those bytes.
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.
This model doesn't support a 2 second sample rate. It appears the
possible sample rate values have been shifted by one to map the value
zero to a 15 second sample rate.
To avoid any trouble with possible out of range values, the index is
shifted in a circular way.
There are two good reasons for this change. First of all, it makes the
Predator data format more consistent with the Petrel data format, which
also has the final block appended to each dive. But even more important
is that we might actually need the information stored in the final block
someday.
The final block contains important information about the device, such as
the firmware and logbook version. Right now this information is simply
lost after the download. But if the data format ever changes to support
some new feature, we'll likely need that information to autodetect the
correct format.
Unfortunately this also changes the dive format in a non-backwards
compatible way. However, to minimize the inconvenience, the legacy
format (without the extra final block) remains supported in the parser.
Because the size of a dive isn't known in advance, we use the worst case
value of 0xFFFFFF (or nearly 16MB). However in practice, the real size
is many orders of magnitude smaller, even after the decompression.
Instead of pre-allocating a huge memory buffer, we now start with a much
smaller one, and increase when necessary.
For the predator and petrel manifests, where the size is known in
advance, we continue to pre-allocate the exact amount of memory as
before.
The Petrel (with updated firmware) supports an enhanced communication
protocol, which is more efficient and powerfull than the legacy Predator
compatibility mode. The new protocol uses data compression for faster
transfers and supports the ability to selectively download individual
dives. Last but not least, the new protocol isn't limited to the last
128kB of logbook data, but can access the full logbook capacity (16MB).
The new Petrel protocol uses a simple data compression scheme to reduce
the transfer times. The data is broken up into blocks of 32 bytes each.
Each block except the first is XOR'ed with the previous block, creating
large runs of zeros due to the similarity of the data. The zeros are
then run-length encoded (RLE) to save space.
This is done in preparation for the implementation of the new Petrel
protocol, which shares the low level communication with the existing
Predator protocol.
With the new interface, an application can easily retrieve the
underlying transport type from the device descriptors and present a
custom user interface element to the end-user for supplying transport
specific parameters. For example the serial port for devices using
serial communcication.
For devices using a usb-serial chipset or the bluetooth Serial Port
Profile (SPP/rfcomm), the transport type is DC_TRANSPORT_SERIAL, because
internally the serial emulation layer is used for the communication.
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.
This is only a preliminary version. There is certainly some room for
improvement, but the basic functionality is already in place. That
should be sufficient for daily use, and possibles issues can always be
fixed when discovered.
After the new firmware upgrade, up to three gas mixes are available
instead of only two. This causes the parsing to fail because there is
now an extra 6 byte gasmix block in the header.
Unfortunately, we can't rely on the firmware version to detect whether
this extra gasmix is present or not. In theory the dive computer can
contain dives in both the old and the new format. Because the firmware
version is a property of the device, and not stored inside each dive,
using the firmware version would either cause the old or the new dives
to fail parsing. This appears to be the approach DM4 is using.
According to some sources on the internet, the logbook gets erased
during the firmware update. However, according to the memory dumps I
received, that appears to be incorrect. The old dives are still
present, and it seems it's only DM4 that fails to download them.
So we need an alternative solution. After a detailed analysis of all
the Suunto dives at my disposal, I noticed something interesting. The
first 5 bytes of each dive are almost static. There are only 5
different variations:
0061906216
0061A06216
0062909118
0062C07118
0063C07118
The interpretation of these bytes is currently unknown, but the second
byte might be some kind of data format version. Each model always has
the same value here, and for the D6i it changes after the firmware
update:
0x61: D4, D6, D9, Cobra 2, Cobra3, Vyper 2, Vyper Air
0x62: D4i, D6i (old firmware), D9tx, HelO2
0x63: D6i (new firmware)
This can't be coincidence, so we use this byte to detect the presence
of the extra gasmix.
The HelO2, D4i, D6i and D9tx all use the same data format for the gas
mixes. The only difference is the number of gas mixes and the initial
byte offset. With this knowledge, we can easily use the same code for
all models. An additional advantage is that because the profile
configuration data is stored immediately after the gasmix section, we
can also replace the hardcoded offset with a simple calculation.
This macro was used to compensate for the fact that the 4 bytes at the
start of each dive, containing the previous and next dive pointers, are
stripped. With the SKIP macro the byte offset remained the same as in
the documentation. Nowadays, this compatibility isn't necessary anymore
and it only makes interpreting the raw binary data more difficult.
The max depth is stored in imperial units (feet), and should be
converted into metric units (meter). But for some reason this unit
conversion was omitted.
Apparantly there are also two different type of serial numbers present,
and their interpretation depends on the application. The Windows Dive
Organizer application shows both a serial number (byte offset 0x04) and
a warranty number (byte offset 0x0C). However, the Mac OS X Divers'
Diary application shows the number at byte offset 0x0C as the serial
number. Very confusing. For now, we just stick to the number at byte
offset 0x0C, because that's the number that is shown by the device
itself.
The serial numbers were not decoded at all. The raw bytes where simply
converted into an arbitrary 32 bit integer. Now the serial number
matches the real serial number as shown by the device.
The Cobalt tracks only the NDL time in the samples. There are however
two indications when the dive changes into a decompression dive, but
they don't always occur at the same time and may or may not appear in
the same sample. The first indication is that the NDL time goes to zero
and the other is the first occurrence of the "deco schedule computed"
bit (0x02) in the violation byte of the sample.
As soon as the NDL time goes to zero, an attempt is made to generate a
deco schedule. Depending upon the algorithm used, a schedule may or may
not have any stops, even though the NDL time is zero. If the schedule
does generate deco stops, the deco schedule computed bit is set in the
violation byte of the sample. This bit is set each time a non-zero
schedule is computed. But because this bit is immediately cleared after
the sample has been stored, and only set again at the completion of the
next schedule computation, not every sample will have this bit set.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The Matrix uses the same communication protocol as the Nemo Wide 2,
except that the sending the request packets with just a single write
operation doesn't seem to work. That's very surprising because it
caused no problems for the Nemo Wide 2 or the Icon HD!
The first two bytes of each request packet are probably some kind of
command type. These two bytes are answerred immediately with an ACK
byte (0xAA). Once this ACK byte has been received, the payload of the
command (if any) can be sent, and finally the response packet can be
received.
I suspect that when trying to send the entire command at once, the
device somehow doesn't receive the payload bytes correctly. Maybe it's
still busy processing those first two bytes, which causes the remainder
of the packet to get dropped? That might explain why the version
commands is not affected, because it doesn't have any payload bytes!
The application shouldn't have to deal with the delay between packets.
If the default value isn't good enough, that should be fixed internally
and not on the application side.
The second gas change event (type 0x06) contains both the oxygen and
helium percentages. These are now reported correctly with the new
GASCHANGE2 event.
The D9 family has begin and end of the deco event and we can therefore
convert this to the deco sample. For compatibility with existing software
we keep the events around.
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
The SAFETYSTOP is conceptually somewhere in between the NDL and the
DECOSTOP, so it makes sense to re-order the constants in the enum to
reflect this order.