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
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
}
#endif /* __cplusplus */

View File

@ -31,10 +31,13 @@
#define SZ_HEADER 82
#define DRAKE 6
typedef struct cressi_leonardo_parser_t cressi_leonardo_parser_t;
struct cressi_leonardo_parser_t {
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);
@ -54,7 +57,7 @@ static const dc_parser_vtable_t cressi_leonardo_parser_vtable = {
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;
@ -68,12 +71,21 @@ cressi_leonardo_parser_create (dc_parser_t **out, dc_context_t *context)
return DC_STATUS_NOMEMORY;
}
parser->model = model;
*out = (dc_parser_t*) parser;
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
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
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)
return DC_STATUS_DATAFORMAT;
const unsigned char *data = abstract->data;
unsigned int interval = 20;
if (parser->model == DRAKE) {
interval = 1;
}
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
if (value) {
switch (type) {
case DC_FIELD_DIVETIME:
*((unsigned int *) value) = array_uint16_le (data + 0x06) * 20;
*((unsigned int *) value) = array_uint16_le (data + 0x06) * interval;
break;
case DC_FIELD_MAXDEPTH:
*((double *) value) = array_uint16_le (data + 0x20) / 10.0;
break;
case DC_FIELD_GASMIX_COUNT:
*((unsigned int *) value) = 1;
if (parser->model == DRAKE) {
*((unsigned int *) value) = 0;
} else {
*((unsigned int *) value) = 1;
}
break;
case DC_FIELD_GASMIX:
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
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;
unsigned int size = abstract->size;
unsigned int time = 0;
unsigned int interval = 20;
if (parser->model == DRAKE) {
interval = 1;
}
unsigned int gasmix_previous = 0xFFFFFFFF;
unsigned int gasmix = 0;
@ -156,36 +182,53 @@ cressi_leonardo_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
while (offset + 2 <= size) {
dc_sample_value_t sample = {0};
unsigned int value = array_uint16_le (data + offset);
unsigned int depth = value & 0x07FF;
unsigned int ascent = (value & 0xC000) >> 14;
if (offset + 4 <= size &&
array_uint16_le (data + offset + 2) == 0xFF00)
{
unsigned int surftime = data[offset] + (data[offset + 1] & 0x07) * 60;
// Time (seconds).
time += interval;
sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
// Time (seconds).
time += surftime;
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);
// Depth (1/10 m).
sample.depth = 0.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;
offset += 4;
} else {
unsigned int value = array_uint16_le (data + offset);
unsigned int depth = value & 0x07FF;
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;

View File

@ -253,6 +253,7 @@ static const dc_descriptor_t g_descriptors[] = {
{"Cressi", "Leonardo", DC_FAMILY_CRESSI_LEONARDO, 1},
{"Cressi", "Giotto", DC_FAMILY_CRESSI_LEONARDO, 4},
{"Cressi", "Newton", DC_FAMILY_CRESSI_LEONARDO, 5},
{"Cressi", "Drake", DC_FAMILY_CRESSI_LEONARDO, 6},
/* Zeagle N2iTiON3 */
{"Zeagle", "N2iTiON3", 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
cressi_edy_parser_create
cressi_leonardo_parser_create
cressi_leonardo_parser_create2
atomics_cobalt_parser_create
atomics_cobalt_parser_set_calibration
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);
break;
case DC_FAMILY_CRESSI_LEONARDO:
rc = cressi_leonardo_parser_create (&parser, context);
rc = cressi_leonardo_parser_create2 (&parser, context, model);
break;
case DC_FAMILY_ATOMICS_COBALT:
rc = atomics_cobalt_parser_create (&parser, context);