Parsing the gas switch events is somewhat complicated, because depending
on the actual model, they can be stored in different ways.
The table below lists the number of gas mixes (G), tanks (T) and alarm
bytes (A) supported by each model. Note that only the representative
model in each group is listed.
Model | G | T | A
==============|===|===|===
Pro | 1 | 0 | 1
Com | 1 | 1 | 1
Tec | 3 | 3 | 1
Aladin Tec | 1 | 0 | 2
Aladin Tec 2G | 3 | 0 | 2
Galileo | 3 | 3 | 3
Models without support for multiple gasmixes only need to set the
initial gas mix correctly. Models with support for one or more tank
pressure sensors can link the gas switches to the tank switches. Models
with at least two alarm bytes can store a gas switch event in the second
alarm byte.
As can be observed from the table, some models can use several different
methods to store the gas switches. The current implementation supports
all of them. In the case of a conflict, the last used method always
takes precedence. That's simply due to the fact that each method just
sets the gasmix index, and only the final value is used. If this
approach turns out to produce wrong results, it can always be fixed
later.
The initial gasmix is always assumed to be the first configured gasmix.
One byte is already more than sufficient to store an oxygen percentage.
Using two bytes doesn't cause any problems for some models, because the
upper byte is always zero, but for other models that's not the case.
Most likely this upper byte is used to store something else.
Internal, these two models use exactly the same data format. For those
features which are only available on one of the models, the
corresponding data fields are set to their unused values. For example,
the Smart Tec supports up to three gasmixes, while the Smart Z supports
only one gasmix. But although the Smart Z has storage reserved for up to
three gas mixes, only the first one is ever used.
For the Galileo Trimix, the header length isn't fixed. The actual length
depends on whether the dive has the trimix setting enabled or not.
Because at this point we're still trying to determine the length of the
header, it hasn't been checked yet and an extra check is necessary.
Because for selecting the correct header and sample tables (and
associated data) only the model number is necessary, they can easily be
stored inside the device handle. The main benefit is less duplicated
code.
The Uwatec Meridian protocol is identical to the Uwatec Smart/Galileo
protocol, except for some additional framing around each data packet,
and the switch from IrDA to usb-serial communication. For parsing, the
data format appears to be identical to the Galileo data format.
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.
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 Uwatec Smart stores a sample value only when it's diffent from the
previous value. While this compressed format does save some space on the
device, it is less practical for use in an application. The original
uncompressed data can easily be obtained by copying missing sample
values from the previous sample.
The implementation uses a two pass approach. In the first pass, all
sample values that are explicitly stored in the profile date are
collected. Any sample value that is not present, will automatically
retain the value from the previous sample. In the second pass, all
sample values are passed back to the application. The presence of an
absolute value is used to decide which sample types are present in the
data.