The dc_parser_set_data() function allows to re-use a parser object for
multiple dives. The advantages of this feature are actually very limited
in practice. The reduction in memory consumption is almost negligible,
because the amount of internal state in the parser is typically very
small. But the implementation requires some additional complexity
because each backend needs code to reset its internal state. Therefore,
the function is removed and the data and size needs to be passed
directly to the dc_parser_new() and dc_parser_new2() functions instead.
Because keeping a reference to the data has also caused issues in the
past, especially for applications implemented in a garbage collected
language, the data will now also get copied internally.
Because the sample struct is passed by value, the size of the structure
can't be changed without also changing the function signature and
breaking backwards compatibility. This prevents adding new fields in the
future, to support some new features.
When passing the sample struct by reference using a pointer, the size of
the pointer does always remains the same.
For gas consumption calculations it's very convenient to know whether a
tank is used for example in a sidemount configuration, or as
oxygen/diluent tank on a rebreather.
For rebreather dives, it's convenient to know whether a gas mix is used
as a closed-circuit mix (oxygen/diluent) or as an open circuit mix
(bailout).
Some dive computers report the time of the next decompression stop,
while others report the Time To Surface (TTS). Some models can even
report both.
Add a TTS field to the deco sample to support both values.
After the previous commit changed the resolution of the sample time to
milliseconds, the dive computers which actually support a higher
resoltion can now enable this feature and report all samples.
Some dive computers, especially freediving computers, supports multiple
samples per second. Since our smallest unit of time is one second, we
can't represent this, and the extra samples are dropped. Therefore, the
units are changed to milliseconds to prepare supporting this extra
resolution.
The bookmark value is a bitfield indicating the type of bookmark:
1 - Pressed the bookmark button during a dive
2 - Reset the stopwatch
4 - Unknown
8 - Unknown
For dive computers where the reference time (epoch) of the device is
unknown, libdivecomputer uses the current time of the device (devtime)
and the host system (systime) to synchronize both clocks.
Currently, both timestamps are passed directly to the constructor of the
parser. With the new public function, the application can adjust the
timestamps afterwards.
Some dive computers store the depth as an absolute pressure value (in
bar). To convert to a depth value (in meters), the atmospheric pressure
and water density are required. For dive computers that do not have
those values available, libdivecomputer uses a default value. With the
new public api functions, applications can adjust those default values.
Some dive computers already provided a backend specific calibration
function. Those functions are now deprecated. They are kept around to
maintain backwards compatibility for now, but they will be removed in
the next version.
Replace hardcoded constants with a layout descriptor. This reduces the
amount of model specific conditions, and makes it easier to add support
for new models.
The parser->mode field is only initialized at the end of the function.
The result is that the current code always used the default value
(zero). Inside the function itself, the local variable should be used
instead.
Like most dive commputers, the Mares Genius uses a surface timeout to
detect the end of the dive. But since there is no explicit dive time
field stored, the total dive time is based on the number of samples,
which includes this surface time at the end of the dive. However, the
dive time displayed by the dive computer (and also the Mares
DiveOrganizer application) does not include this surface time.
For older firmware versions the value is hardcoded to 3 minutes, but
starting with the newer v01.02.00 firmware the value is configurable and
stored in the settings. To detect whether the setting is available, we
need to check the profile version instead of the header version. That's
because the header appears to be generated on-the-fly during the
download, and thus the header version also changes for dives recorded
prior to the firmware update.
For all other models, also take into account a hardcoded timeout of 3
minutes.
The changes in commit 5cb527d53ca88ac692beb55288172fc1003975fa to
support the new Mares Genius firmware v01.02.00 were incomplete.
For dives recorded prior to the firmware upgrade, only the header
version changed from 0.0 to 1.1, while the profile version remained the
same. But for dives recorded after the firmware upgrade, the profile
version also changed from 0.2 to 1.0.
The known header and profile object versions (indicated as
type.major.minor) are now:
Model | Firmware | Header | Profile
========|==========|========|=========
Genius | 1.0.x | 1.0.0 | 0.0.2
Genius | 1.2.0 | 1.1.1 | 0.1.0
Horizon | 1.7.28 | 1.0.1 | 1.0.2
To simplify the object version check, all versions below a certain upper
limit are now considered supported.
The new Mares Genius firmware v01.02.00 has a header which is 10 bytes
larger. This difference is indicated with a change in the major version
from 0 to 1.
The Mares Horizon is a variant of the Mares Genius, with a few changes
to support SCR dives:
The dive header is slightly modified. There is an extra 8 byte field at
offset 0x18, which causes all later fields to have moved up with the
same amount. This difference is indicated in both the object minor
version (with a change from v0.0 to v0.1), and the logformat.
For the profile data, there is a new SDPT sample type which contains a
bit more information compared to the existing DPRS sample type. This
difference is indicated with a change in the object type (from 0 to 1).
The current implementation assumes a fixed order for the record types (a
DSTR record, a TISS record, zero or more DPRS/SDPT records with an AIRS
record every 4 sample, and finally a DEND record), and either only DPRS
or SDPT records but never a mixture of the two. If these assumptions
turns out to be incorrect, the implementation will need to be changed
significantly. Note that the assumption of the fixed order was already
present for the Genius.
Bluetooth support is currently disabled in the Horizon firmware, but
might be re-enabled in the future.
The original Mares Genius support was based on Mares Dive Organizer
2.25, which has a bug in the salinity parsing. The latest version 2.26
has this bug fixed.
Reported-by: Greg McLaughlin <gregm@somemore.com>
The Mares Genius supports a new command to download different types of
objects (e.g. dive header, dive profiles, etc) directly, without needing
to manually read and parse the contents of the flash memory.
The data structure also changed significantly. The profile data is now
organized into different records. Each record starts and ends with a 4
byte ascii marker:
DSTR: Dive start record
TISS: Tissue record
DPRS: Sample record
AIRS: Air integration record
DEND: Dive end record
and contains a CRC checksum. The contents of the records remains very
similar to the existing iconhd data format.
Based-on-code-by: Janice McLaughlin <janice@moremobilesoftware.com>
Split the offset calculation in two steps: first the offset to the
header data, and then the date/time field. The main advantage is that
the resulting code now follows the same logic as in the other functions.
The Mares Genius dive header is no longer located at the end of the data
(after the dive profile), but at the start. Therefore we don't need the
offset to the dive header anymore. Replace with the size of the header
instead.
The length field in the data is checked for the maximum size (e.g. the
size of the buffer), but there is no such check on the minimum size
(e.g. the size of the header). If the length is smaller, the code
accessed data before the start of the buffer.
The Smart Air uses almost the same data format as the Quad Air. Only the
4 bytes containing the dive mode and number of samples moved from the
beginning of the header to the end. This is a change adopted from the
regular Smart.
Allthough most dive computers always use local time and don't support
timezones at all, there are a few exceptions. There are two different
sources of timezone information:
- Some of the newer Uwatec/Scubapro devices use UTC internally and also
support a timezone setting. This UTC offset is currently taken into
account to obtain the dive date/time, but the UTC offset itself is
lost.
- Uwatec/Scubapro and Reefnet devices rely on the clock of the host
system to synchronize the internal device clock and calculate the
dive date/time. The consequence is that the resulting date/time is
always in the timezone of the host system.
In order to preserve this timezone information, the dc_datetime_t
structure is extended with a new "timezone" field, containing the UTC
offset in seconds. Devices without timezone support will set the field
to the special value DC_TIMEZONE_NONE.
The dc_datetime_localtime() and dc_datetime_gmtime() functions will
automatically populate the new field with respectively the local
timezone offset and zero. The dc_datetime_mktime() function will take
into account the new timezone field for the conversion to UTC. The
special value DC_TIMEZONE_NONE is interpreted as zero.
The vendor_product_parser_create() and vendor_product_device_open()
functions should be called indirectly, through the generic
dc_device_open() and dc_parser_new() functions. And the
vendor_product_extract_dives() functions are internal functions that
should never have been part of the public api in the first place.
The number of tank pressure sensors is not necessary equal to the number
of gas mixes. Take for example a dive with two gas mixes, but only a
single tank pressure sensor attached to one of the two tanks. Because
the tank index is shared with the gas mix index, it will refer to a
non-existing sensor when switching to a tank without a pressure sensor
attached.
The invalid tank index should not be considered a fatal error. The tank
pressure values should be ignored instead. The device appears to record
zero values anyway, except for the first value immediately after the gas
switch. I suspect that's caused by the fact that the pressure is only
recorded every 4 samples, and therefore the last pressure value is
reported with a small delay.
The sample interval is stored in the settings, and thus there is no need
to use a hardcoded value. In practice all dives appear to be using the
default value (5 seconds), so this is more about being future proof.
Both the allocation and initialization of the object data structure is
now moved to a single function. The corresponding deallocation function
is intended to free objects that have been allocated, but are not fully
initialized yet. The public cleanup function shouldn't be used in such
case, because it may try to release resources that haven't been
initialized yet.
Instead of freeing the object data structure in the backend specific
cleanup function, the memory is now freed automatically in the base
class function. This reduces the amount of boilerplate code in the
backends. Backends that don't allocate any additional resources, do no
longer require a cleanup function at all.
The new gasmix sample contains the index of the active gas mix.
This new sample is intended as a replacement for the existing gas change
events (SAMPLE_EVENT_GASCHANGE and SAMPLE_EVENT_GASCHANGE2). To maintain
backwards compatibility, the legacy events are marked as deprecated but
not removed yet.
The Mares Smart Apnea uses a different data format than the regular
Smart, because it records not only a summary of each freedive in the
session, but also a full depth profile.
Because both the regular Smart and the Smart Apnea have the same model
number (0x10), another way to distinguish the two variants is needed.
Therefore, the Smart Apnea gets a modified model number, with one of the
higher bit set. The actual type is detected from the contents of the
version packet.
The new Smart Apnea is also capable of recording multiple samples per
second (e.g. 2, 4 or 8). But since our smallest unit of time is one
second, we can't represent this, and the extra samples will get dropped
for now.
The Mares Smart supports not only scuba diving, but also freediving.
Because the freedive data format is fundamentally different from the
regular dives, being able to detect the type of dive in advance is very
important. For that reason, Mares moved the 4 bytes containing the dive
mode and number of samples from the beginning of the header to the end.
Except for this 4 byte shift, there are no changes for regular dives.
For the freedives, there is no real profile available, only a summary of
the entire freedive session. In an attempt to workaround this
limitation, we generate a pseudo profile in exactly the same (but ugly)
way as is done in the Mares Nemo backend.
For a dive in gauge mode, the gas mixes defined in the header should be
ignored, and no gas change event should be emitted. This is done by
hardcoding the number of gas mixes to zero.
The code to find the offset to the footer and parse the gas mix data is
duplicated in multiple places. Move this code to a single place, and
cache the data in the parser instead.