From 9520ecddbc2a13504421de77bbcf9eae6f56c23d Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sun, 10 Jan 2016 22:07:42 +0100 Subject: [PATCH 1/6] Add support for the Oceanic F11. This appears to be an Oceanic branded version of the Aeris F11. --- src/descriptor.c | 1 + src/oceanic_atom2.c | 3 ++- src/oceanic_atom2_parser.c | 23 +++++++++++++++-------- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/descriptor.c b/src/descriptor.c index c5b3228..f1f23ce 100644 --- a/src/descriptor.c +++ b/src/descriptor.c @@ -179,6 +179,7 @@ static const dc_descriptor_t g_descriptors[] = { {"Aeris", "F11", DC_FAMILY_OCEANIC_ATOM2, 0x4549}, {"Oceanic", "OCi", DC_FAMILY_OCEANIC_ATOM2, 0x454B}, {"Aeris", "A300CS", DC_FAMILY_OCEANIC_ATOM2, 0x454C}, + {"Oceanic", "F11", DC_FAMILY_OCEANIC_ATOM2, 0x4554}, {"Oceanic", "VTX", DC_FAMILY_OCEANIC_ATOM2, 0x4557}, /* Mares Nemo */ {"Mares", "Nemo", DC_FAMILY_MARES_NEMO, 0}, diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c index d19d82a..3deb761 100644 --- a/src/oceanic_atom2.c +++ b/src/oceanic_atom2.c @@ -86,7 +86,8 @@ static const oceanic_common_version_t aeris_f10_version[] = { }; static const oceanic_common_version_t aeris_f11_version[] = { - {"AERISF11 \0\0 1024"}, + {"AERISF11 \0\0 1024"}, + {"OCEANF11 \0\0 1024"}, }; static const oceanic_common_version_t oceanic_atom1_version[] = { diff --git a/src/oceanic_atom2_parser.c b/src/oceanic_atom2_parser.c index 54188c2..d829047 100644 --- a/src/oceanic_atom2_parser.c +++ b/src/oceanic_atom2_parser.c @@ -70,9 +70,10 @@ #define AMPHOS 0x4545 #define AMPHOSAIR 0x4546 #define PROPLUS3 0x4548 -#define F11 0x4549 +#define F11A 0x4549 #define OCI 0x454B #define A300CS 0x454C +#define F11B 0x4554 #define VTX 0x4557 #define NORMAL 0 @@ -154,7 +155,7 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned } else if (model == F10) { parser->headersize = 3 * PAGESIZE; parser->footersize = PAGESIZE / 2; - } else if (model == F11) { + } else if (model == F11A || model == F11B) { parser->headersize = 5 * PAGESIZE; parser->footersize = PAGESIZE / 2; } else if (model == A300CS || model == VTX) { @@ -207,7 +208,8 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim oceanic_atom2_parser_t *parser = (oceanic_atom2_parser_t *) abstract; unsigned int header = 8; - if (parser->model == F10 || parser->model == F11) + if (parser->model == F10 || parser->model == F11A || + parser->model == F11B) header = 32; if (abstract->size < header) @@ -261,7 +263,8 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim datetime->minute = bcd2dec (p[0]); break; case F10: - case F11: + case F11A: + case F11B: datetime->year = bcd2dec (p[6]) + 2000; datetime->month = bcd2dec (p[7]); datetime->day = bcd2dec (p[8]); @@ -361,7 +364,8 @@ oceanic_atom2_parser_cache (oceanic_atom2_parser_t *parser) // Get the dive mode. unsigned int mode = NORMAL; - if (parser->model == F10 || parser->model == F11) { + if (parser->model == F10 || parser->model == F11A || + parser->model == F11B) { mode = FREEDIVE; } else if (parser->model == T3B || parser->model == VT3 || parser->model == DG03) { @@ -462,13 +466,15 @@ oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns if (value) { switch (type) { case DC_FIELD_DIVETIME: - if (parser->model == F10 || parser->model == F11) + if (parser->model == F10 || parser->model == F11A || + parser->model == F11B) *((unsigned int *) value) = bcd2dec (data[2]) + bcd2dec (data[3]) * 60 + bcd2dec (data[1]) * 3600; else *((unsigned int *) value) = parser->divetime; break; case DC_FIELD_MAXDEPTH: - if (parser->model == F10 || parser->model == F11) + if (parser->model == F10 || parser->model == F11A || + parser->model == F11B) *((double *) value) = array_uint16_le (data + 4) / 16.0 * FEET; else *((double *) value) = array_uint16_le (data + parser->footer + 4) / 16.0 * FEET; @@ -555,7 +561,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ unsigned int samplesize = PAGESIZE / 2; if (parser->mode == FREEDIVE) { - if (parser->model == F10 || parser->model == F11) { + if (parser->model == F10 || parser->model == F11A || + parser->model == F11B) { samplesize = 2; } else { samplesize = 4; From 9d856e5a369b3044211e4e1d8db3a11074057e20 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Mon, 11 Jan 2016 11:11:26 +0100 Subject: [PATCH 2/6] Fix the memory layout for the Oceanic F11. --- src/oceanic_atom2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/oceanic_atom2.c b/src/oceanic_atom2.c index 3deb761..67fa45a 100644 --- a/src/oceanic_atom2.c +++ b/src/oceanic_atom2.c @@ -198,9 +198,9 @@ static const oceanic_common_layout_t aeris_f11_layout = { 0x0000, /* cf_devinfo */ 0x0040, /* cf_pointers */ 0x0100, /* rb_logbook_begin */ - 0x0AC0, /* rb_logbook_end */ + 0x0D80, /* rb_logbook_end */ 32, /* rb_logbook_entry_size */ - 0xD810, /* rb_profile_begin */ + 0x0D80, /* rb_profile_begin */ 0x20000, /* rb_profile_end */ 0, /* pt_mode_global */ 3 /* pt_mode_logbook */ From 49af321bc5cff5cd3b0dc0b08ebf52e37801f85e Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 12 Jan 2016 22:37:46 +0100 Subject: [PATCH 3/6] Use the correct sample rate from the header. The Oceanic and Aeris F11 have a configurable sample rate. The possible sample intervals are 2, 1, 0.5 and 0.25 seconds. Since our smallest unit of time is one second, we can't represent the last two, and the extra samples will get dropped for now. --- src/oceanic_atom2_parser.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/oceanic_atom2_parser.c b/src/oceanic_atom2_parser.c index d829047..268f963 100644 --- a/src/oceanic_atom2_parser.c +++ b/src/oceanic_atom2_parser.c @@ -539,6 +539,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ unsigned int time = 0; unsigned int interval = 1; + unsigned int samplerate = 1; if (parser->mode != FREEDIVE) { unsigned int idx = 0x17; if (parser->model == A300CS || parser->model == VTX) @@ -557,6 +558,30 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ interval = 60; break; } + } else if (parser->model == F11A || parser->model == F11B) { + unsigned int idx = 0x29; + switch (data[idx] & 0x03) { + case 0: + interval = 1; + samplerate = 4; + break; + case 1: + interval = 1; + samplerate = 2; + break; + case 2: + interval = 1; + break; + case 3: + interval = 2; + break; + } + if (samplerate > 1) { + // Some models supports multiple samples per second. + // Since our smallest unit of time is one second, we can't + // represent this, and the extra samples will get dropped. + WARNING(abstract->context, "Multiple samples per second are not supported!"); + } } unsigned int samplesize = PAGESIZE / 2; @@ -635,7 +660,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ // The sample size is usually fixed, but some sample types have a // larger size. Check whether we have that many bytes available. - unsigned int length = samplesize; + unsigned int length = samplesize * samplerate; if (sampletype == 0xBB) { length = PAGESIZE; if (offset + length > size - PAGESIZE) From ca032783a283d798ce4603ae527b379f5964f934 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 14 Jan 2016 10:50:08 +0100 Subject: [PATCH 4/6] Fix the decoding of the dive time. I originally assumed the second byte contains the hour, but that turns out to be wrong. At least some of the bits have a different meaning. With only seconds and minutes, the maximum divetime is limited to at most 99 minutes and 59 seconds. That shouldn't be a problem for freedives. --- src/oceanic_atom2_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oceanic_atom2_parser.c b/src/oceanic_atom2_parser.c index 268f963..49cf13d 100644 --- a/src/oceanic_atom2_parser.c +++ b/src/oceanic_atom2_parser.c @@ -468,7 +468,7 @@ oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns case DC_FIELD_DIVETIME: if (parser->model == F10 || parser->model == F11A || parser->model == F11B) - *((unsigned int *) value) = bcd2dec (data[2]) + bcd2dec (data[3]) * 60 + bcd2dec (data[1]) * 3600; + *((unsigned int *) value) = bcd2dec (data[2]) + bcd2dec (data[3]) * 60; else *((unsigned int *) value) = parser->divetime; break; From 789fdb4d9afb79230acedb7d4a347ec7e6af0ca3 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sat, 16 Jan 2016 08:47:09 +0100 Subject: [PATCH 5/6] Remove the footer sample for the F10 and F11. The F10 and F11 don't seem to have a special footer sample after the profile data. Those 8 bytes appear to be valid sample data. --- src/oceanic_atom2_parser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/oceanic_atom2_parser.c b/src/oceanic_atom2_parser.c index 49cf13d..d52b379 100644 --- a/src/oceanic_atom2_parser.c +++ b/src/oceanic_atom2_parser.c @@ -154,10 +154,10 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned parser->headersize -= 2 * PAGESIZE; } else if (model == F10) { parser->headersize = 3 * PAGESIZE; - parser->footersize = PAGESIZE / 2; + parser->footersize = 0; } else if (model == F11A || model == F11B) { parser->headersize = 5 * PAGESIZE; - parser->footersize = PAGESIZE / 2; + parser->footersize = 0; } else if (model == A300CS || model == VTX) { parser->headersize = 5 * PAGESIZE; } From 6b3874121d189e4a672bc0915e890dc5e12690d9 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sat, 16 Jan 2016 17:03:06 +0100 Subject: [PATCH 6/6] Don't ignore zero depth samples in freedive mode. In freedive mode, samples are only 2 or 4 bytes large, thus a sample containing all 0x00 bytes represents a zero depth value and not some invalid data that should be ignored. --- src/oceanic_atom2_parser.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/oceanic_atom2_parser.c b/src/oceanic_atom2_parser.c index d52b379..5dc3488 100644 --- a/src/oceanic_atom2_parser.c +++ b/src/oceanic_atom2_parser.c @@ -638,7 +638,8 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_ dc_sample_value_t sample = {0}; // Ignore empty samples. - if (array_isequal (data + offset, samplesize, 0x00) || + if ((parser->mode != FREEDIVE && + array_isequal (data + offset, samplesize, 0x00)) || array_isequal (data + offset, samplesize, 0xFF)) { offset += samplesize; continue;