Add support for the Cressi Drake

The Cressi Drake is a mainly a freedive computer. The data format is
almost identical to the Leonardo. The main difference is that a single
dive now contains an entire freedive session. Each freedive in the
session is delimited with a 4 byte header containing the surface
interval and a special marker.
This commit is contained in:
Jef Driesen 2016-10-29 23:25:33 +02:00
parent 3dbfe9d66d
commit 07dcc8998b
5 changed files with 78 additions and 30 deletions

View File

@ -39,6 +39,9 @@ cressi_leonardo_extract_dives (dc_device_t *abstract, const unsigned char data[]
dc_status_t dc_status_t
cressi_leonardo_parser_create (dc_parser_t **parser, dc_context_t *context); cressi_leonardo_parser_create (dc_parser_t **parser, dc_context_t *context);
dc_status_t
cressi_leonardo_parser_create2 (dc_parser_t **parser, dc_context_t *context, unsigned int model);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */

View File

@ -31,10 +31,13 @@
#define SZ_HEADER 82 #define SZ_HEADER 82
#define DRAKE 6
typedef struct cressi_leonardo_parser_t cressi_leonardo_parser_t; typedef struct cressi_leonardo_parser_t cressi_leonardo_parser_t;
struct cressi_leonardo_parser_t { struct cressi_leonardo_parser_t {
dc_parser_t base; dc_parser_t base;
unsigned int model;
}; };
static dc_status_t cressi_leonardo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size); static dc_status_t cressi_leonardo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
@ -54,7 +57,7 @@ static const dc_parser_vtable_t cressi_leonardo_parser_vtable = {
dc_status_t dc_status_t
cressi_leonardo_parser_create (dc_parser_t **out, dc_context_t *context) cressi_leonardo_parser_create2 (dc_parser_t **out, dc_context_t *context, unsigned int model)
{ {
cressi_leonardo_parser_t *parser = NULL; cressi_leonardo_parser_t *parser = NULL;
@ -68,12 +71,21 @@ cressi_leonardo_parser_create (dc_parser_t **out, dc_context_t *context)
return DC_STATUS_NOMEMORY; return DC_STATUS_NOMEMORY;
} }
parser->model = model;
*out = (dc_parser_t*) parser; *out = (dc_parser_t*) parser;
return DC_STATUS_SUCCESS; return DC_STATUS_SUCCESS;
} }
dc_status_t
cressi_leonardo_parser_create (dc_parser_t **parser, dc_context_t *context)
{
return cressi_leonardo_parser_create2 (parser, context, 0);
}
static dc_status_t static dc_status_t
cressi_leonardo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size) cressi_leonardo_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
{ {
@ -105,23 +117,33 @@ cressi_leonardo_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datet
static dc_status_t static dc_status_t
cressi_leonardo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value) cressi_leonardo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value)
{ {
cressi_leonardo_parser_t *parser = (cressi_leonardo_parser_t *) abstract;
if (abstract->size < SZ_HEADER) if (abstract->size < SZ_HEADER)
return DC_STATUS_DATAFORMAT; return DC_STATUS_DATAFORMAT;
const unsigned char *data = abstract->data; const unsigned char *data = abstract->data;
unsigned int interval = 20;
if (parser->model == DRAKE) {
interval = 1;
}
dc_gasmix_t *gasmix = (dc_gasmix_t *) value; dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
if (value) { if (value) {
switch (type) { switch (type) {
case DC_FIELD_DIVETIME: case DC_FIELD_DIVETIME:
*((unsigned int *) value) = array_uint16_le (data + 0x06) * 20; *((unsigned int *) value) = array_uint16_le (data + 0x06) * interval;
break; break;
case DC_FIELD_MAXDEPTH: case DC_FIELD_MAXDEPTH:
*((double *) value) = array_uint16_le (data + 0x20) / 10.0; *((double *) value) = array_uint16_le (data + 0x20) / 10.0;
break; break;
case DC_FIELD_GASMIX_COUNT: case DC_FIELD_GASMIX_COUNT:
*((unsigned int *) value) = 1; if (parser->model == DRAKE) {
*((unsigned int *) value) = 0;
} else {
*((unsigned int *) value) = 1;
}
break; break;
case DC_FIELD_GASMIX: case DC_FIELD_GASMIX:
gasmix->helium = 0.0; gasmix->helium = 0.0;
@ -143,11 +165,15 @@ cressi_leonardo_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, u
static dc_status_t static dc_status_t
cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata) cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
{ {
cressi_leonardo_parser_t *parser = (cressi_leonardo_parser_t *) abstract;
const unsigned char *data = abstract->data; const unsigned char *data = abstract->data;
unsigned int size = abstract->size; unsigned int size = abstract->size;
unsigned int time = 0; unsigned int time = 0;
unsigned int interval = 20; unsigned int interval = 20;
if (parser->model == DRAKE) {
interval = 1;
}
unsigned int gasmix_previous = 0xFFFFFFFF; unsigned int gasmix_previous = 0xFFFFFFFF;
unsigned int gasmix = 0; unsigned int gasmix = 0;
@ -156,36 +182,53 @@ cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
while (offset + 2 <= size) { while (offset + 2 <= size) {
dc_sample_value_t sample = {0}; dc_sample_value_t sample = {0};
unsigned int value = array_uint16_le (data + offset); if (offset + 4 <= size &&
unsigned int depth = value & 0x07FF; array_uint16_le (data + offset + 2) == 0xFF00)
unsigned int ascent = (value & 0xC000) >> 14; {
unsigned int surftime = data[offset] + (data[offset + 1] & 0x07) * 60;
// Time (seconds). // Time (seconds).
time += interval; time += surftime;
sample.time = time; sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata); if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
// Depth (1/10 m). // Depth (1/10 m).
sample.depth = depth / 10.0; sample.depth = 0.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
// Gas change. offset += 4;
if (gasmix != gasmix_previous) { } else {
sample.gasmix = gasmix; unsigned int value = array_uint16_le (data + offset);
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata); unsigned int depth = value & 0x07FF;
gasmix_previous = gasmix; unsigned int ascent = (value & 0xC000) >> 14;
// Time (seconds).
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
// Depth (1/10 m).
sample.depth = depth / 10.0;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
// Gas change.
if (gasmix != gasmix_previous) {
sample.gasmix = gasmix;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
gasmix_previous = gasmix;
}
// Ascent rate
if (ascent) {
sample.event.type = SAMPLE_EVENT_ASCENT;
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = ascent;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
}
offset += 2;
} }
// Ascent rate
if (ascent) {
sample.event.type = SAMPLE_EVENT_ASCENT;
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = ascent;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
}
offset += 2;
} }
return DC_STATUS_SUCCESS; return DC_STATUS_SUCCESS;

View File

@ -253,6 +253,7 @@ static const dc_descriptor_t g_descriptors[] = {
{"Cressi", "Leonardo", DC_FAMILY_CRESSI_LEONARDO, 1}, {"Cressi", "Leonardo", DC_FAMILY_CRESSI_LEONARDO, 1},
{"Cressi", "Giotto", DC_FAMILY_CRESSI_LEONARDO, 4}, {"Cressi", "Giotto", DC_FAMILY_CRESSI_LEONARDO, 4},
{"Cressi", "Newton", DC_FAMILY_CRESSI_LEONARDO, 5}, {"Cressi", "Newton", DC_FAMILY_CRESSI_LEONARDO, 5},
{"Cressi", "Drake", DC_FAMILY_CRESSI_LEONARDO, 6},
/* Zeagle N2iTiON3 */ /* Zeagle N2iTiON3 */
{"Zeagle", "N2iTiON3", DC_FAMILY_ZEAGLE_N2ITION3, 0}, {"Zeagle", "N2iTiON3", DC_FAMILY_ZEAGLE_N2ITION3, 0},
{"Apeks", "Quantum X", DC_FAMILY_ZEAGLE_N2ITION3, 0}, {"Apeks", "Quantum X", DC_FAMILY_ZEAGLE_N2ITION3, 0},

View File

@ -66,6 +66,7 @@ hw_ostc_parser_create
hw_ostc3_parser_create hw_ostc3_parser_create
cressi_edy_parser_create cressi_edy_parser_create
cressi_leonardo_parser_create cressi_leonardo_parser_create
cressi_leonardo_parser_create2
atomics_cobalt_parser_create atomics_cobalt_parser_create
atomics_cobalt_parser_set_calibration atomics_cobalt_parser_set_calibration
shearwater_predator_parser_create shearwater_predator_parser_create

View File

@ -123,7 +123,7 @@ dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t fa
rc = cressi_edy_parser_create (&parser, context, model); rc = cressi_edy_parser_create (&parser, context, model);
break; break;
case DC_FAMILY_CRESSI_LEONARDO: case DC_FAMILY_CRESSI_LEONARDO:
rc = cressi_leonardo_parser_create (&parser, context); rc = cressi_leonardo_parser_create2 (&parser, context, model);
break; break;
case DC_FAMILY_ATOMICS_COBALT: case DC_FAMILY_ATOMICS_COBALT:
rc = atomics_cobalt_parser_create (&parser, context); rc = atomics_cobalt_parser_create (&parser, context);