From 533e033b88a4a9613a614183cc08aadd689cbe46 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 11 Aug 2011 23:00:48 +0200 Subject: [PATCH] Use the sample configuration data to parse the sample data. The sample configuration data describes which sample data is available and how it is stored. Using this data should be more reliable than using a hardcoded configuration. --- src/suunto_d9_parser.c | 93 ++++++++++++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 30 deletions(-) diff --git a/src/suunto_d9_parser.c b/src/suunto_d9_parser.c index 55a5c67..dbe18e4 100644 --- a/src/suunto_d9_parser.c +++ b/src/suunto_d9_parser.c @@ -28,6 +28,7 @@ #include "array.h" #define SKIP 4 +#define MAXPARAMS 3 #define D9 0x0E #define D6 0x0F @@ -45,6 +46,13 @@ struct suunto_d9_parser_t { unsigned int model; }; +typedef struct sample_info_t { + unsigned int type; + unsigned int size; + unsigned int interval; + unsigned int divisor; +} sample_info_t; + static parser_status_t suunto_d9_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); static parser_status_t suunto_d9_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime); static parser_status_t suunto_d9_parser_get_field (parser_t *abstract, parser_field_type_t type, unsigned int flags, void *value); @@ -226,6 +234,31 @@ suunto_d9_parser_samples_foreach (parser_t *abstract, sample_callback_t callback // Number of parameters in the configuration data. unsigned int nparams = data[config]; + if (nparams > MAXPARAMS) + return PARSER_STATUS_ERROR; + + // Available divisor values. + const unsigned int divisors[] = {1, 2, 4, 5, 10, 50, 100, 1000}; + + // Get the sample configuration. + sample_info_t info[MAXPARAMS] = {{0}}; + for (unsigned int i = 0; i < nparams; ++i) { + unsigned int idx = config + 2 + i * 3; + info[i].type = data[idx + 0]; + info[i].interval = data[idx + 1]; + info[i].divisor = divisors[(data[idx + 2] & 0x1C) >> 2]; + switch (info[i].type) { + case 0x64: // Depth + case 0x68: // Pressure + info[i].size = 2; + break; + case 0x74: // Temperature + info[i].size = 1; + break; + default: // Unknown sample type + return PARSER_STATUS_ERROR; + } + } // Offset to the profile data. unsigned int profile = config + 2 + nparams * 3; @@ -247,50 +280,50 @@ suunto_d9_parser_samples_foreach (parser_t *abstract, sample_callback_t callback if (interval_sample == 0) return PARSER_STATUS_ERROR; - // Temperature recording interval. - unsigned int interval_temperature = data[config + 2 + (nparams - 1) * 3 + 1]; - if (interval_temperature == 0) - return PARSER_STATUS_ERROR; - // Offset to the first marker position. unsigned int marker = array_uint16_le (data + profile + 3); unsigned int time = 0; unsigned int nsamples = 0; unsigned int offset = profile + 5; - while (offset + 2 <= size) { + while (offset < size) { parser_sample_value_t sample = {0}; // Time (seconds). sample.time = time; if (callback) callback (SAMPLE_TYPE_TIME, sample, userdata); - // Depth (cm). - unsigned int depth = array_uint16_le (data + offset); - sample.depth = depth / 100.0; - if (callback) callback (SAMPLE_TYPE_DEPTH, sample, userdata); - offset += 2; + // Sample data. + for (unsigned int i = 0; i < nparams; ++i) { + if (info[i].interval && (nsamples % info[i].interval) == 0) { + if (offset + info[i].size > size) + return PARSER_STATUS_ERROR; - // Tank pressure (1/100 bar). - if (nparams == 3) { - if (offset + 2 > size) - return PARSER_STATUS_ERROR; - unsigned int pressure = array_uint16_le (data + offset); - if (pressure != 0xFFFF) { - sample.pressure.tank = 0; - sample.pressure.value = pressure / 100.0; - if (callback) callback (SAMPLE_TYPE_PRESSURE, sample, userdata); + unsigned int value = 0; + switch (info[i].type) { + case 0x64: // Depth + value = array_uint16_le (data + offset); + sample.depth = value / (double) info[i].divisor; + if (callback) callback (SAMPLE_TYPE_DEPTH, sample, userdata); + break; + case 0x68: // Pressure + value = array_uint16_le (data + offset); + if (value != 0xFFFF) { + sample.pressure.tank = 0; + sample.pressure.value = value / (double) info[i].divisor; + if (callback) callback (SAMPLE_TYPE_PRESSURE, sample, userdata); + } + break; + case 0x74: // Temperature + sample.temperature = (signed char) data[offset] / (double) info[i].divisor; + if (callback) callback (SAMPLE_TYPE_TEMPERATURE, sample, userdata); + break; + default: // Unknown sample type + return PARSER_STATUS_ERROR; + } + + offset += info[i].size; } - offset += 2; - } - - // Temperature (degrees celcius). - if (nsamples % interval_temperature == 0) { - if (offset + 1 > size) - return PARSER_STATUS_ERROR; - sample.temperature = (signed char) data[offset]; - if (callback) callback (SAMPLE_TYPE_TEMPERATURE, sample, userdata); - offset += 1; } // Events