Merge branch 'petrel'

This commit is contained in:
Jef Driesen 2015-07-15 14:36:55 +02:00
commit 98a7b86dcf

View File

@ -37,6 +37,12 @@
#define SZ_SAMPLE_PREDATOR 0x10
#define SZ_SAMPLE_PETREL 0x20
#define GASSWITCH 0x01
#define PPO2_EXTERNAL 0x02
#define SETPOINT_HIGH 0x04
#define SC 0x08
#define OC 0x10
#define METRIC 0
#define IMPERIAL 1
@ -47,8 +53,11 @@ typedef struct shearwater_predator_parser_t shearwater_predator_parser_t;
struct shearwater_predator_parser_t {
dc_parser_t base;
unsigned int petrel;
unsigned int samplesize;
// Cached fields.
unsigned int cached;
unsigned int headersize;
unsigned int footersize;
unsigned int ngasmixes;
unsigned int oxygen[NGASMIXES];
unsigned int helium[NGASMIXES];
@ -96,12 +105,16 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig
parser->petrel = petrel;
if (petrel) {
parser_init (&parser->base, context, &shearwater_petrel_parser_vtable);
parser->samplesize = SZ_SAMPLE_PETREL;
} else {
parser_init (&parser->base, context, &shearwater_predator_parser_vtable);
parser->samplesize = SZ_SAMPLE_PREDATOR;
}
// Set the default values.
parser->cached = 0;
parser->headersize = 0;
parser->footersize = 0;
parser->ngasmixes = 0;
for (unsigned int i = 0; i < NGASMIXES; ++i) {
parser->oxygen[i] = 0;
@ -145,6 +158,8 @@ shearwater_predator_parser_set_data (dc_parser_t *abstract, const unsigned char
// Reset the cache.
parser->cached = 0;
parser->headersize = 0;
parser->footersize = 0;
parser->ngasmixes = 0;
for (unsigned int i = 0; i < NGASMIXES; ++i) {
parser->oxygen[i] = 0;
@ -176,6 +191,7 @@ shearwater_predator_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *d
static dc_status_t
shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
{
dc_parser_t *abstract = (dc_parser_t *) parser;
const unsigned char *data = parser->base.data;
unsigned int size = parser->base.size;
@ -183,6 +199,22 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
return DC_STATUS_SUCCESS;
}
unsigned int headersize = SZ_BLOCK;
unsigned int footersize = SZ_BLOCK;
if (size < headersize + footersize) {
ERROR (abstract->context, "Invalid data length.");
return DC_STATUS_DATAFORMAT;
}
// Adjust the footersize for the final block.
if (parser->petrel || array_uint16_be (data + size - footersize) == 0xFFFD) {
footersize += SZ_BLOCK;
if (size < headersize + footersize) {
ERROR (abstract->context, "Invalid data length.");
return DC_STATUS_DATAFORMAT;
}
}
// Get the gas mixes.
unsigned int ngasmixes = 0;
unsigned int oxygen[NGASMIXES] = {0};
@ -198,6 +230,8 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
}
// Cache the data for later use.
parser->headersize = headersize;
parser->footersize = footersize;
parser->ngasmixes = ngasmixes;
for (unsigned int i = 0; i < ngasmixes; ++i) {
parser->oxygen[i] = oxygen[i];
@ -208,6 +242,33 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
return DC_STATUS_SUCCESS;
}
static dc_divemode_t
shearwater_predator_parser_get_divemode (shearwater_predator_parser_t *parser)
{
dc_parser_t *abstract = (dc_parser_t *) parser;
const unsigned char *data = abstract->data;
unsigned int size = abstract->size;
unsigned int offset = parser->headersize;
unsigned int length = size - parser->footersize;
while (offset < length) {
// Ignore empty samples.
if (array_isequal (data + offset, parser->samplesize, 0x00)) {
offset += parser->samplesize;
continue;
}
// Status flags.
unsigned int status = data[offset + 11];
if ((status & OC) == 0) {
return DC_DIVEMODE_CC;
}
offset += parser->samplesize;
}
return DC_DIVEMODE_OC;
}
static dc_status_t
shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value)
@ -217,26 +278,17 @@ shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ
const unsigned char *data = abstract->data;
unsigned int size = abstract->size;
if (size < 2 * SZ_BLOCK)
return DC_STATUS_DATAFORMAT;
// Get the offset to the footer record.
unsigned int footer = size - SZ_BLOCK;
if (parser->petrel || array_uint16_be (data + footer) == 0xFFFD) {
if (size < 3 * SZ_BLOCK)
return DC_STATUS_DATAFORMAT;
footer -= SZ_BLOCK;
}
// Get the unit system.
unsigned int units = data[8];
// Cache the gas mix data.
// Cache the parser data.
dc_status_t rc = shearwater_predator_parser_cache (parser);
if (rc != DC_STATUS_SUCCESS)
return rc;
// Get the offset to the footer record.
unsigned int footer = size - parser->footersize;
// Get the unit system.
unsigned int units = data[8];
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
dc_salinity_t *water = (dc_salinity_t *) value;
unsigned int density = 0;
@ -271,6 +323,9 @@ shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ
case DC_FIELD_ATMOSPHERIC:
*((double *) value) = array_uint16_be (data + 47) / 1000.0;
break;
case DC_FIELD_DIVEMODE:
*((dc_divemode_t *) value) = shearwater_predator_parser_get_divemode (parser);
break;
default:
return DC_STATUS_UNSUPPORTED;
}
@ -288,23 +343,10 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
const unsigned char *data = abstract->data;
unsigned int size = abstract->size;
if (size < 2 * SZ_BLOCK)
return DC_STATUS_DATAFORMAT;
// Get the offset to the footer record.
unsigned int footer = size - SZ_BLOCK;
if (parser->petrel || array_uint16_be (data + footer) == 0xFFFD) {
if (size < 3 * SZ_BLOCK)
return DC_STATUS_DATAFORMAT;
footer -= SZ_BLOCK;
}
// Get the sample size.
unsigned int samplesize = SZ_SAMPLE_PREDATOR;
if (parser->petrel) {
samplesize = SZ_SAMPLE_PETREL;
}
// Cache the parser data.
dc_status_t rc = shearwater_predator_parser_cache (parser);
if (rc != DC_STATUS_SUCCESS)
return rc;
// Get the unit system.
unsigned int units = data[8];
@ -313,13 +355,14 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
unsigned int o2_previous = 0, he_previous = 0;
unsigned int time = 0;
unsigned int offset = SZ_BLOCK;
while (offset < footer) {
unsigned int offset = parser->headersize;
unsigned int length = size - parser->footersize;
while (offset < length) {
dc_sample_value_t sample = {0};
// Ignore empty samples.
if (array_isequal (data + offset, samplesize, 0x00)) {
offset += samplesize;
if (array_isequal (data + offset, parser->samplesize, 0x00)) {
offset += parser->samplesize;
continue;
}
@ -344,10 +387,27 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
sample.temperature = temperature;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
// Status flags.
unsigned int status = data[offset + 11];
// PPO2
sample.ppo2 = data[offset + 6] / 100.0;
if (callback) callback (DC_SAMPLE_PPO2, sample, userdata);
if ((status & OC) == 0) {
// Setpoint
if (parser->petrel) {
sample.setpoint = data[offset + 18] / 100.0;
} else {
if (status & SETPOINT_HIGH) {
sample.setpoint = data[18] / 100.0;
} else {
sample.setpoint = data[17] / 100.0;
}
}
if (callback) callback (DC_SAMPLE_SETPOINT, sample, userdata);
}
// CNS
if (parser->petrel) {
sample.cns = data[offset + 22] / 100.0;
@ -382,7 +442,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
sample.deco.time = data[offset + 9] * 60;
if (callback) callback (DC_SAMPLE_DECO, sample, userdata);
offset += samplesize;
offset += parser->samplesize;
}
return DC_STATUS_SUCCESS;