Merge git://git.libdivecomputer.org/libdivecomputer into Subsurface-branch

Merge with upstream libdivecomputer:

 - uwatec cleanups and fixes (G2/trimix parsing etc)

 - event and bookmark fixes for Oceanic, iDive/iX3M and Aqualung i300

* git://git.libdivecomputer.org/libdivecomputer:
  Use more descriptive names
  Use two passes to parse the profile data
  Fix the Uwatec trimix data format
  Implement the ndl/deco, rbt and bookmark samples
  Implement the setpoint sample for the iDive and iX3M
  Implement the ndl/deco sample for the Aqualung i300
  Update the msvc project file
This commit is contained in:
Linus Torvalds 2017-09-06 10:58:21 -07:00
commit c0f025b019
4 changed files with 108 additions and 42 deletions

View File

@ -478,6 +478,10 @@
RelativePath="..\src\uwatec_aladin.c"
>
</File>
<File
RelativePath="..\src\uwatec_g2.c"
>
</File>
<File
RelativePath="..\src\uwatec_memomouse.c"
>
@ -796,6 +800,10 @@
RelativePath="..\src\uwatec_aladin.h"
>
</File>
<File
RelativePath="..\src\uwatec_g2.h"
>
</File>
<File
RelativePath="..\src\uwatec_memomouse.h"
>

View File

@ -307,6 +307,13 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
divemode = mode;
}
// Setpoint
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);
}
// Gaschange.
unsigned int o2 = data[offset + 10];
unsigned int he = data[offset + 11];

View File

@ -979,7 +979,9 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
decostop = (data[offset + 5] & 0xF0) >> 4;
decotime = array_uint16_le(data + offset + 4) & 0x03FF;
have_deco = 1;
} else if (parser->model == I200) {
} else if (parser->model == I200 || parser->model == I300 ||
parser->model == OC1A || parser->model == OC1B ||
parser->model == OC1C || parser->model == OCI) {
decostop = (data[offset + 7] & 0xF0) >> 4;
decotime = array_uint16_le(data + offset + 6) & 0x0FFF;
have_deco = 1;
@ -1001,7 +1003,9 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
if (parser->model == ATOM31) {
rbt = array_uint16_le(data + offset + 6) & 0x01FF;
have_rbt = 1;
} else if (parser->model == I450T) {
} else if (parser->model == I450T || parser->model == OC1A ||
parser->model == OC1B || parser->model == OC1C ||
parser->model == OCI) {
rbt = array_uint16_le(data + offset + 8) & 0x01FF;
have_rbt = 1;
} else if (parser->model == VISION || parser->model == XPAIR ||
@ -1014,6 +1018,20 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
if (callback) callback (DC_SAMPLE_RBT, sample, userdata);
}
// Bookmarks
unsigned int have_bookmark = 0;
if (parser->model == OC1A || parser->model == OC1B ||
parser->model == OC1C || parser->model == OCI) {
have_bookmark = data[offset + 12] & 0x80;
}
if (have_bookmark) {
sample.event.type = SAMPLE_EVENT_BOOKMARK;
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = 0;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
}
count++;
complete = 1;
}

View File

