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.
This commit is contained in:
Jef Driesen 2011-08-11 23:00:48 +02:00
parent bc756d7663
commit 533e033b88

View File

@ -28,6 +28,7 @@
#include "array.h" #include "array.h"
#define SKIP 4 #define SKIP 4
#define MAXPARAMS 3
#define D9 0x0E #define D9 0x0E
#define D6 0x0F #define D6 0x0F
@ -45,6 +46,13 @@ struct suunto_d9_parser_t {
unsigned int model; 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_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_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); 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. // Number of parameters in the configuration data.
unsigned int nparams = data[config]; 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. // Offset to the profile data.
unsigned int profile = config + 2 + nparams * 3; 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) if (interval_sample == 0)
return PARSER_STATUS_ERROR; 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. // Offset to the first marker position.
unsigned int marker = array_uint16_le (data + profile + 3); unsigned int marker = array_uint16_le (data + profile + 3);
unsigned int time = 0; unsigned int time = 0;
unsigned int nsamples = 0; unsigned int nsamples = 0;
unsigned int offset = profile + 5; unsigned int offset = profile + 5;
while (offset + 2 <= size) { while (offset < size) {
parser_sample_value_t sample = {0}; parser_sample_value_t sample = {0};
// Time (seconds). // Time (seconds).
sample.time = time; sample.time = time;
if (callback) callback (SAMPLE_TYPE_TIME, sample, userdata); if (callback) callback (SAMPLE_TYPE_TIME, sample, userdata);
// Depth (cm). // Sample data.
unsigned int depth = array_uint16_le (data + offset); for (unsigned int i = 0; i < nparams; ++i) {
sample.depth = depth / 100.0; if (info[i].interval && (nsamples % info[i].interval) == 0) {
if (callback) callback (SAMPLE_TYPE_DEPTH, sample, userdata); if (offset + info[i].size > size)
offset += 2; return PARSER_STATUS_ERROR;
// Tank pressure (1/100 bar). unsigned int value = 0;
if (nparams == 3) { switch (info[i].type) {
if (offset + 2 > size) case 0x64: // Depth
return PARSER_STATUS_ERROR; value = array_uint16_le (data + offset);
unsigned int pressure = array_uint16_le (data + offset); sample.depth = value / (double) info[i].divisor;
if (pressure != 0xFFFF) { if (callback) callback (SAMPLE_TYPE_DEPTH, sample, userdata);
sample.pressure.tank = 0; break;
sample.pressure.value = pressure / 100.0; case 0x68: // Pressure
if (callback) callback (SAMPLE_TYPE_PRESSURE, sample, userdata); 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 // Events