From 7c00b1d74e410f64368c0768eaf317d6374061b9 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Mon, 15 Nov 2010 20:46:04 +0100 Subject: [PATCH] Implement the new field api for the Reefnet devices. --- src/reefnet_sensus_parser.c | 84 +++++++++++++++++++++++++++++++- src/reefnet_sensuspro_parser.c | 74 +++++++++++++++++++++++++++- src/reefnet_sensusultra_parser.c | 73 ++++++++++++++++++++++++++- 3 files changed, 228 insertions(+), 3 deletions(-) diff --git a/src/reefnet_sensus_parser.c b/src/reefnet_sensus_parser.c index 4d2351a..185c15d 100644 --- a/src/reefnet_sensus_parser.c +++ b/src/reefnet_sensus_parser.c @@ -39,10 +39,15 @@ struct reefnet_sensus_parser_t { // Clock synchronization. unsigned int devtime; dc_ticks_t systime; + // Cached fields. + unsigned int cached; + unsigned int divetime; + unsigned int maxdepth; }; static parser_status_t reefnet_sensus_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); static parser_status_t reefnet_sensus_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime); +static parser_status_t reefnet_sensus_parser_get_field (parser_t *abstract, parser_field_type_t type, unsigned int flags, void *value); static parser_status_t reefnet_sensus_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); static parser_status_t reefnet_sensus_parser_destroy (parser_t *abstract); @@ -50,7 +55,7 @@ static const parser_backend_t reefnet_sensus_parser_backend = { PARSER_TYPE_REEFNET_SENSUS, reefnet_sensus_parser_set_data, /* set_data */ reefnet_sensus_parser_get_datetime, /* datetime */ - NULL, /* fields */ + reefnet_sensus_parser_get_field, /* fields */ reefnet_sensus_parser_samples_foreach, /* samples_foreach */ reefnet_sensus_parser_destroy /* destroy */ }; @@ -87,6 +92,9 @@ reefnet_sensus_parser_create (parser_t **out, unsigned int devtime, dc_ticks_t s parser->hydrostatic = 1025.0 * GRAVITY; parser->devtime = devtime; parser->systime = systime; + parser->cached = 0; + parser->divetime = 0; + parser->maxdepth = 0; *out = (parser_t*) parser; @@ -110,9 +118,16 @@ reefnet_sensus_parser_destroy (parser_t *abstract) static parser_status_t reefnet_sensus_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size) { + reefnet_sensus_parser_t *parser = (reefnet_sensus_parser_t*) abstract; + if (! parser_is_reefnet_sensus (abstract)) return PARSER_STATUS_TYPE_MISMATCH; + // Reset the cache. + parser->cached = 0; + parser->divetime = 0; + parser->maxdepth = 0; + return PARSER_STATUS_SUCCESS; } @@ -151,6 +166,73 @@ reefnet_sensus_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime) } +static parser_status_t +reefnet_sensus_parser_get_field (parser_t *abstract, parser_field_type_t type, unsigned int flags, void *value) +{ + reefnet_sensus_parser_t *parser = (reefnet_sensus_parser_t *) abstract; + + if (abstract->size < 7) + return PARSER_STATUS_ERROR; + + if (!parser->cached) { + const unsigned char *data = abstract->data; + unsigned int size = abstract->size; + + unsigned int maxdepth = 0; + unsigned int interval = data[1]; + unsigned int nsamples = 0, count = 0; + + unsigned int offset = 7; + while (offset + 1 <= size) { + // Depth. + unsigned int depth = data[offset++]; + if (depth > maxdepth) + maxdepth = depth; + + // Skip temperature byte. + if ((nsamples % 6) == 0) + offset++; + + // Current sample is complete. + nsamples++; + + // The end of a dive is reached when 17 consecutive + // depth samples of less than 3 feet have been found. + if (depth < SAMPLE_DEPTH_ADJUST + 3) { + count++; + if (count == 17) { + break; + } + } else { + count = 0; + } + } + + parser->cached = 1; + parser->divetime = nsamples * interval; + parser->maxdepth = maxdepth; + } + + if (value) { + switch (type) { + case FIELD_TYPE_DIVETIME: + *((unsigned int *) value) = parser->divetime; + break; + case FIELD_TYPE_MAXDEPTH: + *((double *) value) = ((parser->maxdepth + 33.0 - (double) SAMPLE_DEPTH_ADJUST) * FSW - parser->atmospheric) / parser->hydrostatic; + break; + case FIELD_TYPE_GASMIX_COUNT: + *((unsigned int *) value) = 0; + break; + default: + return PARSER_STATUS_UNSUPPORTED; + } + } + + return PARSER_STATUS_SUCCESS; +} + + static parser_status_t reefnet_sensus_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) { diff --git a/src/reefnet_sensuspro_parser.c b/src/reefnet_sensuspro_parser.c index 27e2cb1..c0f2987 100644 --- a/src/reefnet_sensuspro_parser.c +++ b/src/reefnet_sensuspro_parser.c @@ -38,10 +38,15 @@ struct reefnet_sensuspro_parser_t { // Clock synchronization. unsigned int devtime; dc_ticks_t systime; + // Cached fields. + unsigned int cached; + unsigned int divetime; + unsigned int maxdepth; }; static parser_status_t reefnet_sensuspro_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); static parser_status_t reefnet_sensuspro_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime); +static parser_status_t reefnet_sensuspro_parser_get_field (parser_t *abstract, parser_field_type_t type, unsigned int flags, void *value); static parser_status_t reefnet_sensuspro_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); static parser_status_t reefnet_sensuspro_parser_destroy (parser_t *abstract); @@ -49,7 +54,7 @@ static const parser_backend_t reefnet_sensuspro_parser_backend = { PARSER_TYPE_REEFNET_SENSUSPRO, reefnet_sensuspro_parser_set_data, /* set_data */ reefnet_sensuspro_parser_get_datetime, /* datetime */ - NULL, /* fields */ + reefnet_sensuspro_parser_get_field, /* fields */ reefnet_sensuspro_parser_samples_foreach, /* samples_foreach */ reefnet_sensuspro_parser_destroy /* destroy */ }; @@ -86,6 +91,9 @@ reefnet_sensuspro_parser_create (parser_t **out, unsigned int devtime, dc_ticks_ parser->hydrostatic = 1025.0 * GRAVITY; parser->devtime = devtime; parser->systime = systime; + parser->cached = 0; + parser->divetime = 0; + parser->maxdepth = 0; *out = (parser_t*) parser; @@ -109,9 +117,16 @@ reefnet_sensuspro_parser_destroy (parser_t *abstract) static parser_status_t reefnet_sensuspro_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size) { + reefnet_sensuspro_parser_t *parser = (reefnet_sensuspro_parser_t*) abstract; + if (! parser_is_reefnet_sensuspro (abstract)) return PARSER_STATUS_TYPE_MISMATCH; + // Reset the cache. + parser->cached = 0; + parser->divetime = 0; + parser->maxdepth = 0; + return PARSER_STATUS_SUCCESS; } @@ -150,6 +165,63 @@ reefnet_sensuspro_parser_get_datetime (parser_t *abstract, dc_datetime_t *dateti } +static parser_status_t +reefnet_sensuspro_parser_get_field (parser_t *abstract, parser_field_type_t type, unsigned int flags, void *value) +{ + reefnet_sensuspro_parser_t *parser = (reefnet_sensuspro_parser_t *) abstract; + + if (abstract->size < 12) + return PARSER_STATUS_ERROR; + + if (!parser->cached) { + const unsigned char footer[2] = {0xFF, 0xFF}; + + const unsigned char *data = abstract->data; + unsigned int size = abstract->size; + + unsigned int interval = array_uint16_le (data + 4); + + unsigned int maxdepth = 0; + unsigned int nsamples = 0; + unsigned int offset = 10; + while (offset + sizeof (footer) <= size && + memcmp (data + offset, footer, sizeof (footer)) != 0) + { + unsigned int value = array_uint16_le (data + offset); + unsigned int depth = (value & 0x01FF); + if (depth > maxdepth) + maxdepth = depth; + + nsamples++; + + offset += 2; + } + + parser->cached = 1; + parser->divetime = nsamples * interval; + parser->maxdepth = maxdepth; + } + + if (value) { + switch (type) { + case FIELD_TYPE_DIVETIME: + *((unsigned int *) value) = parser->divetime; + break; + case FIELD_TYPE_MAXDEPTH: + *((double *) value) = (parser->maxdepth * FSW - parser->atmospheric) / parser->hydrostatic; + break; + case FIELD_TYPE_GASMIX_COUNT: + *((unsigned int *) value) = 0; + break; + default: + return PARSER_STATUS_UNSUPPORTED; + } + } + + return PARSER_STATUS_SUCCESS; +} + + static parser_status_t reefnet_sensuspro_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) { diff --git a/src/reefnet_sensusultra_parser.c b/src/reefnet_sensusultra_parser.c index 9ad164d..1203c4c 100644 --- a/src/reefnet_sensusultra_parser.c +++ b/src/reefnet_sensusultra_parser.c @@ -38,10 +38,15 @@ struct reefnet_sensusultra_parser_t { // Clock synchronization. unsigned int devtime; dc_ticks_t systime; + // Cached fields. + unsigned int cached; + unsigned int divetime; + unsigned int maxdepth; }; static parser_status_t reefnet_sensusultra_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); static parser_status_t reefnet_sensusultra_parser_get_datetime (parser_t *abstract, dc_datetime_t *datetime); +static parser_status_t reefnet_sensusultra_parser_get_field (parser_t *abstract, parser_field_type_t type, unsigned int flags, void *value); static parser_status_t reefnet_sensusultra_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); static parser_status_t reefnet_sensusultra_parser_destroy (parser_t *abstract); @@ -49,7 +54,7 @@ static const parser_backend_t reefnet_sensusultra_parser_backend = { PARSER_TYPE_REEFNET_SENSUSULTRA, reefnet_sensusultra_parser_set_data, /* set_data */ reefnet_sensusultra_parser_get_datetime, /* datetime */ - NULL, /* fields */ + reefnet_sensusultra_parser_get_field, /* fields */ reefnet_sensusultra_parser_samples_foreach, /* samples_foreach */ reefnet_sensusultra_parser_destroy /* destroy */ }; @@ -86,6 +91,9 @@ reefnet_sensusultra_parser_create (parser_t **out, unsigned int devtime, dc_tick parser->hydrostatic = 1025.0 * GRAVITY; parser->devtime = devtime; parser->systime = systime; + parser->cached = 0; + parser->divetime = 0; + parser->maxdepth = 0; *out = (parser_t*) parser; @@ -109,9 +117,16 @@ reefnet_sensusultra_parser_destroy (parser_t *abstract) static parser_status_t reefnet_sensusultra_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size) { + reefnet_sensusultra_parser_t *parser = (reefnet_sensusultra_parser_t*) abstract; + if (! parser_is_reefnet_sensusultra (abstract)) return PARSER_STATUS_TYPE_MISMATCH; + // Reset the cache. + parser->cached = 0; + parser->divetime = 0; + parser->maxdepth = 0; + return PARSER_STATUS_SUCCESS; } @@ -150,6 +165,62 @@ reefnet_sensusultra_parser_get_datetime (parser_t *abstract, dc_datetime_t *date } +static parser_status_t +reefnet_sensusultra_parser_get_field (parser_t *abstract, parser_field_type_t type, unsigned int flags, void *value) +{ + reefnet_sensusultra_parser_t *parser = (reefnet_sensusultra_parser_t *) abstract; + + if (abstract->size < 20) + return PARSER_STATUS_ERROR; + + if (!parser->cached) { + const unsigned char footer[4] = {0xFF, 0xFF, 0xFF, 0xFF}; + + const unsigned char *data = abstract->data; + unsigned int size = abstract->size; + + unsigned int interval = array_uint16_le (data + 8); + + unsigned int maxdepth = 0; + unsigned int nsamples = 0; + unsigned int offset = 16; + while (offset + sizeof (footer) <= size && + memcmp (data + offset, footer, sizeof (footer)) != 0) + { + unsigned int depth = array_uint16_le (data + offset + 2); + if (depth > maxdepth) + maxdepth = depth; + + nsamples++; + + offset += 4; + } + + parser->cached = 1; + parser->divetime = nsamples * interval; + parser->maxdepth = maxdepth; + } + + if (value) { + switch (type) { + case FIELD_TYPE_DIVETIME: + *((unsigned int *) value) = parser->divetime; + break; + case FIELD_TYPE_MAXDEPTH: + *((double *) value) = (parser->maxdepth * BAR / 1000.0 - parser->atmospheric) / parser->hydrostatic; + break; + case FIELD_TYPE_GASMIX_COUNT: + *((unsigned int *) value) = 0; + break; + default: + return PARSER_STATUS_UNSUPPORTED; + } + } + + return PARSER_STATUS_SUCCESS; +} + + static parser_status_t reefnet_sensusultra_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) {