Merge remote-tracking branch 'libdivecomputer/master' into update_libdivecomputer_202402
This commit is contained in:
commit
d37cb91734
@ -1,6 +1,6 @@
|
||||
# Versioning.
|
||||
m4_define([dc_version_major],[0])
|
||||
m4_define([dc_version_minor],[8])
|
||||
m4_define([dc_version_minor],[9])
|
||||
m4_define([dc_version_micro],[0])
|
||||
m4_define([dc_version_suffix],[devel-Subsurface-NG])
|
||||
m4_define([dc_version],dc_version_major.dc_version_minor.dc_version_micro[]m4_ifset([dc_version_suffix],-[dc_version_suffix]))
|
||||
|
||||
@ -331,7 +331,6 @@
|
||||
<ClInclude Include="..\..\src\cressi_leonardo.h" />
|
||||
<ClInclude Include="..\..\src\deepblu_cosmiq.h" />
|
||||
<ClInclude Include="..\..\src\deepsix_excursion.h" />
|
||||
<ClInclude Include="..\..\src\descriptor-private.h" />
|
||||
<ClInclude Include="..\..\src\device-private.h" />
|
||||
<ClInclude Include="..\..\src\diverite_nitekq.h" />
|
||||
<ClInclude Include="..\..\src\divesoft_freedom.h" />
|
||||
|
||||
@ -32,7 +32,6 @@ MANPAGES = \
|
||||
dc_parser_get_field.3 \
|
||||
dc_parser_new.3 \
|
||||
dc_parser_samples_foreach.3 \
|
||||
dc_parser_set_data.3 \
|
||||
dc_bluetooth_open.3 \
|
||||
dc_bluetooth_iterator_new.3 \
|
||||
dc_bluetooth_device_get_address.3 \
|
||||
|
||||
@ -53,7 +53,7 @@ with
|
||||
Each dive invokes
|
||||
.Fa callback
|
||||
with the dive data, which should be parsed with
|
||||
.Xr dc_parser_set_data 3 ,
|
||||
.Xr dc_parser_new 3 ,
|
||||
and the binary fingerprint of the dive.
|
||||
The fingerprint can be used to record the newest dive and stop
|
||||
processing (on subsequent invocations) when the same dive fingerprint is
|
||||
@ -72,7 +72,7 @@ If
|
||||
returns zero, this will not be reflected in the return value (usually
|
||||
.Dv DC_STATUS_SUCCESS ) .
|
||||
.Sh SEE ALSO
|
||||
.Xr dc_parser_set_data 3
|
||||
.Xr dc_parser_new 3
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Lb libdivecomputer
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
Extract the date and time of a dive,
|
||||
.Fa parser ,
|
||||
previously initialised with
|
||||
.Xr dc_parser_set_data 3 .
|
||||
.Xr dc_parser_new 3 .
|
||||
This returns the broken-down time-stamp of the dive in the local time of
|
||||
the dive.
|
||||
.Pp
|
||||
@ -57,7 +57,7 @@ messages on further failure.
|
||||
.Sh SEE ALSO
|
||||
.Xr dc_datetime_gmtime 3 ,
|
||||
.Xr dc_datetime_localtime 3 ,
|
||||
.Xr dc_parser_set_data 3
|
||||
.Xr dc_parser_new 3
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Lb libdivecomputer
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
Extract a field from a dive,
|
||||
.Fa parser ,
|
||||
previously initialised with
|
||||
.Xr dc_parser_set_data 3 .
|
||||
.Xr dc_parser_new 3 .
|
||||
The
|
||||
.Fa value
|
||||
field type depends upon the
|
||||
@ -187,7 +187,7 @@ if the field was retrieved,
|
||||
if the field is not supported by the device, or other error messages on
|
||||
further failure.
|
||||
.Sh SEE ALSO
|
||||
.Xr dc_parser_set_data 3
|
||||
.Xr dc_parser_new 3
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Lb libdivecomputer
|
||||
|
||||
@ -39,8 +39,6 @@
|
||||
.Fa "dc_parser_t **parser"
|
||||
.Fa "dc_context_t *context"
|
||||
.Fa "dc_descriptor_t *descriptor"
|
||||
.Fa "unsigned int devtime"
|
||||
.Fa "dc_ticks_t systime"
|
||||
.Fc
|
||||
.Sh DESCRIPTION
|
||||
Creates a parser for a single dive extracted from the dive computer with
|
||||
@ -55,10 +53,6 @@ parameter; and
|
||||
.Nm dc_parser_new2 ,
|
||||
which is given device values (model, etc.) directly.
|
||||
.Pp
|
||||
After filling in the
|
||||
.Fa parser
|
||||
parameter, one usually sets parser data with
|
||||
.Xr dc_parser_set_data 3 .
|
||||
The pointer must later be freed with
|
||||
.Xr dc_parser_destroy 3 .
|
||||
.Sh RETURN VALUES
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
.Ft "typedef void"
|
||||
.Fo "(*dc_sample_callback_t)"
|
||||
.Fa "dc_sample_type_t type"
|
||||
.Fa "dc_sample_value_t value"
|
||||
.Fa "const dc_sample_value_t *value"
|
||||
.Fa "void *userdata"
|
||||
.Fc
|
||||
.Ft dc_status_t
|
||||
@ -42,7 +42,7 @@
|
||||
.Fc
|
||||
.Sh DESCRIPTION
|
||||
Extract the samples taken during a dive as previously initialised with
|
||||
.Xr dc_parser_set_data 3 .
|
||||
.Xr dc_parser_new 3 .
|
||||
Each sample is passed to
|
||||
.Fa callback
|
||||
with the
|
||||
@ -63,7 +63,7 @@ closed.
|
||||
The following sample types may be raised:
|
||||
.Bl -tag -width Ds
|
||||
.It Dv DC_SAMPLE_TIME
|
||||
The time of the sample taken in seconds after the dive began.
|
||||
The time of the sample taken in milliseconds after the dive began.
|
||||
Set in the
|
||||
.Fa time
|
||||
field.
|
||||
@ -184,7 +184,7 @@ Returns
|
||||
.Dv DC_STATUS_OK
|
||||
on success and another code on failure.
|
||||
.Sh SEE ALSO
|
||||
.Xr dc_parser_set_data 3
|
||||
.Xr dc_parser_new 3
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Lb libdivecomputer
|
||||
|
||||
@ -1,65 +0,0 @@
|
||||
.\"
|
||||
.\" libdivecomputer
|
||||
.\"
|
||||
.\" Copyright (C) 2017 Kristaps Dzonsons <kristaps@bsd.lv>
|
||||
.\"
|
||||
.\" This library is free software; you can redistribute it and/or
|
||||
.\" modify it under the terms of the GNU Lesser General Public
|
||||
.\" License as published by the Free Software Foundation; either
|
||||
.\" version 2.1 of the License, or (at your option) any later version.
|
||||
.\"
|
||||
.\" This library is distributed in the hope that it will be useful,
|
||||
.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
.\" Lesser General Public License for more details.
|
||||
.\"
|
||||
.\" You should have received a copy of the GNU Lesser General Public
|
||||
.\" License along with this library; if not, write to the Free Software
|
||||
.\" Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
.\" MA 02110-1301 USA
|
||||
.\"
|
||||
.Dd January 5, 2017
|
||||
.Dt DC_PARSER_SET_DATA 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm dc_parser_set_data
|
||||
.Nd assigns parse data to a dive parser
|
||||
.Sh LIBRARY
|
||||
.Lb libdivecomputer
|
||||
.Sh SYNOPSIS
|
||||
.In libdivecomputer/parser.h
|
||||
.Ft dc_status_t
|
||||
.Fo dc_parser_set_data
|
||||
.Fa "dc_parser_t *parser"
|
||||
.Fa "const unsigned char *data"
|
||||
.Fa "unsigned int size"
|
||||
.Fc
|
||||
.Sh DESCRIPTION
|
||||
Assigns the binary sequence
|
||||
.Fa data
|
||||
of length
|
||||
.Fa size
|
||||
bytes to
|
||||
.Fa parser ,
|
||||
which was created with
|
||||
.Xr dc_parser_new 3 .
|
||||
How the data is parsed depends upon the values provided to
|
||||
.Xr dc_parser_new 3 .
|
||||
The data usually comes from the callback assigned to
|
||||
.Xr dc_device_foreach 3 .
|
||||
.Sh RETURN VALUES
|
||||
Returns
|
||||
.Dv DC_STATUS_OK
|
||||
on success and another code on failure.
|
||||
.Sh SEE ALSO
|
||||
.Xr dc_device_foreach 3 ,
|
||||
.Xr dc_parser_new 3
|
||||
.Sh AUTHORS
|
||||
The
|
||||
.Lb libdivecomputer
|
||||
library was written by
|
||||
.An Jef Driesen ,
|
||||
.Mt jef@libdivecomputer.org .
|
||||
The manpages were written by
|
||||
.An Kristaps Dzonsons ,
|
||||
.Mt kristaps@bsd.lv .
|
||||
@ -82,9 +82,7 @@ Iterate over all dives with
|
||||
.Xr dc_device_foreach 3 .
|
||||
.It
|
||||
For each iterated dive, create a new parser with
|
||||
.Xr dc_parser_new 3
|
||||
and set the parsed data with
|
||||
.Xr dc_parser_set_data 3 .
|
||||
.Xr dc_parser_new 3 .
|
||||
.It
|
||||
Get attributes of the parsed dive with
|
||||
.Xr dc_parser_get_field 3 .
|
||||
|
||||
@ -80,20 +80,12 @@ dive_cb (const unsigned char *data, unsigned int size, const unsigned char *fing
|
||||
|
||||
// Create the parser.
|
||||
message ("Creating the parser.\n");
|
||||
rc = dc_parser_new (&parser, divedata->device);
|
||||
rc = dc_parser_new (&parser, divedata->device, data, size);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR ("Error creating the parser.");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Register the data.
|
||||
message ("Registering the data.\n");
|
||||
rc = dc_parser_set_data (parser, data, size);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR ("Error registering the data.");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Parse the dive data.
|
||||
message ("Parsing the dive data.\n");
|
||||
rc = dctool_output_write (divedata->output, parser, data, size, fingerprint, fsize);
|
||||
|
||||
@ -54,17 +54,17 @@ parse (dc_buffer_t *buffer, dc_context_t *context, dc_descriptor_t *descriptor,
|
||||
|
||||
// Create the parser.
|
||||
message ("Creating the parser.\n");
|
||||
rc = dc_parser_new2 (&parser, context, descriptor, devtime, systime);
|
||||
rc = dc_parser_new2 (&parser, context, descriptor, data, size);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR ("Error creating the parser.");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// Register the data.
|
||||
message ("Registering the data.\n");
|
||||
rc = dc_parser_set_data (parser, data, size);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR ("Error registering the data.");
|
||||
// Set the clock.
|
||||
message ("Setting the clock.\n");
|
||||
rc = dc_parser_set_clock (parser, devtime, systime);
|
||||
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
|
||||
ERROR ("Error setting the clock.");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
||||
@ -90,7 +90,7 @@ convert_volume (double value, dctool_units_t units)
|
||||
}
|
||||
|
||||
static void
|
||||
sample_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata)
|
||||
sample_cb (dc_sample_type_t type, const dc_sample_value_t *value, void *userdata)
|
||||
{
|
||||
static const char *events[] = {
|
||||
"none", "deco", "rbt", "ascent", "ceiling", "workload", "transmitter",
|
||||
@ -104,64 +104,80 @@ sample_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata)
|
||||
|
||||
sample_data_t *sampledata = (sample_data_t *) userdata;
|
||||
|
||||
unsigned int seconds = 0, milliseconds = 0;
|
||||
|
||||
switch (type) {
|
||||
case DC_SAMPLE_TIME:
|
||||
seconds = value->time / 1000;
|
||||
milliseconds = value->time % 1000;
|
||||
if (sampledata->nsamples++)
|
||||
fprintf (sampledata->ostream, "</sample>\n");
|
||||
fprintf (sampledata->ostream, "<sample>\n");
|
||||
fprintf (sampledata->ostream, " <time>%02u:%02u</time>\n", value.time / 60, value.time % 60);
|
||||
if (milliseconds) {
|
||||
fprintf (sampledata->ostream, " <time>%02u:%02u.%03u</time>\n", seconds / 60, seconds % 60, milliseconds);
|
||||
} else {
|
||||
fprintf (sampledata->ostream, " <time>%02u:%02u</time>\n", seconds / 60, seconds % 60);
|
||||
}
|
||||
break;
|
||||
case DC_SAMPLE_DEPTH:
|
||||
fprintf (sampledata->ostream, " <depth>%.2f</depth>\n",
|
||||
convert_depth(value.depth, sampledata->units));
|
||||
convert_depth(value->depth, sampledata->units));
|
||||
break;
|
||||
case DC_SAMPLE_PRESSURE:
|
||||
fprintf (sampledata->ostream, " <pressure tank=\"%u\">%.2f</pressure>\n",
|
||||
value.pressure.tank,
|
||||
convert_pressure(value.pressure.value, sampledata->units));
|
||||
value->pressure.tank,
|
||||
convert_pressure(value->pressure.value, sampledata->units));
|
||||
break;
|
||||
case DC_SAMPLE_TEMPERATURE:
|
||||
fprintf (sampledata->ostream, " <temperature>%.2f</temperature>\n",
|
||||
convert_temperature(value.temperature, sampledata->units));
|
||||
convert_temperature(value->temperature, sampledata->units));
|
||||
break;
|
||||
case DC_SAMPLE_EVENT:
|
||||
if (value.event.type != SAMPLE_EVENT_GASCHANGE && value.event.type != SAMPLE_EVENT_GASCHANGE2) {
|
||||
if (value->event.type != SAMPLE_EVENT_GASCHANGE && value->event.type != SAMPLE_EVENT_GASCHANGE2) {
|
||||
fprintf (sampledata->ostream, " <event type=\"%u\" time=\"%u\" flags=\"%u\" value=\"%u\">%s</event>\n",
|
||||
value.event.type, value.event.time, value.event.flags, value.event.value, events[value.event.type]);
|
||||
value->event.type, value->event.time, value->event.flags, value->event.value, events[value->event.type]);
|
||||
}
|
||||
break;
|
||||
case DC_SAMPLE_RBT:
|
||||
fprintf (sampledata->ostream, " <rbt>%u</rbt>\n", value.rbt);
|
||||
fprintf (sampledata->ostream, " <rbt>%u</rbt>\n", value->rbt);
|
||||
break;
|
||||
case DC_SAMPLE_HEARTBEAT:
|
||||
fprintf (sampledata->ostream, " <heartbeat>%u</heartbeat>\n", value.heartbeat);
|
||||
fprintf (sampledata->ostream, " <heartbeat>%u</heartbeat>\n", value->heartbeat);
|
||||
break;
|
||||
case DC_SAMPLE_BEARING:
|
||||
fprintf (sampledata->ostream, " <bearing>%u</bearing>\n", value.bearing);
|
||||
fprintf (sampledata->ostream, " <bearing>%u</bearing>\n", value->bearing);
|
||||
break;
|
||||
case DC_SAMPLE_VENDOR:
|
||||
fprintf (sampledata->ostream, " <vendor type=\"%u\" size=\"%u\">", value.vendor.type, value.vendor.size);
|
||||
for (unsigned int i = 0; i < value.vendor.size; ++i)
|
||||
fprintf (sampledata->ostream, "%02X", ((const unsigned char *) value.vendor.data)[i]);
|
||||
fprintf (sampledata->ostream, " <vendor type=\"%u\" size=\"%u\">", value->vendor.type, value->vendor.size);
|
||||
for (unsigned int i = 0; i < value->vendor.size; ++i)
|
||||
fprintf (sampledata->ostream, "%02X", ((const unsigned char *) value->vendor.data)[i]);
|
||||
fprintf (sampledata->ostream, "</vendor>\n");
|
||||
break;
|
||||
case DC_SAMPLE_SETPOINT:
|
||||
fprintf (sampledata->ostream, " <setpoint>%.2f</setpoint>\n", value.setpoint);
|
||||
fprintf (sampledata->ostream, " <setpoint>%.2f</setpoint>\n", value->setpoint);
|
||||
break;
|
||||
case DC_SAMPLE_PPO2:
|
||||
fprintf (sampledata->ostream, " <ppo2>%.2f</ppo2>\n", value.ppo2);
|
||||
if (value->ppo2.sensor != DC_SENSOR_NONE) {
|
||||
fprintf (sampledata->ostream, " <ppo2 sensor=\"%u\">%.2f</ppo2>\n", value->ppo2.sensor, value->ppo2.value);
|
||||
} else {
|
||||
fprintf (sampledata->ostream, " <ppo2>%.2f</ppo2>\n", value->ppo2.value);
|
||||
}
|
||||
break;
|
||||
case DC_SAMPLE_CNS:
|
||||
fprintf (sampledata->ostream, " <cns>%.1f</cns>\n", value.cns * 100.0);
|
||||
fprintf (sampledata->ostream, " <cns>%.1f</cns>\n", value->cns * 100.0);
|
||||
break;
|
||||
case DC_SAMPLE_DECO:
|
||||
fprintf (sampledata->ostream, " <deco time=\"%u\" depth=\"%.2f\">%s</deco>\n",
|
||||
value.deco.time,
|
||||
convert_depth(value.deco.depth, sampledata->units),
|
||||
decostop[value.deco.type]);
|
||||
value->deco.time,
|
||||
convert_depth(value->deco.depth, sampledata->units),
|
||||
decostop[value->deco.type]);
|
||||
if (value->deco.tts) {
|
||||
fprintf (sampledata->ostream, " <tts>%u</tts>\n",
|
||||
value->deco.tts);
|
||||
}
|
||||
break;
|
||||
case DC_SAMPLE_GASMIX:
|
||||
fprintf (sampledata->ostream, " <gasmix>%u</gasmix>\n", value.gasmix);
|
||||
fprintf (sampledata->ostream, " <gasmix>%u</gasmix>\n", value->gasmix);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -322,11 +338,19 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u
|
||||
"<gasmix>\n"
|
||||
" <he>%.1f</he>\n"
|
||||
" <o2>%.1f</o2>\n"
|
||||
" <n2>%.1f</n2>\n"
|
||||
"</gasmix>\n",
|
||||
" <n2>%.1f</n2>\n",
|
||||
gasmix.helium * 100.0,
|
||||
gasmix.oxygen * 100.0,
|
||||
gasmix.nitrogen * 100.0);
|
||||
if (gasmix.usage) {
|
||||
const char *usage[] = {"none", "oxygen", "diluent", "sidemount"};
|
||||
fprintf (output->ostream,
|
||||
" <usage>%s</usage>\n",
|
||||
usage[gasmix.usage]);
|
||||
}
|
||||
fprintf (output->ostream,
|
||||
"</gasmix>\n");
|
||||
|
||||
}
|
||||
|
||||
// Parse the tanks.
|
||||
@ -354,6 +378,12 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u
|
||||
" <gasmix>%u</gasmix>\n",
|
||||
tank.gasmix);
|
||||
}
|
||||
if (tank.usage) {
|
||||
const char *usage[] = {"none", "oxygen", "diluent", "sidemount"};
|
||||
fprintf (output->ostream,
|
||||
" <usage>%s</usage>\n",
|
||||
usage[tank.usage]);
|
||||
}
|
||||
if (tank.type != DC_TANKVOLUME_NONE) {
|
||||
fprintf (output->ostream,
|
||||
" <type>%s</type>\n"
|
||||
@ -420,8 +450,14 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u
|
||||
}
|
||||
|
||||
if (status != DC_STATUS_UNSUPPORTED) {
|
||||
fprintf (output->ostream, "<salinity type=\"%u\">%.1f</salinity>\n",
|
||||
salinity.type, salinity.density);
|
||||
const char *names[] = {"fresh", "salt"};
|
||||
if (salinity.density) {
|
||||
fprintf (output->ostream, "<salinity density=\"%.1f\">%s</salinity>\n",
|
||||
salinity.density, names[salinity.type]);
|
||||
} else {
|
||||
fprintf (output->ostream, "<salinity>%s</salinity>\n",
|
||||
names[salinity.type]);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the atmospheric pressure.
|
||||
|
||||
@ -36,9 +36,6 @@ atomics_cobalt_device_version (dc_device_t *device, unsigned char data[], unsign
|
||||
dc_status_t
|
||||
atomics_cobalt_device_set_simulation (dc_device_t *device, unsigned int simulation);
|
||||
|
||||
dc_status_t
|
||||
atomics_cobalt_parser_set_calibration (dc_parser_t *parser, double atmospheric, double hydrostatic);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
@ -29,29 +29,96 @@
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* Opaque object representing a supported dive computer.
|
||||
*/
|
||||
typedef struct dc_descriptor_t dc_descriptor_t;
|
||||
|
||||
/**
|
||||
* Create an iterator to enumerate the supported dive computers.
|
||||
*
|
||||
* @param[out] iterator A location to store the iterator.
|
||||
* @returns #DC_STATUS_SUCCESS on success, or another #dc_status_t code
|
||||
* on failure.
|
||||
*/
|
||||
dc_status_t
|
||||
dc_descriptor_iterator (dc_iterator_t **iterator);
|
||||
|
||||
/**
|
||||
* Free the device descriptor.
|
||||
*
|
||||
* @param[in] descriptor A valid device descriptor.
|
||||
*/
|
||||
void
|
||||
dc_descriptor_free (dc_descriptor_t *descriptor);
|
||||
|
||||
/**
|
||||
* Get the vendor name of the dive computer.
|
||||
*
|
||||
* @param[in] descriptor A valid device descriptor.
|
||||
* @returns The vendor name of the dive computer on success, or NULL on failure.
|
||||
*/
|
||||
const char *
|
||||
dc_descriptor_get_vendor (dc_descriptor_t *descriptor);
|
||||
|
||||
/**
|
||||
* Get the product name of the dive computer.
|
||||
*
|
||||
* @param[in] descriptor A valid device descriptor.
|
||||
* @returns The product name of the dive computer on success, or NULL on
|
||||
* failure.
|
||||
*/
|
||||
const char *
|
||||
dc_descriptor_get_product (dc_descriptor_t *descriptor);
|
||||
|
||||
/**
|
||||
* Get the family type of the dive computer.
|
||||
*
|
||||
* @param[in] descriptor A valid device descriptor.
|
||||
* @returns The family type of the dive computer on success, or DC_FAMILY_NULL
|
||||
* on failure.
|
||||
*/
|
||||
dc_family_t
|
||||
dc_descriptor_get_type (dc_descriptor_t *descriptor);
|
||||
|
||||
/**
|
||||
* Get the model number of the dive computer.
|
||||
*
|
||||
* @param[in] descriptor A valid device descriptor.
|
||||
* @returns The model number of the dive computer on success, or zero on
|
||||
* failure.
|
||||
*/
|
||||
unsigned int
|
||||
dc_descriptor_get_model (dc_descriptor_t *descriptor);
|
||||
|
||||
/**
|
||||
* Get all transports supported by the dive computer.
|
||||
*
|
||||
* @param[in] descriptor A valid device descriptor.
|
||||
* @returns A bitmask with all the transports supported by the dive computer on
|
||||
* success, or DC_TRANSPORT_NONE on failure.
|
||||
*/
|
||||
unsigned int
|
||||
dc_descriptor_get_transports (dc_descriptor_t *descriptor);
|
||||
|
||||
/**
|
||||
* Check if a low-level I/O device matches a supported dive computer.
|
||||
*
|
||||
* @param[in] descriptor A valid device descriptor.
|
||||
* @param[in] transport The transport type of the I/O device.
|
||||
* @param[in] userdata A pointer to a transport specific data structure:
|
||||
* - DC_TRANSPORT_SERIAL: Name of the device node (string)
|
||||
* - DC_TRANSPORT_USB: USB VID/PID (#dc_usb_desc_t)
|
||||
* - DC_TRANSPORT_USBHID: USB VID/PID (#dc_usbhid_desc_t)
|
||||
* - DC_TRANSPORT_IRDA: IrDA device name (string)
|
||||
* - DC_TRANSPORT_BLUETOOTH: Bluetooth device name (string)
|
||||
* - DC_TRANSPORT_BLE: Bluetooth device name (string)
|
||||
* @returns Non-zero if the device matches a supported dive computer, or zero if
|
||||
* there is no match.
|
||||
*/
|
||||
int
|
||||
dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
@ -173,12 +173,21 @@ typedef struct dc_salinity_t {
|
||||
double density;
|
||||
} dc_salinity_t;
|
||||
|
||||
typedef enum dc_usage_t {
|
||||
DC_USAGE_NONE,
|
||||
DC_USAGE_OXYGEN,
|
||||
DC_USAGE_DILUENT,
|
||||
DC_USAGE_SIDEMOUNT,
|
||||
} dc_usage_t;
|
||||
|
||||
typedef struct dc_gasmix_t {
|
||||
double helium;
|
||||
double oxygen;
|
||||
double nitrogen;
|
||||
dc_usage_t usage;
|
||||
} dc_gasmix_t;
|
||||
|
||||
#define DC_SENSOR_NONE 0xFFFFFFFF
|
||||
#define DC_GASMIX_UNKNOWN 0xFFFFFFFF
|
||||
|
||||
typedef unsigned int dc_tankinfo_t;
|
||||
@ -222,6 +231,7 @@ typedef struct dc_tank_t {
|
||||
double workpressure; /* Work pressure (bar) */
|
||||
double beginpressure; /* Begin pressure (bar) */
|
||||
double endpressure; /* End pressure (bar) */
|
||||
dc_usage_t usage;
|
||||
} dc_tank_t;
|
||||
|
||||
typedef enum dc_decomodel_type_t {
|
||||
@ -267,7 +277,7 @@ typedef struct dc_field_string_t {
|
||||
} dc_field_string_t;
|
||||
|
||||
typedef union dc_sample_value_t {
|
||||
unsigned int time;
|
||||
unsigned int time; /* Milliseconds */
|
||||
double depth;
|
||||
struct {
|
||||
unsigned int tank;
|
||||
@ -290,25 +300,29 @@ typedef union dc_sample_value_t {
|
||||
const void *data;
|
||||
} vendor;
|
||||
double setpoint;
|
||||
double ppo2;
|
||||
struct {
|
||||
unsigned int sensor;
|
||||
double value;
|
||||
} ppo2;
|
||||
double cns;
|
||||
struct {
|
||||
unsigned int type;
|
||||
unsigned int time;
|
||||
double depth;
|
||||
unsigned int tts;
|
||||
} deco;
|
||||
unsigned int gasmix; /* Gas mix index */
|
||||
} dc_sample_value_t;
|
||||
|
||||
typedef struct dc_parser_t dc_parser_t;
|
||||
|
||||
typedef void (*dc_sample_callback_t) (dc_sample_type_t type, dc_sample_value_t value, void *userdata);
|
||||
typedef void (*dc_sample_callback_t) (dc_sample_type_t type, const dc_sample_value_t *value, void *userdata);
|
||||
|
||||
dc_status_t
|
||||
dc_parser_new (dc_parser_t **parser, dc_device_t *device);
|
||||
dc_parser_new (dc_parser_t **parser, dc_device_t *device, const unsigned char data[], size_t size);
|
||||
|
||||
dc_status_t
|
||||
dc_parser_new2 (dc_parser_t **parser, dc_context_t *context, dc_descriptor_t *descriptor, unsigned int devtime, dc_ticks_t systime);
|
||||
dc_parser_new2 (dc_parser_t **parser, dc_context_t *context, dc_descriptor_t *descriptor, const unsigned char data[], size_t size);
|
||||
|
||||
dc_family_t
|
||||
dc_parser_get_type (dc_parser_t *parser);
|
||||
@ -322,9 +336,6 @@ dc_parser_set_atmospheric (dc_parser_t *parser, double atmospheric);
|
||||
dc_status_t
|
||||
dc_parser_set_density (dc_parser_t *parser, double density);
|
||||
|
||||
dc_status_t
|
||||
dc_parser_set_data (dc_parser_t *parser, const unsigned char *data, unsigned int size);
|
||||
|
||||
dc_status_t
|
||||
dc_parser_get_datetime (dc_parser_t *parser, dc_datetime_t *datetime);
|
||||
|
||||
|
||||
@ -35,9 +35,6 @@ extern "C" {
|
||||
dc_status_t
|
||||
reefnet_sensus_device_get_handshake (dc_device_t *device, unsigned char data[], unsigned int size);
|
||||
|
||||
dc_status_t
|
||||
reefnet_sensus_parser_set_calibration (dc_parser_t *parser, double atmospheric, double hydrostatic);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
@ -38,9 +38,6 @@ reefnet_sensuspro_device_get_handshake (dc_device_t *device, unsigned char data[
|
||||
dc_status_t
|
||||
reefnet_sensuspro_device_write_interval (dc_device_t *device, unsigned char interval);
|
||||
|
||||
dc_status_t
|
||||
reefnet_sensuspro_parser_set_calibration (dc_parser_t *parser, double atmospheric, double hydrostatic);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
@ -56,9 +56,6 @@ reefnet_sensusultra_device_write_parameter (dc_device_t *device, reefnet_sensusu
|
||||
dc_status_t
|
||||
reefnet_sensusultra_device_sense (dc_device_t *device, unsigned char data[], unsigned int size);
|
||||
|
||||
dc_status_t
|
||||
reefnet_sensusultra_parser_set_calibration (dc_parser_t *parser, double atmospheric, double hydrostatic);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
@ -86,6 +86,14 @@ typedef enum dc_usb_recipient_t {
|
||||
DC_USB_RECIPIENT_OTHER = 0x03,
|
||||
} dc_usb_recipient_t;
|
||||
|
||||
/**
|
||||
* USB device descriptor.
|
||||
*/
|
||||
typedef struct dc_usb_desc_t {
|
||||
unsigned short vid;
|
||||
unsigned short pid;
|
||||
} dc_usb_desc_t;
|
||||
|
||||
/**
|
||||
* Opaque object representing a USB device.
|
||||
*/
|
||||
|
||||
@ -32,6 +32,14 @@
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* USB HID device descriptor.
|
||||
*/
|
||||
typedef struct dc_usbhid_desc_t {
|
||||
unsigned short vid;
|
||||
unsigned short pid;
|
||||
} dc_usbhid_desc_t;
|
||||
|
||||
/**
|
||||
* Opaque object representing a USB HID device.
|
||||
*/
|
||||
|
||||
@ -16,7 +16,7 @@ endif
|
||||
|
||||
libdivecomputer_la_SOURCES = \
|
||||
version.c \
|
||||
descriptor-private.h descriptor.c \
|
||||
descriptor.c \
|
||||
iostream-private.h iostream.c \
|
||||
iterator-private.h iterator.c \
|
||||
common-private.h common.c \
|
||||
|
||||
11
src/array.c
11
src/array.c
@ -404,3 +404,14 @@ signextend (unsigned int value, unsigned int nbits)
|
||||
else
|
||||
return value & mask;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
popcount (unsigned int value)
|
||||
{
|
||||
unsigned int count = 0;
|
||||
while (value) {
|
||||
value &= value - 1;
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -126,6 +126,9 @@ dec2bcd (unsigned char value);
|
||||
unsigned int
|
||||
signextend (unsigned int value, unsigned int nbits);
|
||||
|
||||
unsigned int
|
||||
popcount (unsigned int value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
@ -41,6 +41,8 @@
|
||||
|
||||
#define FP_OFFSET 20
|
||||
|
||||
#define SZ_HEADER 228
|
||||
|
||||
#define SZ_MEMORY1 (29 * 64 * 1024) // Cobalt 1
|
||||
#define SZ_MEMORY2 (41 * 64 * 1024) // Cobalt 2
|
||||
#define SZ_VERSION 14
|
||||
@ -347,6 +349,12 @@ atomics_cobalt_device_foreach (dc_device_t *abstract, dc_dive_callback_t callbac
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (size < SZ_HEADER) {
|
||||
ERROR (abstract->context, "Dive header is too small (%u).", size);
|
||||
dc_buffer_free (buffer);
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
|
||||
if (memcmp (data + FP_OFFSET, device->fingerprint, sizeof (device->fingerprint)) == 0) {
|
||||
dc_buffer_free (buffer);
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
@ -36,7 +36,7 @@ dc_status_t
|
||||
atomics_cobalt_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
atomics_cobalt_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||
atomics_cobalt_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -49,7 +49,6 @@ struct atomics_cobalt_parser_t {
|
||||
double hydrostatic;
|
||||
};
|
||||
|
||||
static dc_status_t atomics_cobalt_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t atomics_cobalt_parser_set_density (dc_parser_t *abstract, double density);
|
||||
static dc_status_t atomics_cobalt_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
@ -58,7 +57,6 @@ static dc_status_t atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract,
|
||||
static const dc_parser_vtable_t atomics_cobalt_parser_vtable = {
|
||||
sizeof(atomics_cobalt_parser_t),
|
||||
DC_FAMILY_ATOMICS_COBALT,
|
||||
atomics_cobalt_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
atomics_cobalt_parser_set_density, /* set_density */
|
||||
@ -70,7 +68,7 @@ static const dc_parser_vtable_t atomics_cobalt_parser_vtable = {
|
||||
|
||||
|
||||
dc_status_t
|
||||
atomics_cobalt_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
atomics_cobalt_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
||||
{
|
||||
atomics_cobalt_parser_t *parser = NULL;
|
||||
|
||||
@ -78,7 +76,7 @@ atomics_cobalt_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (atomics_cobalt_parser_t *) dc_parser_allocate (context, &atomics_cobalt_parser_vtable);
|
||||
parser = (atomics_cobalt_parser_t *) dc_parser_allocate (context, &atomics_cobalt_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -93,27 +91,6 @@ atomics_cobalt_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
atomics_cobalt_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
dc_status_t
|
||||
atomics_cobalt_parser_set_calibration (dc_parser_t *abstract, double atmospheric, double hydrostatic)
|
||||
{
|
||||
atomics_cobalt_parser_t *parser = (atomics_cobalt_parser_t*) abstract;
|
||||
|
||||
if (!ISINSTANCE (abstract))
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
parser->hydrostatic = hydrostatic;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
atomics_cobalt_parser_set_density (dc_parser_t *abstract, double density)
|
||||
{
|
||||
@ -182,6 +159,7 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un
|
||||
*((unsigned int *) value) = p[0x2a];
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
gasmix->helium = p[SZ_HEADER + SZ_GASMIX * flags + 5] / 100.0;
|
||||
gasmix->oxygen = p[SZ_HEADER + SZ_GASMIX * flags + 4] / 100.0;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
@ -213,6 +191,7 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un
|
||||
tank->gasmix = flags;
|
||||
tank->beginpressure = array_uint16_le(p + 6) * PSI / BAR;
|
||||
tank->endpressure = array_uint16_le(p + 14) * PSI / BAR;
|
||||
tank->usage = DC_USAGE_NONE;
|
||||
break;
|
||||
case DC_FIELD_DIVEMODE:
|
||||
switch(p[0x24]) {
|
||||
@ -310,19 +289,19 @@ atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
||||
|
||||
// Time (seconds).
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Depth (1/1000 bar).
|
||||
unsigned int depth = array_uint16_le (data + offset + 0);
|
||||
sample.depth = (signed int)(depth - atmospheric) * (BAR / 1000.0) / parser->hydrostatic;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Pressure (1 psi).
|
||||
unsigned int pressure = array_uint16_le (data + offset + 2);
|
||||
sample.pressure.tank = tank;
|
||||
sample.pressure.value = pressure * PSI / BAR;
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
||||
|
||||
// Current gas mix
|
||||
unsigned int gasmix = data[offset + 4];
|
||||
@ -338,14 +317,14 @@ atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
sample.gasmix = idx;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
gasmix_previous = gasmix;
|
||||
}
|
||||
|
||||
// Temperature (1 °F).
|
||||
unsigned int temperature = data[offset + 8];
|
||||
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
|
||||
// violation status
|
||||
sample.event.type = 0;
|
||||
@ -355,15 +334,15 @@ atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
||||
unsigned int violation = data[offset + 11];
|
||||
if (violation & 0x01) {
|
||||
sample.event.type = SAMPLE_EVENT_ASCENT;
|
||||
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
||||
}
|
||||
if (violation & 0x04) {
|
||||
sample.event.type = SAMPLE_EVENT_CEILING;
|
||||
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
||||
}
|
||||
if (violation & 0x08) {
|
||||
sample.event.type = SAMPLE_EVENT_PO2;
|
||||
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
||||
}
|
||||
|
||||
// NDL & deco
|
||||
@ -378,7 +357,8 @@ atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
||||
sample.deco.type = DC_DECO_NDL;
|
||||
sample.deco.time = ndl;
|
||||
sample.deco.depth = 0.0;
|
||||
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = 0;
|
||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
||||
|
||||
offset += SZ_SEGMENT;
|
||||
}
|
||||
|
||||
@ -51,7 +51,6 @@
|
||||
#include "context-private.h"
|
||||
#include "iostream-private.h"
|
||||
#include "iterator-private.h"
|
||||
#include "descriptor-private.h"
|
||||
#include "platform.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
@ -455,7 +454,7 @@ dc_bluetooth_iterator_next (dc_iterator_t *abstract, void *out)
|
||||
INFO (abstract->context, "Discover: address=" DC_ADDRESS_FORMAT ", name=%s",
|
||||
address, name ? name : "");
|
||||
|
||||
if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_BLUETOOTH, name, NULL)) {
|
||||
if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_BLUETOOTH, name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@ -31,6 +31,8 @@
|
||||
|
||||
#define ISINSTANCE(device) dc_device_isinstance((device), &citizen_aqualand_device_vtable)
|
||||
|
||||
#define SZ_HEADER 32
|
||||
|
||||
typedef struct citizen_aqualand_device_t {
|
||||
dc_device_t base;
|
||||
dc_iostream_t *iostream;
|
||||
@ -200,6 +202,12 @@ citizen_aqualand_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
|
||||
unsigned char *data = dc_buffer_get_data (buffer);
|
||||
unsigned int size = dc_buffer_get_size (buffer);
|
||||
|
||||
if (size < SZ_HEADER) {
|
||||
ERROR (abstract->context, "Dive header is too small (%u).", size);
|
||||
dc_buffer_free (buffer);
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
|
||||
if (callback && memcmp (data + 0x05, device->fingerprint, sizeof (device->fingerprint)) != 0) {
|
||||
callback (data, size, data + 0x05, sizeof (device->fingerprint), userdata);
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ dc_status_t
|
||||
citizen_aqualand_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
citizen_aqualand_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||
citizen_aqualand_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -36,7 +36,6 @@ typedef struct citizen_aqualand_parser_t {
|
||||
dc_parser_t base;
|
||||
} citizen_aqualand_parser_t;
|
||||
|
||||
static dc_status_t citizen_aqualand_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t citizen_aqualand_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t citizen_aqualand_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t citizen_aqualand_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -44,7 +43,6 @@ static dc_status_t citizen_aqualand_parser_samples_foreach (dc_parser_t *abstrac
|
||||
static const dc_parser_vtable_t citizen_aqualand_parser_vtable = {
|
||||
sizeof(citizen_aqualand_parser_t),
|
||||
DC_FAMILY_CITIZEN_AQUALAND,
|
||||
citizen_aqualand_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -56,7 +54,7 @@ static const dc_parser_vtable_t citizen_aqualand_parser_vtable = {
|
||||
|
||||
|
||||
dc_status_t
|
||||
citizen_aqualand_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
citizen_aqualand_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
||||
{
|
||||
citizen_aqualand_parser_t *parser = NULL;
|
||||
|
||||
@ -64,7 +62,7 @@ citizen_aqualand_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (citizen_aqualand_parser_t *) dc_parser_allocate (context, &citizen_aqualand_parser_vtable);
|
||||
parser = (citizen_aqualand_parser_t *) dc_parser_allocate (context, &citizen_aqualand_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -76,13 +74,6 @@ citizen_aqualand_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
citizen_aqualand_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
citizen_aqualand_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -241,15 +232,15 @@ citizen_aqualand_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
|
||||
// Time
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Depth
|
||||
if (metric)
|
||||
sample.depth = depth / 10.0;
|
||||
else
|
||||
sample.depth = depth * FEET;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Temperature
|
||||
if (time % 300 == 0) {
|
||||
@ -260,7 +251,7 @@ citizen_aqualand_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
sample.temperature = temperature / 10.0;
|
||||
else
|
||||
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ dc_status_t
|
||||
cochran_commander_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
cochran_commander_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||
cochran_commander_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -99,7 +99,6 @@ typedef struct cochran_commander_parser_t {
|
||||
unsigned int nevents;
|
||||
} cochran_commander_parser_t ;
|
||||
|
||||
static dc_status_t cochran_commander_parser_set_data (dc_parser_t *parser, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t cochran_commander_parser_get_datetime (dc_parser_t *parser, dc_datetime_t *datetime);
|
||||
static dc_status_t cochran_commander_parser_get_field (dc_parser_t *parser, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t cochran_commander_parser_samples_foreach (dc_parser_t *parser, dc_sample_callback_t callback, void *userdata);
|
||||
@ -107,7 +106,6 @@ static dc_status_t cochran_commander_parser_samples_foreach (dc_parser_t *parser
|
||||
static const dc_parser_vtable_t cochran_commander_parser_vtable = {
|
||||
sizeof(cochran_commander_parser_t),
|
||||
DC_FAMILY_COCHRAN_COMMANDER,
|
||||
cochran_commander_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -315,7 +313,7 @@ cochran_commander_handle_event (cochran_commander_parser_t *parser, unsigned cha
|
||||
sample.event.time = 0;
|
||||
sample.event.value = 0;
|
||||
sample.event.flags = event->flag;
|
||||
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
||||
}
|
||||
}
|
||||
|
||||
@ -352,7 +350,7 @@ cochran_commander_backparse(cochran_commander_parser_t *parser, const unsigned c
|
||||
|
||||
|
||||
dc_status_t
|
||||
cochran_commander_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||
cochran_commander_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
||||
{
|
||||
cochran_commander_parser_t *parser = NULL;
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
@ -361,7 +359,7 @@ cochran_commander_parser_create (dc_parser_t **out, dc_context_t *context, unsig
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (cochran_commander_parser_t *) dc_parser_allocate (context, &cochran_commander_parser_vtable);
|
||||
parser = (cochran_commander_parser_t *) dc_parser_allocate (context, &cochran_commander_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -407,13 +405,6 @@ error_free:
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
cochran_commander_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
cochran_commander_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -514,6 +505,7 @@ cochran_commander_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
|
||||
// Gas percentages are decimal and encoded as
|
||||
// highbyte = integer portion
|
||||
// lowbyte = decimal portion, divide by 256 to get decimal value
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
gasmix->oxygen = array_uint16_le (data + layout->oxygen + 2 * flags) / 256.0 / 100;
|
||||
if (layout->helium == UNSUPPORTED) {
|
||||
gasmix->helium = 0;
|
||||
@ -578,26 +570,26 @@ cochran_commander_parser_samples_foreach_tm (dc_parser_t *abstract, dc_sample_ca
|
||||
unsigned int temp = samples[0]; // Half degrees F
|
||||
unsigned int depth = samples[1]; // Half feet
|
||||
|
||||
last_sample_time = sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
last_sample_time = sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
sample.depth = (depth / 2.0) * FEET;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
sample.temperature = (temp / 2.0 - 32.0) / 1.8;
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
|
||||
sample.gasmix = 0;
|
||||
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
|
||||
while (offset < size) {
|
||||
const unsigned char *s = samples + offset;
|
||||
|
||||
sample.time = time;
|
||||
sample.time = time * 1000;
|
||||
if (last_sample_time != sample.time) {
|
||||
// We haven't issued this time yet.
|
||||
last_sample_time = sample.time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
}
|
||||
|
||||
if (*s & 0x80) {
|
||||
@ -615,7 +607,8 @@ cochran_commander_parser_samples_foreach_tm (dc_parser_t *abstract, dc_sample_ca
|
||||
sample.deco.type = DC_DECO_DECOSTOP;
|
||||
sample.deco.time = 60; // We don't know the duration
|
||||
sample.deco.depth = deco_ceiling * FEET;
|
||||
if (callback) callback(DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = 0;
|
||||
if (callback) callback(DC_SAMPLE_DECO, &sample, userdata);
|
||||
break;
|
||||
case 0xAD: // Increment ceiling (shallower)
|
||||
deco_ceiling -= 10; // feet
|
||||
@ -623,7 +616,8 @@ cochran_commander_parser_samples_foreach_tm (dc_parser_t *abstract, dc_sample_ca
|
||||
sample.deco.type = DC_DECO_DECOSTOP;
|
||||
sample.deco.depth = deco_ceiling * FEET;
|
||||
sample.deco.time = 60; // We don't know the duration
|
||||
if (callback) callback(DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = 0;
|
||||
if (callback) callback(DC_SAMPLE_DECO, &sample, userdata);
|
||||
break;
|
||||
default:
|
||||
cochran_commander_handle_event(parser, s[0], callback, userdata);
|
||||
@ -636,7 +630,7 @@ cochran_commander_parser_samples_foreach_tm (dc_parser_t *abstract, dc_sample_ca
|
||||
else
|
||||
temp += (*s & 0x0f);
|
||||
sample.temperature = (temp / 2.0 - 32.0) / 1.8;
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
}
|
||||
|
||||
offset++;
|
||||
@ -650,7 +644,7 @@ cochran_commander_parser_samples_foreach_tm (dc_parser_t *abstract, dc_sample_ca
|
||||
depth += s[0] & 0x3f;
|
||||
|
||||
sample.depth = (depth / 2.0) * FEET;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
offset++;
|
||||
time += sample_interval;
|
||||
@ -714,27 +708,27 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
|
||||
start_depth = array_uint16_le (data + layout->start_depth) / 256.0;
|
||||
}
|
||||
|
||||
last_sample_time = sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
last_sample_time = sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
sample.depth = start_depth * FEET;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
sample.temperature = (data[layout->start_temp] - 32.0) / 1.8;
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
|
||||
sample.gasmix = 0;
|
||||
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
unsigned int last_gasmix = sample.gasmix;
|
||||
|
||||
while (offset < size) {
|
||||
const unsigned char *s = samples + offset;
|
||||
|
||||
sample.time = time;
|
||||
sample.time = time * 1000;
|
||||
if (last_sample_time != sample.time) {
|
||||
// We haven't issued this time yet.
|
||||
last_sample_time = sample.time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
}
|
||||
|
||||
// If corrupt_dive end before offset
|
||||
@ -774,7 +768,8 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
|
||||
sample.deco.type = DC_DECO_DECOSTOP;
|
||||
sample.deco.time = (array_uint16_le(s + 3) + 1) * 60;
|
||||
sample.deco.depth = deco_ceiling * FEET;
|
||||
if (callback) callback(DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = 0;
|
||||
if (callback) callback(DC_SAMPLE_DECO, &sample, userdata);
|
||||
break;
|
||||
case 0xAD: // Increment ceiling (shallower)
|
||||
deco_ceiling -= 10; // feet
|
||||
@ -782,7 +777,8 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
|
||||
sample.deco.type = DC_DECO_DECOSTOP;
|
||||
sample.deco.depth = deco_ceiling * FEET;
|
||||
sample.deco.time = (array_uint16_le(s + 3) + 1) * 60;
|
||||
if (callback) callback(DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = 0;
|
||||
if (callback) callback(DC_SAMPLE_DECO, &sample, userdata);
|
||||
break;
|
||||
case 0xC0: // Switched to FO2 21% mode (surface)
|
||||
// Event seen upon surfacing
|
||||
@ -791,14 +787,14 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
|
||||
case 0xEF: // Switched to gas blend 2
|
||||
if (last_gasmix != 1) {
|
||||
sample.gasmix = 1;
|
||||
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
last_gasmix = sample.gasmix;
|
||||
}
|
||||
break;
|
||||
case 0xF3: // Switched to gas blend 1
|
||||
if (last_gasmix != 0) {
|
||||
sample.gasmix = 0;
|
||||
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
last_gasmix = sample.gasmix;
|
||||
}
|
||||
break;
|
||||
@ -818,7 +814,7 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
|
||||
depth += (s[0] & 0x3f);
|
||||
|
||||
sample.depth = (start_depth + depth / 4.0) * FEET;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Ascent rate is logged in the 0th sample, temp in the 1st, repeat.
|
||||
if (time % 2 == 0) {
|
||||
@ -834,7 +830,7 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
|
||||
double temperature = s[1] / 2.0 + 20.0;
|
||||
sample.temperature = (temperature - 32.0) / 1.8;
|
||||
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
}
|
||||
|
||||
// Cochran EMC models store NDL and deco stop time
|
||||
@ -855,7 +851,8 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
|
||||
sample.deco.type = DC_DECO_NDL;
|
||||
sample.deco.time = deco_time * 60;
|
||||
sample.deco.depth = 0;
|
||||
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = 0;
|
||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
||||
}
|
||||
break;
|
||||
case 23:
|
||||
@ -865,7 +862,8 @@ cochran_commander_parser_samples_foreach_emc (dc_parser_t *abstract, dc_sample_c
|
||||
sample.deco.type = DC_DECO_DECOSTOP;
|
||||
sample.deco.depth = deco_ceiling * FEET;
|
||||
sample.deco.time = deco_time * 60;
|
||||
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = 0;
|
||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -38,6 +38,8 @@
|
||||
#define SZ_PACKET 0x80
|
||||
#define SZ_PAGE (SZ_PACKET / 4)
|
||||
|
||||
#define SZ_HEADER 32
|
||||
|
||||
#define IQ700 0x05
|
||||
#define EDY 0x08
|
||||
|
||||
@ -522,6 +524,13 @@ cressi_edy_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (length < SZ_HEADER) {
|
||||
ERROR (abstract->context, "Dive header is too small (%u).", length);
|
||||
dc_rbstream_free (rbstream);
|
||||
free (buffer);
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
|
||||
unsigned char *p = buffer + offset;
|
||||
|
||||
if (memcmp (p, device->fingerprint, sizeof (device->fingerprint)) == 0)
|
||||
|
||||
@ -35,7 +35,7 @@ dc_status_t
|
||||
cressi_edy_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
cressi_edy_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||
cressi_edy_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -31,6 +31,8 @@
|
||||
#define IQ700 0x05
|
||||
#define EDY 0x08
|
||||
|
||||
#define SZ_HEADER 32
|
||||
|
||||
typedef struct cressi_edy_parser_t cressi_edy_parser_t;
|
||||
|
||||
struct cressi_edy_parser_t {
|
||||
@ -38,7 +40,6 @@ struct cressi_edy_parser_t {
|
||||
unsigned int model;
|
||||
};
|
||||
|
||||
static dc_status_t cressi_edy_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t cressi_edy_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t cressi_edy_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t cressi_edy_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -46,7 +47,6 @@ static dc_status_t cressi_edy_parser_samples_foreach (dc_parser_t *abstract, dc_
|
||||
static const dc_parser_vtable_t cressi_edy_parser_vtable = {
|
||||
sizeof(cressi_edy_parser_t),
|
||||
DC_FAMILY_CRESSI_EDY,
|
||||
cressi_edy_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -73,7 +73,7 @@ cressi_edy_parser_count_gasmixes (const unsigned char *data)
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
cressi_edy_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||
cressi_edy_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
||||
{
|
||||
cressi_edy_parser_t *parser = NULL;
|
||||
|
||||
@ -81,7 +81,7 @@ cressi_edy_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (cressi_edy_parser_t *) dc_parser_allocate (context, &cressi_edy_parser_vtable);
|
||||
parser = (cressi_edy_parser_t *) dc_parser_allocate (context, &cressi_edy_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -96,17 +96,10 @@ cressi_edy_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
cressi_edy_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
cressi_edy_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
if (abstract->size < 32)
|
||||
if (abstract->size < SZ_HEADER)
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
|
||||
const unsigned char *p = abstract->data;
|
||||
@ -130,7 +123,7 @@ cressi_edy_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign
|
||||
{
|
||||
cressi_edy_parser_t *parser = (cressi_edy_parser_t *) abstract;
|
||||
|
||||
if (abstract->size < 32)
|
||||
if (abstract->size < SZ_HEADER)
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
|
||||
const unsigned char *p = abstract->data;
|
||||
@ -152,6 +145,7 @@ cressi_edy_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign
|
||||
*((unsigned int *) value) = cressi_edy_parser_count_gasmixes(p);
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
gasmix->helium = 0.0;
|
||||
gasmix->oxygen = bcd2dec (p[0x17 - flags]) / 100.0;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
@ -188,7 +182,7 @@ cressi_edy_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
||||
unsigned int ngasmixes = cressi_edy_parser_count_gasmixes(data);
|
||||
unsigned int gasmix = 0xFFFFFFFF;
|
||||
|
||||
unsigned int offset = 32;
|
||||
unsigned int offset = SZ_HEADER;
|
||||
while (offset + 2 <= size) {
|
||||
dc_sample_value_t sample = {0};
|
||||
|
||||
@ -201,13 +195,13 @@ cressi_edy_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
||||
|
||||
// Time (seconds).
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Depth (1/10 m).
|
||||
unsigned int depth = bcd2dec (data[offset + 0] & 0x0F) * 100 + bcd2dec (data[offset + 1]);
|
||||
sample.depth = depth / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Current gasmix
|
||||
if (ngasmixes) {
|
||||
@ -220,7 +214,7 @@ cressi_edy_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
||||
}
|
||||
if (idx != gasmix) {
|
||||
sample.gasmix = idx;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
gasmix = idx;
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ dc_status_t
|
||||
cressi_goa_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
cressi_goa_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||
cressi_goa_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -62,7 +62,6 @@ typedef struct cressi_goa_layout_t {
|
||||
unsigned int temperature;
|
||||
} cressi_goa_layout_t;
|
||||
|
||||
static dc_status_t cressi_goa_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t cressi_goa_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t cressi_goa_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t cressi_goa_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -70,7 +69,6 @@ static dc_status_t cressi_goa_parser_samples_foreach (dc_parser_t *abstract, dc_
|
||||
static const dc_parser_vtable_t cressi_goa_parser_vtable = {
|
||||
sizeof(cressi_goa_parser_t),
|
||||
DC_FAMILY_CRESSI_GOA,
|
||||
cressi_goa_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -128,7 +126,7 @@ static const cressi_goa_layout_t layouts[] = {
|
||||
};
|
||||
|
||||
dc_status_t
|
||||
cressi_goa_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||
cressi_goa_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
||||
{
|
||||
cressi_goa_parser_t *parser = NULL;
|
||||
|
||||
@ -136,7 +134,7 @@ cressi_goa_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (cressi_goa_parser_t *) dc_parser_allocate (context, &cressi_goa_parser_vtable);
|
||||
parser = (cressi_goa_parser_t *) dc_parser_allocate (context, &cressi_goa_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -149,12 +147,6 @@ cressi_goa_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
cressi_goa_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
cressi_goa_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -250,6 +242,7 @@ cressi_goa_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign
|
||||
*((unsigned int *) value) = ngasmixes;
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
gasmix->helium = 0.0;
|
||||
gasmix->oxygen = data[layout->gasmix + 2 * flags + 1] / 100.0;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
@ -329,25 +322,25 @@ cressi_goa_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
||||
|
||||
if (complete) {
|
||||
// Time (seconds).
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Temperature (1/10 °C).
|
||||
if (have_temperature) {
|
||||
sample.temperature = temperature / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
have_temperature = 0;
|
||||
}
|
||||
|
||||
// Depth (1/10 m).
|
||||
sample.depth = depth / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Gas change
|
||||
if (divemode == SCUBA || divemode == NITROX) {
|
||||
if (gasmix != gasmix_previous) {
|
||||
sample.gasmix = gasmix;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
gasmix_previous = gasmix;
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ dc_status_t
|
||||
cressi_leonardo_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
cressi_leonardo_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||
cressi_leonardo_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -39,7 +39,6 @@ struct cressi_leonardo_parser_t {
|
||||
unsigned int model;
|
||||
};
|
||||
|
||||
static dc_status_t cressi_leonardo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t cressi_leonardo_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t cressi_leonardo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -47,7 +46,6 @@ static dc_status_t cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract
|
||||
static const dc_parser_vtable_t cressi_leonardo_parser_vtable = {
|
||||
sizeof(cressi_leonardo_parser_t),
|
||||
DC_FAMILY_CRESSI_LEONARDO,
|
||||
cressi_leonardo_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -59,7 +57,7 @@ static const dc_parser_vtable_t cressi_leonardo_parser_vtable = {
|
||||
|
||||
|
||||
dc_status_t
|
||||
cressi_leonardo_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||
cressi_leonardo_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
||||
{
|
||||
cressi_leonardo_parser_t *parser = NULL;
|
||||
|
||||
@ -67,7 +65,7 @@ cressi_leonardo_parser_create (dc_parser_t **out, dc_context_t *context, unsigne
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (cressi_leonardo_parser_t *) dc_parser_allocate (context, &cressi_leonardo_parser_vtable);
|
||||
parser = (cressi_leonardo_parser_t *) dc_parser_allocate (context, &cressi_leonardo_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -81,13 +79,6 @@ cressi_leonardo_parser_create (dc_parser_t **out, dc_context_t *context, unsigne
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
cressi_leonardo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
cressi_leonardo_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -146,6 +137,7 @@ cressi_leonardo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, u
|
||||
}
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
gasmix->helium = 0.0;
|
||||
gasmix->oxygen = data[0x19] / 100.0;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
@ -196,12 +188,12 @@ cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
|
||||
|
||||
// Time (seconds).
|
||||
time += surftime;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Depth (1/10 m).
|
||||
sample.depth = 0.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
offset += 4;
|
||||
} else {
|
||||
@ -211,17 +203,17 @@ cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
|
||||
|
||||
// Time (seconds).
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Depth (1/10 m).
|
||||
sample.depth = depth / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Gas change.
|
||||
if (gasmix != gasmix_previous) {
|
||||
sample.gasmix = gasmix;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
gasmix_previous = gasmix;
|
||||
}
|
||||
|
||||
@ -235,8 +227,7 @@ cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
|
||||
else
|
||||
sample.event.flags = 0;
|
||||
sample.event.value = ascent;
|
||||
|
||||
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
||||
}
|
||||
|
||||
offset += 2;
|
||||
|
||||
@ -36,7 +36,7 @@ dc_status_t
|
||||
deepblu_cosmiq_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
deepblu_cosmiq_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||
deepblu_cosmiq_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -41,7 +41,6 @@ typedef struct deepblu_cosmiq_parser_t {
|
||||
double hydrostatic;
|
||||
} deepblu_cosmiq_parser_t;
|
||||
|
||||
static dc_status_t deepblu_cosmiq_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t deepblu_cosmiq_parser_set_density (dc_parser_t *abstract, double density);
|
||||
static dc_status_t deepblu_cosmiq_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t deepblu_cosmiq_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
@ -50,7 +49,6 @@ static dc_status_t deepblu_cosmiq_parser_samples_foreach (dc_parser_t *abstract,
|
||||
static const dc_parser_vtable_t deepblu_cosmiq_parser_vtable = {
|
||||
sizeof(deepblu_cosmiq_parser_t),
|
||||
DC_FAMILY_DEEPBLU_COSMIQ,
|
||||
deepblu_cosmiq_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
deepblu_cosmiq_parser_set_density, /* set_density */
|
||||
@ -61,7 +59,7 @@ static const dc_parser_vtable_t deepblu_cosmiq_parser_vtable = {
|
||||
};
|
||||
|
||||
dc_status_t
|
||||
deepblu_cosmiq_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
deepblu_cosmiq_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
||||
{
|
||||
deepblu_cosmiq_parser_t *parser = NULL;
|
||||
|
||||
@ -69,7 +67,7 @@ deepblu_cosmiq_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (deepblu_cosmiq_parser_t *) dc_parser_allocate (context, &deepblu_cosmiq_parser_vtable);
|
||||
parser = (deepblu_cosmiq_parser_t *) dc_parser_allocate (context, &deepblu_cosmiq_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -83,12 +81,6 @@ deepblu_cosmiq_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
deepblu_cosmiq_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
deepblu_cosmiq_parser_set_density (dc_parser_t *abstract, double density)
|
||||
{
|
||||
@ -151,6 +143,7 @@ deepblu_cosmiq_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un
|
||||
*((unsigned int *) value) = mode == SCUBA;
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
gasmix->oxygen = data[3] / 100.0;
|
||||
gasmix->helium = 0.0;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
@ -204,14 +197,14 @@ deepblu_cosmiq_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
||||
offset += SZ_SAMPLE;
|
||||
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
sample.depth = (signed int) (depth - atmospheric) * (BAR / 1000.0) / parser->hydrostatic;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
sample.temperature = temperature / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
@ -35,7 +35,7 @@ dc_status_t
|
||||
deepsix_excursion_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
deepsix_excursion_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||
deepsix_excursion_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -112,7 +112,6 @@ typedef struct deepsix_excursion_parser_t {
|
||||
deepsix_excursion_gasmix_t gasmix[MAX_GASMIXES];
|
||||
} deepsix_excursion_parser_t;
|
||||
|
||||
static dc_status_t deepsix_excursion_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t deepsix_excursion_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t deepsix_excursion_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t deepsix_excursion_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -122,7 +121,6 @@ static dc_status_t deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abs
|
||||
static const dc_parser_vtable_t deepsix_parser_vtable = {
|
||||
sizeof(deepsix_excursion_parser_t),
|
||||
DC_FAMILY_DEEPSIX_EXCURSION,
|
||||
deepsix_excursion_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -185,7 +183,7 @@ deepsix_excursion_find_gasmix(deepsix_excursion_parser_t *parser, unsigned int o
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
deepsix_excursion_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
deepsix_excursion_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
||||
{
|
||||
deepsix_excursion_parser_t *parser = NULL;
|
||||
|
||||
@ -193,7 +191,7 @@ deepsix_excursion_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (deepsix_excursion_parser_t *) dc_parser_allocate (context, &deepsix_parser_vtable);
|
||||
parser = (deepsix_excursion_parser_t *) dc_parser_allocate (context, &deepsix_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -213,23 +211,6 @@ deepsix_excursion_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
deepsix_excursion_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
deepsix_excursion_parser_t *parser = (deepsix_excursion_parser_t *) abstract;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->ngasmixes = 0;
|
||||
for (unsigned int i = 0; i < MAX_GASMIXES; ++i) {
|
||||
parser->gasmix[i].id = 0;
|
||||
parser->gasmix[i].oxygen = 0;
|
||||
parser->gasmix[i].helium = 0;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
deepsix_excursion_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -322,6 +303,7 @@ deepsix_excursion_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
|
||||
*((unsigned int *) value) = parser->ngasmixes;
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
||||
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
@ -423,11 +405,11 @@ deepsix_excursion_parser_samples_foreach_v0 (dc_parser_t *abstract, dc_sample_ca
|
||||
|
||||
if (type == TEMPERATURE) {
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback(DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback(DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
sample.depth = pressure_to_depth(depth, atmospheric, DENSITY);
|
||||
if (callback) callback(DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
}
|
||||
|
||||
if (type == ALARM) {
|
||||
@ -440,11 +422,11 @@ deepsix_excursion_parser_samples_foreach_v0 (dc_parser_t *abstract, dc_sample_ca
|
||||
length = 8;
|
||||
} else if (temperature >= 10) {
|
||||
sample.temperature = temperature / 10.0;
|
||||
if (callback) callback(DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
}
|
||||
} else {
|
||||
sample.temperature = temperature / 10.0;
|
||||
if (callback) callback(DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
}
|
||||
} else if (type == DECO) {
|
||||
unsigned int deco = array_uint16_le(data + offset + 4);
|
||||
@ -454,7 +436,7 @@ deepsix_excursion_parser_samples_foreach_v0 (dc_parser_t *abstract, dc_sample_ca
|
||||
} else if (type == CNS) {
|
||||
unsigned int cns = array_uint16_le(data + offset + 4);
|
||||
sample.cns = cns / 100.0;
|
||||
if (callback) callback(DC_SAMPLE_CNS, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_CNS, &sample, userdata);
|
||||
}
|
||||
|
||||
offset += length;
|
||||
@ -591,12 +573,12 @@ deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abstract, dc_sample_ca
|
||||
|
||||
// Time (seconds).
|
||||
time += samplerate;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
unsigned int depth = array_uint16_le (data + offset);
|
||||
sample.depth = pressure_to_depth(depth, atmospheric, density);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
offset += 2;
|
||||
|
||||
// event info
|
||||
@ -664,7 +646,7 @@ deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abstract, dc_sample_ca
|
||||
break;
|
||||
}
|
||||
if (sample.event.type != SAMPLE_EVENT_NONE) {
|
||||
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -686,7 +668,7 @@ deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abstract, dc_sample_ca
|
||||
}
|
||||
|
||||
sample.gasmix = mix_idx;
|
||||
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
break;
|
||||
case EVENT_SAMPLES_MISSED:
|
||||
count = array_uint16_le(data + offset + event_offset);
|
||||
@ -727,12 +709,12 @@ deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abstract, dc_sample_ca
|
||||
case SAMPLE_TEMPERATURE:
|
||||
value = array_uint16_le(data + offset);
|
||||
sample.temperature = value / 10.0;
|
||||
if (callback) callback(DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
break;
|
||||
case SAMPLE_CNS:
|
||||
value = array_uint16_le(data + offset);
|
||||
sample.cns = value / 10000.0;
|
||||
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_CNS, &sample, userdata);
|
||||
break;
|
||||
case SAMPLE_DECO_NDL:
|
||||
deco_flags = data[offset];
|
||||
@ -752,7 +734,7 @@ deepsix_excursion_parser_samples_foreach_v1 (dc_parser_t *abstract, dc_sample_ca
|
||||
sample.deco.depth = 0;
|
||||
sample.deco.time = deco_ndl_tts;
|
||||
}
|
||||
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* libdivecomputer
|
||||
*
|
||||
* Copyright (C) 2017 Jef Driesen
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef DC_DESCRIPTOR_PRIVATE_H
|
||||
#define DC_DESCRIPTOR_PRIVATE_H
|
||||
|
||||
#include <libdivecomputer/descriptor.h>
|
||||
|
||||
// Oh joy. Windows is some truly horrendously broken crap
|
||||
#undef interface
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct dc_usb_desc_t {
|
||||
unsigned short vid;
|
||||
unsigned short pid;
|
||||
} dc_usb_desc_t;
|
||||
|
||||
typedef struct dc_usb_params_t {
|
||||
unsigned int interface;
|
||||
unsigned char endpoint_in;
|
||||
unsigned char endpoint_out;
|
||||
} dc_usb_params_t;
|
||||
|
||||
int
|
||||
dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
#endif /* DC_DESCRIPTOR_PRIVATE_H */
|
||||
146
src/descriptor.c
146
src/descriptor.c
@ -23,7 +23,10 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "descriptor-private.h"
|
||||
#include <libdivecomputer/descriptor.h>
|
||||
#include <libdivecomputer/usbhid.h>
|
||||
#include <libdivecomputer/usb.h>
|
||||
|
||||
#include "iterator-private.h"
|
||||
#include "platform.h"
|
||||
|
||||
@ -36,36 +39,26 @@
|
||||
values, \
|
||||
C_ARRAY_SIZE(values) - isnullterminated, \
|
||||
C_ARRAY_ITEMSIZE(values), \
|
||||
match, \
|
||||
NULL, NULL, 0)
|
||||
|
||||
#define DC_FILTER_INTERNAL_WITH_PARAMS(key, values, isnullterminated, match, params_dst, params_src) \
|
||||
dc_filter_internal( \
|
||||
key, \
|
||||
values, \
|
||||
C_ARRAY_SIZE(values) - isnullterminated, \
|
||||
C_ARRAY_ITEMSIZE(values), \
|
||||
match, \
|
||||
params_dst, params_src, sizeof *(params_src))
|
||||
match)
|
||||
|
||||
typedef int (*dc_match_t)(const void *, const void *);
|
||||
|
||||
typedef int (*dc_filter_t) (dc_transport_t transport, const void *userdata, void *params);
|
||||
typedef int (*dc_filter_t) (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
||||
|
||||
static int dc_filter_uwatec (dc_transport_t transport, const void *userdata, void *params);
|
||||
static int dc_filter_suunto (dc_transport_t transport, const void *userdata, void *params);
|
||||
static int dc_filter_shearwater (dc_transport_t transport, const void *userdata, void *params);
|
||||
static int dc_filter_hw (dc_transport_t transport, const void *userdata, void *params);
|
||||
static int dc_filter_tecdiving (dc_transport_t transport, const void *userdata, void *params);
|
||||
static int dc_filter_mares (dc_transport_t transport, const void *userdata, void *params);
|
||||
static int dc_filter_divesystem (dc_transport_t transport, const void *userdata, void *params);
|
||||
static int dc_filter_oceanic (dc_transport_t transport, const void *userdata, void *params);
|
||||
static int dc_filter_mclean (dc_transport_t transport, const void *userdata, void *params);
|
||||
static int dc_filter_atomic (dc_transport_t transport, const void *userdata, void *params);
|
||||
static int dc_filter_deepsix (dc_transport_t transport, const void *userdata, void *params);
|
||||
static int dc_filter_deepblu (dc_transport_t transport, const void *userdata, void *params);
|
||||
static int dc_filter_oceans (dc_transport_t transport, const void *userdata, void *params);
|
||||
static int dc_filter_divesoft (dc_transport_t transport, const void *userdata, void *params);
|
||||
static int dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
||||
static int dc_filter_suunto (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
||||
static int dc_filter_shearwater (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
||||
static int dc_filter_hw (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
||||
static int dc_filter_tecdiving (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
||||
static int dc_filter_mares (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
||||
static int dc_filter_divesystem (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
||||
static int dc_filter_oceanic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
||||
static int dc_filter_mclean (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
||||
static int dc_filter_atomic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
||||
static int dc_filter_deepsix (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
||||
static int dc_filter_deepblu (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
||||
static int dc_filter_oceans (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
||||
static int dc_filter_divesoft (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata);
|
||||
|
||||
// Not merged upstream yet
|
||||
static int dc_filter_garmin (dc_transport_t transport, const void *userdata, void *params);
|
||||
@ -180,7 +173,10 @@ static const dc_descriptor_t g_descriptors[] = {
|
||||
{"Scubapro", "G2 TEK", DC_FAMILY_UWATEC_SMART, 0x31, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
|
||||
{"Scubapro", "G2", DC_FAMILY_UWATEC_SMART, 0x32, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
|
||||
{"Scubapro", "G2 Console", DC_FAMILY_UWATEC_SMART, 0x32, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
|
||||
{"Scubapro", "G3", DC_FAMILY_UWATEC_SMART, 0x34, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
|
||||
{"Scubapro", "G2 HUD", DC_FAMILY_UWATEC_SMART, 0x42, DC_TRANSPORT_USBHID | DC_TRANSPORT_BLE, dc_filter_uwatec},
|
||||
{"Scubapro", "Luna 2.0 AI", DC_FAMILY_UWATEC_SMART, 0x50, DC_TRANSPORT_BLE, dc_filter_uwatec},
|
||||
{"Scubapro", "Luna 2.0", DC_FAMILY_UWATEC_SMART, 0x51, DC_TRANSPORT_BLE, dc_filter_uwatec},
|
||||
/* Reefnet */
|
||||
{"Reefnet", "Sensus", DC_FAMILY_REEFNET_SENSUS, 1, DC_TRANSPORT_SERIAL, NULL},
|
||||
{"Reefnet", "Sensus Pro", DC_FAMILY_REEFNET_SENSUSPRO, 2, DC_TRANSPORT_SERIAL, NULL},
|
||||
@ -364,6 +360,7 @@ static const dc_descriptor_t g_descriptors[] = {
|
||||
{"Shearwater", "Peregrine", DC_FAMILY_SHEARWATER_PETREL, 9, DC_TRANSPORT_BLE, dc_filter_shearwater},
|
||||
{"Shearwater", "Petrel 3", DC_FAMILY_SHEARWATER_PETREL, 10, DC_TRANSPORT_BLE, dc_filter_shearwater},
|
||||
{"Shearwater", "Perdix 2", DC_FAMILY_SHEARWATER_PETREL, 11, DC_TRANSPORT_BLE, dc_filter_shearwater},
|
||||
{"Shearwater", "Tern", DC_FAMILY_SHEARWATER_PETREL, 12, DC_TRANSPORT_BLE, dc_filter_shearwater},
|
||||
/* Dive Rite NiTek Q */
|
||||
{"Dive Rite", "NiTek Q", DC_FAMILY_DIVERITE_NITEKQ, 0, DC_TRANSPORT_SERIAL, NULL},
|
||||
/* Citizen Hyper Aqualand */
|
||||
@ -417,6 +414,20 @@ static const dc_descriptor_t g_descriptors[] = {
|
||||
{"Ratio", "iX3M 2021 Pro Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x73, DC_TRANSPORT_SERIAL, NULL},
|
||||
{"Ratio", "iX3M 2021 Pro Tech+", DC_FAMILY_DIVESYSTEM_IDIVE, 0x74, DC_TRANSPORT_SERIAL, NULL},
|
||||
{"Ratio", "iX3M 2021 Pro Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x75, DC_TRANSPORT_SERIAL, NULL},
|
||||
{"Ratio", "iDive 2 Free", DC_FAMILY_DIVESYSTEM_IDIVE, 0x80, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||
{"Ratio", "iDive 2 Fancy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x81, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||
{"Ratio", "iDive 2 Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x82, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||
{"Ratio", "iDive 2 Pro", DC_FAMILY_DIVESYSTEM_IDIVE, 0x83, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||
{"Ratio", "iDive 2 Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x84, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||
{"Ratio", "iDive 2 Tech", DC_FAMILY_DIVESYSTEM_IDIVE, 0x85, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||
{"Ratio", "iDive 2 Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x86, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||
{"Ratio", "iX3M 2 GPS Gauge", DC_FAMILY_DIVESYSTEM_IDIVE, 0x90, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||
{"Ratio", "iX3M 2 GPS Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x91, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||
{"Ratio", "iX3M 2 GPS Pro", DC_FAMILY_DIVESYSTEM_IDIVE, 0x92, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||
{"Ratio", "iX3M 2 GPS Deep", DC_FAMILY_DIVESYSTEM_IDIVE, 0x93, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||
{"Ratio", "iX3M 2 GPS Tech", DC_FAMILY_DIVESYSTEM_IDIVE, 0x94, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||
{"Ratio", "iX3M 2 GPS Reb", DC_FAMILY_DIVESYSTEM_IDIVE, 0x95, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||
{"Ratio", "ATOM", DC_FAMILY_DIVESYSTEM_IDIVE, 0x96, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||
{"Ratio", "iX3M 2 Gauge", DC_FAMILY_DIVESYSTEM_IDIVE, 0x100, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||
{"Ratio", "iX3M 2 Easy", DC_FAMILY_DIVESYSTEM_IDIVE, 0x101, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||
{"Ratio", "iX3M 2 Pro", DC_FAMILY_DIVESYSTEM_IDIVE, 0x102, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLE, dc_filter_divesystem},
|
||||
@ -446,7 +457,6 @@ static const dc_descriptor_t g_descriptors[] = {
|
||||
{"Deep Six", "Excursion", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
|
||||
{"Crest", "CR-4", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
|
||||
{"Genesis", "Centauri", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
|
||||
{"Tusa", "TC1", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
|
||||
{"Scorpena", "Alpha", DC_FAMILY_DEEPSIX_EXCURSION, 0, DC_TRANSPORT_BLE, dc_filter_deepsix},
|
||||
/* Seac Screen */
|
||||
{"Seac", "Screen", DC_FAMILY_SEAC_SCREEN, 0, DC_TRANSPORT_SERIAL, NULL},
|
||||
@ -504,6 +514,15 @@ dc_match_usb (const void *key, const void *value)
|
||||
return k->vid == v->vid && k->pid == v->pid;
|
||||
}
|
||||
|
||||
static int
|
||||
dc_match_usbhid (const void *key, const void *value)
|
||||
{
|
||||
const dc_usbhid_desc_t *k = (const dc_usbhid_desc_t *) key;
|
||||
const dc_usbhid_desc_t *v = (const dc_usbhid_desc_t *) value;
|
||||
|
||||
return k->vid == v->vid && k->pid == v->pid;
|
||||
}
|
||||
|
||||
static int
|
||||
dc_match_number_with_prefix (const void *key, const void *value)
|
||||
{
|
||||
@ -544,16 +563,13 @@ dc_match_oceanic (const void *key, const void *value)
|
||||
}
|
||||
|
||||
static int
|
||||
dc_filter_internal (const void *key, const void *values, size_t count, size_t size, dc_match_t match, void *params_dst, const void *params_src, size_t params_size)
|
||||
dc_filter_internal (const void *key, const void *values, size_t count, size_t size, dc_match_t match)
|
||||
{
|
||||
if (key == NULL)
|
||||
return 1;
|
||||
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
if (match (key, (const unsigned char *) values + i * size)) {
|
||||
if (params_src && params_dst) {
|
||||
memcpy (params_dst, params_src, params_size);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -568,7 +584,8 @@ static const char * const rfcomm[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static int dc_filter_uwatec (dc_transport_t transport, const void *userdata, void *params)
|
||||
static int
|
||||
dc_filter_uwatec (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
||||
{
|
||||
static const char * const irda[] = {
|
||||
"Aladin Smart Com",
|
||||
@ -579,7 +596,7 @@ static int dc_filter_uwatec (dc_transport_t transport, const void *userdata, voi
|
||||
"UWATEC Galileo",
|
||||
"UWATEC Galileo Sol",
|
||||
};
|
||||
static const dc_usb_desc_t usbhid[] = {
|
||||
static const dc_usbhid_desc_t usbhid[] = {
|
||||
{0x2e6c, 0x3201}, // G2, G2 TEK
|
||||
{0x2e6c, 0x3211}, // G2 Console
|
||||
{0x2e6c, 0x4201}, // G2 HUD
|
||||
@ -592,12 +609,15 @@ static int dc_filter_uwatec (dc_transport_t transport, const void *userdata, voi
|
||||
"A1",
|
||||
"A2",
|
||||
"G2 TEK",
|
||||
"Galileo 3",
|
||||
"Luna 2.0 AI",
|
||||
"Luna 2.0",
|
||||
};
|
||||
|
||||
if (transport == DC_TRANSPORT_IRDA) {
|
||||
return DC_FILTER_INTERNAL (userdata, irda, 0, dc_match_name);
|
||||
} else if (transport == DC_TRANSPORT_USBHID) {
|
||||
return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usb);
|
||||
return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usbhid);
|
||||
} else if (transport == DC_TRANSPORT_BLE) {
|
||||
return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_name);
|
||||
}
|
||||
@ -605,9 +625,10 @@ static int dc_filter_uwatec (dc_transport_t transport, const void *userdata, voi
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dc_filter_suunto (dc_transport_t transport, const void *userdata, void *params)
|
||||
static int
|
||||
dc_filter_suunto (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
||||
{
|
||||
static const dc_usb_desc_t usbhid[] = {
|
||||
static const dc_usbhid_desc_t usbhid[] = {
|
||||
{0x1493, 0x0030}, // Eon Steel
|
||||
{0x1493, 0x0033}, // Eon Core
|
||||
{0x1493, 0x0035}, // D5
|
||||
@ -621,7 +642,7 @@ static int dc_filter_suunto (dc_transport_t transport, const void *userdata, voi
|
||||
};
|
||||
|
||||
if (transport == DC_TRANSPORT_USBHID) {
|
||||
return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usb);
|
||||
return DC_FILTER_INTERNAL (userdata, usbhid, 0, dc_match_usbhid);
|
||||
} else if (transport == DC_TRANSPORT_BLE) {
|
||||
return DC_FILTER_INTERNAL (userdata, bluetooth, 0, dc_match_prefix);
|
||||
}
|
||||
@ -629,7 +650,8 @@ static int dc_filter_suunto (dc_transport_t transport, const void *userdata, voi
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dc_filter_hw (dc_transport_t transport, const void *userdata, void *params)
|
||||
static int
|
||||
dc_filter_hw (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
||||
{
|
||||
static const char * const bluetooth[] = {
|
||||
"OSTC",
|
||||
@ -645,7 +667,8 @@ static int dc_filter_hw (dc_transport_t transport, const void *userdata, void *p
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dc_filter_shearwater (dc_transport_t transport, const void *userdata, void *params)
|
||||
static int
|
||||
dc_filter_shearwater (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
||||
{
|
||||
static const char * const bluetooth[] = {
|
||||
"Predator",
|
||||
@ -657,6 +680,7 @@ static int dc_filter_shearwater (dc_transport_t transport, const void *userdata,
|
||||
"Perdix 2",
|
||||
"Teric",
|
||||
"Peregrine",
|
||||
"Tern"
|
||||
};
|
||||
|
||||
if (transport == DC_TRANSPORT_BLUETOOTH || transport == DC_TRANSPORT_BLE) {
|
||||
@ -668,7 +692,8 @@ static int dc_filter_shearwater (dc_transport_t transport, const void *userdata,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dc_filter_tecdiving (dc_transport_t transport, const void *userdata, void *params)
|
||||
static int
|
||||
dc_filter_tecdiving (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
||||
{
|
||||
static const char * const bluetooth[] = {
|
||||
"DiveComputer",
|
||||
@ -683,7 +708,8 @@ static int dc_filter_tecdiving (dc_transport_t transport, const void *userdata,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dc_filter_mares (dc_transport_t transport, const void *userdata, void *params)
|
||||
static int
|
||||
dc_filter_mares (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
||||
{
|
||||
static const char * const bluetooth[] = {
|
||||
"Mares bluelink pro",
|
||||
@ -697,11 +723,13 @@ static int dc_filter_mares (dc_transport_t transport, const void *userdata, void
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dc_filter_divesystem (dc_transport_t transport, const void *userdata, void *params)
|
||||
static int
|
||||
dc_filter_divesystem (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
||||
{
|
||||
static const char * const bluetooth[] = {
|
||||
"DS",
|
||||
"IX5M",
|
||||
"RATIO-",
|
||||
};
|
||||
|
||||
if (transport == DC_TRANSPORT_BLUETOOTH || transport == DC_TRANSPORT_BLE) {
|
||||
@ -711,7 +739,8 @@ static int dc_filter_divesystem (dc_transport_t transport, const void *userdata,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dc_filter_oceanic (dc_transport_t transport, const void *userdata, void *params)
|
||||
static int
|
||||
dc_filter_oceanic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
||||
{
|
||||
static const unsigned int model[] = {
|
||||
0x4552, // Oceanic Pro Plus X
|
||||
@ -738,7 +767,8 @@ static int dc_filter_oceanic (dc_transport_t transport, const void *userdata, vo
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dc_filter_mclean(dc_transport_t transport, const void *userdata, void *params)
|
||||
static int
|
||||
dc_filter_mclean(dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
||||
{
|
||||
static const char * const bluetooth[] = {
|
||||
"McLean Extreme",
|
||||
@ -753,30 +783,27 @@ static int dc_filter_mclean(dc_transport_t transport, const void *userdata, void
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dc_filter_atomic (dc_transport_t transport, const void *userdata, void *params)
|
||||
static int
|
||||
dc_filter_atomic (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
||||
{
|
||||
static const dc_usb_desc_t usb[] = {
|
||||
{0x0471, 0x0888}, // Atomic Aquatics Cobalt
|
||||
};
|
||||
|
||||
static const dc_usb_params_t usb_params = {
|
||||
0, 0x82, 0x02
|
||||
};
|
||||
|
||||
if (transport == DC_TRANSPORT_USB) {
|
||||
return DC_FILTER_INTERNAL_WITH_PARAMS (userdata, usb, 0, dc_match_usb, params, &usb_params);
|
||||
return DC_FILTER_INTERNAL (userdata, usb, 0, dc_match_usb);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dc_filter_deepsix (dc_transport_t transport, const void *userdata, void *params)
|
||||
static int
|
||||
dc_filter_deepsix (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
||||
{
|
||||
static const char * const bluetooth[] = {
|
||||
"EXCURSION",
|
||||
"Crest-CR4",
|
||||
"CENTAURI",
|
||||
"TC1",
|
||||
"ALPHA",
|
||||
};
|
||||
|
||||
@ -787,7 +814,8 @@ static int dc_filter_deepsix (dc_transport_t transport, const void *userdata, vo
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dc_filter_deepblu (dc_transport_t transport, const void *userdata, void *params)
|
||||
static int
|
||||
dc_filter_deepblu (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
||||
{
|
||||
static const char * const bluetooth[] = {
|
||||
"COSMIQ",
|
||||
@ -800,7 +828,8 @@ static int dc_filter_deepblu (dc_transport_t transport, const void *userdata, vo
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dc_filter_oceans (dc_transport_t transport, const void *userdata, void *params)
|
||||
static int
|
||||
dc_filter_oceans (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
||||
{
|
||||
static const char * const bluetooth[] = {
|
||||
"S1",
|
||||
@ -813,7 +842,8 @@ static int dc_filter_oceans (dc_transport_t transport, const void *userdata, voi
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int dc_filter_divesoft (dc_transport_t transport, const void *userdata, void *params)
|
||||
static int
|
||||
dc_filter_divesoft (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
||||
{
|
||||
static const char * const bluetooth[] = {
|
||||
"Freedom",
|
||||
@ -933,10 +963,10 @@ dc_descriptor_get_transports (dc_descriptor_t *descriptor)
|
||||
}
|
||||
|
||||
int
|
||||
dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata, void *params)
|
||||
dc_descriptor_filter (dc_descriptor_t *descriptor, dc_transport_t transport, const void *userdata)
|
||||
{
|
||||
if (descriptor == NULL || descriptor->filter == NULL || userdata == NULL)
|
||||
return 1;
|
||||
|
||||
return descriptor->filter (transport, userdata, params);
|
||||
return descriptor->filter (descriptor, transport, userdata);
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ dc_status_t
|
||||
diverite_nitekq_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
diverite_nitekq_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||
diverite_nitekq_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -49,7 +49,6 @@ struct diverite_nitekq_parser_t {
|
||||
double maxdepth;
|
||||
};
|
||||
|
||||
static dc_status_t diverite_nitekq_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t diverite_nitekq_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t diverite_nitekq_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t diverite_nitekq_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -57,7 +56,6 @@ static dc_status_t diverite_nitekq_parser_samples_foreach (dc_parser_t *abstract
|
||||
static const dc_parser_vtable_t diverite_nitekq_parser_vtable = {
|
||||
sizeof(diverite_nitekq_parser_t),
|
||||
DC_FAMILY_DIVERITE_NITEKQ,
|
||||
diverite_nitekq_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -69,7 +67,7 @@ static const dc_parser_vtable_t diverite_nitekq_parser_vtable = {
|
||||
|
||||
|
||||
dc_status_t
|
||||
diverite_nitekq_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
diverite_nitekq_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
||||
{
|
||||
diverite_nitekq_parser_t *parser = NULL;
|
||||
|
||||
@ -77,7 +75,7 @@ diverite_nitekq_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (diverite_nitekq_parser_t *) dc_parser_allocate (context, &diverite_nitekq_parser_vtable);
|
||||
parser = (diverite_nitekq_parser_t *) dc_parser_allocate (context, &diverite_nitekq_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -101,13 +99,6 @@ diverite_nitekq_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
diverite_nitekq_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
diverite_nitekq_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -161,6 +152,7 @@ diverite_nitekq_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, u
|
||||
*((unsigned int *) value) = parser->ngasmixes;
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
gasmix->helium = parser->he[flags] / 100.0;
|
||||
gasmix->oxygen = parser->o2[flags] / 100.0;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
@ -264,13 +256,13 @@ diverite_nitekq_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
|
||||
|
||||
// Time (seconds).
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Gas change
|
||||
if (gasmix != gasmix_previous) {
|
||||
sample.gasmix = gasmix;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
gasmix_previous = gasmix;
|
||||
}
|
||||
|
||||
@ -282,7 +274,7 @@ diverite_nitekq_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
|
||||
sample.depth = depth / 10.0;
|
||||
else
|
||||
sample.depth = depth * FEET / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
offset += 2;
|
||||
|
||||
if (type == 3) {
|
||||
@ -293,8 +285,9 @@ diverite_nitekq_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
|
||||
if (offset + 1 > size)
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
unsigned int ppo2 = data[offset];
|
||||
sample.ppo2 = ppo2 / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_PPO2, sample, userdata);
|
||||
sample.ppo2.sensor = DC_SENSOR_NONE;
|
||||
sample.ppo2.value = ppo2 / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_PPO2, &sample, userdata);
|
||||
offset++;
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -35,7 +35,7 @@ dc_status_t
|
||||
divesoft_freedom_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
divesoft_freedom_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||
divesoft_freedom_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -254,7 +254,6 @@ typedef struct divesoft_freedom_parser_t {
|
||||
unsigned int calibrated;
|
||||
} divesoft_freedom_parser_t;
|
||||
|
||||
static dc_status_t divesoft_freedom_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t divesoft_freedom_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t divesoft_freedom_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -262,7 +261,6 @@ static dc_status_t divesoft_freedom_parser_samples_foreach (dc_parser_t *abstrac
|
||||
static const dc_parser_vtable_t divesoft_freedom_parser_vtable = {
|
||||
sizeof(divesoft_freedom_parser_t),
|
||||
DC_FAMILY_DIVESOFT_FREEDOM,
|
||||
divesoft_freedom_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -643,7 +641,7 @@ divesoft_freedom_cache (divesoft_freedom_parser_t *parser)
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
divesoft_freedom_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
divesoft_freedom_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
||||
{
|
||||
divesoft_freedom_parser_t *parser = NULL;
|
||||
|
||||
@ -651,7 +649,7 @@ divesoft_freedom_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (divesoft_freedom_parser_t *) dc_parser_allocate (context, &divesoft_freedom_parser_vtable);
|
||||
parser = (divesoft_freedom_parser_t *) dc_parser_allocate (context, &divesoft_freedom_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -698,50 +696,6 @@ divesoft_freedom_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
divesoft_freedom_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
divesoft_freedom_parser_t *parser = (divesoft_freedom_parser_t *) abstract;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->version = 0;
|
||||
parser->headersize = 0;
|
||||
parser->divetime = 0;
|
||||
parser->divemode = 0;
|
||||
parser->temperature_min = 0;
|
||||
parser->maxdepth = 0;
|
||||
parser->atmospheric = 0;
|
||||
parser->avgdepth = 0;
|
||||
parser->ngasmixes = 0;
|
||||
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||
parser->gasmix[i].oxygen = 0;
|
||||
parser->gasmix[i].helium = 0;
|
||||
parser->gasmix[i].type = 0;
|
||||
parser->gasmix[i].id = 0;
|
||||
}
|
||||
parser->diluent = UNDEFINED;
|
||||
parser->ntanks = 0;
|
||||
for (unsigned int i = 0; i < NTANKS; ++i) {
|
||||
parser->tank[i].volume = 0;
|
||||
parser->tank[i].workpressure = 0;
|
||||
parser->tank[i].beginpressure = 0;
|
||||
parser->tank[i].endpressure = 0;
|
||||
parser->tank[i].transmitter = 0;
|
||||
parser->tank[i].active = 0;
|
||||
}
|
||||
parser->vpm = 0;
|
||||
parser->gf_lo = 0;
|
||||
parser->gf_hi = 0;
|
||||
parser->seawater = 0;
|
||||
for (unsigned int i = 0; i < NSENSORS; ++i) {
|
||||
parser->calibration[i] = 0;
|
||||
}
|
||||
parser->calibrated = 0;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
divesoft_freedom_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -838,6 +792,13 @@ divesoft_freedom_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
|
||||
*((unsigned int *) value) = parser->ngasmixes;
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
if (parser->gasmix[flags].type == OXYGEN) {
|
||||
gasmix->usage = DC_USAGE_OXYGEN;
|
||||
} else if (parser->gasmix[flags].type == DILUENT) {
|
||||
gasmix->usage = DC_USAGE_DILUENT;
|
||||
} else {
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
}
|
||||
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
||||
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
@ -859,6 +820,7 @@ divesoft_freedom_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
|
||||
tank->beginpressure = parser->tank[flags].beginpressure * 2.0;
|
||||
tank->endpressure = parser->tank[flags].endpressure * 2.0;
|
||||
tank->gasmix = flags;
|
||||
tank->usage = DC_USAGE_NONE;
|
||||
break;
|
||||
case DC_FIELD_DECOMODEL:
|
||||
if (parser->vpm) {
|
||||
@ -924,15 +886,15 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
continue;
|
||||
}
|
||||
time = timestamp;
|
||||
sample.time = time;
|
||||
if (callback) callback(DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback(DC_SAMPLE_TIME, &sample, userdata);
|
||||
}
|
||||
|
||||
// Initial diluent.
|
||||
if (!initial) {
|
||||
if (parser->diluent != UNDEFINED) {
|
||||
sample.gasmix = parser->diluent;
|
||||
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
}
|
||||
initial = 1;
|
||||
}
|
||||
@ -943,18 +905,19 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
unsigned int ppo2 = array_uint16_le (data + offset + 6);
|
||||
|
||||
sample.depth = depth / 100.0;
|
||||
if (callback) callback(DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
if (ppo2) {
|
||||
sample.ppo2 = ppo2 * 10.0 / BAR;
|
||||
if (callback) callback(DC_SAMPLE_PPO2, sample, userdata);
|
||||
sample.ppo2.sensor = DC_SENSOR_NONE;
|
||||
sample.ppo2.value = ppo2 * 10.0 / BAR;
|
||||
if (callback) callback(DC_SAMPLE_PPO2, &sample, userdata);
|
||||
}
|
||||
|
||||
if (id == POINT_2) {
|
||||
unsigned int orientation = array_uint32_le (data + offset + 8);
|
||||
unsigned int heading = orientation & 0x1FF;
|
||||
sample.bearing = heading;
|
||||
if (callback) callback (DC_SAMPLE_BEARING, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_BEARING, &sample, userdata);
|
||||
} else if (id == POINT_1 || id == POINT_1_OLD) {
|
||||
unsigned int misc = array_uint32_le (data + offset + 8);
|
||||
unsigned int ceiling = array_uint16_le (data + offset + 12);
|
||||
@ -965,7 +928,7 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
|
||||
// Temperature
|
||||
sample.temperature = (signed int) signextend (temp, 10) / 10.0;
|
||||
if (callback) callback(DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
|
||||
// Deco / NDL
|
||||
if (ceiling) {
|
||||
@ -977,12 +940,13 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
sample.deco.time = ndl * 60;
|
||||
sample.deco.depth = 0.0;
|
||||
}
|
||||
if (callback) callback(DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = tts * 60;
|
||||
if (callback) callback(DC_SAMPLE_DECO, &sample, userdata);
|
||||
|
||||
// Setpoint
|
||||
if (setpoint) {
|
||||
sample.setpoint = setpoint / 100.0;
|
||||
if (callback) callback(DC_SAMPLE_SETPOINT, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_SETPOINT, &sample, userdata);
|
||||
}
|
||||
}
|
||||
} else if ((type >= LREC_MANIPULATION && type <= LREC_ACTIVITY) || type == LREC_INFO) {
|
||||
@ -994,7 +958,7 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
sample.event.time = 0;
|
||||
sample.event.flags = 0;
|
||||
sample.event.value = 0;
|
||||
if (callback) callback(DC_SAMPLE_EVENT, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_EVENT, &sample, userdata);
|
||||
} else if (event == EVENT_MIX_CHANGED || event == EVENT_DILUENT || event == EVENT_CHANGE_MODE) {
|
||||
unsigned int o2 = data[offset + 6];
|
||||
unsigned int he = data[offset + 7];
|
||||
@ -1014,13 +978,13 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
sample.gasmix = idx;
|
||||
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
} else if (event == EVENT_CNS) {
|
||||
sample.cns = array_uint16_le (data + offset + 6) / 100.0;
|
||||
if (callback) callback(DC_SAMPLE_CNS, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_CNS, &sample, userdata);
|
||||
} else if (event == EVENT_SETPOINT_MANUAL || event == EVENT_SETPOINT_AUTO) {
|
||||
sample.setpoint = data[6] / 100.0;
|
||||
if (callback) callback(DC_SAMPLE_SETPOINT, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_SETPOINT, &sample, userdata);
|
||||
}
|
||||
} else if (type == LREC_MEASURE) {
|
||||
// Measurement record.
|
||||
@ -1038,25 +1002,27 @@ divesoft_freedom_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
|
||||
sample.pressure.tank = idx;
|
||||
sample.pressure.value = pressure * 2.0;
|
||||
if (callback) callback(DC_SAMPLE_PRESSURE, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_PRESSURE, &sample, userdata);
|
||||
}
|
||||
} else if (id == MEASURE_ID_OXYGEN) {
|
||||
for (unsigned int i = 0; i < NSENSORS; ++i) {
|
||||
unsigned int ppo2 = array_uint16_le (data + offset + 4 + i * 2);
|
||||
if (ppo2 == 0 || ppo2 == 0xFFFF)
|
||||
continue;
|
||||
sample.ppo2 = ppo2 * 10.0 / BAR;
|
||||
if (callback) callback(DC_SAMPLE_PPO2, sample, userdata);
|
||||
sample.ppo2.sensor = i;
|
||||
sample.ppo2.value = ppo2 * 10.0 / BAR;
|
||||
if (callback) callback(DC_SAMPLE_PPO2, &sample, userdata);
|
||||
}
|
||||
} else if (id == MEASURE_ID_OXYGEN_MV) {
|
||||
for (unsigned int i = 0; i < NSENSORS; ++i) {
|
||||
unsigned int value = array_uint16_le (data + offset + 4 + i * 2);
|
||||
unsigned int state = data[offset + 12 + i];
|
||||
if (!parser->calibrated || state == SENSTAT_UNCALIBRATED ||
|
||||
state == SENSTAT_NOT_EXIST)
|
||||
if (!parser->calibrated || parser->calibration[i] == 0 ||
|
||||
state == SENSTAT_UNCALIBRATED || state == SENSTAT_NOT_EXIST)
|
||||
continue;
|
||||
sample.ppo2 = value / 100.0 * parser->calibration[i] / BAR;
|
||||
if (callback) callback(DC_SAMPLE_PPO2, sample, userdata);
|
||||
sample.ppo2.sensor = i;
|
||||
sample.ppo2.value = value / 100.0 * parser->calibration[i] / BAR;
|
||||
if (callback) callback(DC_SAMPLE_PPO2, &sample, userdata);
|
||||
}
|
||||
}
|
||||
} else if (type == LREC_STATE) {
|
||||
|
||||
@ -36,7 +36,7 @@ dc_status_t
|
||||
divesystem_idive_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
|
||||
|
||||
dc_status_t
|
||||
divesystem_idive_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||
divesystem_idive_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -58,6 +58,9 @@
|
||||
#define IX3M2_ZHL16C 2
|
||||
#define IX3M2_VPM 3
|
||||
|
||||
#define REC_SAMPLE 0
|
||||
#define REC_INFO 1
|
||||
|
||||
typedef struct divesystem_idive_parser_t divesystem_idive_parser_t;
|
||||
|
||||
typedef struct divesystem_idive_gasmix_t {
|
||||
@ -89,7 +92,6 @@ struct divesystem_idive_parser_t {
|
||||
unsigned int gf_high;
|
||||
};
|
||||
|
||||
static dc_status_t divesystem_idive_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t divesystem_idive_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t divesystem_idive_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -97,7 +99,6 @@ static dc_status_t divesystem_idive_parser_samples_foreach (dc_parser_t *abstrac
|
||||
static const dc_parser_vtable_t divesystem_idive_parser_vtable = {
|
||||
sizeof(divesystem_idive_parser_t),
|
||||
DC_FAMILY_DIVESYSTEM_IDIVE,
|
||||
divesystem_idive_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -109,7 +110,7 @@ static const dc_parser_vtable_t divesystem_idive_parser_vtable = {
|
||||
|
||||
|
||||
dc_status_t
|
||||
divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||
divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
||||
{
|
||||
divesystem_idive_parser_t *parser = NULL;
|
||||
|
||||
@ -117,7 +118,7 @@ divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, unsign
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (divesystem_idive_parser_t *) dc_parser_allocate (context, &divesystem_idive_parser_vtable);
|
||||
parser = (divesystem_idive_parser_t *) dc_parser_allocate (context, &divesystem_idive_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -156,35 +157,6 @@ divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, unsign
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
divesystem_idive_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
divesystem_idive_parser_t *parser = (divesystem_idive_parser_t *) abstract;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->divemode = INVALID;
|
||||
parser->divetime = 0;
|
||||
parser->maxdepth = 0;
|
||||
parser->ngasmixes = 0;
|
||||
parser->ntanks = 0;
|
||||
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||
parser->gasmix[i].oxygen = 0;
|
||||
parser->gasmix[i].helium = 0;
|
||||
}
|
||||
for (unsigned int i = 0; i < NTANKS; ++i) {
|
||||
parser->tank[i].id = 0;
|
||||
parser->tank[i].beginpressure = 0;
|
||||
parser->tank[i].endpressure = 0;
|
||||
}
|
||||
parser->algorithm = INVALID;
|
||||
parser->gf_low = INVALID;
|
||||
parser->gf_high = INVALID;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
divesystem_idive_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -317,6 +289,7 @@ divesystem_idive_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
|
||||
*((unsigned int *) value) = parser->ngasmixes;
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
||||
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
@ -331,6 +304,7 @@ divesystem_idive_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
|
||||
tank->beginpressure = parser->tank[flags].beginpressure;
|
||||
tank->endpressure = parser->tank[flags].endpressure;
|
||||
tank->gasmix = DC_GASMIX_UNKNOWN;
|
||||
tank->usage = DC_USAGE_NONE;
|
||||
break;
|
||||
case DC_FIELD_ATMOSPHERIC:
|
||||
if (ISIX3M(parser->model)) {
|
||||
@ -439,6 +413,7 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
unsigned int algorithm_previous = INVALID;
|
||||
unsigned int gf_low = INVALID;
|
||||
unsigned int gf_high = INVALID;
|
||||
unsigned int have_bearing = 0;
|
||||
|
||||
unsigned int firmware = 0;
|
||||
unsigned int apos4 = 0;
|
||||
@ -467,27 +442,37 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
while (offset + samplesize <= size) {
|
||||
dc_sample_value_t sample = {0};
|
||||
|
||||
// Get the record type.
|
||||
unsigned int type = ISIX3M(parser->model) ?
|
||||
array_uint16_le (data + offset + 52) :
|
||||
REC_SAMPLE;
|
||||
if (type != REC_SAMPLE) {
|
||||
// Skip non-sample records.
|
||||
offset += samplesize;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Time (seconds).
|
||||
unsigned int timestamp = array_uint32_le (data + offset + 2);
|
||||
if (timestamp <= time) {
|
||||
ERROR (abstract->context, "Timestamp moved backwards.");
|
||||
if (timestamp <= time && time != 0) {
|
||||
ERROR (abstract->context, "Timestamp moved backwards (%u %u).", timestamp, time);
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
time = timestamp;
|
||||
sample.time = timestamp;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = timestamp * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Depth (1/10 m).
|
||||
unsigned int depth = array_uint16_le (data + offset + 6);
|
||||
if (maxdepth < depth)
|
||||
maxdepth = depth;
|
||||
sample.depth = depth / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Temperature (Celsius).
|
||||
signed int temperature = (signed short) array_uint16_le (data + offset + 8);
|
||||
sample.temperature = temperature / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
|
||||
// Dive mode
|
||||
unsigned int mode = data[offset + 18];
|
||||
@ -521,7 +506,7 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
if (mode == SCR || mode == CCR) {
|
||||
unsigned int setpoint = array_uint16_le (data + offset + 19);
|
||||
sample.setpoint = setpoint / 1000.0;
|
||||
if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata);
|
||||
}
|
||||
|
||||
// Gaschange.
|
||||
@ -548,7 +533,7 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
}
|
||||
|
||||
sample.gasmix = i;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
o2_previous = o2;
|
||||
he_previous = he;
|
||||
}
|
||||
@ -566,18 +551,20 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
if (decostop) {
|
||||
sample.deco.type = DC_DECO_DECOSTOP;
|
||||
sample.deco.depth = decostop / 10.0;
|
||||
sample.deco.time = apos4 ? decotime : tts;
|
||||
sample.deco.time = decotime;
|
||||
sample.deco.tts = tts;
|
||||
} else {
|
||||
sample.deco.type = DC_DECO_NDL;
|
||||
sample.deco.depth = 0.0;
|
||||
sample.deco.time = tts;
|
||||
sample.deco.tts = 0;
|
||||
}
|
||||
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
||||
|
||||
// CNS
|
||||
unsigned int cns = array_uint16_le (data + offset + 29);
|
||||
sample.cns = cns / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_CNS, &sample, userdata);
|
||||
|
||||
// Tank Pressure
|
||||
if (samplesize == SZ_SAMPLE_IX3M_APOS4) {
|
||||
@ -598,7 +585,7 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
sample.event.time = 0;
|
||||
sample.event.flags = 0;
|
||||
sample.event.value = 0;
|
||||
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
||||
} else {
|
||||
// Get the index of the tank.
|
||||
if (id != tank_previous) {
|
||||
@ -628,10 +615,20 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
if (tank_idx < ntanks) {
|
||||
sample.pressure.tank = tank_idx;
|
||||
sample.pressure.value = pressure;
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
||||
tank[tank_idx].endpressure = pressure;
|
||||
}
|
||||
}
|
||||
|
||||
// Compass bearing
|
||||
unsigned int bearing = array_uint16_le (data + offset + 50);
|
||||
if (bearing != 0) {
|
||||
have_bearing = 1; // Stop ignoring zero values.
|
||||
}
|
||||
if (have_bearing && bearing != 0xFFFF) {
|
||||
sample.bearing = bearing;
|
||||
if (callback) callback (DC_SAMPLE_BEARING, &sample, userdata);
|
||||
}
|
||||
}
|
||||
|
||||
offset += samplesize;
|
||||
|
||||
@ -26,6 +26,7 @@ typedef struct dc_field_cache {
|
||||
// dc_tank_t TANK[MAXGASES]
|
||||
// but that's for later
|
||||
dc_tankinfo_t tankinfo[MAXGASES];
|
||||
dc_usage_t tankusage[MAXGASES];
|
||||
double tanksize[MAXGASES];
|
||||
double tankworkingpressure[MAXGASES];
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ dc_status_t
|
||||
hw_ostc_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
hw_ostc_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int serial);
|
||||
hw_ostc_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int serial);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -240,7 +240,7 @@ hw_ostc3_write (hw_ostc3_device_t *device, dc_event_progress_t *progress, const
|
||||
size_t nbytes = 0;
|
||||
while (nbytes < size) {
|
||||
// Set the maximum packet size.
|
||||
size_t length = 64;
|
||||
size_t length = (device->hardware == OSTC4) ? 64 : 1024;
|
||||
|
||||
// Limit the packet size to the total size.
|
||||
if (nbytes + length > size)
|
||||
|
||||
@ -36,7 +36,7 @@ dc_status_t
|
||||
hw_ostc3_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
hw_ostc3_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int serial, unsigned int model);
|
||||
hw_ostc3_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -43,10 +43,6 @@
|
||||
|
||||
#define UNDEFINED 0xFFFFFFFF
|
||||
|
||||
#define ALL 0
|
||||
#define FIXED 1
|
||||
#define MANUAL 2
|
||||
|
||||
#define HEADER 1
|
||||
#define PROFILE 2
|
||||
|
||||
@ -117,10 +113,12 @@ typedef struct hw_ostc_layout_t {
|
||||
} hw_ostc_layout_t;
|
||||
|
||||
typedef struct hw_ostc_gasmix_t {
|
||||
unsigned int id;
|
||||
unsigned int oxygen;
|
||||
unsigned int helium;
|
||||
unsigned int type;
|
||||
unsigned int enabled;
|
||||
unsigned int active;
|
||||
unsigned int diluent;
|
||||
} hw_ostc_gasmix_t;
|
||||
|
||||
@ -136,6 +134,7 @@ typedef struct hw_ostc_parser_t {
|
||||
const hw_ostc_layout_t *layout;
|
||||
unsigned int ngasmixes;
|
||||
unsigned int nfixed;
|
||||
unsigned int ndisabled;
|
||||
unsigned int initial;
|
||||
unsigned int initial_setpoint;
|
||||
unsigned int initial_cns;
|
||||
@ -143,15 +142,15 @@ typedef struct hw_ostc_parser_t {
|
||||
unsigned int current_divemode_ccr;
|
||||
} hw_ostc_parser_t;
|
||||
|
||||
static dc_status_t hw_ostc_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t hw_ostc_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
|
||||
static dc_status_t hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t callback, void *userdata);
|
||||
|
||||
static const dc_parser_vtable_t hw_ostc_parser_vtable = {
|
||||
sizeof(hw_ostc_parser_t),
|
||||
DC_FAMILY_HW_OSTC,
|
||||
hw_ostc_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -216,15 +215,10 @@ static const hw_ostc_layout_t hw_ostc_layout_ostc3 = {
|
||||
};
|
||||
|
||||
static unsigned int
|
||||
hw_ostc_find_gasmix (hw_ostc_parser_t *parser, unsigned int o2, unsigned int he, unsigned int dil, unsigned int type)
|
||||
hw_ostc_find_gasmix_manual (hw_ostc_parser_t *parser, unsigned int o2, unsigned int he, unsigned int dil)
|
||||
{
|
||||
unsigned int offset = 0;
|
||||
unsigned int offset = parser->nfixed - parser->ndisabled;
|
||||
unsigned int count = parser->ngasmixes;
|
||||
if (type == FIXED) {
|
||||
count = parser->nfixed;
|
||||
} else if (type == MANUAL) {
|
||||
offset = parser->nfixed;
|
||||
}
|
||||
|
||||
unsigned int i = offset;
|
||||
while (i < count) {
|
||||
@ -236,6 +230,22 @@ hw_ostc_find_gasmix (hw_ostc_parser_t *parser, unsigned int o2, unsigned int he,
|
||||
return i;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
hw_ostc_find_gasmix_fixed (hw_ostc_parser_t *parser, unsigned int id)
|
||||
{
|
||||
unsigned int offset = 0;
|
||||
unsigned int count = parser->nfixed - parser->ndisabled;
|
||||
|
||||
unsigned int i = offset;
|
||||
while (i < count) {
|
||||
if (id == parser->gasmix[i].id)
|
||||
break;
|
||||
i++;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
hw_ostc_is_ccr (unsigned int divemode, unsigned int version)
|
||||
{
|
||||
@ -317,19 +327,23 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
|
||||
initial = data[31];
|
||||
}
|
||||
for (unsigned int i = 0; i < ngasmixes; ++i) {
|
||||
gasmix[i].id = i + 1;
|
||||
gasmix[i].oxygen = data[25 + 2 * i];
|
||||
gasmix[i].helium = 0;
|
||||
gasmix[i].type = 0;
|
||||
gasmix[i].enabled = 1;
|
||||
gasmix[i].active = 0;
|
||||
gasmix[i].diluent = 0;
|
||||
}
|
||||
} else if (version == 0x23 || version == 0x24) {
|
||||
ngasmixes = 5;
|
||||
for (unsigned int i = 0; i < ngasmixes; ++i) {
|
||||
gasmix[i].id = i + 1;
|
||||
gasmix[i].oxygen = data[28 + 4 * i + 0];
|
||||
gasmix[i].helium = data[28 + 4 * i + 1];
|
||||
gasmix[i].type = data[28 + 4 * i + 3];
|
||||
gasmix[i].enabled = gasmix[i].type != 0;
|
||||
gasmix[i].active = 0;
|
||||
gasmix[i].diluent = ccr;
|
||||
// Find the first gas marked as the initial gas.
|
||||
if (initial == UNDEFINED && data[28 + 4 * i + 3] == 1) {
|
||||
@ -348,6 +362,7 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
|
||||
initial = data[31];
|
||||
}
|
||||
for (unsigned int i = 0; i < ngasmixes; ++i) {
|
||||
gasmix[i].id = i + 1;
|
||||
gasmix[i].oxygen = data[19 + 2 * i + 0];
|
||||
gasmix[i].helium = data[19 + 2 * i + 1];
|
||||
gasmix[i].type = 0;
|
||||
@ -356,6 +371,7 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
|
||||
} else {
|
||||
gasmix[i].enabled = 1;
|
||||
}
|
||||
gasmix[i].active = 0;
|
||||
gasmix[i].diluent = ccr;
|
||||
}
|
||||
}
|
||||
@ -364,7 +380,6 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
|
||||
ERROR(abstract->context, "Invalid initial gas mix.");
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
initial--; /* Convert to a zero based index. */
|
||||
} else {
|
||||
WARNING(abstract->context, "No initial gas mix available.");
|
||||
}
|
||||
@ -375,6 +390,7 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
|
||||
parser->layout = layout;
|
||||
parser->ngasmixes = ngasmixes;
|
||||
parser->nfixed = ngasmixes;
|
||||
parser->ndisabled = 0;
|
||||
parser->initial = initial;
|
||||
parser->initial_setpoint = initial_setpoint;
|
||||
parser->initial_cns = initial_cns;
|
||||
@ -387,7 +403,7 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, unsigned int serial, unsigned int hwos, unsigned int model)
|
||||
hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int hwos, unsigned int model, unsigned int serial)
|
||||
{
|
||||
hw_ostc_parser_t *parser = NULL;
|
||||
|
||||
@ -395,7 +411,7 @@ hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, unsign
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (hw_ostc_parser_t *) dc_parser_allocate (context, &hw_ostc_parser_vtable);
|
||||
parser = (hw_ostc_parser_t *) dc_parser_allocate (context, &hw_ostc_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -410,14 +426,17 @@ hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, unsign
|
||||
parser->layout = NULL;
|
||||
parser->ngasmixes = 0;
|
||||
parser->nfixed = 0;
|
||||
parser->ndisabled = 0;
|
||||
parser->initial = 0;
|
||||
parser->initial_setpoint = 0;
|
||||
parser->initial_cns = 0;
|
||||
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||
parser->gasmix[i].id = 0;
|
||||
parser->gasmix[i].oxygen = 0;
|
||||
parser->gasmix[i].helium = 0;
|
||||
parser->gasmix[i].type = 0;
|
||||
parser->gasmix[i].enabled = 0;
|
||||
parser->gasmix[i].active = 0;
|
||||
parser->gasmix[i].diluent = 0;
|
||||
}
|
||||
parser->serial = serial;
|
||||
@ -429,44 +448,17 @@ hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, unsign
|
||||
|
||||
|
||||
dc_status_t
|
||||
hw_ostc_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int serial)
|
||||
hw_ostc_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int serial)
|
||||
{
|
||||
return hw_ostc_parser_create_internal (out, context, serial, 0, 0);
|
||||
return hw_ostc_parser_create_internal (out, context, data, size, 0, 0, serial);
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
hw_ostc3_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int serial, unsigned int model)
|
||||
hw_ostc3_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial)
|
||||
{
|
||||
return hw_ostc_parser_create_internal (out, context, serial, 1, model);
|
||||
return hw_ostc_parser_create_internal (out, context, data, size, 1, model, serial);
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
hw_ostc_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
hw_ostc_parser_t *parser = (hw_ostc_parser_t *) abstract;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->version = 0;
|
||||
parser->header = 0;
|
||||
parser->layout = NULL;
|
||||
parser->ngasmixes = 0;
|
||||
parser->nfixed = 0;
|
||||
parser->initial = 0;
|
||||
parser->initial_setpoint = 0;
|
||||
parser->initial_cns = 0;
|
||||
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||
parser->gasmix[i].oxygen = 0;
|
||||
parser->gasmix[i].helium = 0;
|
||||
parser->gasmix[i].type = 0;
|
||||
parser->gasmix[i].enabled = 0;
|
||||
parser->gasmix[i].diluent = 0;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
hw_ostc_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -542,7 +534,7 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned
|
||||
|
||||
// Cache the profile data.
|
||||
if (parser->cached < PROFILE) {
|
||||
rc = hw_ostc_parser_samples_foreach (abstract, NULL, NULL);
|
||||
rc = hw_ostc_parser_internal_foreach (parser, NULL, NULL);
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
return rc;
|
||||
}
|
||||
@ -582,6 +574,8 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
gasmix->usage = parser->gasmix[flags].diluent ?
|
||||
DC_USAGE_DILUENT : DC_USAGE_NONE;
|
||||
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
||||
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
@ -839,7 +833,7 @@ static void hw_ostc_notify_bailout(hw_ostc_parser_t *parser, const unsigned char
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
callback(DC_SAMPLE_EVENT, sample, userdata);
|
||||
callback(DC_SAMPLE_EVENT, &sample, userdata);
|
||||
}
|
||||
|
||||
parser->current_divemode_ccr = parser->gasmix[index].diluent;
|
||||
@ -847,17 +841,12 @@ static void hw_ostc_notify_bailout(hw_ostc_parser_t *parser, const unsigned char
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
|
||||
hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t callback, void *userdata)
|
||||
{
|
||||
hw_ostc_parser_t *parser = (hw_ostc_parser_t *) abstract;
|
||||
dc_parser_t *abstract = (dc_parser_t *) parser;
|
||||
const unsigned char *data = abstract->data;
|
||||
unsigned int size = abstract->size;
|
||||
|
||||
// Cache the parser data.
|
||||
dc_status_t rc = hw_ostc_parser_cache (parser);
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
unsigned int version = parser->version;
|
||||
unsigned int header = parser->header;
|
||||
const hw_ostc_layout_t *layout = parser->layout;
|
||||
@ -964,7 +953,7 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
|
||||
|
||||
unsigned int time = 0;
|
||||
unsigned int nsamples = 0;
|
||||
unsigned int tank = parser->initial != UNDEFINED ? parser->initial : 0;
|
||||
unsigned int tank = parser->initial != UNDEFINED ? parser->initial - 1 : 0;
|
||||
|
||||
unsigned int offset = header;
|
||||
if (version == 0x23 || version == 0x24)
|
||||
@ -976,31 +965,33 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
|
||||
|
||||
// Time (seconds).
|
||||
time += samplerate;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Initial gas mix.
|
||||
if (time == samplerate && parser->initial != UNDEFINED) {
|
||||
sample.gasmix = parser->initial;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
unsigned int idx = hw_ostc_find_gasmix_fixed (parser, parser->initial);
|
||||
parser->gasmix[idx].active = 1;
|
||||
sample.gasmix = idx;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
}
|
||||
|
||||
// Initial setpoint (mbar).
|
||||
if (time == samplerate && parser->initial_setpoint != UNDEFINED) {
|
||||
sample.setpoint = parser->initial_setpoint / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata);
|
||||
}
|
||||
|
||||
// Initial CNS (%).
|
||||
if (time == samplerate && parser->initial_cns != UNDEFINED) {
|
||||
sample.cns = parser->initial_cns / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_CNS, &sample, userdata);
|
||||
}
|
||||
|
||||
// Depth (1/100 m).
|
||||
unsigned int depth = array_uint16_le (data + offset);
|
||||
sample.depth = depth / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
offset += 2;
|
||||
|
||||
// Extended sample info.
|
||||
@ -1059,7 +1050,7 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
|
||||
break;
|
||||
}
|
||||
if (sample.event.type && callback)
|
||||
callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||
callback (DC_SAMPLE_EVENT, &sample, userdata);
|
||||
|
||||
// Manual Gas Set & Change
|
||||
if (events & 0x10) {
|
||||
@ -1076,22 +1067,24 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
|
||||
diluent = ccr;
|
||||
}
|
||||
unsigned int he = data[offset + 1];
|
||||
unsigned int idx = hw_ostc_find_gasmix (parser, o2, he, diluent, MANUAL);
|
||||
unsigned int idx = hw_ostc_find_gasmix_manual (parser, o2, he, diluent);
|
||||
if (idx >= parser->ngasmixes) {
|
||||
if (idx >= NGASMIXES) {
|
||||
ERROR (abstract->context, "Maximum number of gas mixes reached.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
parser->gasmix[idx].id = 0;
|
||||
parser->gasmix[idx].oxygen = o2;
|
||||
parser->gasmix[idx].helium = he;
|
||||
parser->gasmix[idx].type = 0;
|
||||
parser->gasmix[idx].enabled = 1;
|
||||
parser->gasmix[idx].active = 1;
|
||||
parser->gasmix[idx].diluent = diluent;
|
||||
parser->ngasmixes = idx + 1;
|
||||
}
|
||||
|
||||
sample.gasmix = idx;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
|
||||
hw_ostc_notify_bailout(parser, data, idx, callback, userdata);
|
||||
|
||||
@ -1105,19 +1098,20 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
|
||||
ERROR (abstract->context, "Buffer overflow detected!");
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
unsigned int idx = data[offset];
|
||||
if (idx > parser->nfixed && idx <= parser->nfixed + OSTC4_CC_DILUENT_GAS_OFFSET) {
|
||||
unsigned int id = data[offset];
|
||||
if (id > parser->nfixed && id <= parser->nfixed + OSTC4_CC_DILUENT_GAS_OFFSET) {
|
||||
// OSTC4 reports gas changes to another diluent with an offset
|
||||
idx -= OSTC4_CC_DILUENT_GAS_OFFSET;
|
||||
id -= OSTC4_CC_DILUENT_GAS_OFFSET;
|
||||
}
|
||||
if (idx < 1 || idx > parser->nfixed) {
|
||||
ERROR(abstract->context, "Invalid gas mix (%u).", idx);
|
||||
if (id < 1 || id > parser->nfixed) {
|
||||
ERROR(abstract->context, "Invalid gas mix (%u).", id);
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
idx--; /* Convert to a zero based index. */
|
||||
unsigned int idx = hw_ostc_find_gasmix_fixed (parser, id);
|
||||
parser->gasmix[idx].active = 1;
|
||||
sample.gasmix = idx;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
tank = idx;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
tank = id - 1;
|
||||
|
||||
hw_ostc_notify_bailout(parser, data, idx, callback, userdata);
|
||||
|
||||
@ -1133,7 +1127,7 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
sample.setpoint = data[offset] / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata);
|
||||
offset++;
|
||||
length--;
|
||||
}
|
||||
@ -1147,22 +1141,24 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
|
||||
|
||||
unsigned int o2 = data[offset];
|
||||
unsigned int he = data[offset + 1];
|
||||
unsigned int idx = hw_ostc_find_gasmix (parser, o2, he, 0, MANUAL);
|
||||
unsigned int idx = hw_ostc_find_gasmix_manual (parser, o2, he, 0);
|
||||
if (idx >= parser->ngasmixes) {
|
||||
if (idx >= NGASMIXES) {
|
||||
ERROR (abstract->context, "Maximum number of gas mixes reached.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
parser->gasmix[idx].id = 0;
|
||||
parser->gasmix[idx].oxygen = o2;
|
||||
parser->gasmix[idx].helium = he;
|
||||
parser->gasmix[idx].type = 0;
|
||||
parser->gasmix[idx].enabled = 1;
|
||||
parser->gasmix[idx].active = 1;
|
||||
parser->gasmix[idx].diluent = 0;
|
||||
parser->ngasmixes = idx + 1;
|
||||
}
|
||||
|
||||
sample.gasmix = idx;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
|
||||
hw_ostc_notify_bailout(parser, data, idx, callback, userdata);
|
||||
|
||||
@ -1197,7 +1193,7 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
|
||||
case TEMPERATURE:
|
||||
value = array_uint16_le (data + offset);
|
||||
sample.temperature = value / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
break;
|
||||
case DECO:
|
||||
// Due to a firmware bug, the deco/ndl info is incorrect for
|
||||
@ -1212,7 +1208,8 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
|
||||
sample.deco.depth = 0.0;
|
||||
}
|
||||
sample.deco.time = data[offset + 1] * 60;
|
||||
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = 0;
|
||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
||||
break;
|
||||
case PPO2:
|
||||
for (unsigned int j = 0; j < 3; ++j) {
|
||||
@ -1226,8 +1223,9 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
|
||||
}
|
||||
if (count) {
|
||||
for (unsigned int j = 0; j < 3; ++j) {
|
||||
sample.ppo2 = ppo2[j] / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_PPO2, sample, userdata);
|
||||
sample.ppo2.sensor = i;
|
||||
sample.ppo2.value = ppo2[j] / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_PPO2, &sample, userdata);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -1236,7 +1234,7 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
|
||||
sample.cns = array_uint16_le (data + offset) / 100.0;
|
||||
else
|
||||
sample.cns = data[offset] / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_CNS, &sample, userdata);
|
||||
break;
|
||||
case TANK:
|
||||
value = array_uint16_le (data + offset);
|
||||
@ -1249,7 +1247,7 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
|
||||
(firmware >= OSTC3FW(10,40) && firmware <= OSTC3FW(10,50))) {
|
||||
sample.pressure.value /= 10.0;
|
||||
}
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
||||
}
|
||||
break;
|
||||
default: // Not yet used.
|
||||
@ -1269,7 +1267,7 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
sample.setpoint = data[offset] / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata);
|
||||
offset++;
|
||||
length--;
|
||||
}
|
||||
@ -1283,22 +1281,24 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
|
||||
|
||||
unsigned int o2 = data[offset];
|
||||
unsigned int he = data[offset + 1];
|
||||
unsigned int idx = hw_ostc_find_gasmix (parser, o2, he, 0, MANUAL);
|
||||
unsigned int idx = hw_ostc_find_gasmix_manual (parser, o2, he, 0);
|
||||
if (idx >= parser->ngasmixes) {
|
||||
if (idx >= NGASMIXES) {
|
||||
ERROR (abstract->context, "Maximum number of gas mixes reached.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
parser->gasmix[idx].id = 0;
|
||||
parser->gasmix[idx].oxygen = o2;
|
||||
parser->gasmix[idx].helium = he;
|
||||
parser->gasmix[idx].type = 0;
|
||||
parser->gasmix[idx].enabled = 1;
|
||||
parser->gasmix[idx].active = 1;
|
||||
parser->gasmix[idx].diluent = 0;
|
||||
parser->ngasmixes = idx + 1;
|
||||
}
|
||||
|
||||
sample.gasmix = idx;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
|
||||
hw_ostc_notify_bailout(parser, data, idx, callback, userdata);
|
||||
|
||||
@ -1319,7 +1319,50 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
|
||||
// Remove the disabled gas mixes from the fixed gas mixes.
|
||||
unsigned int ndisabled = 0, nenabled = 0;
|
||||
unsigned int count = parser->nfixed - parser->ndisabled;
|
||||
for (unsigned int i = 0; i < count; ++i) {
|
||||
if (parser->gasmix[i].enabled || parser->gasmix[i].active) {
|
||||
// Move the fixed gas mix.
|
||||
parser->gasmix[nenabled] = parser->gasmix[i];
|
||||
nenabled++;
|
||||
} else {
|
||||
ndisabled++;
|
||||
}
|
||||
}
|
||||
|
||||
// Move all the manual gas mixes.
|
||||
memmove (parser->gasmix + nenabled, parser->gasmix + count,
|
||||
(parser->ngasmixes - count) * sizeof (hw_ostc_gasmix_t));
|
||||
memset (parser->gasmix + parser->ngasmixes - ndisabled, 0,
|
||||
ndisabled * sizeof (hw_ostc_gasmix_t));
|
||||
|
||||
// Adjust the counts.
|
||||
parser->ngasmixes -= ndisabled;
|
||||
parser->ndisabled += ndisabled;
|
||||
|
||||
parser->cached = PROFILE;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
|
||||
{
|
||||
hw_ostc_parser_t *parser = (hw_ostc_parser_t *) abstract;
|
||||
|
||||
// Cache the header data.
|
||||
dc_status_t rc = hw_ostc_parser_cache (parser);
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
// Cache the profile data.
|
||||
if (parser->cached < PROFILE) {
|
||||
rc = hw_ostc_parser_internal_foreach (parser, NULL, NULL);
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return hw_ostc_parser_internal_foreach (parser, callback, userdata);
|
||||
}
|
||||
|
||||
@ -47,7 +47,6 @@
|
||||
#include "context-private.h"
|
||||
#include "iostream-private.h"
|
||||
#include "iterator-private.h"
|
||||
#include "descriptor-private.h"
|
||||
#include "array.h"
|
||||
#include "platform.h"
|
||||
|
||||
@ -226,7 +225,7 @@ dc_irda_iterator_new (dc_iterator_t **out, dc_context_t *context, dc_descriptor_
|
||||
INFO (context, "Discover: address=%08x, name=%s, charset=%02x, hints=%04x",
|
||||
address, name, charset, hints);
|
||||
|
||||
if (!dc_descriptor_filter (descriptor, DC_TRANSPORT_IRDA, name, NULL)) {
|
||||
if (!dc_descriptor_filter (descriptor, DC_TRANSPORT_IRDA, name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@ -34,6 +34,7 @@ dc_descriptor_get_product
|
||||
dc_descriptor_get_type
|
||||
dc_descriptor_get_model
|
||||
dc_descriptor_get_transports
|
||||
dc_descriptor_filter
|
||||
|
||||
dc_iostream_get_transport
|
||||
dc_iostream_set_timeout
|
||||
@ -93,17 +94,11 @@ dc_parser_set_clock
|
||||
dc_parser_set_atmospheric
|
||||
dc_parser_set_density
|
||||
dc_parser_get_type
|
||||
dc_parser_set_data
|
||||
dc_parser_get_datetime
|
||||
dc_parser_get_field
|
||||
dc_parser_samples_foreach
|
||||
dc_parser_destroy
|
||||
|
||||
reefnet_sensus_parser_set_calibration
|
||||
reefnet_sensuspro_parser_set_calibration
|
||||
reefnet_sensusultra_parser_set_calibration
|
||||
atomics_cobalt_parser_set_calibration
|
||||
|
||||
dc_device_open
|
||||
dc_device_close
|
||||
dc_device_dump
|
||||
|
||||
@ -35,7 +35,7 @@ dc_status_t
|
||||
liquivision_lynx_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
liquivision_lynx_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||
liquivision_lynx_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -117,7 +117,6 @@ struct liquivision_lynx_parser_t {
|
||||
liquivision_lynx_tank_t tank[NTANKS];
|
||||
};
|
||||
|
||||
static dc_status_t liquivision_lynx_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t liquivision_lynx_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t liquivision_lynx_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t liquivision_lynx_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -125,7 +124,6 @@ static dc_status_t liquivision_lynx_parser_samples_foreach (dc_parser_t *abstrac
|
||||
static const dc_parser_vtable_t liquivision_lynx_parser_vtable = {
|
||||
sizeof(liquivision_lynx_parser_t),
|
||||
DC_FAMILY_LIQUIVISION_LYNX,
|
||||
liquivision_lynx_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -137,7 +135,7 @@ static const dc_parser_vtable_t liquivision_lynx_parser_vtable = {
|
||||
|
||||
|
||||
dc_status_t
|
||||
liquivision_lynx_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||
liquivision_lynx_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
||||
{
|
||||
liquivision_lynx_parser_t *parser = NULL;
|
||||
|
||||
@ -145,7 +143,7 @@ liquivision_lynx_parser_create (dc_parser_t **out, dc_context_t *context, unsign
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (liquivision_lynx_parser_t *) dc_parser_allocate (context, &liquivision_lynx_parser_vtable);
|
||||
parser = (liquivision_lynx_parser_t *) dc_parser_allocate (context, &liquivision_lynx_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -173,29 +171,6 @@ liquivision_lynx_parser_create (dc_parser_t **out, dc_context_t *context, unsign
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
liquivision_lynx_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
liquivision_lynx_parser_t *parser = (liquivision_lynx_parser_t *) abstract;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->ngasmixes = 0;
|
||||
parser->ntanks = 0;
|
||||
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||
parser->gasmix[i].oxygen = 0;
|
||||
parser->gasmix[i].helium = 0;
|
||||
}
|
||||
for (unsigned int i = 0; i < NTANKS; ++i) {
|
||||
parser->tank[i].id = 0;
|
||||
parser->tank[i].beginpressure = 0;
|
||||
parser->tank[i].endpressure = 0;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
liquivision_lynx_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -315,6 +290,7 @@ liquivision_lynx_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
|
||||
*((unsigned int *) value) = parser->ngasmixes;
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
||||
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
@ -329,6 +305,7 @@ liquivision_lynx_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
|
||||
tank->beginpressure = parser->tank[flags].beginpressure / 100.0;
|
||||
tank->endpressure = parser->tank[flags].endpressure / 100.0;
|
||||
tank->gasmix = DC_GASMIX_UNKNOWN;
|
||||
tank->usage = DC_USAGE_NONE;
|
||||
break;
|
||||
default:
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
@ -545,29 +522,29 @@ liquivision_lynx_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
|
||||
// Time (seconds).
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Depth (1/100 m).
|
||||
sample.depth = value / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Temperature (1/10 °C).
|
||||
int temperature = (signed short) array_uint16_le (data + offset);
|
||||
sample.temperature = temperature / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
|
||||
// Gas mix
|
||||
if (have_gasmix) {
|
||||
sample.gasmix = gasmix_idx;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
have_gasmix = 0;
|
||||
}
|
||||
|
||||
// Setpoint (1/10 bar).
|
||||
if (have_setpoint) {
|
||||
sample.setpoint = setpoint / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata);
|
||||
have_setpoint = 0;
|
||||
}
|
||||
|
||||
@ -577,7 +554,7 @@ liquivision_lynx_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
if (have_pressure & (1 << i)) {
|
||||
sample.pressure.tank = i;
|
||||
sample.pressure.value = pressure[i] / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
||||
}
|
||||
}
|
||||
have_pressure = 0;
|
||||
@ -593,7 +570,8 @@ liquivision_lynx_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
sample.deco.depth = 0.0;
|
||||
}
|
||||
sample.deco.time = 0;
|
||||
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = 0;
|
||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
||||
have_deco = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ dc_status_t
|
||||
mares_darwin_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
|
||||
|
||||
dc_status_t
|
||||
mares_darwin_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||
mares_darwin_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -47,7 +47,6 @@ struct mares_darwin_parser_t {
|
||||
unsigned int samplesize;
|
||||
};
|
||||
|
||||
static dc_status_t mares_darwin_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t mares_darwin_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t mares_darwin_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -55,7 +54,6 @@ static dc_status_t mares_darwin_parser_samples_foreach (dc_parser_t *abstract, d
|
||||
static const dc_parser_vtable_t mares_darwin_parser_vtable = {
|
||||
sizeof(mares_darwin_parser_t),
|
||||
DC_FAMILY_MARES_DARWIN,
|
||||
mares_darwin_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -67,7 +65,7 @@ static const dc_parser_vtable_t mares_darwin_parser_vtable = {
|
||||
|
||||
|
||||
dc_status_t
|
||||
mares_darwin_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||
mares_darwin_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
||||
{
|
||||
mares_darwin_parser_t *parser = NULL;
|
||||
|
||||
@ -75,7 +73,7 @@ mares_darwin_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (mares_darwin_parser_t *) dc_parser_allocate (context, &mares_darwin_parser_vtable);
|
||||
parser = (mares_darwin_parser_t *) dc_parser_allocate (context, &mares_darwin_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -97,13 +95,6 @@ mares_darwin_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
mares_darwin_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
mares_darwin_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -159,6 +150,7 @@ mares_darwin_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
|
||||
}
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
gasmix->helium = 0.0;
|
||||
if (mode == NITROX) {
|
||||
gasmix->oxygen = p[0x0E] / 100.0;
|
||||
@ -185,6 +177,7 @@ mares_darwin_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
|
||||
tank->gasmix = 0;
|
||||
tank->beginpressure = array_uint16_be (p + 0x17);
|
||||
tank->endpressure = array_uint16_be (p + 0x19);
|
||||
tank->usage = DC_USAGE_NONE;
|
||||
} else {
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
@ -242,17 +235,17 @@ mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
|
||||
// Surface Time (seconds).
|
||||
time += 20;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Depth (1/10 m).
|
||||
sample.depth = depth / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Gas change.
|
||||
if (gasmix != gasmix_previous) {
|
||||
sample.gasmix = gasmix;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
gasmix_previous = gasmix;
|
||||
}
|
||||
|
||||
@ -262,7 +255,7 @@ mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
sample.event.time = 0;
|
||||
sample.event.flags = 0;
|
||||
sample.event.value = ascent;
|
||||
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
||||
}
|
||||
|
||||
// Deco violation
|
||||
@ -271,7 +264,7 @@ mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
sample.event.time = 0;
|
||||
sample.event.flags = 0;
|
||||
sample.event.value = 0;
|
||||
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
||||
}
|
||||
|
||||
// Deco stop
|
||||
@ -282,7 +275,8 @@ mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
}
|
||||
sample.deco.time = 0;
|
||||
sample.deco.depth = 0.0;
|
||||
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = 0;
|
||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
||||
|
||||
if (parser->samplesize == 3) {
|
||||
unsigned int type = (time / 20 + 2) % 3;
|
||||
@ -291,7 +285,7 @@ mares_darwin_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
pressure -= abstract->data[offset + 2];
|
||||
sample.pressure.tank = 0;
|
||||
sample.pressure.value = pressure;
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -21,7 +21,6 @@
|
||||
|
||||
#include <string.h> // memcpy, memcmp
|
||||
#include <stdlib.h> // malloc, free
|
||||
#include <assert.h> // assert
|
||||
|
||||
#include "mares_iconhd.h"
|
||||
#include "context-private.h"
|
||||
@ -94,7 +93,6 @@ typedef struct mares_iconhd_device_t {
|
||||
unsigned char version[140];
|
||||
unsigned int model;
|
||||
unsigned int packetsize;
|
||||
unsigned int splitcommand;
|
||||
} mares_iconhd_device_t;
|
||||
|
||||
static dc_status_t mares_iconhd_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
|
||||
@ -179,27 +177,35 @@ mares_iconhd_get_model (mares_iconhd_device_t *device)
|
||||
|
||||
static dc_status_t
|
||||
mares_iconhd_packet (mares_iconhd_device_t *device,
|
||||
const unsigned char command[], unsigned int csize,
|
||||
unsigned char cmd,
|
||||
const unsigned char data[], unsigned int size,
|
||||
unsigned char answer[], unsigned int asize)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
unsigned int split_csize;
|
||||
|
||||
assert (csize >= 2);
|
||||
|
||||
if (device_is_cancelled (abstract))
|
||||
return DC_STATUS_CANCELLED;
|
||||
|
||||
split_csize = device->splitcommand ? 2 : csize;
|
||||
|
||||
// Send the command header to the dive computer.
|
||||
status = dc_iostream_write (device->iostream, command, split_csize, NULL);
|
||||
const unsigned char command[2] = {
|
||||
cmd, cmd ^ XOR,
|
||||
};
|
||||
status = dc_iostream_write (device->iostream, command, sizeof(command), NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return status;
|
||||
}
|
||||
|
||||
// Send the command payload to the dive computer.
|
||||
if (size) {
|
||||
status = dc_iostream_write (device->iostream, data, size, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
// Receive the header byte.
|
||||
unsigned char header[1] = {0};
|
||||
status = dc_iostream_read (device->iostream, header, sizeof (header), NULL);
|
||||
@ -214,15 +220,6 @@ mares_iconhd_packet (mares_iconhd_device_t *device,
|
||||
return DC_STATUS_PROTOCOL;
|
||||
}
|
||||
|
||||
// Send any remaining command payload to the dive computer.
|
||||
if (csize > split_csize) {
|
||||
status = dc_iostream_write (device->iostream, command + split_csize, csize - split_csize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to send the command.");
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the packet.
|
||||
status = dc_iostream_read (device->iostream, answer, asize, NULL);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
@ -248,11 +245,11 @@ mares_iconhd_packet (mares_iconhd_device_t *device,
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
mares_iconhd_transfer (mares_iconhd_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize)
|
||||
mares_iconhd_transfer (mares_iconhd_device_t *device, unsigned char cmd, const unsigned char data[], unsigned int size, unsigned char answer[], unsigned int asize)
|
||||
{
|
||||
unsigned int nretries = 0;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
while ((rc = mares_iconhd_packet (device, command, csize, answer, asize)) != DC_STATUS_SUCCESS) {
|
||||
while ((rc = mares_iconhd_packet (device, cmd, data, size, answer, asize)) != DC_STATUS_SUCCESS) {
|
||||
// Automatically discard a corrupted packet,
|
||||
// and request a new one.
|
||||
if (rc != DC_STATUS_PROTOCOL && rc != DC_STATUS_TIMEOUT)
|
||||
@ -287,23 +284,21 @@ mares_iconhd_read_object(mares_iconhd_device_t *device, dc_event_progress_t *pro
|
||||
|
||||
// Transfer the init packet.
|
||||
unsigned char rsp_init[16];
|
||||
unsigned char cmd_init[18] = {
|
||||
CMD_OBJ_INIT,
|
||||
CMD_OBJ_INIT ^ XOR,
|
||||
unsigned char cmd_init[16] = {
|
||||
0x40,
|
||||
(index >> 0) & 0xFF,
|
||||
(index >> 8) & 0xFF,
|
||||
subindex & 0xFF
|
||||
};
|
||||
memset (cmd_init + 6, 0x00, sizeof(cmd_init) - 6);
|
||||
status = mares_iconhd_transfer (device, cmd_init, sizeof (cmd_init), rsp_init, sizeof (rsp_init));
|
||||
status = mares_iconhd_transfer (device, CMD_OBJ_INIT, cmd_init, sizeof (cmd_init), rsp_init, sizeof (rsp_init));
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to transfer the init packet.");
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the packet header.
|
||||
if (memcmp (cmd_init + 3, rsp_init + 1, 3) != 0) {
|
||||
if (memcmp (cmd_init + 1, rsp_init + 1, 3) != 0) {
|
||||
ERROR (abstract->context, "Unexpected packet header.");
|
||||
return DC_STATUS_PROTOCOL;
|
||||
}
|
||||
@ -351,8 +346,7 @@ mares_iconhd_read_object(mares_iconhd_device_t *device, dc_event_progress_t *pro
|
||||
|
||||
// Transfer the segment packet.
|
||||
unsigned char rsp_segment[1 + 504];
|
||||
unsigned char cmd_segment[] = {cmd, cmd ^ XOR};
|
||||
status = mares_iconhd_transfer (device, cmd_segment, sizeof (cmd_segment), rsp_segment, len + 1);
|
||||
status = mares_iconhd_transfer (device, cmd, NULL, 0, rsp_segment, len + 1);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to transfer the segment packet.");
|
||||
return status;
|
||||
@ -419,15 +413,6 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_
|
||||
device->iostream = iostream;
|
||||
}
|
||||
|
||||
/*
|
||||
* At least the Mares Matrix needs the command to be split into
|
||||
* base and argument, with a wait for the ACK byte in between.
|
||||
*
|
||||
* See commit 59bfb0f3189b ("Add support for the Mares Matrix")
|
||||
* for details.
|
||||
*/
|
||||
device->splitcommand = 1;
|
||||
|
||||
// Set the serial communication protocol (115200 8E1).
|
||||
status = dc_iostream_configure (device->iostream, 115200, 8, DC_PARITY_EVEN, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
@ -460,8 +445,7 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_
|
||||
dc_iostream_purge (device->iostream, DC_DIRECTION_ALL);
|
||||
|
||||
// Send the version command.
|
||||
unsigned char command[] = {CMD_VERSION, CMD_VERSION ^ XOR};
|
||||
status = mares_iconhd_transfer (device, command, sizeof (command),
|
||||
status = mares_iconhd_transfer (device, CMD_VERSION, NULL, 0,
|
||||
device->version, sizeof (device->version));
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
goto error_free_iostream;
|
||||
@ -473,9 +457,8 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_
|
||||
// Read the size of the flash memory.
|
||||
unsigned int memsize = 0;
|
||||
if (device->model == QUAD) {
|
||||
unsigned char cmd_flash[] = {CMD_FLASHSIZE, CMD_FLASHSIZE ^ XOR};
|
||||
unsigned char rsp_flash[4] = {0};
|
||||
status = mares_iconhd_transfer (device, cmd_flash, sizeof (cmd_flash), rsp_flash, sizeof (rsp_flash));
|
||||
status = mares_iconhd_transfer (device, CMD_FLASHSIZE, NULL, 0, rsp_flash, sizeof (rsp_flash));
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
WARNING (context, "Failed to read the flash memory size.");
|
||||
} else {
|
||||
@ -538,14 +521,6 @@ mares_iconhd_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_
|
||||
*/
|
||||
if (device->packetsize > 128)
|
||||
device->packetsize = 128;
|
||||
/*
|
||||
* With BLE, don't wait for ACK before sending the arguments
|
||||
* to a command.
|
||||
*
|
||||
* There is some timing issue that makes that take too long
|
||||
* and causes the command to be aborted.
|
||||
*/
|
||||
device->splitcommand = 0;
|
||||
}
|
||||
|
||||
*out = (dc_device_t *) device;
|
||||
@ -608,7 +583,7 @@ mares_iconhd_device_read (dc_device_t *abstract, unsigned int address, unsigned
|
||||
len = device->packetsize;
|
||||
|
||||
// Read the packet.
|
||||
unsigned char command[] = {CMD_READ, CMD_READ ^ XOR,
|
||||
unsigned char command[] = {
|
||||
(address ) & 0xFF,
|
||||
(address >> 8) & 0xFF,
|
||||
(address >> 16) & 0xFF,
|
||||
@ -617,7 +592,7 @@ mares_iconhd_device_read (dc_device_t *abstract, unsigned int address, unsigned
|
||||
(len >> 8) & 0xFF,
|
||||
(len >> 16) & 0xFF,
|
||||
(len >> 24) & 0xFF};
|
||||
rc = mares_iconhd_transfer (device, command, sizeof (command), data, len);
|
||||
rc = mares_iconhd_transfer (device, CMD_READ, command, sizeof (command), data, len);
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ dc_status_t
|
||||
mares_iconhd_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
mares_iconhd_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model, unsigned int serial);
|
||||
mares_iconhd_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -267,7 +267,6 @@ static const mares_iconhd_layout_t horizon = {
|
||||
0x54 + 8, /* tanks */
|
||||
};
|
||||
|
||||
static dc_status_t mares_iconhd_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t mares_iconhd_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -275,7 +274,6 @@ static dc_status_t mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, d
|
||||
static const dc_parser_vtable_t mares_iconhd_parser_vtable = {
|
||||
sizeof(mares_iconhd_parser_t),
|
||||
DC_FAMILY_MARES_ICONHD,
|
||||
mares_iconhd_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -404,12 +402,12 @@ mares_iconhd_cache (mares_iconhd_parser_t *parser)
|
||||
unsigned int samplerate = 0;
|
||||
if (parser->model == SMARTAPNEA) {
|
||||
unsigned int idx = (settings & 0x0600) >> 9;
|
||||
interval = 1;
|
||||
samplerate = 1 << idx;
|
||||
interval = 1000 / samplerate;
|
||||
} else {
|
||||
const unsigned int intervals[] = {1, 5, 10, 20};
|
||||
unsigned int idx = (settings & 0x0C00) >> 10;
|
||||
interval = intervals[idx];
|
||||
interval = intervals[idx] * 1000;
|
||||
samplerate = 1;
|
||||
}
|
||||
|
||||
@ -628,7 +626,7 @@ mares_genius_cache (mares_iconhd_parser_t *parser)
|
||||
parser->headersize = headersize;
|
||||
parser->settings = settings;
|
||||
parser->surftime = surftime * 60;
|
||||
parser->interval = 5;
|
||||
parser->interval = 5000;
|
||||
parser->samplerate = 1;
|
||||
parser->ntanks = ntanks;
|
||||
parser->ngasmixes = ngasmixes;
|
||||
@ -659,7 +657,7 @@ mares_iconhd_parser_cache (mares_iconhd_parser_t *parser)
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
mares_iconhd_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial)
|
||||
mares_iconhd_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial)
|
||||
{
|
||||
mares_iconhd_parser_t *parser = NULL;
|
||||
|
||||
@ -667,7 +665,7 @@ mares_iconhd_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (mares_iconhd_parser_t *) dc_parser_allocate (context, &mares_iconhd_parser_vtable);
|
||||
parser = (mares_iconhd_parser_t *) dc_parser_allocate (context, &mares_iconhd_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -705,41 +703,6 @@ mares_iconhd_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
mares_iconhd_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
mares_iconhd_parser_t *parser = (mares_iconhd_parser_t *) abstract;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->logformat = 0;
|
||||
parser->mode = (parser->model == GENIUS || parser->model == HORIZON) ? GENIUS_AIR : ICONHD_AIR;
|
||||
parser->nsamples = 0;
|
||||
parser->samplesize = 0;
|
||||
parser->headersize = 0;
|
||||
parser->settings = 0;
|
||||
parser->surftime = 0;
|
||||
parser->interval = 0;
|
||||
parser->samplerate = 0;
|
||||
parser->ntanks = 0;
|
||||
parser->ngasmixes = 0;
|
||||
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||
parser->gasmix[i].oxygen = 0;
|
||||
parser->gasmix[i].helium = 0;
|
||||
}
|
||||
for (unsigned int i = 0; i < NTANKS; ++i) {
|
||||
parser->tank[i].volume = 0;
|
||||
parser->tank[i].workpressure = 0;
|
||||
parser->tank[i].beginpressure = 0;
|
||||
parser->tank[i].endpressure = 0;
|
||||
}
|
||||
parser->layout = NULL;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
mares_iconhd_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -827,7 +790,7 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
|
||||
if (parser->layout->divetime != UNSUPPORTED) {
|
||||
*((unsigned int *) value) = array_uint16_le (p + parser->layout->divetime);
|
||||
} else {
|
||||
*((unsigned int *) value) = parser->nsamples * parser->interval - parser->surftime;
|
||||
*((unsigned int *) value) = parser->nsamples * parser->interval / 1000 - parser->surftime;
|
||||
}
|
||||
break;
|
||||
case DC_FIELD_MAXDEPTH:
|
||||
@ -837,6 +800,7 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
|
||||
*((unsigned int *) value) = parser->ngasmixes;
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
||||
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
@ -864,6 +828,7 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
|
||||
} else {
|
||||
tank->gasmix = DC_GASMIX_UNKNOWN;
|
||||
}
|
||||
tank->usage = DC_USAGE_NONE;
|
||||
break;
|
||||
case DC_FIELD_ATMOSPHERIC:
|
||||
*((double *) value) = array_uint16_le (p + parser->layout->atmospheric) / (1000.0 * parser->layout->atmospheric_divisor);
|
||||
@ -981,14 +946,6 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
|
||||
const unsigned char *data = abstract->data;
|
||||
|
||||
if (parser->samplerate > 1) {
|
||||
// The Smart Apnea supports multiple samples per second
|
||||
// (e.g. 2, 4 or 8). Since our smallest unit of time is one
|
||||
// second, we can't represent this, and the extra samples
|
||||
// will get dropped.
|
||||
WARNING(abstract->context, "Multiple samples per second are not supported!");
|
||||
}
|
||||
|
||||
// Previous gas mix - initialize with impossible value
|
||||
unsigned int gasmix_previous = 0xFFFFFFFF;
|
||||
|
||||
@ -1039,29 +996,30 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
unsigned int surftime = array_uint16_le (data + offset + 4);
|
||||
|
||||
// Surface Time (seconds).
|
||||
time += surftime;
|
||||
time += surftime * 1000;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Surface Depth (0 m).
|
||||
sample.depth = 0.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
offset += parser->samplesize;
|
||||
nsamples++;
|
||||
|
||||
for (unsigned int i = 0; i < divetime; ++i) {
|
||||
unsigned int count = divetime * parser->samplerate;
|
||||
for (unsigned int i = 0; i < count; ++i) {
|
||||
// Time (seconds).
|
||||
time += parser->interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Depth (1/10 m).
|
||||
unsigned int depth = array_uint16_le (data + offset);
|
||||
sample.depth = depth / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
offset += 2 * parser->samplerate;
|
||||
offset += 2;
|
||||
}
|
||||
} else if (parser->model != GENIUS && parser->model != HORIZON && parser->mode == ICONHD_FREEDIVE) {
|
||||
unsigned int maxdepth = array_uint16_le (data + offset + 0);
|
||||
@ -1069,22 +1027,22 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
unsigned int surftime = array_uint16_le (data + offset + 4);
|
||||
|
||||
// Surface Time (seconds).
|
||||
time += surftime;
|
||||
time += surftime * 1000;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Surface Depth (0 m).
|
||||
sample.depth = 0.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Dive Time (seconds).
|
||||
time += divetime;
|
||||
time += divetime * 1000;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Maximum Depth (1/10 m).
|
||||
sample.depth = maxdepth / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
offset += parser->samplesize;
|
||||
nsamples++;
|
||||
@ -1142,15 +1100,15 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
// Time (seconds).
|
||||
time += parser->interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Depth (1/10 m).
|
||||
sample.depth = depth / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Temperature (1/10 °C).
|
||||
sample.temperature = temperature / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
|
||||
// Current gas mix
|
||||
if (parser->ngasmixes > 0) {
|
||||
@ -1160,7 +1118,7 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
}
|
||||
if (gasmix != gasmix_previous) {
|
||||
sample.gasmix = gasmix;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
gasmix_previous = gasmix;
|
||||
}
|
||||
}
|
||||
@ -1171,7 +1129,7 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
sample.event.time = 0;
|
||||
sample.event.flags = 0;
|
||||
sample.event.value = bookmark;
|
||||
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
||||
}
|
||||
|
||||
if (parser->model == GENIUS || parser->model == HORIZON) {
|
||||
@ -1184,7 +1142,8 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
sample.deco.depth = 0.0;
|
||||
}
|
||||
sample.deco.time = decotime * 60;
|
||||
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = tts;
|
||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
||||
|
||||
// Alarms
|
||||
for (unsigned int v = alarms, i = 0; v; v >>= 1, ++i) {
|
||||
@ -1210,7 +1169,7 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
sample.event.time = 0;
|
||||
sample.event.flags = 0;
|
||||
sample.event.value = 0;
|
||||
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1231,7 +1190,7 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
if (gasmix < parser->ntanks) {
|
||||
sample.pressure.tank = gasmix;
|
||||
sample.pressure.value = pressure / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
||||
} else if (pressure != 0) {
|
||||
WARNING (abstract->context, "Invalid tank with non-zero pressure.");
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ dc_status_t
|
||||
mares_nemo_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
mares_nemo_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||
mares_nemo_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -59,7 +59,6 @@ struct mares_nemo_parser_t {
|
||||
unsigned int extra;
|
||||
};
|
||||
|
||||
static dc_status_t mares_nemo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t mares_nemo_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t mares_nemo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -67,7 +66,6 @@ static dc_status_t mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_
|
||||
static const dc_parser_vtable_t mares_nemo_parser_vtable = {
|
||||
sizeof(mares_nemo_parser_t),
|
||||
DC_FAMILY_MARES_NEMO,
|
||||
mares_nemo_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -79,15 +77,16 @@ static const dc_parser_vtable_t mares_nemo_parser_vtable = {
|
||||
|
||||
|
||||
dc_status_t
|
||||
mares_nemo_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||
mares_nemo_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
mares_nemo_parser_t *parser = NULL;
|
||||
|
||||
if (out == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (mares_nemo_parser_t *) dc_parser_allocate (context, &mares_nemo_parser_vtable);
|
||||
parser = (mares_nemo_parser_t *) dc_parser_allocate (context, &mares_nemo_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -98,70 +97,42 @@ mares_nemo_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int
|
||||
if (model == NEMOWIDE || model == NEMOAIR || model == PUCK || model == PUCKAIR)
|
||||
freedive = GAUGE;
|
||||
|
||||
// Set the default values.
|
||||
parser->model = model;
|
||||
parser->freedive = freedive;
|
||||
parser->mode = AIR;
|
||||
parser->length = 0;
|
||||
parser->sample_count = 0;
|
||||
parser->sample_size = 0;
|
||||
parser->header = 0;
|
||||
parser->extra = 0;
|
||||
|
||||
*out = (dc_parser_t*) parser;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
mares_nemo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
mares_nemo_parser_t *parser = (mares_nemo_parser_t *) abstract;
|
||||
|
||||
// Clear the previous state.
|
||||
parser->base.data = NULL;
|
||||
parser->base.size = 0;
|
||||
parser->mode = AIR;
|
||||
parser->length = 0;
|
||||
parser->sample_count = 0;
|
||||
parser->sample_size = 0;
|
||||
parser->header = 0;
|
||||
parser->extra = 0;
|
||||
|
||||
if (size == 0)
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
if (size < 2 + 3)
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
if (size < 2 + 3) {
|
||||
status = DC_STATUS_DATAFORMAT;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
unsigned int length = array_uint16_le (data);
|
||||
if (length > size)
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
if (length > size) {
|
||||
status = DC_STATUS_DATAFORMAT;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
unsigned int extra = 0;
|
||||
const unsigned char marker[3] = {0xAA, 0xBB, 0xCC};
|
||||
if (memcmp (data + length - 3, marker, sizeof (marker)) == 0) {
|
||||
if (parser->model == PUCKAIR)
|
||||
if (model == PUCKAIR)
|
||||
extra = 7;
|
||||
else
|
||||
extra = 12;
|
||||
}
|
||||
|
||||
if (length < 2 + extra + 3)
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
if (length < 2 + extra + 3) {
|
||||
status = DC_STATUS_DATAFORMAT;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
unsigned int mode = data[length - extra - 1];
|
||||
|
||||
unsigned int header_size = 53;
|
||||
unsigned int sample_size = 2;
|
||||
if (extra) {
|
||||
if (parser->model == PUCKAIR)
|
||||
if (model == PUCKAIR)
|
||||
sample_size = 3;
|
||||
else
|
||||
sample_size = 5;
|
||||
}
|
||||
if (mode == parser->freedive) {
|
||||
if (mode == freedive) {
|
||||
header_size = 28;
|
||||
sample_size = 6;
|
||||
}
|
||||
@ -169,12 +140,14 @@ mares_nemo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, un
|
||||
unsigned int nsamples = array_uint16_le (data + length - extra - 3);
|
||||
|
||||
unsigned int nbytes = 2 + nsamples * sample_size + header_size + extra;
|
||||
if (length != nbytes)
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
if (length != nbytes) {
|
||||
status = DC_STATUS_DATAFORMAT;
|
||||
goto error_free;
|
||||
}
|
||||
|
||||
// Store the new state.
|
||||
parser->base.data = data;
|
||||
parser->base.size = size;
|
||||
// Set the default values.
|
||||
parser->model = model;
|
||||
parser->freedive = freedive;
|
||||
parser->mode = mode;
|
||||
parser->length = length;
|
||||
parser->sample_count = nsamples;
|
||||
@ -182,7 +155,13 @@ mares_nemo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, un
|
||||
parser->header = header_size;
|
||||
parser->extra = extra;
|
||||
|
||||
*out = (dc_parser_t*) parser;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_free:
|
||||
dc_parser_deallocate ((dc_parser_t *) parser);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@ -251,6 +230,7 @@ mares_nemo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign
|
||||
}
|
||||
gasmix->helium = 0.0;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
break;
|
||||
case DC_FIELD_TANK_COUNT:
|
||||
if (parser->extra)
|
||||
@ -290,6 +270,7 @@ mares_nemo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsign
|
||||
} else {
|
||||
tank->gasmix = DC_GASMIX_UNKNOWN;
|
||||
}
|
||||
tank->usage = DC_USAGE_NONE;
|
||||
break;
|
||||
case DC_FIELD_TEMPERATURE_MINIMUM:
|
||||
*((double *) value) = (signed char) p[53 - 11];
|
||||
@ -382,17 +363,17 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
||||
|
||||
// Time (seconds).
|
||||
time += 20;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Depth (1/10 m).
|
||||
sample.depth = depth / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Gas change.
|
||||
if (gasmix != gasmix_previous) {
|
||||
sample.gasmix = gasmix;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
gasmix_previous = gasmix;
|
||||
}
|
||||
|
||||
@ -402,7 +383,7 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
||||
sample.event.time = 0;
|
||||
sample.event.flags = 0;
|
||||
sample.event.value = ascent;
|
||||
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
||||
}
|
||||
|
||||
// Deco violation
|
||||
@ -411,7 +392,7 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
||||
sample.event.time = 0;
|
||||
sample.event.flags = 0;
|
||||
sample.event.value = 0;
|
||||
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
||||
}
|
||||
|
||||
// Deco stop
|
||||
@ -422,20 +403,21 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
||||
}
|
||||
sample.deco.time = 0;
|
||||
sample.deco.depth = 0.0;
|
||||
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = 0;
|
||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
||||
|
||||
// Pressure (1 bar).
|
||||
if (parser->sample_size == 3) {
|
||||
sample.pressure.tank = 0;
|
||||
sample.pressure.value = data[idx + 2];
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
||||
} else if (parser->sample_size == 5) {
|
||||
unsigned int type = (time / 20) % 3;
|
||||
if (type == 0) {
|
||||
pressure -= data[idx + 2] * 100;
|
||||
sample.pressure.tank = 0;
|
||||
sample.pressure.value = pressure / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -459,12 +441,12 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
||||
|
||||
// Surface Time (seconds).
|
||||
time += surftime;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Surface Depth (0 m).
|
||||
sample.depth = 0.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
if (profiles) {
|
||||
// Get the freedive sample interval for this model.
|
||||
@ -500,12 +482,12 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
||||
time += interval;
|
||||
if (time > maxtime)
|
||||
time = maxtime; // Adjust the last sample.
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Depth (1/10 m).
|
||||
sample.depth = depth / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
}
|
||||
|
||||
// Verify that the number of samples in the profile data
|
||||
@ -519,12 +501,12 @@ mares_nemo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
|
||||
} else {
|
||||
// Dive Time (seconds).
|
||||
time += divetime;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Maximum Depth (1/10 m).
|
||||
sample.depth = maxdepth / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ dc_status_t
|
||||
mclean_extreme_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
mclean_extreme_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||
mclean_extreme_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -58,7 +58,6 @@ struct mclean_extreme_parser_t {
|
||||
unsigned int gasmix[NGASMIXES];
|
||||
};
|
||||
|
||||
static dc_status_t mclean_extreme_parser_set_data(dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t mclean_extreme_parser_get_datetime(dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t mclean_extreme_parser_get_field(dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t mclean_extreme_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -66,7 +65,6 @@ static dc_status_t mclean_extreme_parser_samples_foreach(dc_parser_t *abstract,
|
||||
static const dc_parser_vtable_t mclean_extreme_parser_vtable = {
|
||||
sizeof(mclean_extreme_parser_t),
|
||||
DC_FAMILY_MCLEAN_EXTREME,
|
||||
mclean_extreme_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -77,7 +75,7 @@ static const dc_parser_vtable_t mclean_extreme_parser_vtable = {
|
||||
};
|
||||
|
||||
dc_status_t
|
||||
mclean_extreme_parser_create(dc_parser_t **out, dc_context_t *context)
|
||||
mclean_extreme_parser_create(dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
||||
{
|
||||
mclean_extreme_parser_t *parser = NULL;
|
||||
|
||||
@ -86,7 +84,7 @@ mclean_extreme_parser_create(dc_parser_t **out, dc_context_t *context)
|
||||
}
|
||||
|
||||
// Allocate memory.
|
||||
parser = (mclean_extreme_parser_t *)dc_parser_allocate(context, &mclean_extreme_parser_vtable);
|
||||
parser = (mclean_extreme_parser_t *)dc_parser_allocate(context, &mclean_extreme_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR(context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -104,21 +102,6 @@ mclean_extreme_parser_create(dc_parser_t **out, dc_context_t *context)
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
mclean_extreme_parser_set_data(dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
mclean_extreme_parser_t *parser = (mclean_extreme_parser_t *)abstract;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->ngasmixes = 0;
|
||||
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||
parser->gasmix[i] = INVALID;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
mclean_extreme_parser_get_datetime(dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -221,6 +204,7 @@ mclean_extreme_parser_get_field(dc_parser_t *abstract, dc_field_type_t type, uns
|
||||
*((unsigned int *)value) = parser->ngasmixes;
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
gasmix->helium = 0.01 * abstract->data[0x0001 + 1 + 2 * parser->gasmix[flags]];
|
||||
gasmix->oxygen = 0.01 * abstract->data[0x0001 + 0 + 2 * parser->gasmix[flags]];
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
@ -269,14 +253,14 @@ mclean_extreme_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback_
|
||||
const unsigned int setpoint = abstract->data[0x0013 + sp_index];
|
||||
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback(DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback(DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
sample.depth = 0.1 * depth;
|
||||
if (callback) callback(DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
sample.temperature = temperature;
|
||||
if (callback) callback(DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
|
||||
if (gasmix_id != gasmix_previous) {
|
||||
// Find the gasmix in the list.
|
||||
@ -298,13 +282,13 @@ mclean_extreme_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback_
|
||||
}
|
||||
|
||||
sample.gasmix = idx;
|
||||
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
gasmix_previous = gasmix_id;
|
||||
}
|
||||
|
||||
if (ccr) {
|
||||
sample.setpoint = 0.01 * setpoint;
|
||||
if (callback) callback(DC_SAMPLE_SETPOINT, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_SETPOINT, &sample, userdata);
|
||||
}
|
||||
|
||||
offset += SZ_SAMPLE;
|
||||
|
||||
@ -339,7 +339,7 @@ static const oceanic_common_layout_t oceanic_reactpro_layout = {
|
||||
0x0600, /* rb_logbook_end */
|
||||
8, /* rb_logbook_entry_size */
|
||||
0x0600, /* rb_profile_begin */
|
||||
0xFFF0, /* rb_profile_end */
|
||||
0xFE00, /* rb_profile_end */
|
||||
1, /* pt_mode_global */
|
||||
1, /* pt_mode_logbook */
|
||||
0, /* pt_mode_serial */
|
||||
|
||||
@ -37,7 +37,7 @@ dc_status_t
|
||||
oceanic_atom2_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
|
||||
|
||||
dc_status_t
|
||||
oceanic_atom2_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model, unsigned int serial);
|
||||
oceanic_atom2_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -62,7 +62,6 @@ struct oceanic_atom2_parser_t {
|
||||
double maxdepth;
|
||||
};
|
||||
|
||||
static dc_status_t oceanic_atom2_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -70,7 +69,6 @@ static dc_status_t oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract,
|
||||
static const dc_parser_vtable_t oceanic_atom2_parser_vtable = {
|
||||
sizeof(oceanic_atom2_parser_t),
|
||||
DC_FAMILY_OCEANIC_ATOM2,
|
||||
oceanic_atom2_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -82,7 +80,7 @@ static const dc_parser_vtable_t oceanic_atom2_parser_vtable = {
|
||||
|
||||
|
||||
dc_status_t
|
||||
oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial)
|
||||
oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial)
|
||||
{
|
||||
oceanic_atom2_parser_t *parser = NULL;
|
||||
|
||||
@ -90,7 +88,7 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (oceanic_atom2_parser_t *) dc_parser_allocate (context, &oceanic_atom2_parser_vtable);
|
||||
parser = (oceanic_atom2_parser_t *) dc_parser_allocate (context, &oceanic_atom2_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -157,28 +155,6 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
oceanic_atom2_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
oceanic_atom2_parser_t *parser = (oceanic_atom2_parser_t *) abstract;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->header = 0;
|
||||
parser->footer = 0;
|
||||
parser->mode = NORMAL;
|
||||
parser->ngasmixes = 0;
|
||||
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||
parser->oxygen[i] = 0;
|
||||
parser->helium[i] = 0;
|
||||
}
|
||||
parser->divetime = 0;
|
||||
parser->maxdepth = 0.0;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -524,6 +500,7 @@ oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns
|
||||
*((unsigned int *) value) = parser->ngasmixes;
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
gasmix->oxygen = parser->oxygen[flags] / 100.0;
|
||||
gasmix->helium = parser->helium[flags] / 100.0;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
@ -605,7 +582,7 @@ oceanic_atom2_parser_vendor (oceanic_atom2_parser_t *parser, const unsigned char
|
||||
sample.vendor.type = SAMPLE_VENDOR_OCEANIC_ATOM2;
|
||||
sample.vendor.size = length;
|
||||
sample.vendor.data = data + offset;
|
||||
if (callback) callback (DC_SAMPLE_VENDOR, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_VENDOR, &sample, userdata);
|
||||
|
||||
offset += length;
|
||||
}
|
||||
@ -627,8 +604,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
||||
|
||||
unsigned int extratime = 0;
|
||||
unsigned int time = 0;
|
||||
unsigned int interval = 1;
|
||||
unsigned int samplerate = 1;
|
||||
unsigned int interval = 1000;
|
||||
if (parser->mode != FREEDIVE) {
|
||||
unsigned int offset = 0x17;
|
||||
if (parser->model == A300CS || parser->model == VTX ||
|
||||
@ -636,21 +612,13 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
||||
parser->model == PROPLUSX || parser->model == I770R ||
|
||||
parser->model == SAGE || parser->model == BEACON)
|
||||
offset = 0x1f;
|
||||
const unsigned int intervals[] = {2, 15, 30, 60};
|
||||
const unsigned int intervals[] = {2000, 15000, 30000, 60000};
|
||||
unsigned int idx = data[offset] & 0x03;
|
||||
interval = intervals[idx];
|
||||
} else if (parser->model == F11A || parser->model == F11B) {
|
||||
const unsigned int intervals[] = {1, 1, 1, 2};
|
||||
const unsigned int samplerates[] = {4, 2, 1, 1};
|
||||
const unsigned int intervals[] = {250, 500, 1000, 2000};
|
||||
unsigned int idx = data[0x29] & 0x03;
|
||||
interval = intervals[idx];
|
||||
samplerate = samplerates[idx];
|
||||
if (samplerate > 1) {
|
||||
// Some models supports multiple samples per second.
|
||||
// Since our smallest unit of time is one second, we can't
|
||||
// represent this, and the extra samples will get dropped.
|
||||
WARNING(abstract->context, "Multiple samples per second are not supported!");
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int samplesize = PAGESIZE / 2;
|
||||
@ -771,14 +739,14 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
||||
// The surface time is not always a nice multiple of the samplerate.
|
||||
// The number of inserted surface samples is therefore rounded down
|
||||
// to keep the timestamps aligned at multiples of the samplerate.
|
||||
unsigned int surftime = 60 * bcd2dec (data[offset + 1]) + bcd2dec (data[offset + 2]);
|
||||
unsigned int surftime = (60 * bcd2dec (data[offset + 1]) + bcd2dec (data[offset + 2])) * 1000;
|
||||
unsigned int nsamples = surftime / interval;
|
||||
|
||||
for (unsigned int i = 0; i < nsamples; ++i) {
|
||||
// Time
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Vendor specific data
|
||||
if (i == 0) {
|
||||
@ -790,25 +758,18 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
||||
|
||||
// Depth
|
||||
sample.depth = 0.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
complete = 1;
|
||||
}
|
||||
|
||||
extratime += surftime;
|
||||
} else {
|
||||
// Skip the extra samples.
|
||||
if ((count % samplerate) != 0) {
|
||||
offset += samplesize;
|
||||
count++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Time.
|
||||
if (parser->model == I450T || parser->model == I470TC) {
|
||||
unsigned int minute = bcd2dec(data[offset + 0]);
|
||||
unsigned int hour = bcd2dec(data[offset + 1] & 0x0F);
|
||||
unsigned int second = bcd2dec(data[offset + 2]);
|
||||
unsigned int timestamp = (hour * 3600) + (minute * 60 ) + second + extratime;
|
||||
unsigned int timestamp = ((hour * 3600) + (minute * 60 ) + second) * 1000 + extratime;
|
||||
if (timestamp < time) {
|
||||
ERROR (abstract->context, "Timestamp moved backwards.");
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
@ -822,7 +783,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
||||
time += interval;
|
||||
}
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Vendor specific data
|
||||
oceanic_atom2_parser_vendor (parser,
|
||||
@ -884,7 +845,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
||||
temperature += (data[offset + 7] & 0x0C) >> 2;
|
||||
}
|
||||
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
}
|
||||
|
||||
// Tank Pressure (psi)
|
||||
@ -912,7 +873,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
||||
pressure -= data[offset + 1];
|
||||
sample.pressure.tank = tank;
|
||||
sample.pressure.value = pressure * PSI / BAR;
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
||||
}
|
||||
|
||||
// Depth (1/16 ft)
|
||||
@ -935,7 +896,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
||||
else
|
||||
depth = (data[offset + 2] + (data[offset + 3] << 8)) & 0x0FFF;
|
||||
sample.depth = depth / 16.0 * FEET;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Gas mix
|
||||
unsigned int have_gasmix = 0;
|
||||
@ -950,7 +911,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
sample.gasmix = gasmix - 1;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
gasmix_previous = gasmix;
|
||||
}
|
||||
|
||||
@ -999,7 +960,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
||||
sample.deco.depth = 0.0;
|
||||
}
|
||||
sample.deco.time = decotime * 60;
|
||||
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = 0;
|
||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
||||
}
|
||||
|
||||
unsigned int have_rbt = 0;
|
||||
@ -1022,7 +984,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
||||
}
|
||||
if (have_rbt) {
|
||||
sample.rbt = rbt;
|
||||
if (callback) callback (DC_SAMPLE_RBT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_RBT, &sample, userdata);
|
||||
}
|
||||
|
||||
// Bookmarks
|
||||
@ -1037,7 +999,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
||||
sample.event.time = 0;
|
||||
sample.event.flags = 0;
|
||||
sample.event.value = 0;
|
||||
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
@ -37,7 +37,7 @@ dc_status_t
|
||||
oceanic_veo250_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
oceanic_veo250_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||
oceanic_veo250_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -42,7 +42,6 @@ struct oceanic_veo250_parser_t {
|
||||
double maxdepth;
|
||||
};
|
||||
|
||||
static dc_status_t oceanic_veo250_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t oceanic_veo250_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t oceanic_veo250_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -50,7 +49,6 @@ static dc_status_t oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract,
|
||||
static const dc_parser_vtable_t oceanic_veo250_parser_vtable = {
|
||||
sizeof(oceanic_veo250_parser_t),
|
||||
DC_FAMILY_OCEANIC_VEO250,
|
||||
oceanic_veo250_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -62,7 +60,7 @@ static const dc_parser_vtable_t oceanic_veo250_parser_vtable = {
|
||||
|
||||
|
||||
dc_status_t
|
||||
oceanic_veo250_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||
oceanic_veo250_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
||||
{
|
||||
oceanic_veo250_parser_t *parser = NULL;
|
||||
|
||||
@ -70,7 +68,7 @@ oceanic_veo250_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (oceanic_veo250_parser_t *) dc_parser_allocate (context, &oceanic_veo250_parser_vtable);
|
||||
parser = (oceanic_veo250_parser_t *) dc_parser_allocate (context, &oceanic_veo250_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -88,20 +86,6 @@ oceanic_veo250_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
oceanic_veo250_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
oceanic_veo250_parser_t *parser = (oceanic_veo250_parser_t *) abstract;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->divetime = 0;
|
||||
parser->maxdepth = 0.0;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
oceanic_veo250_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -170,6 +154,7 @@ oceanic_veo250_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un
|
||||
*((unsigned int *) value) = 1;
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
gasmix->helium = 0.0;
|
||||
if (data[footer + 6])
|
||||
gasmix->oxygen = data[footer + 6] / 100.0;
|
||||
@ -230,19 +215,19 @@ oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
||||
|
||||
// Time.
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Vendor specific data
|
||||
sample.vendor.type = SAMPLE_VENDOR_OCEANIC_VEO250;
|
||||
sample.vendor.size = PAGESIZE / 2;
|
||||
sample.vendor.data = data + offset;
|
||||
if (callback) callback (DC_SAMPLE_VENDOR, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_VENDOR, &sample, userdata);
|
||||
|
||||
// Depth (ft)
|
||||
unsigned int depth = data[offset + 2];
|
||||
sample.depth = depth * FEET;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Temperature (°F)
|
||||
unsigned int temperature;
|
||||
@ -253,7 +238,7 @@ oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
||||
temperature = data[offset + 7];
|
||||
}
|
||||
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
|
||||
// NDL / Deco
|
||||
unsigned int have_deco = 0;
|
||||
@ -277,7 +262,8 @@ oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
||||
sample.deco.depth = 0.0;
|
||||
}
|
||||
sample.deco.time = decotime * 60;
|
||||
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = 0;
|
||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
||||
}
|
||||
|
||||
offset += PAGESIZE / 2;
|
||||
|
||||
@ -37,7 +37,7 @@ dc_status_t
|
||||
oceanic_vtpro_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
|
||||
|
||||
dc_status_t
|
||||
oceanic_vtpro_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
||||
oceanic_vtpro_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -42,7 +42,6 @@ struct oceanic_vtpro_parser_t {
|
||||
double maxdepth;
|
||||
};
|
||||
|
||||
static dc_status_t oceanic_vtpro_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t oceanic_vtpro_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t oceanic_vtpro_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -50,7 +49,6 @@ static dc_status_t oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract,
|
||||
static const dc_parser_vtable_t oceanic_vtpro_parser_vtable = {
|
||||
sizeof(oceanic_vtpro_parser_t),
|
||||
DC_FAMILY_OCEANIC_VTPRO,
|
||||
oceanic_vtpro_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -62,7 +60,7 @@ static const dc_parser_vtable_t oceanic_vtpro_parser_vtable = {
|
||||
|
||||
|
||||
dc_status_t
|
||||
oceanic_vtpro_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
||||
oceanic_vtpro_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model)
|
||||
{
|
||||
oceanic_vtpro_parser_t *parser = NULL;
|
||||
|
||||
@ -70,7 +68,7 @@ oceanic_vtpro_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (oceanic_vtpro_parser_t *) dc_parser_allocate (context, &oceanic_vtpro_parser_vtable);
|
||||
parser = (oceanic_vtpro_parser_t *) dc_parser_allocate (context, &oceanic_vtpro_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -88,20 +86,6 @@ oceanic_vtpro_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
oceanic_vtpro_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
oceanic_vtpro_parser_t *parser = (oceanic_vtpro_parser_t *) abstract;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->divetime = 0;
|
||||
parser->maxdepth = 0.0;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
oceanic_vtpro_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -200,6 +184,7 @@ oceanic_vtpro_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns
|
||||
*((unsigned int *) value) = 1;
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
gasmix->helium = 0.0;
|
||||
if (oxygen)
|
||||
gasmix->oxygen = oxygen / 100.0;
|
||||
@ -220,6 +205,7 @@ oceanic_vtpro_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns
|
||||
tank->gasmix = flags;
|
||||
tank->beginpressure = beginpressure * 2 * PSI / BAR;
|
||||
tank->endpressure = endpressure * 2 * PSI / BAR;
|
||||
tank->usage = DC_USAGE_NONE;
|
||||
break;
|
||||
default:
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
@ -331,14 +317,14 @@ oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
||||
time = timestamp * 60 + (i + 1) * interval;
|
||||
else
|
||||
time = timestamp * 60 + (i + 1) * 60.0 / count + 0.5;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Vendor specific data
|
||||
sample.vendor.type = SAMPLE_VENDOR_OCEANIC_VTPRO;
|
||||
sample.vendor.size = PAGESIZE / 2;
|
||||
sample.vendor.data = data + offset;
|
||||
if (callback) callback (DC_SAMPLE_VENDOR, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_VENDOR, &sample, userdata);
|
||||
|
||||
// Depth (ft)
|
||||
unsigned int depth = 0;
|
||||
@ -348,7 +334,7 @@ oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
||||
depth = data[offset + 3];
|
||||
}
|
||||
sample.depth = depth * FEET;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Temperature (°F)
|
||||
unsigned int temperature = 0;
|
||||
@ -358,7 +344,7 @@ oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
||||
temperature = data[offset + 6];
|
||||
}
|
||||
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
|
||||
// NDL / Deco
|
||||
if (parser->model != AERIS500AI) {
|
||||
@ -372,7 +358,8 @@ oceanic_vtpro_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
|
||||
sample.deco.depth = 0.0;
|
||||
}
|
||||
sample.deco.time = decotime * 60;
|
||||
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = 0;
|
||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
||||
}
|
||||
|
||||
offset += PAGESIZE / 2;
|
||||
|
||||
@ -36,7 +36,7 @@ dc_status_t
|
||||
oceans_s1_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
oceans_s1_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||
oceans_s1_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -58,7 +58,6 @@ struct oceans_s1_parser_t {
|
||||
unsigned int divetime;
|
||||
};
|
||||
|
||||
static dc_status_t oceans_s1_parser_set_data(dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t oceans_s1_parser_get_datetime(dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t oceans_s1_parser_get_field(dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t oceans_s1_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -66,7 +65,6 @@ static dc_status_t oceans_s1_parser_samples_foreach(dc_parser_t *abstract, dc_sa
|
||||
static const dc_parser_vtable_t oceans_s1_parser_vtable = {
|
||||
sizeof(oceans_s1_parser_t),
|
||||
DC_FAMILY_OCEANS_S1,
|
||||
oceans_s1_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -77,7 +75,7 @@ static const dc_parser_vtable_t oceans_s1_parser_vtable = {
|
||||
};
|
||||
|
||||
dc_status_t
|
||||
oceans_s1_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
oceans_s1_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
||||
{
|
||||
oceans_s1_parser_t *parser = NULL;
|
||||
|
||||
@ -85,7 +83,7 @@ oceans_s1_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (oceans_s1_parser_t *) dc_parser_allocate (context, &oceans_s1_parser_vtable);
|
||||
parser = (oceans_s1_parser_t *) dc_parser_allocate (context, &oceans_s1_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -105,23 +103,6 @@ oceans_s1_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
oceans_s1_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
oceans_s1_parser_t *parser = (oceans_s1_parser_t *) abstract;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->timestamp = 0;
|
||||
parser->number = 0;
|
||||
parser->divemode = 0;
|
||||
parser->oxygen = 0;
|
||||
parser->maxdepth = 0;
|
||||
parser->divetime = 0;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
oceans_s1_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -166,6 +147,7 @@ oceans_s1_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne
|
||||
*((unsigned int *) value) = parser->divemode == SCUBA;
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
gasmix->helium = 0.0;
|
||||
gasmix->oxygen = parser->oxygen / 100.0;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
@ -249,19 +231,19 @@ oceans_s1_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca
|
||||
unsigned int nsamples = seconds / interval;
|
||||
for (unsigned int i = 0; i < nsamples; ++i) {
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
sample.depth = 0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
}
|
||||
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
sample.depth = depth / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
} else if (strncmp(line, "enddive", 7) == 0) {
|
||||
if (sscanf(line, "enddive %u,%u", &maxdepth, &divetime) != 2) {
|
||||
ERROR (parser->base.context, "Failed to parse the line '%s'.", line);
|
||||
@ -280,14 +262,14 @@ oceans_s1_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca
|
||||
}
|
||||
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
sample.depth = depth / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
sample.temperature = temperature;
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
|
||||
if (events & EVENT_DECO_STOP) {
|
||||
sample.deco.type = DC_DECO_DECOSTOP;
|
||||
@ -298,7 +280,8 @@ oceans_s1_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca
|
||||
}
|
||||
sample.deco.depth = 0.0;
|
||||
sample.deco.time = 0;
|
||||
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = 0;
|
||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -41,7 +41,7 @@ typedef struct dc_parser_vtable_t dc_parser_vtable_t;
|
||||
struct dc_parser_t {
|
||||
const dc_parser_vtable_t *vtable;
|
||||
dc_context_t *context;
|
||||
const unsigned char *data;
|
||||
unsigned char *data;
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
@ -50,8 +50,6 @@ struct dc_parser_vtable_t {
|
||||
|
||||
dc_family_t type;
|
||||
|
||||
dc_status_t (*set_data) (dc_parser_t *parser, const unsigned char *data, unsigned int size);
|
||||
|
||||
dc_status_t (*set_clock) (dc_parser_t *parser, unsigned int devtime, dc_ticks_t systime);
|
||||
|
||||
dc_status_t (*set_atmospheric) (dc_parser_t *parser, double atmospheric);
|
||||
@ -68,7 +66,7 @@ struct dc_parser_vtable_t {
|
||||
};
|
||||
|
||||
dc_parser_t *
|
||||
dc_parser_allocate (dc_context_t *context, const dc_parser_vtable_t *vtable);
|
||||
dc_parser_allocate (dc_context_t *context, const dc_parser_vtable_t *vtable, const unsigned char data[], size_t size);
|
||||
|
||||
void
|
||||
dc_parser_deallocate (dc_parser_t *parser);
|
||||
@ -84,7 +82,7 @@ typedef struct sample_statistics_t {
|
||||
#define SAMPLE_STATISTICS_INITIALIZER {0, 0.0}
|
||||
|
||||
void
|
||||
sample_statistics_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata);
|
||||
sample_statistics_cb (dc_sample_type_t type, const dc_sample_value_t *value, void *userdata);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
166
src/parser.c
166
src/parser.c
@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "suunto_d9.h"
|
||||
@ -75,7 +76,7 @@
|
||||
#define REACTPROWHITE 0x4354
|
||||
|
||||
static dc_status_t
|
||||
dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t family, unsigned int model, unsigned int serial, unsigned int devtime, dc_ticks_t systime)
|
||||
dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, dc_family_t family, unsigned int model, unsigned int serial)
|
||||
{
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
dc_parser_t *parser = NULL;
|
||||
@ -85,126 +86,126 @@ dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t fa
|
||||
|
||||
switch (family) {
|
||||
case DC_FAMILY_SUUNTO_SOLUTION:
|
||||
rc = suunto_solution_parser_create (&parser, context);
|
||||
rc = suunto_solution_parser_create (&parser, context, data, size);
|
||||
break;
|
||||
case DC_FAMILY_SUUNTO_EON:
|
||||
rc = suunto_eon_parser_create (&parser, context, 0);
|
||||
rc = suunto_eon_parser_create (&parser, context, data, size, 0);
|
||||
break;
|
||||
case DC_FAMILY_SUUNTO_VYPER:
|
||||
if (model == 0x01)
|
||||
rc = suunto_eon_parser_create (&parser, context, 1);
|
||||
rc = suunto_eon_parser_create (&parser, context, data, size, 1);
|
||||
else
|
||||
rc = suunto_vyper_parser_create (&parser, context, serial);
|
||||
rc = suunto_vyper_parser_create (&parser, context, data, size, serial);
|
||||
break;
|
||||
case DC_FAMILY_SUUNTO_VYPER2:
|
||||
case DC_FAMILY_SUUNTO_D9:
|
||||
rc = suunto_d9_parser_create (&parser, context, model, serial);
|
||||
rc = suunto_d9_parser_create (&parser, context, data, size, model, serial);
|
||||
break;
|
||||
case DC_FAMILY_SUUNTO_EONSTEEL:
|
||||
rc = suunto_eonsteel_parser_create(&parser, context, model);
|
||||
rc = suunto_eonsteel_parser_create(&parser, context, data, size, model);
|
||||
break;
|
||||
case DC_FAMILY_UWATEC_ALADIN:
|
||||
case DC_FAMILY_UWATEC_MEMOMOUSE:
|
||||
rc = uwatec_memomouse_parser_create (&parser, context, devtime, systime);
|
||||
rc = uwatec_memomouse_parser_create (&parser, context, data, size);
|
||||
break;
|
||||
case DC_FAMILY_UWATEC_SMART:
|
||||
rc = uwatec_smart_parser_create (&parser, context, model);
|
||||
rc = uwatec_smart_parser_create (&parser, context, data, size, model);
|
||||
break;
|
||||
case DC_FAMILY_REEFNET_SENSUS:
|
||||
rc = reefnet_sensus_parser_create (&parser, context, devtime, systime);
|
||||
rc = reefnet_sensus_parser_create (&parser, context, data, size);
|
||||
break;
|
||||
case DC_FAMILY_REEFNET_SENSUSPRO:
|
||||
rc = reefnet_sensuspro_parser_create (&parser, context, devtime, systime);
|
||||
rc = reefnet_sensuspro_parser_create (&parser, context, data, size);
|
||||
break;
|
||||
case DC_FAMILY_REEFNET_SENSUSULTRA:
|
||||
rc = reefnet_sensusultra_parser_create (&parser, context, devtime, systime);
|
||||
rc = reefnet_sensusultra_parser_create (&parser, context, data, size);
|
||||
break;
|
||||
case DC_FAMILY_OCEANIC_VTPRO:
|
||||
rc = oceanic_vtpro_parser_create (&parser, context, model);
|
||||
rc = oceanic_vtpro_parser_create (&parser, context, data, size, model);
|
||||
break;
|
||||
case DC_FAMILY_OCEANIC_VEO250:
|
||||
rc = oceanic_veo250_parser_create (&parser, context, model);
|
||||
rc = oceanic_veo250_parser_create (&parser, context, data, size, model);
|
||||
break;
|
||||
case DC_FAMILY_OCEANIC_ATOM2:
|
||||
if (model == REACTPROWHITE)
|
||||
rc = oceanic_veo250_parser_create (&parser, context, model);
|
||||
rc = oceanic_veo250_parser_create (&parser, context, data, size, model);
|
||||
else
|
||||
rc = oceanic_atom2_parser_create (&parser, context, model, serial);
|
||||
rc = oceanic_atom2_parser_create (&parser, context, data, size, model, serial);
|
||||
break;
|
||||
case DC_FAMILY_MARES_NEMO:
|
||||
case DC_FAMILY_MARES_PUCK:
|
||||
rc = mares_nemo_parser_create (&parser, context, model);
|
||||
rc = mares_nemo_parser_create (&parser, context, data, size, model);
|
||||
break;
|
||||
case DC_FAMILY_MARES_DARWIN:
|
||||
rc = mares_darwin_parser_create (&parser, context, model);
|
||||
rc = mares_darwin_parser_create (&parser, context, data, size, model);
|
||||
break;
|
||||
case DC_FAMILY_MARES_ICONHD:
|
||||
rc = mares_iconhd_parser_create (&parser, context, model, serial);
|
||||
rc = mares_iconhd_parser_create (&parser, context, data, size, model, serial);
|
||||
break;
|
||||
case DC_FAMILY_HW_OSTC:
|
||||
rc = hw_ostc_parser_create (&parser, context, serial);
|
||||
rc = hw_ostc_parser_create (&parser, context, data, size, serial);
|
||||
break;
|
||||
case DC_FAMILY_HW_FROG:
|
||||
case DC_FAMILY_HW_OSTC3:
|
||||
rc = hw_ostc3_parser_create (&parser, context, serial, model);
|
||||
rc = hw_ostc3_parser_create (&parser, context, data, size, model, serial);
|
||||
break;
|
||||
case DC_FAMILY_CRESSI_EDY:
|
||||
case DC_FAMILY_ZEAGLE_N2ITION3:
|
||||
rc = cressi_edy_parser_create (&parser, context, model);
|
||||
rc = cressi_edy_parser_create (&parser, context, data, size, model);
|
||||
break;
|
||||
case DC_FAMILY_CRESSI_LEONARDO:
|
||||
rc = cressi_leonardo_parser_create (&parser, context, model);
|
||||
rc = cressi_leonardo_parser_create (&parser, context, data, size, model);
|
||||
break;
|
||||
case DC_FAMILY_CRESSI_GOA:
|
||||
rc = cressi_goa_parser_create (&parser, context, model);
|
||||
rc = cressi_goa_parser_create (&parser, context, data, size, model);
|
||||
break;
|
||||
case DC_FAMILY_ATOMICS_COBALT:
|
||||
rc = atomics_cobalt_parser_create (&parser, context);
|
||||
rc = atomics_cobalt_parser_create (&parser, context, data, size);
|
||||
break;
|
||||
case DC_FAMILY_SHEARWATER_PREDATOR:
|
||||
rc = shearwater_predator_parser_create (&parser, context, model, serial);
|
||||
rc = shearwater_predator_parser_create (&parser, context, data, size, model, serial);
|
||||
break;
|
||||
case DC_FAMILY_SHEARWATER_PETREL:
|
||||
rc = shearwater_petrel_parser_create (&parser, context, model, serial);
|
||||
rc = shearwater_petrel_parser_create (&parser, context, data, size, model, serial);
|
||||
break;
|
||||
case DC_FAMILY_DIVERITE_NITEKQ:
|
||||
rc = diverite_nitekq_parser_create (&parser, context);
|
||||
rc = diverite_nitekq_parser_create (&parser, context, data, size);
|
||||
break;
|
||||
case DC_FAMILY_CITIZEN_AQUALAND:
|
||||
rc = citizen_aqualand_parser_create (&parser, context);
|
||||
rc = citizen_aqualand_parser_create (&parser, context, data, size);
|
||||
break;
|
||||
case DC_FAMILY_DIVESYSTEM_IDIVE:
|
||||
rc = divesystem_idive_parser_create (&parser, context, model);
|
||||
rc = divesystem_idive_parser_create (&parser, context, data, size, model);
|
||||
break;
|
||||
case DC_FAMILY_COCHRAN_COMMANDER:
|
||||
rc = cochran_commander_parser_create (&parser, context, model);
|
||||
rc = cochran_commander_parser_create (&parser, context, data, size, model);
|
||||
break;
|
||||
case DC_FAMILY_TECDIVING_DIVECOMPUTEREU:
|
||||
rc = tecdiving_divecomputereu_parser_create (&parser, context);
|
||||
rc = tecdiving_divecomputereu_parser_create (&parser, context, data, size);
|
||||
break;
|
||||
case DC_FAMILY_MCLEAN_EXTREME:
|
||||
rc = mclean_extreme_parser_create (&parser, context);
|
||||
rc = mclean_extreme_parser_create (&parser, context, data, size);
|
||||
break;
|
||||
case DC_FAMILY_LIQUIVISION_LYNX:
|
||||
rc = liquivision_lynx_parser_create (&parser, context, model);
|
||||
rc = liquivision_lynx_parser_create (&parser, context, data, size, model);
|
||||
break;
|
||||
case DC_FAMILY_SPORASUB_SP2:
|
||||
rc = sporasub_sp2_parser_create (&parser, context);
|
||||
rc = sporasub_sp2_parser_create (&parser, context, data, size);
|
||||
break;
|
||||
case DC_FAMILY_DEEPSIX_EXCURSION:
|
||||
rc = deepsix_excursion_parser_create (&parser, context);
|
||||
rc = deepsix_excursion_parser_create (&parser, context, data, size);
|
||||
break;
|
||||
case DC_FAMILY_SEAC_SCREEN:
|
||||
rc = seac_screen_parser_create (&parser, context);
|
||||
rc = seac_screen_parser_create (&parser, context, data, size);
|
||||
break;
|
||||
case DC_FAMILY_DEEPBLU_COSMIQ:
|
||||
rc = deepblu_cosmiq_parser_create (&parser, context);
|
||||
rc = deepblu_cosmiq_parser_create (&parser, context, data, size);
|
||||
break;
|
||||
case DC_FAMILY_OCEANS_S1:
|
||||
rc = oceans_s1_parser_create (&parser, context);
|
||||
rc = oceans_s1_parser_create (&parser, context, data, size);
|
||||
break;
|
||||
case DC_FAMILY_DIVESOFT_FREEDOM:
|
||||
rc = divesoft_freedom_parser_create (&parser, context);
|
||||
rc = divesoft_freedom_parser_create (&parser, context, data, size);
|
||||
break;
|
||||
default:
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
@ -221,30 +222,42 @@ dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t fa
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
dc_parser_new (dc_parser_t **out, dc_device_t *device)
|
||||
dc_parser_new (dc_parser_t **out, dc_device_t *device, const unsigned char data[], size_t size)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_parser_t *parser = NULL;
|
||||
|
||||
if (device == NULL)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
return dc_parser_new_internal (out, device->context,
|
||||
dc_device_get_type (device),
|
||||
device->devinfo.model,
|
||||
device->devinfo.serial,
|
||||
device->clock.devtime, device->clock.systime);
|
||||
status = dc_parser_new_internal (&parser, device->context, data, size,
|
||||
dc_device_get_type (device), device->devinfo.model, 0);
|
||||
if (status != DC_STATUS_SUCCESS)
|
||||
goto error_exit;
|
||||
|
||||
status = dc_parser_set_clock (parser, device->clock.devtime, device->clock.systime);
|
||||
if (status != DC_STATUS_SUCCESS && status != DC_STATUS_UNSUPPORTED)
|
||||
goto error_free;
|
||||
|
||||
*out = parser;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
|
||||
error_free:
|
||||
dc_parser_deallocate (parser);
|
||||
error_exit:
|
||||
return status;
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
dc_parser_new2 (dc_parser_t **out, dc_context_t *context, dc_descriptor_t *descriptor, unsigned int devtime, dc_ticks_t systime)
|
||||
dc_parser_new2 (dc_parser_t **out, dc_context_t *context, dc_descriptor_t *descriptor, const unsigned char data[], size_t size)
|
||||
{
|
||||
return dc_parser_new_internal (out, context,
|
||||
dc_descriptor_get_type (descriptor),
|
||||
dc_descriptor_get_model (descriptor),
|
||||
0,
|
||||
devtime, systime);
|
||||
return dc_parser_new_internal (out, context, data, size,
|
||||
dc_descriptor_get_type (descriptor), dc_descriptor_get_model (descriptor), 0);
|
||||
}
|
||||
|
||||
dc_parser_t *
|
||||
dc_parser_allocate (dc_context_t *context, const dc_parser_vtable_t *vtable)
|
||||
dc_parser_allocate (dc_context_t *context, const dc_parser_vtable_t *vtable, const unsigned char data[], size_t size)
|
||||
{
|
||||
dc_parser_t *parser = NULL;
|
||||
|
||||
@ -261,15 +274,34 @@ dc_parser_allocate (dc_context_t *context, const dc_parser_vtable_t *vtable)
|
||||
// Initialize the base class.
|
||||
parser->vtable = vtable;
|
||||
parser->context = context;
|
||||
parser->data = NULL;
|
||||
parser->size = 0;
|
||||
|
||||
if (size) {
|
||||
// Allocate memory for the data.
|
||||
parser->data = malloc (size);
|
||||
if (parser->data == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
free (parser);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Copy the data.
|
||||
memcpy (parser->data, data, size);
|
||||
parser->size = size;
|
||||
} else {
|
||||
parser->data = NULL;
|
||||
parser->size = 0;
|
||||
|
||||
}
|
||||
return parser;
|
||||
}
|
||||
|
||||
void
|
||||
dc_parser_deallocate (dc_parser_t *parser)
|
||||
{
|
||||
if (parser == NULL)
|
||||
return;
|
||||
|
||||
free (parser->data);
|
||||
free (parser);
|
||||
}
|
||||
|
||||
@ -332,22 +364,6 @@ dc_parser_set_density (dc_parser_t *parser, double density)
|
||||
}
|
||||
|
||||
|
||||
dc_status_t
|
||||
dc_parser_set_data (dc_parser_t *parser, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
if (parser == NULL)
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
|
||||
if (parser->vtable->set_data == NULL)
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
|
||||
parser->data = data;
|
||||
parser->size = size;
|
||||
|
||||
return parser->vtable->set_data (parser, data, size);
|
||||
}
|
||||
|
||||
|
||||
dc_status_t
|
||||
dc_parser_get_datetime (dc_parser_t *parser, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -405,17 +421,17 @@ dc_parser_destroy (dc_parser_t *parser)
|
||||
|
||||
|
||||
void
|
||||
sample_statistics_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata)
|
||||
sample_statistics_cb (dc_sample_type_t type, const dc_sample_value_t *value, void *userdata)
|
||||
{
|
||||
sample_statistics_t *statistics = (sample_statistics_t *) userdata;
|
||||
|
||||
switch (type) {
|
||||
case DC_SAMPLE_TIME:
|
||||
statistics->divetime = value.time;
|
||||
statistics->divetime = value->time / 1000;
|
||||
break;
|
||||
case DC_SAMPLE_DEPTH:
|
||||
if (statistics->maxdepth < value.depth)
|
||||
statistics->maxdepth = value.depth;
|
||||
if (statistics->maxdepth < value->depth)
|
||||
statistics->maxdepth = value->depth;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@ -36,7 +36,7 @@ dc_status_t
|
||||
reefnet_sensus_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
reefnet_sensus_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int devtime, dc_ticks_t systime);
|
||||
reefnet_sensus_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -48,7 +48,6 @@ struct reefnet_sensus_parser_t {
|
||||
unsigned int maxdepth;
|
||||
};
|
||||
|
||||
static dc_status_t reefnet_sensus_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t reefnet_sensus_parser_set_clock (dc_parser_t *abstract, unsigned int devtime, dc_ticks_t systime);
|
||||
static dc_status_t reefnet_sensus_parser_set_atmospheric (dc_parser_t *abstract, double atmospheric);
|
||||
static dc_status_t reefnet_sensus_parser_set_density (dc_parser_t *abstract, double density);
|
||||
@ -59,7 +58,6 @@ static dc_status_t reefnet_sensus_parser_samples_foreach (dc_parser_t *abstract,
|
||||
static const dc_parser_vtable_t reefnet_sensus_parser_vtable = {
|
||||
sizeof(reefnet_sensus_parser_t),
|
||||
DC_FAMILY_REEFNET_SENSUS,
|
||||
reefnet_sensus_parser_set_data, /* set_data */
|
||||
reefnet_sensus_parser_set_clock, /* set_clock */
|
||||
reefnet_sensus_parser_set_atmospheric, /* set_atmospheric */
|
||||
reefnet_sensus_parser_set_density, /* set_density */
|
||||
@ -71,7 +69,7 @@ static const dc_parser_vtable_t reefnet_sensus_parser_vtable = {
|
||||
|
||||
|
||||
dc_status_t
|
||||
reefnet_sensus_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int devtime, dc_ticks_t systime)
|
||||
reefnet_sensus_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
||||
{
|
||||
reefnet_sensus_parser_t *parser = NULL;
|
||||
|
||||
@ -79,7 +77,7 @@ reefnet_sensus_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (reefnet_sensus_parser_t *) dc_parser_allocate (context, &reefnet_sensus_parser_vtable);
|
||||
parser = (reefnet_sensus_parser_t *) dc_parser_allocate (context, &reefnet_sensus_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -88,8 +86,8 @@ reefnet_sensus_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
|
||||
// Set the default values.
|
||||
parser->atmospheric = DEF_ATMOSPHERIC;
|
||||
parser->hydrostatic = DEF_DENSITY_SALT * GRAVITY;
|
||||
parser->devtime = devtime;
|
||||
parser->systime = systime;
|
||||
parser->devtime = 0;
|
||||
parser->systime = 0;
|
||||
parser->cached = 0;
|
||||
parser->divetime = 0;
|
||||
parser->maxdepth = 0;
|
||||
@ -100,35 +98,6 @@ reefnet_sensus_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
reefnet_sensus_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
reefnet_sensus_parser_t *parser = (reefnet_sensus_parser_t*) abstract;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->divetime = 0;
|
||||
parser->maxdepth = 0;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
dc_status_t
|
||||
reefnet_sensus_parser_set_calibration (dc_parser_t *abstract, double atmospheric, double hydrostatic)
|
||||
{
|
||||
reefnet_sensus_parser_t *parser = (reefnet_sensus_parser_t*) abstract;
|
||||
|
||||
if (!ISINSTANCE (abstract))
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
parser->atmospheric = atmospheric;
|
||||
parser->hydrostatic = hydrostatic;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
reefnet_sensus_parser_set_clock (dc_parser_t *abstract, unsigned int devtime, dc_ticks_t systime)
|
||||
{
|
||||
@ -279,13 +248,13 @@ reefnet_sensus_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
||||
|
||||
// Time (seconds)
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Depth (adjusted feet of seawater).
|
||||
unsigned int depth = data[offset++];
|
||||
sample.depth = ((depth + 33.0 - (double) SAMPLE_DEPTH_ADJUST) * FSW - parser->atmospheric) / parser->hydrostatic;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Temperature (degrees Fahrenheit)
|
||||
if ((nsamples % 6) == 0) {
|
||||
@ -293,7 +262,7 @@ reefnet_sensus_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
unsigned int temperature = data[offset++];
|
||||
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
}
|
||||
|
||||
// Current sample is complete.
|
||||
|
||||
@ -36,7 +36,7 @@ dc_status_t
|
||||
reefnet_sensuspro_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
reefnet_sensuspro_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int devtime, dc_ticks_t systime);
|
||||
reefnet_sensuspro_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -47,7 +47,6 @@ struct reefnet_sensuspro_parser_t {
|
||||
unsigned int maxdepth;
|
||||
};
|
||||
|
||||
static dc_status_t reefnet_sensuspro_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t reefnet_sensuspro_parser_set_clock (dc_parser_t *abstract, unsigned int devtime, dc_ticks_t systime);
|
||||
static dc_status_t reefnet_sensuspro_parser_set_atmospheric (dc_parser_t *abstract, double atmospheric);
|
||||
static dc_status_t reefnet_sensuspro_parser_set_density (dc_parser_t *abstract, double density);
|
||||
@ -58,7 +57,6 @@ static dc_status_t reefnet_sensuspro_parser_samples_foreach (dc_parser_t *abstra
|
||||
static const dc_parser_vtable_t reefnet_sensuspro_parser_vtable = {
|
||||
sizeof(reefnet_sensuspro_parser_t),
|
||||
DC_FAMILY_REEFNET_SENSUSPRO,
|
||||
reefnet_sensuspro_parser_set_data, /* set_data */
|
||||
reefnet_sensuspro_parser_set_clock, /* set_clock */
|
||||
reefnet_sensuspro_parser_set_atmospheric, /* set_atmospheric */
|
||||
reefnet_sensuspro_parser_set_density, /* set_density */
|
||||
@ -70,7 +68,7 @@ static const dc_parser_vtable_t reefnet_sensuspro_parser_vtable = {
|
||||
|
||||
|
||||
dc_status_t
|
||||
reefnet_sensuspro_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int devtime, dc_ticks_t systime)
|
||||
reefnet_sensuspro_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
||||
{
|
||||
reefnet_sensuspro_parser_t *parser = NULL;
|
||||
|
||||
@ -78,7 +76,7 @@ reefnet_sensuspro_parser_create (dc_parser_t **out, dc_context_t *context, unsig
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (reefnet_sensuspro_parser_t *) dc_parser_allocate (context, &reefnet_sensuspro_parser_vtable);
|
||||
parser = (reefnet_sensuspro_parser_t *) dc_parser_allocate (context, &reefnet_sensuspro_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -87,8 +85,8 @@ reefnet_sensuspro_parser_create (dc_parser_t **out, dc_context_t *context, unsig
|
||||
// Set the default values.
|
||||
parser->atmospheric = DEF_ATMOSPHERIC;
|
||||
parser->hydrostatic = DEF_DENSITY_SALT * GRAVITY;
|
||||
parser->devtime = devtime;
|
||||
parser->systime = systime;
|
||||
parser->devtime = 0;
|
||||
parser->systime = 0;
|
||||
parser->cached = 0;
|
||||
parser->divetime = 0;
|
||||
parser->maxdepth = 0;
|
||||
@ -99,35 +97,6 @@ reefnet_sensuspro_parser_create (dc_parser_t **out, dc_context_t *context, unsig
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
reefnet_sensuspro_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
reefnet_sensuspro_parser_t *parser = (reefnet_sensuspro_parser_t*) abstract;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->divetime = 0;
|
||||
parser->maxdepth = 0;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
dc_status_t
|
||||
reefnet_sensuspro_parser_set_calibration (dc_parser_t *abstract, double atmospheric, double hydrostatic)
|
||||
{
|
||||
reefnet_sensuspro_parser_t *parser = (reefnet_sensuspro_parser_t*) abstract;
|
||||
|
||||
if (!ISINSTANCE (abstract))
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
parser->atmospheric = atmospheric;
|
||||
parser->hydrostatic = hydrostatic;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
reefnet_sensuspro_parser_set_clock (dc_parser_t *abstract, unsigned int devtime, dc_ticks_t systime)
|
||||
{
|
||||
@ -278,16 +247,16 @@ reefnet_sensuspro_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callb
|
||||
|
||||
// Time (seconds)
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Temperature (°F)
|
||||
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
|
||||
// Depth (absolute pressure in fsw)
|
||||
sample.depth = (depth * FSW - parser->atmospheric) / parser->hydrostatic;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@ dc_status_t
|
||||
reefnet_sensusultra_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
reefnet_sensusultra_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int devtime, dc_ticks_t systime);
|
||||
reefnet_sensusultra_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -47,7 +47,6 @@ struct reefnet_sensusultra_parser_t {
|
||||
unsigned int maxdepth;
|
||||
};
|
||||
|
||||
static dc_status_t reefnet_sensusultra_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t reefnet_sensusultra_parser_set_clock (dc_parser_t *abstract, unsigned int devtime, dc_ticks_t systime);
|
||||
static dc_status_t reefnet_sensusultra_parser_set_atmospheric (dc_parser_t *abstract, double atmospheric);
|
||||
static dc_status_t reefnet_sensusultra_parser_set_density (dc_parser_t *abstract, double density);
|
||||
@ -58,7 +57,6 @@ static dc_status_t reefnet_sensusultra_parser_samples_foreach (dc_parser_t *abst
|
||||
static const dc_parser_vtable_t reefnet_sensusultra_parser_vtable = {
|
||||
sizeof(reefnet_sensusultra_parser_t),
|
||||
DC_FAMILY_REEFNET_SENSUSULTRA,
|
||||
reefnet_sensusultra_parser_set_data, /* set_data */
|
||||
reefnet_sensusultra_parser_set_clock, /* set_clock */
|
||||
reefnet_sensusultra_parser_set_atmospheric, /* set_atmospheric */
|
||||
reefnet_sensusultra_parser_set_density, /* set_density */
|
||||
@ -70,7 +68,7 @@ static const dc_parser_vtable_t reefnet_sensusultra_parser_vtable = {
|
||||
|
||||
|
||||
dc_status_t
|
||||
reefnet_sensusultra_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int devtime, dc_ticks_t systime)
|
||||
reefnet_sensusultra_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
||||
{
|
||||
reefnet_sensusultra_parser_t *parser = NULL;
|
||||
|
||||
@ -78,7 +76,7 @@ reefnet_sensusultra_parser_create (dc_parser_t **out, dc_context_t *context, uns
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (reefnet_sensusultra_parser_t *) dc_parser_allocate (context, &reefnet_sensusultra_parser_vtable);
|
||||
parser = (reefnet_sensusultra_parser_t *) dc_parser_allocate (context, &reefnet_sensusultra_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -87,8 +85,8 @@ reefnet_sensusultra_parser_create (dc_parser_t **out, dc_context_t *context, uns
|
||||
// Set the default values.
|
||||
parser->atmospheric = DEF_ATMOSPHERIC;
|
||||
parser->hydrostatic = DEF_DENSITY_SALT * GRAVITY;
|
||||
parser->devtime = devtime;
|
||||
parser->systime = systime;
|
||||
parser->devtime = 0;
|
||||
parser->systime = 0;
|
||||
parser->cached = 0;
|
||||
parser->divetime = 0;
|
||||
parser->maxdepth = 0;
|
||||
@ -99,35 +97,6 @@ reefnet_sensusultra_parser_create (dc_parser_t **out, dc_context_t *context, uns
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
reefnet_sensusultra_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
reefnet_sensusultra_parser_t *parser = (reefnet_sensusultra_parser_t*) abstract;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->divetime = 0;
|
||||
parser->maxdepth = 0;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
dc_status_t
|
||||
reefnet_sensusultra_parser_set_calibration (dc_parser_t *abstract, double atmospheric, double hydrostatic)
|
||||
{
|
||||
reefnet_sensusultra_parser_t *parser = (reefnet_sensusultra_parser_t*) abstract;
|
||||
|
||||
if (!ISINSTANCE (abstract))
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
parser->atmospheric = atmospheric;
|
||||
parser->hydrostatic = hydrostatic;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
reefnet_sensusultra_parser_set_clock (dc_parser_t *abstract, unsigned int devtime, dc_ticks_t systime)
|
||||
{
|
||||
@ -275,18 +244,18 @@ reefnet_sensusultra_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
||||
|
||||
// Time (seconds)
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Temperature (0.01 °K)
|
||||
unsigned int temperature = array_uint16_le (data + offset);
|
||||
sample.temperature = temperature / 100.0 - 273.15;
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
|
||||
// Depth (absolute pressure in millibar)
|
||||
unsigned int depth = array_uint16_le (data + offset + 2);
|
||||
sample.depth = (depth * BAR / 1000.0 - parser->atmospheric) / parser->hydrostatic;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
offset += 4;
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ dc_status_t
|
||||
seac_screen_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
seac_screen_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||
seac_screen_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -48,7 +48,6 @@ struct seac_screen_parser_t {
|
||||
unsigned int gf_high;
|
||||
};
|
||||
|
||||
static dc_status_t seac_screen_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t seac_screen_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t seac_screen_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t seac_screen_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -56,7 +55,6 @@ static dc_status_t seac_screen_parser_samples_foreach (dc_parser_t *abstract, dc
|
||||
static const dc_parser_vtable_t seac_screen_parser_vtable = {
|
||||
sizeof(seac_screen_parser_t),
|
||||
DC_FAMILY_SEAC_SCREEN,
|
||||
seac_screen_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -67,7 +65,7 @@ static const dc_parser_vtable_t seac_screen_parser_vtable = {
|
||||
};
|
||||
|
||||
dc_status_t
|
||||
seac_screen_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
seac_screen_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
||||
{
|
||||
seac_screen_parser_t *parser = NULL;
|
||||
|
||||
@ -75,7 +73,7 @@ seac_screen_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (seac_screen_parser_t *) dc_parser_allocate (context, &seac_screen_parser_vtable);
|
||||
parser = (seac_screen_parser_t *) dc_parser_allocate (context, &seac_screen_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -95,23 +93,6 @@ seac_screen_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
seac_screen_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
seac_screen_parser_t *parser = (seac_screen_parser_t *)abstract;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->ngasmixes = 0;
|
||||
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||
parser->oxygen[i] = 0;
|
||||
}
|
||||
parser->gf_low = 0;
|
||||
parser->gf_high = 0;
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
seac_screen_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -239,6 +220,7 @@ seac_screen_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsig
|
||||
*((unsigned int *)value) = parser->ngasmixes;
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->usage = DC_USAGE_NONE;
|
||||
gasmix->helium = 0.0;
|
||||
gasmix->oxygen = parser->oxygen[flags] / 100.0;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
@ -331,16 +313,16 @@ seac_screen_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
time = timestamp;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Depth (1/100 m).
|
||||
sample.depth = depth / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Temperature (1/100 °C).
|
||||
sample.temperature = temperature / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
|
||||
// Gas mix
|
||||
if (o2 != o2_previous) {
|
||||
@ -363,7 +345,7 @@ seac_screen_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
}
|
||||
|
||||
sample.gasmix = idx;
|
||||
if (callback) callback(DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback(DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
o2_previous = o2;
|
||||
}
|
||||
|
||||
@ -377,11 +359,12 @@ seac_screen_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
sample.deco.time = ndl_tts;
|
||||
sample.deco.depth = 0;
|
||||
}
|
||||
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = 0;
|
||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
||||
|
||||
// CNS
|
||||
sample.cns = cns / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_CNS, &sample, userdata);
|
||||
|
||||
// Deco model
|
||||
if (gf_low == 0 && gf_high == 0) {
|
||||
|
||||
@ -57,7 +57,6 @@
|
||||
#include "context-private.h"
|
||||
#include "iostream-private.h"
|
||||
#include "iterator-private.h"
|
||||
#include "descriptor-private.h"
|
||||
#include "platform.h"
|
||||
#include "timer.h"
|
||||
|
||||
@ -230,7 +229,7 @@ dc_serial_iterator_next (dc_iterator_t *abstract, void *out)
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_SERIAL, filename, NULL)) {
|
||||
if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_SERIAL, filename)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@ -31,7 +31,6 @@
|
||||
#include "context-private.h"
|
||||
#include "iostream-private.h"
|
||||
#include "iterator-private.h"
|
||||
#include "descriptor-private.h"
|
||||
#include "platform.h"
|
||||
|
||||
static dc_status_t dc_serial_iterator_next (dc_iterator_t *iterator, void *item);
|
||||
@ -228,7 +227,7 @@ dc_serial_iterator_next (dc_iterator_t *abstract, void *out)
|
||||
// Null terminate the string.
|
||||
data[data_len] = 0;
|
||||
|
||||
if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_SERIAL, data, NULL)) {
|
||||
if (!dc_descriptor_filter (iterator->descriptor, DC_TRANSPORT_SERIAL, data)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@ -36,10 +36,13 @@
|
||||
#define ESC_END 0xDC
|
||||
#define ESC_ESC 0xDD
|
||||
|
||||
// SIDs for CAN WDBI (Write Data By Identifier) as defined by ISO 14229-1
|
||||
// (the RDBI command is implemented in shearwater_common_identifier)
|
||||
#define CAN_WDBI_REQUEST_SID 0x2E
|
||||
#define CAN_WDBI_RESPONSE_SID 0x6E
|
||||
#define RDBI_REQUEST 0x22
|
||||
#define RDBI_RESPONSE 0x62
|
||||
|
||||
#define WDBI_REQUEST 0x2E
|
||||
#define WDBI_RESPONSE 0x6E
|
||||
|
||||
#define NAK 0x7F
|
||||
|
||||
dc_status_t
|
||||
shearwater_common_setup (shearwater_common_device_t *device, dc_context_t *context, dc_iostream_t *iostream)
|
||||
@ -90,7 +93,7 @@ shearwater_common_decompress_lre (unsigned char *data, unsigned int size, dc_buf
|
||||
|
||||
// The 9th bit indicates whether the remaining 8 bits represent
|
||||
// a run of zero bytes or not. If the bit is set, the value is
|
||||
// not a run and doesn’t need expansion. If the bit is not set,
|
||||
// not a run and doesn't need expansion. If the bit is not set,
|
||||
// the value contains the number of zero bytes in the run. A
|
||||
// zero-length run indicates the end of the compressed stream.
|
||||
if (value & 0x100) {
|
||||
@ -517,195 +520,237 @@ shearwater_common_download (shearwater_common_device_t *device, dc_buffer_t *buf
|
||||
|
||||
|
||||
dc_status_t
|
||||
shearwater_common_identifier (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int id)
|
||||
shearwater_common_rdbi (shearwater_common_device_t *device, unsigned int id, unsigned char data[], unsigned int size)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Erase the buffer.
|
||||
if (!dc_buffer_clear (buffer)) {
|
||||
ERROR (abstract->context, "Insufficient buffer space available.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
// Transfer the request.
|
||||
unsigned int n = 0;
|
||||
unsigned char request[] = {0x22,
|
||||
unsigned char request[] = {
|
||||
RDBI_REQUEST,
|
||||
(id >> 8) & 0xFF,
|
||||
(id ) & 0xFF};
|
||||
unsigned char response[SZ_PACKET];
|
||||
rc = shearwater_common_transfer (device, request, sizeof (request), response, sizeof (response), &n);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
return rc;
|
||||
status = shearwater_common_transfer (device, request, sizeof (request), response, sizeof (response), &n);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
// Verify the response.
|
||||
if (n < 3 || response[0] != 0x62 || response[1] != request[1] || response[2] != request[2]) {
|
||||
if (n < 3 || response[0] != RDBI_RESPONSE || response[1] != request[1] || response[2] != request[2]) {
|
||||
if (n == 3 && response[0] == NAK && response[1] == RDBI_REQUEST) {
|
||||
ERROR (abstract->context, "Received NAK packet with error code 0x%02x.", response[2]);
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
ERROR (abstract->context, "Unexpected response packet.");
|
||||
return DC_STATUS_PROTOCOL;
|
||||
}
|
||||
|
||||
// Append the packet to the output buffer.
|
||||
if (!dc_buffer_append (buffer, response + 3, n - 3)) {
|
||||
ERROR (abstract->context, "Insufficient buffer space available.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
dc_status_t shearwater_common_can_wdbi (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int id)
|
||||
{
|
||||
dc_device_t *abstract = (dc_device_t *)device;
|
||||
|
||||
unsigned n = 0;
|
||||
char request_header[] = {
|
||||
CAN_WDBI_REQUEST_SID,
|
||||
(id >> 8) & 0xFF,
|
||||
id & 0xFF
|
||||
};
|
||||
if (!dc_buffer_prepend(buffer, request_header, sizeof(request_header))) {
|
||||
ERROR(abstract->context, "Insufficient buffer space available.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
char response[SZ_PACKET];
|
||||
dc_status_t rc = shearwater_common_transfer(device, dc_buffer_get_data(buffer), dc_buffer_get_size(buffer), response, sizeof(response), &n);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Verify the response.
|
||||
if (n < 3 || response[0] != CAN_WDBI_RESPONSE_SID || response[1] != request_header[1] || response[2] != request_header[2]) {
|
||||
ERROR(abstract->context, "Unexpected response packet.");
|
||||
unsigned int length = n - 3;
|
||||
|
||||
if (length != size) {
|
||||
ERROR (abstract->context, "Unexpected packet size (%u bytes).", length);
|
||||
return DC_STATUS_PROTOCOL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
if (length) {
|
||||
memcpy (data, response + 3, length);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
dc_status_t shearwater_common_device_timesync(dc_device_t *abstract, const dc_datetime_t *datetime)
|
||||
dc_status_t
|
||||
shearwater_common_wdbi (shearwater_common_device_t *device, unsigned int id, const unsigned char data[], unsigned int size)
|
||||
{
|
||||
shearwater_common_device_t *device = (shearwater_common_device_t *)abstract;
|
||||
|
||||
dc_datetime_t local_time;
|
||||
memcpy(&local_time, datetime, sizeof(local_time));
|
||||
|
||||
// We need to supply a unix timestamp in _local_ time
|
||||
local_time.timezone = DC_TIMEZONE_NONE;
|
||||
|
||||
dc_ticks_t unix_timestamp = dc_datetime_mktime(&local_time);
|
||||
if (unix_timestamp == -1) {
|
||||
ERROR(abstract->context, "Invalid date/time value specified.");
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
if (size + 3 > SZ_PACKET) {
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
}
|
||||
|
||||
dc_buffer_t *buffer = dc_buffer_new(WDBI_TIME_PACKET_SIZE);
|
||||
if (buffer == NULL) {
|
||||
ERROR(abstract->context, "Insufficient buffer space available.");
|
||||
dc_buffer_free(buffer);
|
||||
|
||||
return DC_STATUS_NOMEMORY;
|
||||
// Transfer the request.
|
||||
unsigned int n = 0;
|
||||
unsigned char request[SZ_PACKET] = {
|
||||
WDBI_REQUEST,
|
||||
(id >> 8) & 0xFF,
|
||||
(id ) & 0xFF};
|
||||
if (size) {
|
||||
memcpy (request + 3, data, size);
|
||||
}
|
||||
unsigned char response[SZ_PACKET];
|
||||
status = shearwater_common_transfer (device, request, size + 3, response, sizeof (response), &n);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
char shearwater_timestamp[] = {
|
||||
(unix_timestamp >> 24) & 0xFF,
|
||||
(unix_timestamp >> 16) & 0xFF,
|
||||
(unix_timestamp >> 8) & 0xFF,
|
||||
unix_timestamp & 0xFF,
|
||||
};
|
||||
dc_buffer_append(buffer, shearwater_timestamp, 4);
|
||||
|
||||
dc_status_t rc = shearwater_common_can_wdbi(device, buffer, ID_LOCAL_TIME);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR(abstract->context, "Failed to write the dive computer time.");
|
||||
// Verify the response.
|
||||
if (n < 3 || response[0] != WDBI_RESPONSE || response[1] != request[1] || response[2] != request[2]) {
|
||||
if (n == 3 && response[0] == NAK && response[1] == WDBI_REQUEST) {
|
||||
ERROR (abstract->context, "Received NAK packet with error code 0x%02x.", response[2]);
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
}
|
||||
ERROR (abstract->context, "Unexpected response packet.");
|
||||
return DC_STATUS_PROTOCOL;
|
||||
}
|
||||
|
||||
dc_buffer_free(buffer);
|
||||
|
||||
return rc;
|
||||
return status;
|
||||
}
|
||||
|
||||
dc_status_t shearwater_common_read_model(shearwater_common_device_t *device, unsigned int *model)
|
||||
dc_status_t
|
||||
shearwater_common_timesync_local (shearwater_common_device_t *device, const dc_datetime_t *datetime)
|
||||
{
|
||||
dc_buffer_t *buffer = dc_buffer_new(SZ_PACKET);
|
||||
if (buffer == NULL) {
|
||||
ERROR(device->base.context, "Insufficient buffer space available.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Convert to local time.
|
||||
dc_datetime_t local = *datetime;
|
||||
local.timezone = DC_TIMEZONE_NONE;
|
||||
|
||||
dc_ticks_t ticks = dc_datetime_mktime (&local);
|
||||
if (ticks == -1) {
|
||||
ERROR (abstract->context, "Invalid date/time value specified.");
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
}
|
||||
|
||||
// Read the hardware type.
|
||||
dc_status_t rc = shearwater_common_identifier(device, buffer, ID_HARDWARE);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR(device->base.context, "Failed to read the hardware type.");
|
||||
dc_buffer_free(buffer);
|
||||
const unsigned char timestamp[] = {
|
||||
(ticks >> 24) & 0xFF,
|
||||
(ticks >> 16) & 0xFF,
|
||||
(ticks >> 8) & 0xFF,
|
||||
(ticks ) & 0xFF,
|
||||
};
|
||||
|
||||
return rc;
|
||||
status = shearwater_common_wdbi (device, ID_TIME_LOCAL, timestamp, sizeof(timestamp));
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to write the dive computer local time.");
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
dc_status_t
|
||||
shearwater_common_timesync_utc (shearwater_common_device_t *device, const dc_datetime_t *datetime)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
dc_device_t *abstract = (dc_device_t *) device;
|
||||
|
||||
// Convert to UTC time.
|
||||
dc_ticks_t ticks = dc_datetime_mktime (datetime);
|
||||
if (ticks == -1) {
|
||||
ERROR (abstract->context, "Invalid date/time value specified.");
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
}
|
||||
|
||||
const unsigned char timestamp[] = {
|
||||
(ticks >> 24) & 0xFF,
|
||||
(ticks >> 16) & 0xFF,
|
||||
(ticks >> 8) & 0xFF,
|
||||
(ticks ) & 0xFF,
|
||||
};
|
||||
|
||||
status = shearwater_common_wdbi (device, ID_TIME_UTC, timestamp, sizeof(timestamp));
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to write the dive computer UTC time.");
|
||||
return status;
|
||||
}
|
||||
|
||||
int timezone = datetime->timezone / 60;
|
||||
const unsigned char offset[] = {
|
||||
(timezone >> 24) & 0xFF,
|
||||
(timezone >> 16) & 0xFF,
|
||||
(timezone >> 8) & 0xFF,
|
||||
(timezone ) & 0xFF,
|
||||
};
|
||||
|
||||
status = shearwater_common_wdbi (device, ID_TIME_OFFSET, offset, sizeof (offset));
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to write the dive computer timezone offset.");
|
||||
return status;
|
||||
}
|
||||
|
||||
// We don't have a way to determine the daylight savings time setting,
|
||||
// but the required offset is already factored into the timezone offset.
|
||||
const unsigned char dst[] = {0, 0, 0, 0};
|
||||
|
||||
status = shearwater_common_wdbi (device, ID_TIME_DST, dst, sizeof (dst));
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to write the dive computer DST setting.");
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
dc_status_t shearwater_common_get_model(shearwater_common_device_t *device, unsigned int *model)
|
||||
{
|
||||
// Read the hardware type.
|
||||
unsigned char rsp_hardware[2] = {0};
|
||||
status = shearwater_common_rdbi (device, ID_HARDWARE, rsp_hardware, sizeof(rsp_hardware));
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to read the hardware type.");
|
||||
return status;
|
||||
}
|
||||
|
||||
// Convert and map to the model number.
|
||||
unsigned int hardware = array_uint_be(dc_buffer_get_data(buffer), dc_buffer_get_size(buffer));
|
||||
unsigned int hardware = array_uint16_be (rsp_hardware);
|
||||
switch (hardware) {
|
||||
case 0x0101:
|
||||
case 0x0202:
|
||||
*model = PREDATOR;
|
||||
break;
|
||||
case 0x0606:
|
||||
case 0x0A0A: // Nerd 1
|
||||
*model = NERD;
|
||||
break;
|
||||
case 0x7E2D:
|
||||
case 0x0E0D: // Nerd 2
|
||||
*model = NERD2;
|
||||
model = PREDATOR;
|
||||
break;
|
||||
case 0x0404:
|
||||
case 0x0909: // Petrel 1
|
||||
*model = PETREL;
|
||||
case 0x0909:
|
||||
model = PETREL;
|
||||
break;
|
||||
case 0x0505:
|
||||
case 0x0808:
|
||||
case 0x0838:
|
||||
case 0x08A5:
|
||||
case 0x0B0B:
|
||||
case 0x7828:
|
||||
case 0x7B2C:
|
||||
case 0x8838: // Petrel 2
|
||||
case 0x0B0B: // current docs (June 2023) imply this is a Petrel 2
|
||||
*model = PETREL;
|
||||
case 0x8838:
|
||||
model = PETREL2;
|
||||
break;
|
||||
case 0xB407: // Petrel 3
|
||||
*model = PETREL3;
|
||||
case 0xB407:
|
||||
model = PETREL3;
|
||||
break;
|
||||
case 0x0707: // Perdix
|
||||
*model = PERDIX;
|
||||
case 0x0606:
|
||||
case 0x0A0A:
|
||||
model = NERD;
|
||||
break;
|
||||
case 0x0C0C: // current docs (June 2023) imply this is not a valid hardware ID
|
||||
case 0x0C0D: // current docs (June 2023) show this as Perdix AI
|
||||
case 0x0D0D: // current docs (June 2023) imply this is not a valid hardware ID
|
||||
case 0x7C2D: // Perdix AI
|
||||
case 0x0E0D:
|
||||
case 0x7E2D:
|
||||
model = NERD2;
|
||||
break;
|
||||
case 0x0707:
|
||||
model = PERDIX;
|
||||
break;
|
||||
case 0x0C0D:
|
||||
case 0x7C2D:
|
||||
case 0x8D6C:
|
||||
*model = PERDIXAI;
|
||||
model = PERDIXAI;
|
||||
break;
|
||||
case 0xC407: // Perdix 2
|
||||
*model = PERDIX2;
|
||||
case 0xC407:
|
||||
model = PERDIX2;
|
||||
break;
|
||||
case 0x0F0F:
|
||||
case 0x1F0A:
|
||||
case 0x1F0F:
|
||||
*model = TERIC;
|
||||
model = TERIC;
|
||||
break;
|
||||
case 0x1512:
|
||||
*model = PEREGRINE;
|
||||
case 0x1512:
|
||||
model = PEREGRINE;
|
||||
break;
|
||||
case 0xC0E0:
|
||||
model = TERN;
|
||||
break;
|
||||
default:
|
||||
// return a model of 0 which is unknown
|
||||
WARNING(device->base.context, "Unknown hardware type %04x. Assuming Petrel.", hardware);
|
||||
WARNING (device->base.context, "Unknown hardware type 0x%04x.", hardware);
|
||||
}
|
||||
|
||||
dc_buffer_free(buffer);
|
||||
|
||||
return rc;
|
||||
return model;
|
||||
}
|
||||
|
||||
@ -41,6 +41,11 @@ extern "C" {
|
||||
|
||||
#define WDBI_TIME_PACKET_SIZE 7
|
||||
|
||||
#define ID_TIME_LOCAL 0x9030
|
||||
#define ID_TIME_UTC 0x9031
|
||||
#define ID_TIME_OFFSET 0x9032
|
||||
#define ID_TIME_DST 0x9033
|
||||
|
||||
#define PREDATOR 2
|
||||
#define PETREL 3
|
||||
#define PETREL2 PETREL
|
||||
@ -52,6 +57,7 @@ extern "C" {
|
||||
#define PEREGRINE 9
|
||||
#define PETREL3 10
|
||||
#define PERDIX2 11
|
||||
#define TERN 12
|
||||
|
||||
#define NSTEPS 10000
|
||||
#define STEP(i,n) ((NSTEPS * (i) + (n) / 2) / (n))
|
||||
@ -71,7 +77,19 @@ dc_status_t
|
||||
shearwater_common_download (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int address, unsigned int size, unsigned int compression, dc_event_progress_t *progress);
|
||||
|
||||
dc_status_t
|
||||
shearwater_common_identifier (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int id);
|
||||
shearwater_common_rdbi (shearwater_common_device_t *device, unsigned int id, unsigned char data[], unsigned int size);
|
||||
|
||||
dc_status_t
|
||||
shearwater_common_wdbi (shearwater_common_device_t *device, unsigned int id, const unsigned char data[], unsigned int size);
|
||||
|
||||
dc_status_t
|
||||
shearwater_common_timesync_local (shearwater_common_device_t *device, const dc_datetime_t *datetime);
|
||||
|
||||
dc_status_t
|
||||
shearwater_common_timesync_utc (shearwater_common_device_t *device, const dc_datetime_t *datetime);
|
||||
|
||||
unsigned int
|
||||
shearwater_common_get_model (shearwater_common_device_t *device, unsigned int hardware);
|
||||
|
||||
dc_status_t shearwater_common_can_wdbi (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int id);
|
||||
|
||||
|
||||
@ -45,80 +45,9 @@ typedef struct shearwater_petrel_device_t {
|
||||
} shearwater_petrel_device_t;
|
||||
|
||||
|
||||
static dc_status_t shearwater_petrel_device_timesync(dc_device_t *abstract, const dc_datetime_t *datetime)
|
||||
{
|
||||
shearwater_common_device_t *device = (shearwater_common_device_t *)abstract;
|
||||
|
||||
unsigned int model = 0;
|
||||
shearwater_common_read_model(device, &model);
|
||||
if (model == TERIC) {
|
||||
dc_ticks_t unix_timestamp = dc_datetime_mktime(datetime);
|
||||
if (unix_timestamp == -1) {
|
||||
ERROR(abstract->context, "Invalid date/time value specified.");
|
||||
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
}
|
||||
|
||||
dc_buffer_t *buffer = dc_buffer_new(WDBI_TIME_PACKET_SIZE);
|
||||
if (buffer == NULL) {
|
||||
ERROR(abstract->context, "Insufficient buffer space available.");
|
||||
dc_buffer_free(buffer);
|
||||
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
char shearwater_timestamp[] = {
|
||||
(unix_timestamp >> 24) & 0xFF,
|
||||
(unix_timestamp >> 16) & 0xFF,
|
||||
(unix_timestamp >> 8) & 0xFF,
|
||||
unix_timestamp & 0xFF,
|
||||
};
|
||||
dc_buffer_append(buffer, shearwater_timestamp, 4);
|
||||
|
||||
dc_status_t rc = shearwater_common_can_wdbi(device, buffer, ID_UTC_TIME);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR(abstract->context, "Failed to write the dive computer UTC time.");
|
||||
}
|
||||
|
||||
dc_buffer_clear(buffer);
|
||||
|
||||
int local_time_offset_minutes = datetime->timezone / 60;
|
||||
char shearwater_local_time_offset[] = {
|
||||
(local_time_offset_minutes >> 24) & 0xFF,
|
||||
(local_time_offset_minutes >> 16) & 0xFF,
|
||||
(local_time_offset_minutes >> 8) & 0xFF,
|
||||
local_time_offset_minutes & 0xFF,
|
||||
};
|
||||
dc_buffer_append(buffer, shearwater_local_time_offset, 4);
|
||||
|
||||
rc = shearwater_common_can_wdbi(device, buffer, ID_LOCAL_TIME_OFFSET);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR(abstract->context, "Failed to write the dive computer local time offset.");
|
||||
}
|
||||
|
||||
dc_buffer_clear(buffer);
|
||||
|
||||
// We don't have a way to determine the daylight savings time setting,
|
||||
// but the required offset is already factored into ID_LOCAL_TIME_OFFSET
|
||||
char shearwater_local_time_dst[] = { 0, 0, 0, 0 };
|
||||
dc_buffer_append(buffer, shearwater_local_time_dst, 4);
|
||||
|
||||
rc = shearwater_common_can_wdbi(device, buffer, ID_LOCAL_TIME_DST);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR(abstract->context, "Failed to write the dive computer DST setting.");
|
||||
}
|
||||
|
||||
dc_buffer_free(buffer);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
return shearwater_common_device_timesync(abstract, datetime);
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t shearwater_petrel_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
|
||||
static dc_status_t shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata);
|
||||
static dc_status_t shearwater_petrel_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime);
|
||||
static dc_status_t shearwater_petrel_device_close (dc_device_t *abstract);
|
||||
|
||||
static const dc_device_vtable_t shearwater_petrel_device_vtable = {
|
||||
@ -225,55 +154,43 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
|
||||
shearwater_petrel_device_t *device = (shearwater_petrel_device_t *) abstract;
|
||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||
|
||||
// Allocate memory buffers for the manifests.
|
||||
dc_buffer_t *buffer = dc_buffer_new (MANIFEST_SIZE);
|
||||
dc_buffer_t *manifests = dc_buffer_new (MANIFEST_SIZE);
|
||||
if (buffer == NULL || manifests == NULL) {
|
||||
ERROR (abstract->context, "Insufficient buffer space available.");
|
||||
dc_buffer_free (buffer);
|
||||
dc_buffer_free (manifests);
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
// Enable progress notifications.
|
||||
unsigned int current = 0, maximum = 0;
|
||||
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
|
||||
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
|
||||
|
||||
// Read the serial number.
|
||||
rc = shearwater_common_identifier (&device->base, buffer, ID_SERIAL);
|
||||
unsigned char rsp_serial[8] = {0};
|
||||
rc = shearwater_common_rdbi (&device->base, ID_SERIAL, rsp_serial, sizeof(rsp_serial));
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to read the serial number.");
|
||||
dc_buffer_free (buffer);
|
||||
dc_buffer_free (manifests);
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Convert to a number.
|
||||
unsigned char serial[4] = {0};
|
||||
if (array_convert_hex2bin (dc_buffer_get_data (buffer), dc_buffer_get_size (buffer),
|
||||
serial, sizeof (serial)) != 0 ) {
|
||||
if (array_convert_hex2bin (rsp_serial, sizeof(rsp_serial), serial, sizeof (serial)) != 0 ) {
|
||||
ERROR (abstract->context, "Failed to convert the serial number.");
|
||||
dc_buffer_free (buffer);
|
||||
dc_buffer_free (manifests);
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
|
||||
}
|
||||
|
||||
// Read the firmware version.
|
||||
rc = shearwater_common_identifier (&device->base, buffer, ID_FIRMWARE);
|
||||
unsigned char rsp_firmware[11] = {0};
|
||||
rc = shearwater_common_rdbi (&device->base, ID_FIRMWARE, rsp_firmware, sizeof(rsp_firmware));
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to read the firmware version.");
|
||||
dc_buffer_free (buffer);
|
||||
dc_buffer_free (manifests);
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Convert to a number.
|
||||
unsigned int firmware = str2num (dc_buffer_get_data (buffer), dc_buffer_get_size (buffer), 1);
|
||||
unsigned int firmware = str2num (rsp_firmware, sizeof(rsp_firmware), 1);
|
||||
|
||||
unsigned int model = 0;
|
||||
shearwater_common_read_model((shearwater_common_device_t *)device, &model);
|
||||
rc = shearwater_common_get_model (&device->base, &model);
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to read the hardware type.");
|
||||
return rc;
|
||||
}
|
||||
|
||||
// Emit a device info event.
|
||||
dc_event_devinfo_t devinfo;
|
||||
@ -283,22 +200,14 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
|
||||
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);
|
||||
|
||||
// Read the logbook type
|
||||
rc = shearwater_common_identifier (&device->base, buffer, ID_LOGUPLOAD);
|
||||
unsigned char rsp_logupload[9] = {0};
|
||||
rc = shearwater_common_rdbi (&device->base, ID_LOGUPLOAD, rsp_logupload, sizeof(rsp_logupload));
|
||||
if (rc != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to read the logbook type.");
|
||||
dc_buffer_free (buffer);
|
||||
dc_buffer_free (manifests);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (dc_buffer_get_size (buffer) != 9) {
|
||||
ERROR (abstract->context, "Unexpected packet size (" DC_PRINTF_SIZE " bytes).", dc_buffer_get_size(buffer));
|
||||
dc_buffer_free (buffer);
|
||||
dc_buffer_free (manifests);
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
|
||||
unsigned int base_addr = array_uint32_be (dc_buffer_get_data (buffer) + 1);
|
||||
unsigned int base_addr = array_uint32_be (rsp_logupload + 1);
|
||||
switch (base_addr) {
|
||||
case 0xDD000000: // Predator - we shouldn't get here, we could give up or we can try 0xC0000000
|
||||
case 0xC0000000: // Predator-Like Format (what we used to call the Petrel format)
|
||||
@ -311,9 +220,17 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
|
||||
break;
|
||||
default: // unknown format
|
||||
ERROR (abstract->context, "Unknown logbook format %08x", base_addr);
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
|
||||
// Allocate memory buffers for the manifests.
|
||||
dc_buffer_t *buffer = dc_buffer_new (MANIFEST_SIZE);
|
||||
dc_buffer_t *manifests = dc_buffer_new (MANIFEST_SIZE);
|
||||
if (buffer == NULL || manifests == NULL) {
|
||||
ERROR (abstract->context, "Insufficient buffer space available.");
|
||||
dc_buffer_free (buffer);
|
||||
dc_buffer_free (manifests);
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
return DC_STATUS_NOMEMORY;
|
||||
}
|
||||
|
||||
// Read the manifest pages
|
||||
@ -430,3 +347,23 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
shearwater_petrel_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime)
|
||||
{
|
||||
dc_status_t status = DC_STATUS_SUCCESS;
|
||||
shearwater_common_device_t *device = (shearwater_common_device_t *) abstract;
|
||||
|
||||
unsigned int model = 0;
|
||||
status = shearwater_common_get_model (&device->base, &model);
|
||||
if (status != DC_STATUS_SUCCESS) {
|
||||
ERROR (abstract->context, "Failed to read the hardware type.");
|
||||
return status;
|
||||
}
|
||||
|
||||
if (model == TERIC) {
|
||||
return shearwater_common_timesync_utc (device, datetime);
|
||||
} else {
|
||||
return shearwater_common_timesync_local (device, datetime);
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ dc_status_t
|
||||
shearwater_petrel_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
shearwater_petrel_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model, unsigned int serial);
|
||||
shearwater_petrel_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -44,6 +44,7 @@ typedef struct shearwater_predator_device_t {
|
||||
static dc_status_t shearwater_predator_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
|
||||
static dc_status_t shearwater_predator_device_dump (dc_device_t *abstract, dc_buffer_t *buffer);
|
||||
static dc_status_t shearwater_predator_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata);
|
||||
static dc_status_t shearwater_predator_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime);
|
||||
|
||||
static const dc_device_vtable_t shearwater_predator_device_vtable = {
|
||||
sizeof(shearwater_predator_device_t),
|
||||
@ -53,7 +54,7 @@ static const dc_device_vtable_t shearwater_predator_device_vtable = {
|
||||
NULL, /* write */
|
||||
shearwater_predator_device_dump, /* dump */
|
||||
shearwater_predator_device_foreach, /* foreach */
|
||||
shearwater_common_device_timesync,
|
||||
shearwater_predator_device_timesync,
|
||||
NULL /* close */
|
||||
};
|
||||
|
||||
@ -357,3 +358,9 @@ shearwater_predator_extract_dives (dc_device_t *abstract, const unsigned char da
|
||||
return shearwater_predator_extract_predator (abstract, data, size, callback, userdata);
|
||||
}
|
||||
}
|
||||
|
||||
static dc_status_t
|
||||
shearwater_predator_device_timesync (dc_device_t *abstract, const dc_datetime_t *datetime)
|
||||
{
|
||||
return shearwater_common_timesync_local ((shearwater_common_device_t *) abstract, datetime);
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ dc_status_t
|
||||
shearwater_predator_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
shearwater_predator_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model, unsigned int serial);
|
||||
shearwater_predator_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -109,6 +109,8 @@ typedef struct shearwater_predator_gasmix_t {
|
||||
unsigned int oxygen;
|
||||
unsigned int helium;
|
||||
unsigned int diluent;
|
||||
unsigned int enabled;
|
||||
unsigned int active;
|
||||
} shearwater_predator_gasmix_t;
|
||||
|
||||
typedef struct shearwater_predator_tank_t {
|
||||
@ -121,6 +123,7 @@ typedef struct shearwater_predator_tank_t {
|
||||
unsigned int serial;
|
||||
char name[2];
|
||||
unsigned int battery;
|
||||
dc_usage_t usage;
|
||||
} shearwater_predator_tank_t;
|
||||
|
||||
struct shearwater_predator_parser_t {
|
||||
@ -143,8 +146,10 @@ struct shearwater_predator_parser_t {
|
||||
shearwater_predator_tank_t tank[NTANKS];
|
||||
unsigned int tankidx[NTANKS];
|
||||
unsigned int aimode;
|
||||
unsigned int hpccr;
|
||||
unsigned int calibrated;
|
||||
double calibration[3];
|
||||
unsigned int divemode;
|
||||
unsigned int serial;
|
||||
unsigned int units;
|
||||
unsigned int atmospheric;
|
||||
@ -154,7 +159,6 @@ struct shearwater_predator_parser_t {
|
||||
struct dc_field_cache cache;
|
||||
};
|
||||
|
||||
static dc_status_t shearwater_predator_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t shearwater_predator_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -164,7 +168,6 @@ static dc_status_t shearwater_predator_parser_cache (shearwater_predator_parser_
|
||||
static const dc_parser_vtable_t shearwater_predator_parser_vtable = {
|
||||
sizeof(shearwater_predator_parser_t),
|
||||
DC_FAMILY_SHEARWATER_PREDATOR,
|
||||
shearwater_predator_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -177,7 +180,6 @@ static const dc_parser_vtable_t shearwater_predator_parser_vtable = {
|
||||
static const dc_parser_vtable_t shearwater_petrel_parser_vtable = {
|
||||
sizeof(shearwater_predator_parser_t),
|
||||
DC_FAMILY_SHEARWATER_PETREL,
|
||||
shearwater_predator_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -188,6 +190,12 @@ static const dc_parser_vtable_t shearwater_petrel_parser_vtable = {
|
||||
};
|
||||
|
||||
|
||||
static unsigned int
|
||||
shearwater_predator_is_ccr (unsigned int divemode)
|
||||
{
|
||||
return divemode == M_CC || divemode == M_CC2 || divemode == M_SC;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
shearwater_predator_find_gasmix (shearwater_predator_parser_t *parser, unsigned int o2, unsigned int he, unsigned int dil)
|
||||
{
|
||||
@ -203,7 +211,7 @@ shearwater_predator_find_gasmix (shearwater_predator_parser_t *parser, unsigned
|
||||
|
||||
|
||||
static dc_status_t
|
||||
shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial, unsigned int petrel)
|
||||
shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int petrel, unsigned int serial)
|
||||
{
|
||||
shearwater_predator_parser_t *parser = NULL;
|
||||
const dc_parser_vtable_t *vtable = NULL;
|
||||
@ -221,7 +229,7 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig
|
||||
}
|
||||
|
||||
// Allocate memory.
|
||||
parser = (shearwater_predator_parser_t *) dc_parser_allocate (context, vtable);
|
||||
parser = (shearwater_predator_parser_t *) dc_parser_allocate (context, vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -249,6 +257,8 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig
|
||||
parser->gasmix[i].oxygen = 0;
|
||||
parser->gasmix[i].helium = 0;
|
||||
parser->gasmix[i].diluent = 0;
|
||||
parser->gasmix[i].enabled = 0;
|
||||
parser->gasmix[i].active = 0;
|
||||
}
|
||||
parser->ntanks = 0;
|
||||
for (unsigned int i = 0; i < NTANKS; ++i) {
|
||||
@ -261,9 +271,11 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig
|
||||
parser->tank[i].serial = 0;
|
||||
memset (parser->tank[i].name, 0, sizeof (parser->tank[i].name));
|
||||
parser->tank[i].battery = 0;
|
||||
parser->tank[i].usage = DC_USAGE_NONE;
|
||||
parser->tankidx[i] = i;
|
||||
}
|
||||
parser->aimode = AI_OFF;
|
||||
parser->hpccr = 0;
|
||||
parser->calibrated = 0;
|
||||
for (unsigned int i = 0; i < 3; ++i) {
|
||||
parser->calibration[i] = 0.0;
|
||||
@ -281,65 +293,16 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig
|
||||
|
||||
|
||||
dc_status_t
|
||||
shearwater_predator_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial)
|
||||
shearwater_predator_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial)
|
||||
{
|
||||
return shearwater_common_parser_create (out, context, model, serial, 0);
|
||||
return shearwater_common_parser_create (out, context, data, size, model, 0, serial);
|
||||
}
|
||||
|
||||
|
||||
dc_status_t
|
||||
shearwater_petrel_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial)
|
||||
shearwater_petrel_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size, unsigned int model, unsigned int serial)
|
||||
{
|
||||
return shearwater_common_parser_create (out, context, model, serial, 1);
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
shearwater_predator_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
shearwater_predator_parser_t *parser = (shearwater_predator_parser_t *) abstract;
|
||||
|
||||
// Reset the cache.
|
||||
parser->cached = 0;
|
||||
parser->pnf = 0;
|
||||
parser->logversion = 0;
|
||||
parser->headersize = 0;
|
||||
parser->footersize = 0;
|
||||
for (unsigned int i = 0; i < NRECORDS; ++i) {
|
||||
parser->opening[i] = UNDEFINED;
|
||||
parser->closing[i] = UNDEFINED;
|
||||
}
|
||||
parser->final = UNDEFINED;
|
||||
parser->ngasmixes = 0;
|
||||
for (unsigned int i = 0; i < NGASMIXES; ++i) {
|
||||
parser->gasmix[i].oxygen = 0;
|
||||
parser->gasmix[i].helium = 0;
|
||||
parser->gasmix[i].diluent = 0;
|
||||
}
|
||||
parser->ntanks = 0;
|
||||
for (unsigned int i = 0; i < NTANKS; ++i) {
|
||||
parser->tank[i].enabled = 0;
|
||||
parser->tank[i].active = 0;
|
||||
parser->tank[i].beginpressure = 0;
|
||||
parser->tank[i].endpressure = 0;
|
||||
parser->tank[i].pressure_max = 0;
|
||||
parser->tank[i].pressure_reserve = 0;
|
||||
parser->tank[i].serial = 0;
|
||||
memset (parser->tank[i].name, 0, sizeof (parser->tank[i].name));
|
||||
parser->tankidx[i] = i;
|
||||
}
|
||||
parser->aimode = AI_OFF;
|
||||
parser->calibrated = 0;
|
||||
for (unsigned int i = 0; i < 3; ++i) {
|
||||
parser->calibration[i] = 0.0;
|
||||
}
|
||||
parser->units = METRIC;
|
||||
parser->density = DEF_DENSITY_SALT;
|
||||
parser->atmospheric = DEF_ATMOSPHERIC / (BAR / 1000);
|
||||
|
||||
DC_ASSIGN_FIELD(parser->cache, DIVEMODE, DC_DIVEMODE_OC);
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
return shearwater_common_parser_create (out, context, data, size, model, 1, serial);
|
||||
}
|
||||
|
||||
|
||||
@ -522,11 +485,13 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
||||
shearwater_predator_tank_t tank[NTANKS] = {0};
|
||||
unsigned int o2_previous = UNDEFINED, he_previous = UNDEFINED, dil_previous = UNDEFINED;
|
||||
unsigned int aimode = AI_OFF;
|
||||
unsigned int hpccr = 0;
|
||||
if (!pnf) {
|
||||
for (unsigned int i = 0; i < NFIXED; ++i) {
|
||||
gasmix[i].oxygen = data[20 + i];
|
||||
gasmix[i].helium = data[30 + i];
|
||||
gasmix[i].diluent = i >= 5;
|
||||
gasmix[i].enabled = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -575,6 +540,8 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
||||
ngasmixes = idx + 1;
|
||||
}
|
||||
|
||||
gasmix[idx].active = 1;
|
||||
|
||||
o2_previous = o2;
|
||||
he_previous = he;
|
||||
dil_previous = ccr;
|
||||
@ -636,8 +603,8 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
||||
tank[id].enabled = 1;
|
||||
tank[id].beginpressure = pressure;
|
||||
tank[id].endpressure = pressure;
|
||||
tank[id].name[0] = i == 0 ? 'D': 'O';
|
||||
tank[id].name[1] = 0;
|
||||
tank[id].usage = i == 0 ? DC_USAGE_DILUENT : DC_USAGE_OXYGEN;
|
||||
hpccr = 1;
|
||||
}
|
||||
tank[id].endpressure = pressure;
|
||||
}
|
||||
@ -681,9 +648,24 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
||||
if (aimode == AI_HPCCR) {
|
||||
for (unsigned int i = 0; i < 2; ++i) {
|
||||
tank[4 + i].enabled = 1;
|
||||
tank[4 + i].name[0] = i == 0 ? 'D': 'O';
|
||||
tank[4 + i].name[1] = 0;
|
||||
tank[4 + i].usage = i == 0 ? DC_USAGE_DILUENT : DC_USAGE_OXYGEN;
|
||||
}
|
||||
hpccr = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gas mix on/off state.
|
||||
unsigned int state = array_uint16_be (data + offset + 17);
|
||||
for (unsigned int i = 0; i < NFIXED; ++i) {
|
||||
gasmix[i].enabled = (state & (1 << i)) != 0;
|
||||
}
|
||||
|
||||
unsigned int gtrmode = data[offset + 29];
|
||||
if (popcount(gtrmode) >= 2) {
|
||||
for (unsigned int i = 0; i < 4; ++i) {
|
||||
if (gtrmode & (1 << i)) {
|
||||
tank[i].usage = DC_USAGE_SIDEMOUNT;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -809,6 +791,10 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
||||
for (unsigned int i = 0; i < ngasmixes; ++i) {
|
||||
if (gasmix[i].oxygen == 0 && gasmix[i].helium == 0)
|
||||
continue;
|
||||
if (!gasmix[i].enabled && !gasmix[i].active)
|
||||
continue;
|
||||
if (gasmix[i].diluent && !shearwater_predator_is_ccr (divemode))
|
||||
continue;
|
||||
parser->gasmix[parser->ngasmixes] = gasmix[i];
|
||||
parser->ngasmixes++;
|
||||
}
|
||||
@ -824,6 +810,8 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
||||
}
|
||||
}
|
||||
parser->aimode = aimode;
|
||||
parser->hpccr = hpccr;
|
||||
parser->divemode = divemode;
|
||||
parser->units = data[parser->opening[0] + 8];
|
||||
parser->atmospheric = array_uint16_be (data + parser->opening[1] + (parser->pnf ? 16 : 47));
|
||||
parser->density = array_uint16_be (data + parser->opening[3] + (parser->pnf ? 3 : 83));
|
||||
@ -907,6 +895,7 @@ shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ
|
||||
*((unsigned int *) value) = parser->ngasmixes;
|
||||
break;
|
||||
case DC_FIELD_GASMIX:
|
||||
gasmix->usage = parser->gasmix[flags].diluent ? DC_USAGE_DILUENT : DC_USAGE_NONE;
|
||||
gasmix->oxygen = parser->gasmix[flags].oxygen / 100.0;
|
||||
gasmix->helium = parser->gasmix[flags].helium / 100.0;
|
||||
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
|
||||
@ -921,6 +910,21 @@ shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ
|
||||
tank->beginpressure = parser->tank[flags].beginpressure * 2 * PSI / BAR;
|
||||
tank->endpressure = parser->tank[flags].endpressure * 2 * PSI / BAR;
|
||||
tank->gasmix = DC_GASMIX_UNKNOWN;
|
||||
if (shearwater_predator_is_ccr (parser->divemode) && !parser->hpccr) {
|
||||
switch (parser->tank[flags].name[0]) {
|
||||
case 'O':
|
||||
tank->usage = DC_USAGE_OXYGEN;
|
||||
break;
|
||||
case 'D':
|
||||
tank->usage = DC_USAGE_DILUENT;
|
||||
break;
|
||||
default:
|
||||
tank->usage = DC_USAGE_NONE;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
tank->usage = parser->tank[flags].usage;
|
||||
}
|
||||
break;
|
||||
case DC_FIELD_SALINITY:
|
||||
if (parser->density == 1000)
|
||||
@ -984,14 +988,9 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
||||
|
||||
// Sample interval.
|
||||
unsigned int time = 0;
|
||||
unsigned int interval = 10;
|
||||
unsigned int interval = 10000;
|
||||
if (parser->pnf && parser->logversion >= 9 && parser->opening[5] != UNDEFINED) {
|
||||
interval = array_uint16_be (data + parser->opening[5] + 23);
|
||||
if (interval % 1000 != 0) {
|
||||
ERROR (abstract->context, "Unsupported sample interval (%u ms).", interval);
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
interval /= 1000;
|
||||
}
|
||||
|
||||
unsigned int pnf = parser->pnf;
|
||||
@ -1017,7 +1016,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
||||
// Time (seconds).
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Depth (1/10 m or ft).
|
||||
unsigned int depth = array_uint16_be (data + pnf + offset);
|
||||
@ -1025,7 +1024,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
||||
sample.depth = depth * FEET / 10.0;
|
||||
else
|
||||
sample.depth = depth / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Temperature (°C or °F).
|
||||
int temperature = (signed char) data[offset + pnf + 13];
|
||||
@ -1040,7 +1039,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
||||
sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
|
||||
else
|
||||
sample.temperature = temperature;
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
|
||||
// Status flags.
|
||||
unsigned int status = data[offset + pnf + 11];
|
||||
@ -1049,19 +1048,21 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
||||
if (ccr) {
|
||||
// PPO2
|
||||
if ((status & PPO2_EXTERNAL) == 0) {
|
||||
if (!parser->calibrated) {
|
||||
sample.ppo2 = data[offset + pnf + 6] / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_PPO2, sample, userdata);
|
||||
} else {
|
||||
sample.ppo2 = data[offset + pnf + 12] * parser->calibration[0];
|
||||
if (callback && (parser->calibrated & 0x01)) callback (DC_SAMPLE_PPO2, sample, userdata);
|
||||
sample.ppo2.sensor = DC_SENSOR_NONE;
|
||||
sample.ppo2.value = data[offset + pnf + 6] / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_PPO2, &sample, userdata);
|
||||
|
||||
sample.ppo2 = data[offset + pnf + 14] * parser->calibration[1];
|
||||
if (callback && (parser->calibrated & 0x02)) callback (DC_SAMPLE_PPO2, sample, userdata);
|
||||
sample.ppo2.sensor = 0;
|
||||
sample.ppo2.value = data[offset + pnf + 12] * parser->calibration[0];
|
||||
if (callback && (parser->calibrated & 0x01)) callback (DC_SAMPLE_PPO2, &sample, userdata);
|
||||
|
||||
sample.ppo2 = data[offset + pnf + 15] * parser->calibration[2];
|
||||
if (callback && (parser->calibrated & 0x04)) callback (DC_SAMPLE_PPO2, sample, userdata);
|
||||
}
|
||||
sample.ppo2.sensor = 1;
|
||||
sample.ppo2.value = data[offset + pnf + 14] * parser->calibration[1];
|
||||
if (callback && (parser->calibrated & 0x02)) callback (DC_SAMPLE_PPO2, &sample, userdata);
|
||||
|
||||
sample.ppo2.sensor = 2;
|
||||
sample.ppo2.value = data[offset + pnf + 15] * parser->calibration[2];
|
||||
if (callback && (parser->calibrated & 0x04)) callback (DC_SAMPLE_PPO2, &sample, userdata);
|
||||
}
|
||||
|
||||
// Setpoint
|
||||
@ -1075,13 +1076,13 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
||||
sample.setpoint = data[17] / 100.0;
|
||||
}
|
||||
}
|
||||
if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_SETPOINT, &sample, userdata);
|
||||
}
|
||||
|
||||
// CNS
|
||||
if (parser->petrel) {
|
||||
sample.cns = data[offset + pnf + 22] / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_CNS, &sample, userdata);
|
||||
}
|
||||
|
||||
// Gaschange.
|
||||
@ -1096,7 +1097,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
||||
}
|
||||
|
||||
sample.gasmix = idx;
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
|
||||
o2_previous = o2;
|
||||
he_previous = he;
|
||||
dil_previous = ccr;
|
||||
@ -1115,7 +1116,8 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
||||
sample.deco.depth = 0.0;
|
||||
}
|
||||
sample.deco.time = data[offset + pnf + 9] * 60;
|
||||
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
|
||||
sample.deco.tts = array_uint16_be (data + offset + pnf + 4) * 60;
|
||||
if (callback) callback (DC_SAMPLE_DECO, &sample, userdata);
|
||||
|
||||
// for logversion 7 and newer (introduced for Perdix AI)
|
||||
// detect tank pressure
|
||||
@ -1137,7 +1139,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
||||
pressure &= 0x0FFF;
|
||||
sample.pressure.tank = parser->tankidx[id];
|
||||
sample.pressure.value = pressure * 2 * PSI / BAR;
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1150,7 +1152,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
||||
// 0xFB Tank size or max pressure haven’t been set up
|
||||
if (data[offset + pnf + 21] < 0xF0) {
|
||||
sample.rbt = data[offset + pnf + 21];
|
||||
if (callback) callback (DC_SAMPLE_RBT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_RBT, &sample, userdata);
|
||||
}
|
||||
}
|
||||
} else if (type == LOG_RECORD_DIVE_SAMPLE_EXT) {
|
||||
@ -1163,7 +1165,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
||||
pressure &= 0x0FFF;
|
||||
sample.pressure.tank = parser->tankidx[id];
|
||||
sample.pressure.value = pressure * 2 * PSI / BAR;
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1175,7 +1177,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
||||
if (pressure) {
|
||||
sample.pressure.tank = parser->tankidx[id];
|
||||
sample.pressure.value = pressure * 2 * PSI / BAR;
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, &sample, userdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1194,17 +1196,17 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
||||
// Time (seconds).
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Depth (absolute pressure in millibar)
|
||||
unsigned int depth = array_uint16_be (data + idx + 1);
|
||||
sample.depth = (signed int)(depth - parser->atmospheric) * (BAR / 1000.0) / (parser->density * GRAVITY);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Temperature (1/10 °C).
|
||||
int temperature = (signed short) array_uint16_be (data + idx + 3);
|
||||
sample.temperature = temperature / 10.0;
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
}
|
||||
} else if (type == LOG_RECORD_INFO_EVENT) {
|
||||
unsigned int event = data[offset + 1];
|
||||
@ -1216,7 +1218,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
||||
// Compass heading
|
||||
if (w1 != 0xFFFFFFFF) {
|
||||
sample.bearing = w1;
|
||||
if (callback) callback (DC_SAMPLE_BEARING, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_BEARING, &sample, userdata);
|
||||
}
|
||||
|
||||
// Tag
|
||||
@ -1224,7 +1226,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
||||
sample.event.time = 0;
|
||||
sample.event.flags = 0;
|
||||
sample.event.value = w2;
|
||||
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_EVENT, &sample, userdata);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ dc_status_t
|
||||
sporasub_sp2_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||
|
||||
dc_status_t
|
||||
sporasub_sp2_parser_create (dc_parser_t **parser, dc_context_t *context);
|
||||
sporasub_sp2_parser_create (dc_parser_t **parser, dc_context_t *context, const unsigned char data[], size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -37,7 +37,6 @@ struct sporasub_sp2_parser_t {
|
||||
dc_parser_t base;
|
||||
};
|
||||
|
||||
static dc_status_t sporasub_sp2_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||
static dc_status_t sporasub_sp2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
|
||||
static dc_status_t sporasub_sp2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
|
||||
static dc_status_t sporasub_sp2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
|
||||
@ -45,7 +44,6 @@ static dc_status_t sporasub_sp2_parser_samples_foreach (dc_parser_t *abstract, d
|
||||
static const dc_parser_vtable_t sporasub_sp2_parser_vtable = {
|
||||
sizeof(sporasub_sp2_parser_t),
|
||||
DC_FAMILY_SPORASUB_SP2,
|
||||
sporasub_sp2_parser_set_data, /* set_data */
|
||||
NULL, /* set_clock */
|
||||
NULL, /* set_atmospheric */
|
||||
NULL, /* set_density */
|
||||
@ -57,7 +55,7 @@ static const dc_parser_vtable_t sporasub_sp2_parser_vtable = {
|
||||
|
||||
|
||||
dc_status_t
|
||||
sporasub_sp2_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
sporasub_sp2_parser_create (dc_parser_t **out, dc_context_t *context, const unsigned char data[], size_t size)
|
||||
{
|
||||
sporasub_sp2_parser_t *parser = NULL;
|
||||
|
||||
@ -65,7 +63,7 @@ sporasub_sp2_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
return DC_STATUS_INVALIDARGS;
|
||||
|
||||
// Allocate memory.
|
||||
parser = (sporasub_sp2_parser_t *) dc_parser_allocate (context, &sporasub_sp2_parser_vtable);
|
||||
parser = (sporasub_sp2_parser_t *) dc_parser_allocate (context, &sporasub_sp2_parser_vtable, data, size);
|
||||
if (parser == NULL) {
|
||||
ERROR (context, "Failed to allocate memory.");
|
||||
return DC_STATUS_NOMEMORY;
|
||||
@ -77,13 +75,6 @@ sporasub_sp2_parser_create (dc_parser_t **out, dc_context_t *context)
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
sporasub_sp2_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
|
||||
{
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static dc_status_t
|
||||
sporasub_sp2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
||||
{
|
||||
@ -184,21 +175,21 @@ sporasub_sp2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
|
||||
|
||||
// Time (seconds)
|
||||
time += interval;
|
||||
sample.time = time;
|
||||
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
|
||||
sample.time = time * 1000;
|
||||
if (callback) callback (DC_SAMPLE_TIME, &sample, userdata);
|
||||
|
||||
// Depth (1/100 m)
|
||||
sample.depth = depth / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_DEPTH, &sample, userdata);
|
||||
|
||||
// Temperature (1/10 °C)
|
||||
sample.temperature = temperature / 10.0 - 20.0;
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_TEMPERATURE, &sample, userdata);
|
||||
|
||||
// Heartrate
|
||||
if (heartrate) {
|
||||
sample.heartbeat = heartrate;
|
||||
if (callback) callback (DC_SAMPLE_HEARTBEAT, sample, userdata);
|
||||
if (callback) callback (DC_SAMPLE_HEARTBEAT, &sample, userdata);
|
||||
}
|
||||
|
||||
offset += SZ_SAMPLE;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user