diff --git a/msvc/libdivecomputer.vcproj b/msvc/libdivecomputer.vcproj index f7b7883..c194f9f 100644 --- a/msvc/libdivecomputer.vcproj +++ b/msvc/libdivecomputer.vcproj @@ -478,6 +478,10 @@ RelativePath="..\src\uwatec_aladin.c" > + + @@ -796,6 +800,10 @@ RelativePath="..\src\uwatec_aladin.h" > + + diff --git a/src/divesystem_idive_parser.c b/src/divesystem_idive_parser.c index ff9f480..f37d142 100644 --- a/src/divesystem_idive_parser.c +++ b/src/divesystem_idive_parser.c @@ -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]; diff --git a/src/oceanic_atom2_parser.c b/src/oceanic_atom2_parser.c index f527c7e..444ed1e 100644 --- a/src/oceanic_atom2_parser.c +++ b/src/oceanic_atom2_parser.c @@ -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; } diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index 54bdee5..639d0e4 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -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); +}