@ -74,8 +74,8 @@ typedef enum {
BEARING,
ALARMS,
TIME,
UNKNOWN1,
UNKNOWN2,
APNEA,
MISC,
} uwatec_smart_sample_t;
typedef enum {
@ -142,9 +142,9 @@ struct uwatec_smart_parser_t {
unsigned int nsamples;
const uwatec_smart_event_info_t *events[NEVENTS];
unsigned int nevents[NEVENTS];
unsigned int trimix;
// Cached fields.
unsigned int cached;
unsigned int trimix;
unsigned int ngasmixes;
uwatec_smart_gasmix_t gasmix[NGASMIXES];
unsigned int ntanks;
@ -158,6 +158,8 @@ static dc_status_t uwatec_smart_parser_get_datetime (dc_parser_t *abstract, dc_d
static dc_status_t uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
static dc_status_t uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
static dc_status_t uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t callback, void *userdata);
static const dc_parser_vtable_t uwatec_smart_parser_vtable = {
sizeof(uwatec_smart_parser_t),
DC_FAMILY_UWATEC_SMART,
@ -194,6 +196,19 @@ uwatec_smart_header_info_t uwatec_smart_galileo_header = {
92, /* settings */
};
static const
uwatec_smart_header_info_t uwatec_smart_trimix_header = {
22, /* maxdepth */
26, /* divetime */
UNSUPPORTED, 0, /* gasmixes */
30, /* temp_minimum */
28, /* temp_maximum */
32, /* temp_surface */
UNSUPPORTED, /* tankpressure */
16, /* timezone */
68, /* settings */
};
static const
uwatec_smart_header_info_t uwatec_smart_aladin_tec_header = {
22,
@ -277,8 +292,8 @@ uwatec_smart_sample_info_t uwatec_smart_galileo_samples[] = {
{HEARTRATE, 1, 0, 8, 0, 1}, // 1111 0111 dddddddd
{BEARING, 1, 0, 8, 0, 2}, // 1111 1000 dddddddd dddddddd
{ALARMS, 1, 2, 8, 0, 1}, // 1111 1001 dddddddd
{UNKNOWN1, 1, 0, 8, 0, 0}, // 1111 1010 (8 bytes)
{UNKNOWN2, 1, 0, 8, 0, 1}, // 1111 1011 dddddddd (n-1 bytes)
{APNEA, 1, 0, 8, 0, 0}, // 1111 1010 (8 bytes)
{MISC, 1, 0, 8, 0, 1}, // 1111 1011 dddddddd (n-1 bytes)
};
@ -418,32 +433,32 @@ uwatec_smart_parser_cache (uwatec_smart_parser_t *parser)
{
const unsigned char *data = parser->base.data;
unsigned int size = parser->base.size;
const uwatec_smart_header_info_t *header = parser->header;
if (parser->cached) {
return DC_STATUS_SUCCESS;
}
unsigned int trimix = 0;
if (parser->model == GALILEO || parser->model == GALILEOTRIMIX) {
if (size < 44)
return DC_STATUS_DATAFORMAT;
if (data[43] & 0x80) {
trimix = 1;
}
if (trimix) {
parser->trimix = 1;
parser->headersize = 84;
parser->header = &uwatec_smart_trimix_header;
parser->events[2] = uwatec_smart_trimix_events_2;
parser->nevents[2] = C_ARRAY_SIZE (uwatec_smart_trimix_events_2);
} else {
parser->trimix = 0;
parser->headersize = 152;
parser->header = &uwatec_smart_galileo_header;
parser->events[2] = uwatec_smart_galileo_events_2;
parser->nevents[2] = C_ARRAY_SIZE (uwatec_smart_galileo_events_2);
}
} else if (parser->model == G2) {
trimix = 1;
}
const uwatec_smart_header_info_t *header = parser->header;
// Get the settings.
dc_divemode_t divemode = DC_DIVEMODE_OC;
dc_water_t watertype = DC_WATER_FRESH;
@ -479,7 +494,7 @@ uwatec_smart_parser_cache (uwatec_smart_parser_t *parser)
unsigned int ngasmixes = 0;
uwatec_smart_tank_t tank[NGASMIXES] = {{0}};
uwatec_smart_gasmix_t gasmix[NGASMIXES] = {{0}};
if (!trimix) {
if (header->gasmix != UNSUPPORTED) {
for (unsigned int i = 0; i < header->ngases; ++i) {
unsigned int idx = DC_GASMIX_UNKNOWN;
unsigned int o2 = 0;
@ -526,7 +541,6 @@ uwatec_smart_parser_cache (uwatec_smart_parser_t *parser)
}
// Cache the data for later use.
parser->trimix = trimix;
parser->ngasmixes = ngasmixes;
for (unsigned int i = 0; i < ngasmixes; ++i) {
parser->gasmix[i] = gasmix[i];
@ -563,6 +577,7 @@ uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i
parser->model = model;
parser->devtime = devtime;
parser->systime = systime;
parser->trimix = 0;
for (unsigned int i = 0; i < NEVENTS; ++i) {
parser->events[i] = NULL;
parser->nevents[i] = 0;
@ -582,7 +597,6 @@ uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i
case MERIDIAN:
case CHROMIS:
case MANTIS2:
case G2:
parser->headersize = 152;
parser->header = &uwatec_smart_galileo_header;
parser->samples = uwatec_smart_galileo_samples;
@ -594,6 +608,19 @@ uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i
parser->nevents[1] = C_ARRAY_SIZE (uwatec_smart_galileo_events_1);
parser->nevents[2] = C_ARRAY_SIZE (uwatec_smart_galileo_events_2);
break;
case G2:
parser->headersize = 84;
parser->header = &uwatec_smart_trimix_header;
parser->samples = uwatec_smart_galileo_samples;
parser->nsamples = C_ARRAY_SIZE (uwatec_smart_galileo_samples);
parser->events[0] = uwatec_smart_galileo_events_0;
parser->events[1] = uwatec_smart_galileo_events_1;
parser->events[2] = uwatec_smart_trimix_events_2;
parser->nevents[0] = C_ARRAY_SIZE (uwatec_smart_galileo_events_0);
parser->nevents[1] = C_ARRAY_SIZE (uwatec_smart_galileo_events_1);
parser->nevents[2] = C_ARRAY_SIZE (uwatec_smart_trimix_events_2);
parser->trimix = 1;
break;
case ALADINTEC:
parser->headersize = 108;
parser->header = &uwatec_smart_aladin_tec_header;
@ -635,7 +662,6 @@ uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i
}
parser->cached = 0;
parser->trimix = 0;
parser->ngasmixes = 0;
parser->ntanks = 0;
for (unsigned int i = 0; i < NGASMIXES; ++i) {
@ -667,7 +693,6 @@ uwatec_smart_parser_set_data (dc_parser_t *abstract, const unsigned char *data,
// Reset the cache.
parser->cached = 0;
parser->trimix = 0;
parser->ngasmixes = 0;
parser->ntanks = 0;
for (unsigned int i = 0; i < NGASMIXES; ++i) {
@ -728,9 +753,6 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
{
uwatec_smart_parser_t *parser = (uwatec_smart_parser_t *) abstract;
const unsigned char *data = abstract->data;
const uwatec_smart_header_info_t *table = parser->header;
// Cache the parser data.
dc_status_t rc = uwatec_smart_parser_cache (parser);
if (rc != DC_STATUS_SUCCESS)
@ -738,11 +760,14 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
// Cache the profile data.
if (parser->cached < PROFILE) {
rc = uwatec_smart_parser_samples_foreach (abstract, NULL, NULL);
rc = uwatec_smart_parse (parser, NULL, NULL);
if (rc != DC_STATUS_SUCCESS)
return rc;
}
const uwatec_smart_header_info_t *table = parser->header;
const unsigned char *data = abstract->data;
double salinity = (parser->watertype == DC_WATER_SALT ? SALT : FRESH);
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
@ -766,13 +791,9 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
break;
case DC_FIELD_TANK_COUNT:
if (table->tankpressure == UNSUPPORTED)
return DC_STATUS_UNSUPPORTED;
*((unsigned int *) value) = parser->ntanks;
break;
case DC_FIELD_TANK:
if (table->tankpressure == UNSUPPORTED)
return DC_STATUS_UNSUPPORTED;
tank->type = DC_TANKVOLUME_NONE;
tank->volume = 0.0;
tank->workpressure = 0.0;
@ -871,24 +892,15 @@ uwatec_smart_fixsignbit (unsigned int x, unsigned int n)
static dc_status_t
uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
uwatec_smart_parse (uwatec_smart_parser_t *parser, dc_sample_callback_t callback, void *userdata)
{
uwatec_smart_parser_t *parser = (uwatec_smart_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 = uwatec_smart_parser_cache (parser);
if (rc != DC_STATUS_SUCCESS)
return rc;
const uwatec_smart_sample_info_t *table = parser->samples;
unsigned int entries = parser->nsamples;
unsigned int header = parser->headersize;
if (parser->trimix) {
header = 0xB1;
}
// Get the maximum number of alarm bytes.
unsigned int nalarms = 0;
@ -927,7 +939,7 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
int have_depth = 0, have_temperature = 0, have_pressure = 0, have_rbt = 0,
have_heartrate = 0, have_bearing = 0;
unsigned int offset = header;
unsigned int offset = parser->headersize;
while (offset < size) {
dc_sample_value_t sample = {0};
@ -1079,14 +1091,14 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
case TIME:
complete = value;
break;
case UNKNOWN1:
case APNEA:
if (offset + 8 > size) {
ERROR (abstract->context, "Incomplete sample data.");
return DC_STATUS_DATAFORMAT;
}
offset += 8;
break;
case UNKNOWN2:
case MISC:
if (value < 1 || offset + value - 1 > size) {
ERROR (abstract->context, "Incomplete sample data.");
return DC_STATUS_DATAFORMAT;
@ -1211,3 +1223,24 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
return DC_STATUS_SUCCESS;
}
static dc_status_t
uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
{
uwatec_smart_parser_t *parser = (uwatec_smart_parser_t *) abstract;
// Cache the parser data.
dc_status_t rc = uwatec_smart_parser_cache (parser);
if (rc != DC_STATUS_SUCCESS)
return rc;
// Cache the profile data.
if (parser->cached < PROFILE) {
rc = uwatec_smart_parse (parser, NULL, NULL);
if (rc != DC_STATUS_SUCCESS)
return rc;
}
return uwatec_smart_parse (parser, callback, userdata);
}