From c195404920b32f177c8c2199b628bf71d22e9f97 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 18 Apr 2013 08:19:05 +0200 Subject: [PATCH] Add support for the Suunto DX. The Suunto DX has support for 8 gas mixes (OC) and 3 diluents (CC). Because it's still unknown how rebreather dives are stored, we simply return all 11 gas mixes. For the rest, the DX data format is very similar to that of the existing Suunto models, with only a few different offsets here and there. --- src/descriptor.c | 1 + src/suunto_d9.c | 14 +++++++++++++- src/suunto_d9_parser.c | 28 ++++++++++++++++++++++------ 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/descriptor.c b/src/descriptor.c index 2061408..e45a286 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -72,6 +72,7 @@ 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 Air Twin", DC_FAMILY_UWATEC_ALADIN, 0x1C}, {"Uwatec", "Aladin Sport Plus", DC_FAMILY_UWATEC_ALADIN, 0x3E}, diff --git a/src/suunto_d9.c b/src/suunto_d9.c index 259cbe9..cdd2961 100644 --- a/src/suunto_d9.c +++ b/src/suunto_d9.c @@ -41,6 +41,7 @@ #define D4i 0x19 #define D6i 0x1A #define D9tx 0x1B +#define DX 0x1C typedef struct suunto_d9_device_t { suunto_common2_device_t base; @@ -79,6 +80,15 @@ 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 int device_is_suunto_d9 (dc_device_t *abstract) { @@ -100,7 +110,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) { @@ -195,6 +205,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 24de752..d9d1ed2 100644 --- a/src/suunto_d9_parser.c +++ b/src/suunto_d9_parser.c @@ -41,6 +41,7 @@ #define D4i 0x19 #define D6i 0x1A #define D9tx 0x1B +#define DX 0x1C #define AIR 0 #define NITROX 1 @@ -146,7 +147,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; @@ -157,7 +158,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]; @@ -203,6 +205,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. @@ -210,7 +215,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) @@ -222,6 +228,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; @@ -231,7 +239,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; @@ -253,7 +262,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 { @@ -299,6 +309,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. @@ -306,7 +319,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) @@ -357,6 +371,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;