From 95d69ea30d620ac962e2d82b8d6f27b50f6472aa Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 10 Mar 2016 20:46:10 +0100 Subject: [PATCH] Add support for the Suunto Zoop/Vyper Novo. The Zoop Novo and Vyper Novo are compatible with respectively the D4i and D6i. --- src/descriptor.c | 2 ++ src/suunto_d9.c | 8 ++++++-- src/suunto_d9_parser.c | 28 +++++++++++++++++++--------- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/src/descriptor.c b/src/descriptor.c index be247bc..e037f46 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -77,6 +77,8 @@ static const dc_descriptor_t g_descriptors[] = { {"Suunto", "D6i", DC_FAMILY_SUUNTO_D9, 0x1A}, {"Suunto", "D9tx", DC_FAMILY_SUUNTO_D9, 0x1B}, {"Suunto", "DX", DC_FAMILY_SUUNTO_D9, 0x1C}, + {"Suunto", "Vyper Novo", DC_FAMILY_SUUNTO_D9, 0x1D}, + {"Suunto", "Zoop Novo", DC_FAMILY_SUUNTO_D9, 0x1E}, /* Suunto EON Steel */ #ifdef HAVE_LIBUSB {"Suunto", "EON Steel", DC_FAMILY_SUUNTO_EONSTEEL, 0}, diff --git a/src/suunto_d9.c b/src/suunto_d9.c index 0d51540..dcacd99 100644 --- a/src/suunto_d9.c +++ b/src/suunto_d9.c @@ -44,6 +44,8 @@ #define D6i 0x1A #define D9tx 0x1B #define DX 0x1C +#define VYPERNOVO 0x1D +#define ZOOPNOVO 0x1E typedef struct suunto_d9_device_t { suunto_common2_device_t base; @@ -103,7 +105,8 @@ 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 || model == DX) + if (model == D4i || model == D6i || model == D9tx || + model == DX || model == VYPERNOVO || model == ZOOPNOVO) hint = 1; for (unsigned int i = 0; i < C_ARRAY_SIZE(baudrates); ++i) { @@ -194,7 +197,8 @@ suunto_d9_device_open (dc_device_t **out, dc_context_t *context, const char *nam // Override the base class values. model = device->base.version[0]; - if (model == D4i || model == D6i || model == D9tx) + if (model == D4i || model == D6i || model == D9tx || + model == VYPERNOVO || model == ZOOPNOVO) device->base.layout = &suunto_d9tx_layout; else if (model == DX) device->base.layout = &suunto_dx_layout; diff --git a/src/suunto_d9_parser.c b/src/suunto_d9_parser.c index eeb1783..da0f8ba 100644 --- a/src/suunto_d9_parser.c +++ b/src/suunto_d9_parser.c @@ -46,6 +46,8 @@ #define D6i 0x1A #define D9tx 0x1B #define DX 0x1C +#define VYPERNOVO 0x1D +#define ZOOPNOVO 0x1E #define ID_D6I_V1_MIX2 0x1871C062 #define ID_D6I_V1_MIX3 0x1871C063 @@ -137,14 +139,14 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser) gasmode_offset = 0x1F; gasmix_offset = 0x54; gasmix_count = 8; - } else if (parser->model == D4i) { + } else if (parser->model == D4i || parser->model == ZOOPNOVO) { gasmode_offset = 0x1D; if (id == ID_D4I_V2) gasmix_offset = 0x67; else gasmix_offset = 0x5F; gasmix_count = 1; - } else if (parser->model == D6i) { + } else if (parser->model == D6i || parser->model == VYPERNOVO) { gasmode_offset = 0x1D; if (id == ID_D6I_V2) gasmix_offset = 0x67; @@ -170,7 +172,8 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser) config += 1; } else if (parser->model == HELO2 || parser->model == D4i || parser->model == D6i || parser->model == D9tx || - parser->model == DX) { + parser->model == DX || parser->model == ZOOPNOVO || + parser->model == VYPERNOVO) { config = gasmix_offset + gasmix_count * 6; } if (config + 1 > size) @@ -190,7 +193,8 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser) for (unsigned int i = 0; i < gasmix_count; ++i) { if (parser->model == HELO2 || parser->model == D4i || parser->model == D6i || parser->model == D9tx || - parser->model == DX) { + parser->model == DX || parser->model == ZOOPNOVO || + parser->model == VYPERNOVO) { parser->oxygen[i] = data[gasmix_offset + 6 * i + 1]; parser->helium[i] = data[gasmix_offset + 6 * i + 2]; } else { @@ -207,7 +211,8 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser) if (parser->model == HELO2) { parser->gasmix = data[0x26]; } else if (parser->model == D4i || parser->model == D6i || - parser->model == D9tx) { + parser->model == D9tx || parser->model == ZOOPNOVO || + parser->model == VYPERNOVO) { if (id == ID_D4I_V2 || id == ID_D6I_V2) { parser->gasmix = data[0x2D]; } else { @@ -283,7 +288,9 @@ suunto_d9_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime) unsigned int offset = 0x11; if (parser->model == HELO2 || parser->model == DX) offset = 0x17; - else if (parser->model == D4i || parser->model == D6i || parser->model == D9tx) + else if (parser->model == D4i || parser->model == D6i || + parser->model == D9tx || parser->model == ZOOPNOVO || + parser->model == VYPERNOVO) offset = 0x13; if (abstract->size < offset + 7) @@ -293,7 +300,8 @@ suunto_d9_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime) if (datetime) { if (parser->model == D4i || parser->model == D6i || - parser->model == D9tx || parser->model == DX) { + parser->model == D9tx || parser->model == DX || + parser->model == ZOOPNOVO || parser->model == VYPERNOVO) { datetime->year = p[0] + (p[1] << 8); datetime->month = p[2]; datetime->day = p[3]; @@ -339,7 +347,8 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne if (parser->model == D4) *((unsigned int *) value) = array_uint16_le (data + 0x0B); else if (parser->model == D4i || parser->model == D6i || - parser->model == D9tx || parser->model == DX) + parser->model == D9tx || parser->model == DX || + parser->model == ZOOPNOVO || parser->model == VYPERNOVO) *((unsigned int *) value) = array_uint16_le (data + 0x0D); else if (parser->model == HELO2) *((unsigned int *) value) = array_uint16_le (data + 0x0D) * 60; @@ -460,7 +469,8 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca // Sample recording interval. unsigned int interval_sample_offset = 0x18; if (parser->model == HELO2 || parser->model == D4i || - parser->model == D6i || parser->model == D9tx) + parser->model == D6i || parser->model == D9tx || + parser->model == ZOOPNOVO || parser->model == VYPERNOVO) interval_sample_offset = 0x1E; else if (parser->model == DX) interval_sample_offset = 0x22;