diff --git a/examples/universal.c b/examples/universal.c index e0cb4e7..4eef0c5 100644 --- a/examples/universal.c +++ b/examples/universal.c @@ -245,7 +245,7 @@ sample_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata) "OLF", "PO2", "airtime", "rgbm", "heading", "tissue level warning", "gaschange2"}; static const char *decostop[] = { - "ndl", "deco", "deep", "safety"}; + "ndl", "safety", "deco", "deep"}; sample_data_t *sampledata = (sample_data_t *) userdata; diff --git a/src/cressi_leonardo.c b/src/cressi_leonardo.c index fa29310..e18b496 100644 --- a/src/cressi_leonardo.c +++ b/src/cressi_leonardo.c @@ -124,6 +124,9 @@ cressi_leonardo_device_open (dc_device_t **out, dc_context_t *context, const cha return DC_STATUS_IO; } + serial_sleep (device->port, 100); + serial_flush (device->port, SERIAL_QUEUE_BOTH); + *out = (dc_device_t *) device; return DC_STATUS_SUCCESS; @@ -268,6 +271,13 @@ cressi_leonardo_device_foreach (dc_device_t *abstract, dc_dive_callback_t callba return rc; } + unsigned char *data = dc_buffer_get_data (buffer); + dc_event_devinfo_t devinfo; + devinfo.model = 0; + devinfo.firmware = 0; + devinfo.serial = array_uint32_le (data + 1); + device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo); + rc = cressi_leonardo_extract_dives (abstract, dc_buffer_get_data (buffer), dc_buffer_get_size (buffer), callback, userdata); @@ -328,7 +338,7 @@ cressi_leonardo_extract_dives (dc_device_t *abstract, const unsigned char data[] if (header < RB_PROFILE_BEGIN || header + 2 > RB_PROFILE_END || footer < RB_PROFILE_BEGIN || footer + 2 > RB_PROFILE_END) { - ERROR (abstract->context, "Invalid ringbuffer pointer detected."); + ERROR (context, "Invalid ringbuffer pointer detected."); free (buffer); return DC_STATUS_DATAFORMAT; } @@ -337,7 +347,7 @@ cressi_leonardo_extract_dives (dc_device_t *abstract, const unsigned char data[] unsigned int header2 = array_uint16_le (data + footer); unsigned int footer2 = array_uint16_le (data + header); if (header2 != header || footer2 != footer) { - ERROR (abstract->context, "Invalid ringbuffer pointer detected."); + ERROR (context, "Invalid ringbuffer pointer detected."); free (buffer); return DC_STATUS_DATAFORMAT; } diff --git a/src/descriptor.c b/src/descriptor.c index 8a6b80b..9190abc 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -76,20 +76,33 @@ static const dc_descriptor_t g_descriptors[] = { {"Suunto", "D4i", DC_FAMILY_SUUNTO_D9, 0x19}, {"Suunto", "D6i", DC_FAMILY_SUUNTO_D9, 0x1A}, {"Suunto", "D9tx", DC_FAMILY_SUUNTO_D9, 0x1B}, + {"Suunto", "DX", DC_FAMILY_SUUNTO_D9, 0x1C}, /* Uwatec Aladin */ - {"Uwatec", "Aladin", DC_FAMILY_UWATEC_ALADIN, 0}, + {"Uwatec", "Aladin Air Twin", DC_FAMILY_UWATEC_ALADIN, 0x1C}, + {"Uwatec", "Aladin Sport Plus", DC_FAMILY_UWATEC_ALADIN, 0x3E}, + {"Uwatec", "Aladin Pro", DC_FAMILY_UWATEC_ALADIN, 0x3F}, + {"Uwatec", "Aladin Air Z", DC_FAMILY_UWATEC_ALADIN, 0x44}, + {"Uwatec", "Aladin Air Z O2", DC_FAMILY_UWATEC_ALADIN, 0xA4}, + {"Uwatec", "Aladin Air Z Nitrox", DC_FAMILY_UWATEC_ALADIN, 0xF4}, + {"Uwatec", "Aladin Pro Ultra", DC_FAMILY_UWATEC_ALADIN, 0xFF}, /* Uwatec Memomouse */ {"Uwatec", "Memomouse", DC_FAMILY_UWATEC_MEMOMOUSE, 0}, /* Uwatec Smart */ #ifdef HAVE_IRDA {"Uwatec", "Smart Pro", DC_FAMILY_UWATEC_SMART, 0x10}, - {"Uwatec", "Galileo", DC_FAMILY_UWATEC_SMART, 0x11}, + {"Uwatec", "Galileo Sol", DC_FAMILY_UWATEC_SMART, 0x11}, + {"Uwatec", "Galileo Luna", DC_FAMILY_UWATEC_SMART, 0x11}, + {"Uwatec", "Galileo Terra", DC_FAMILY_UWATEC_SMART, 0x11}, {"Uwatec", "Aladin Tec", DC_FAMILY_UWATEC_SMART, 0x12}, + {"Uwatec", "Aladin Prime", DC_FAMILY_UWATEC_SMART, 0x12}, {"Uwatec", "Aladin Tec 2G", DC_FAMILY_UWATEC_SMART, 0x13}, + {"Uwatec", "Aladin 2G", DC_FAMILY_UWATEC_SMART, 0x13}, + {"Subgear","XP-10", DC_FAMILY_UWATEC_SMART, 0x13}, {"Uwatec", "Smart Com", DC_FAMILY_UWATEC_SMART, 0x14}, {"Uwatec", "Smart Tec", DC_FAMILY_UWATEC_SMART, 0x18}, {"Uwatec", "Galileo Trimix",DC_FAMILY_UWATEC_SMART, 0x19}, {"Uwatec", "Smart Z", DC_FAMILY_UWATEC_SMART, 0x1C}, + {"Subgear","XP Air", DC_FAMILY_UWATEC_SMART, 0x1C}, #endif /* Reefnet */ {"Reefnet", "Sensus", DC_FAMILY_REEFNET_SENSUS, 1}, @@ -97,10 +110,12 @@ static const dc_descriptor_t g_descriptors[] = { {"Reefnet", "Sensus Ultra", DC_FAMILY_REEFNET_SENSUSULTRA, 3}, /* Oceanic VT Pro */ {"Oceanic", "Versa Pro", DC_FAMILY_OCEANIC_VTPRO, 0x4155}, + {"Aeris", "Atmos 2", DC_FAMILY_OCEANIC_VTPRO, 0x4158}, {"Oceanic", "Pro Plus 2", DC_FAMILY_OCEANIC_VTPRO, 0x4159}, {"Aeris", "Atmos AI", DC_FAMILY_OCEANIC_VTPRO, 0x4244}, {"Oceanic", "VT Pro", DC_FAMILY_OCEANIC_VTPRO, 0x4245}, {"Sherwood", "Wisdom", DC_FAMILY_OCEANIC_VTPRO, 0x4246}, + {"Aeris", "Elite", DC_FAMILY_OCEANIC_VTPRO, 0x424F}, /* Oceanic Veo 250 */ {"Genesis", "React Pro", DC_FAMILY_OCEANIC_VEO250, 0x4247}, {"Oceanic", "Veo 200", DC_FAMILY_OCEANIC_VEO250, 0x424B}, @@ -123,6 +138,7 @@ static const dc_descriptor_t g_descriptors[] = { {"Oceanic", "OC1", DC_FAMILY_OCEANIC_ATOM2, 0x434E}, {"Sherwood", "Wisdom 2", DC_FAMILY_OCEANIC_ATOM2, 0x4350}, {"Sherwood", "Insight 2", DC_FAMILY_OCEANIC_ATOM2, 0x4353}, + {"Genesis", "React Pro White", DC_FAMILY_OCEANIC_ATOM2, 0x4354}, {"Tusa", "Element II (IQ-750)", DC_FAMILY_OCEANIC_ATOM2, 0x4357}, {"Oceanic", "Veo 1.0", DC_FAMILY_OCEANIC_ATOM2, 0x4358}, {"Oceanic", "Veo 2.0", DC_FAMILY_OCEANIC_ATOM2, 0x4359}, @@ -137,14 +153,18 @@ static const dc_descriptor_t g_descriptors[] = { {"Oceanic", "Atom 3.0", DC_FAMILY_OCEANIC_ATOM2, 0x444C}, {"Hollis", "DG03", DC_FAMILY_OCEANIC_ATOM2, 0x444D}, {"Oceanic", "OCS", DC_FAMILY_OCEANIC_ATOM2, 0x4450}, + {"Oceanic", "OC1", DC_FAMILY_OCEANIC_ATOM2, 0x4451}, {"Oceanic", "VT 4.1", DC_FAMILY_OCEANIC_ATOM2, 0x4452}, {"Aeris", "Epic", DC_FAMILY_OCEANIC_ATOM2, 0x4453}, {"Aeris", "Elite T3", DC_FAMILY_OCEANIC_ATOM2, 0x4455}, {"Oceanic", "Atom 3.1", DC_FAMILY_OCEANIC_ATOM2, 0x4456}, {"Aeris", "A300 AI", DC_FAMILY_OCEANIC_ATOM2, 0x4457}, {"Sherwood", "Wisdom 3", DC_FAMILY_OCEANIC_ATOM2, 0x4458}, + {"Oceanic", "Pro Plus 3", DC_FAMILY_OCEANIC_ATOM2, 0x4548}, /* Mares Nemo */ {"Mares", "Nemo", DC_FAMILY_MARES_NEMO, 0}, + {"Mares", "Nemo Steel", DC_FAMILY_MARES_NEMO, 0}, + {"Mares", "Nemo Titanium",DC_FAMILY_MARES_NEMO, 0}, {"Mares", "Nemo Excel", DC_FAMILY_MARES_NEMO, 17}, {"Mares", "Nemo Apneist", DC_FAMILY_MARES_NEMO, 18}, /* Mares Puck */ diff --git a/src/mares_iconhd_parser.c b/src/mares_iconhd_parser.c index 9d7bb75..0c8668a 100644 --- a/src/mares_iconhd_parser.c +++ b/src/mares_iconhd_parser.c @@ -152,6 +152,8 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi dc_gasmix_t *gasmix = (dc_gasmix_t *) value; + unsigned int air = (p[0] & 0x02) == 0; + if (value) { switch (type) { case DC_FIELD_DIVETIME: @@ -161,11 +163,27 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi *((double *) value) = array_uint16_le (p + 0x04) / 10.0; break; case DC_FIELD_GASMIX_COUNT: - *((unsigned int *) value) = 3; + if (air) { + *((unsigned int *) value) = 1; + } else { + // Count the number of active gas mixes. The active gas + // mixes are always first, so we stop counting as soon + // as the first gas marked as disabled is found. + unsigned int i = 0; + while (i < 3) { + if (p[0x14 + i * 4 + 1] & 0x80) + break; + i++; + } + *((unsigned int *) value) = i; + } break; case DC_FIELD_GASMIX: + if (air) + gasmix->oxygen = 0.21; + else + gasmix->oxygen = p[0x14 + flags * 4] / 100.0; gasmix->helium = 0.0; - gasmix->oxygen = p[0x14 + flags * 4] / 100.0; gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium; break; default: diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c index 137a34b..e58ae34 100644 --- a/src/oceanic_atom2.c +++ b/src/oceanic_atom2.c @@ -89,6 +89,7 @@ static const oceanic_common_version_t oceanic_atom2b_version[] = { {"ELEMENT2 \0\0 512K"}, {"OCEVEO20 \0\0 512K"}, {"TUSAZEN \0\0 512K"}, + {"PROPLUS3 \0\0 512K"}, }; static const oceanic_common_version_t oceanic_atom2c_version[] = { @@ -124,6 +125,10 @@ static const oceanic_common_version_t oceanic_veo1_version[] = { {"OCEVEO10 \0\0 8K"}, }; +static const oceanic_common_version_t oceanic_reactpro_version[] = { + {"REACPRO2 \0\0 512K"}, +}; + static const oceanic_common_layout_t aeris_f10_layout = { 0x10000, /* memsize */ 0x0000, /* cf_devinfo */ @@ -241,6 +246,18 @@ static const oceanic_common_layout_t oceanic_veo1_layout = { 0 /* pt_mode_logbook */ }; +static const oceanic_common_layout_t oceanic_reactpro_layout = { + 0xFFF0, /* memsize */ + 0x0000, /* cf_devinfo */ + 0x0040, /* cf_pointers */ + 0x0400, /* rb_logbook_begin */ + 0x0600, /* rb_logbook_end */ + 8, /* rb_logbook_entry_size */ + 0x0600, /* rb_profile_begin */ + 0xFFF0, /* rb_profile_end */ + 1, /* pt_mode_global */ + 1 /* pt_mode_logbook */ +}; static dc_status_t oceanic_atom2_send (oceanic_atom2_device_t *device, const unsigned char command[], unsigned int csize, unsigned char ack) @@ -418,6 +435,8 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, const char device->base.layout = &oceanic_oc1_layout; } else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_veo1_version)) { device->base.layout = &oceanic_veo1_layout; + } else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_reactpro_version)) { + device->base.layout = &oceanic_reactpro_layout; } else { device->base.layout = &oceanic_default_layout; } diff --git a/src/oceanic_atom2_parser.c b/src/oceanic_atom2_parser.c index 1694d48..de5e116 100644 --- a/src/oceanic_atom2_parser.c +++ b/src/oceanic_atom2_parser.c @@ -41,6 +41,7 @@ #define COMPUMASK 0x4348 #define OC1A 0x434E #define F10 0x434D +#define ELEMENT2 0x4357 #define VEO20 0x4359 #define VEO30 0x435A #define ZENAIR 0x4442 @@ -51,10 +52,12 @@ #define ATOM3 0x444C #define DG03 0x444D #define OCS 0x4450 +#define OC1C 0x4451 #define VT41 0x4452 #define EPICB 0x4453 #define ATOM31 0x4456 #define A300AI 0x4457 +#define PROPLUS3 0x4548 typedef struct oceanic_atom2_parser_t oceanic_atom2_parser_t; @@ -156,6 +159,7 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim switch (parser->model) { case OC1A: case OC1B: + case OC1C: case OCS: case VT4: case VT41: @@ -262,7 +266,7 @@ oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns if (parser->model == DATAMASK || parser->model == COMPUMASK || parser->model == GEO || parser->model == GEO20 || parser->model == VEO20 || parser->model == VEO30 || - parser->model == OCS) { + parser->model == OCS || parser->model == PROPLUS3) { headersize -= PAGESIZE; } else if (parser->model == VT4 || parser->model == VT41) { headersize += PAGESIZE; @@ -353,7 +357,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ if (parser->model == DATAMASK || parser->model == COMPUMASK || parser->model == GEO || parser->model == GEO20 || parser->model == VEO20 || parser->model == VEO30 || - parser->model == OCS) { + parser->model == OCS || parser->model == PROPLUS3) { headersize -= PAGESIZE; } else if (parser->model == VT4 || parser->model == VT41) { headersize += PAGESIZE; @@ -390,13 +394,14 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ } unsigned int samplesize = PAGESIZE / 2; - if (parser->model == OC1A || parser->model == OC1B) + if (parser->model == OC1A || parser->model == OC1B || parser->model == OC1C) samplesize = PAGESIZE; else if (parser->model == F10) samplesize = 2; unsigned int have_temperature = 1, have_pressure = 1; - if (parser->model == VEO30 || parser->model == OCS) { + if (parser->model == VEO30 || parser->model == OCS || + parser->model == ELEMENT2) { have_pressure = 0; } else if (parser->model == F10) { have_temperature = 0; @@ -494,11 +499,12 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ } else { // Temperature (°F) if (have_temperature) { - if (parser->model == GEO || parser->model == ATOM1) { + if (parser->model == GEO || parser->model == ATOM1 || + parser->model == ELEMENT2) { temperature = data[offset + 6]; } else if (parser->model == GEO20 || parser->model == VEO20 || parser->model == VEO30 || parser->model == OC1A || - parser->model == OC1B) { + parser->model == OC1B || parser->model == OC1C) { temperature = data[offset + 3]; } else if (parser->model == OCS) { temperature = data[offset + 1]; @@ -506,7 +512,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ temperature = ((data[offset + 7] & 0xF0) >> 4) | ((data[offset + 7] & 0x0C) << 2) | ((data[offset + 5] & 0x0C) << 4); } else { unsigned int sign; - if (parser->model == DG03) + if (parser->model == DG03 || parser->model == PROPLUS3) sign = (~data[offset + 5] & 0x04) >> 2; else if (parser->model == ATOM2 || parser->model == PROPLUS21 || parser->model == EPICA || parser->model == EPICB) @@ -524,12 +530,12 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ // Tank Pressure (psi) if (have_pressure) { - if (parser->model == OC1A || parser->model == OC1B) + if (parser->model == OC1A || parser->model == OC1B || parser->model == OC1C) pressure = (data[offset + 10] + (data[offset + 11] << 8)) & 0x0FFF; else if (parser->model == VT4 || parser->model == VT41|| parser->model == ATOM3 || parser->model == ATOM31 || parser->model == ZENAIR ||parser->model == A300AI || - parser->model == DG03) + parser->model == DG03 || parser->model == PROPLUS3) pressure = (((data[offset + 0] & 0x03) << 8) + data[offset + 1]) * 5; else pressure -= data[offset + 1]; @@ -542,7 +548,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ unsigned int depth; if (parser->model == GEO20 || parser->model == VEO20 || parser->model == VEO30 || parser->model == OC1A || - parser->model == OC1B) + parser->model == OC1B || parser->model == OC1C) depth = (data[offset + 4] + (data[offset + 5] << 8)) & 0x0FFF; else if (parser->model == ATOM1) depth = data[offset + 3] * 16; diff --git a/src/oceanic_veo250_parser.c b/src/oceanic_veo250_parser.c index baffc4c..36eeeb4 100644 --- a/src/oceanic_veo250_parser.c +++ b/src/oceanic_veo250_parser.c @@ -31,6 +31,11 @@ #define ISINSTANCE(parser) dc_parser_isinstance((parser), &oceanic_veo250_parser_vtable) +#define REACTPRO 0x4247 +#define VEO200 0x424B +#define VEO250 0x424C +#define REACTPROWHITE 0x4354 + typedef struct oceanic_veo250_parser_t oceanic_veo250_parser_t; struct oceanic_veo250_parser_t { @@ -128,8 +133,10 @@ oceanic_veo250_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *dateti datetime->minute = p[2]; datetime->second = 0; - if (parser->model == 0x424B || parser->model == 0x424C) + if (parser->model == VEO200 || parser->model == VEO250) datetime->year += 3; + else if (parser->model == REACTPRO) + datetime->year += 2; } return DC_STATUS_SUCCESS; @@ -194,6 +201,7 @@ oceanic_veo250_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un static dc_status_t oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata) { + oceanic_veo250_parser_t *parser = (oceanic_veo250_parser_t *) abstract; const unsigned char *data = abstract->data; unsigned int size = abstract->size; @@ -202,7 +210,12 @@ oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback unsigned int time = 0; unsigned int interval = 0; - switch (data[0x27] & 0x03) { + unsigned int interval_idx = data[0x27] & 0x03; + if (parser->model == REACTPRO || parser->model == REACTPROWHITE) { + interval_idx += 1; + interval_idx %= 4; + } + switch (interval_idx) { case 0: interval = 2; break; @@ -244,7 +257,12 @@ oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); // Temperature (°F) - unsigned int temperature = data[offset + 7]; + unsigned int temperature; + if (parser->model == REACTPRO || parser->model == REACTPROWHITE) { + temperature = data[offset + 6]; + } else { + temperature = data[offset + 7]; + } sample.temperature = (temperature - 32.0) * (5.0 / 9.0); if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata); diff --git a/src/oceanic_vtpro.c b/src/oceanic_vtpro.c index 44a925a..cdc5ee7 100644 --- a/src/oceanic_vtpro.c +++ b/src/oceanic_vtpro.c @@ -65,9 +65,11 @@ static const dc_device_vtable_t oceanic_vtpro_device_vtable = { static const oceanic_common_version_t oceanic_vtpro_version[] = { {"VERSAPRO \0\0 256K"}, + {"ATMOSTWO \0\0 256K"}, {"PROPLUS2 \0\0 256K"}, {"ATMOSAIR \0\0 256K"}, {"VTPRO r\0\0 256K"}, + {"ELITE r\0\0 256K"}, }; static const oceanic_common_version_t oceanic_wisdom_version[] = { diff --git a/src/parser.c b/src/parser.c index 00a59d2..73ab0e7 100644 --- a/src/parser.c +++ b/src/parser.c @@ -35,6 +35,8 @@ #include "parser-private.h" #include "device-private.h" +#define REACTPROWHITE 0x4354 + dc_status_t dc_parser_new (dc_parser_t **out, dc_device_t *device) { @@ -86,7 +88,10 @@ dc_parser_new (dc_parser_t **out, dc_device_t *device) rc = oceanic_veo250_parser_create (&parser, context, device->devinfo.model); break; case DC_FAMILY_OCEANIC_ATOM2: - rc = oceanic_atom2_parser_create (&parser, context, device->devinfo.model); + if (device->devinfo.model == REACTPROWHITE) + rc = oceanic_veo250_parser_create (&parser, context, device->devinfo.model); + else + rc = oceanic_atom2_parser_create (&parser, context, device->devinfo.model); break; case DC_FAMILY_MARES_NEMO: case DC_FAMILY_MARES_PUCK: diff --git a/src/shearwater_predator_parser.c b/src/shearwater_predator_parser.c index bf136a9..43c44b5 100644 --- a/src/shearwater_predator_parser.c +++ b/src/shearwater_predator_parser.c @@ -141,7 +141,7 @@ shearwater_predator_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *d unsigned int ticks = array_uint32_be (data + 12); - if (!dc_datetime_localtime (datetime, ticks)) + if (!dc_datetime_gmtime (datetime, ticks)) return DC_STATUS_DATAFORMAT; return DC_STATUS_SUCCESS; diff --git a/src/suunto_d9.c b/src/suunto_d9.c index 7069ca9..039ae98 100644 --- a/src/suunto_d9.c +++ b/src/suunto_d9.c @@ -43,6 +43,7 @@ #define D4i 0x19 #define D6i 0x1A #define D9tx 0x1B +#define DX 0x1C typedef struct suunto_d9_device_t { suunto_common2_device_t base; @@ -81,6 +82,14 @@ static const suunto_common2_layout_t suunto_d9tx_layout = { 0xEBF0 /* rb_profile_end */ }; +static const suunto_common2_layout_t suunto_dx_layout = { + 0x10000, /* memsize */ + 0x0017, /* fingerprint */ + 0x0024, /* serial */ + 0x019A, /* rb_profile_begin */ + 0xEBF0 /* rb_profile_end */ +}; + static dc_status_t suunto_d9_device_autodetect (suunto_d9_device_t *device, unsigned int model) @@ -93,7 +102,7 @@ suunto_d9_device_autodetect (suunto_d9_device_t *device, unsigned int model) // Use the model number as a hint to speedup the detection. unsigned int hint = 0; - if (model == D4i || model == D6i || model == D9tx) + if (model == D4i || model == D6i || model == D9tx || model == DX) hint = 1; for (unsigned int i = 0; i < C_ARRAY_SIZE(baudrates); ++i) { @@ -188,6 +197,8 @@ suunto_d9_device_open (dc_device_t **out, dc_context_t *context, const char *nam model = device->base.version[0]; if (model == D4i || model == D6i || model == D9tx) device->base.layout = &suunto_d9tx_layout; + else if (model == DX) + device->base.layout = &suunto_dx_layout; else device->base.layout = &suunto_d9_layout; diff --git a/src/suunto_d9_parser.c b/src/suunto_d9_parser.c index 19f681b..11c7d0f 100644 --- a/src/suunto_d9_parser.c +++ b/src/suunto_d9_parser.c @@ -43,6 +43,7 @@ #define D4i 0x19 #define D6i 0x1A #define D9tx 0x1B +#define DX 0x1C #define AIR 0 #define NITROX 1 @@ -132,7 +133,7 @@ suunto_d9_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime) suunto_d9_parser_t *parser = (suunto_d9_parser_t*) abstract; unsigned int offset = 0x11; - if (parser->model == HELO2) + if (parser->model == HELO2 || parser->model == DX) offset = 0x17; else if (parser->model == D4i || parser->model == D6i || parser->model == D9tx) offset = 0x13; @@ -143,7 +144,8 @@ suunto_d9_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime) const unsigned char *p = abstract->data + offset; if (datetime) { - if (parser->model == D4i || parser->model == D6i || parser->model == D9tx) { + if (parser->model == D4i || parser->model == D6i || + parser->model == D9tx || parser->model == DX) { datetime->year = p[0] + (p[1] << 8); datetime->month = p[2]; datetime->day = p[3]; @@ -189,6 +191,9 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne } else if (parser->model == D9tx) { gasmix_offset = 0x87; gasmix_count = 8; + } else if (parser->model == DX) { + gasmix_offset = 0xC1; + gasmix_count = 11; } // Offset to the configuration data. @@ -196,7 +201,8 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne if (parser->model == D4) { config += 1; } else if (parser->model == HELO2 || parser->model == D4i || - parser->model == D6i || parser->model == D9tx) { + parser->model == D6i || parser->model == D9tx || + parser->model == DX) { config = gasmix_offset + gasmix_count * 6; } if (config + 1 > size) @@ -208,6 +214,8 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne gasmodel_offset = 0x1F; else if (parser->model == D4i || parser->model == D6i || parser->model == D9tx) gasmodel_offset = 0x1D; + else if (parser->model == DX) + gasmodel_offset = 0x21; unsigned int gasmodel = data[gasmodel_offset]; dc_gasmix_t *gasmix = (dc_gasmix_t *) value; @@ -217,7 +225,8 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne case DC_FIELD_DIVETIME: if (parser->model == D4) *((unsigned int *) value) = array_uint16_le (data + 0x0B); - else if (parser->model == D4i || parser->model == D6i || parser->model == D9tx) + else if (parser->model == D4i || parser->model == D6i || + parser->model == D9tx || parser->model == DX) *((unsigned int *) value) = array_uint16_le (data + 0x0D); else if (parser->model == HELO2) *((unsigned int *) value) = array_uint16_le (data + 0x0D) * 60; @@ -239,7 +248,8 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne gasmix->helium = 0.0; gasmix->oxygen = 0.21; } else if (parser->model == HELO2 || parser->model == D4i || - parser->model == D6i || parser->model == D9tx) { + parser->model == D6i || parser->model == D9tx || + parser->model == DX) { gasmix->helium = data[gasmix_offset + 6 * flags + 2] / 100.0; gasmix->oxygen = data[gasmix_offset + 6 * flags + 1] / 100.0; } else { @@ -282,6 +292,9 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca } else if (parser->model == D9tx) { gasmix_offset = 0x87; gasmix_count = 8; + } else if (parser->model == DX) { + gasmix_offset = 0xC1; + gasmix_count = 11; } // Offset to the configuration data. @@ -289,7 +302,8 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca if (parser->model == D4) { config += 1; } else if (parser->model == HELO2 || parser->model == D4i || - parser->model == D6i || parser->model == D9tx) { + parser->model == D6i || parser->model == D9tx || + parser->model == DX) { config = gasmix_offset + gasmix_count * 6; } if (config + 1 > size) @@ -297,7 +311,7 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca // Number of parameters in the configuration data. unsigned int nparams = data[config]; - if (nparams > MAXPARAMS) + if (nparams == 0 || nparams > MAXPARAMS) return DC_STATUS_DATAFORMAT; // Available divisor values. @@ -340,6 +354,8 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca if (parser->model == HELO2 || parser->model == D4i || parser->model == D6i || parser->model == D9tx) interval_sample_offset = 0x1E; + else if (parser->model == DX) + interval_sample_offset = 0x22; unsigned int interval_sample = data[interval_sample_offset]; if (interval_sample == 0) return DC_STATUS_DATAFORMAT; diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index 6c53730..60cbfa4 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -584,7 +584,7 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t break; case TEMPERATURE: if (table[id].absolute) { - temperature = value / 2.5; + temperature = svalue / 2.5; have_temperature = 1; } else { temperature += svalue / 2.5;