From ce57cc756dd56a1ef3a1a0d9af8fb8f2319b178c Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 31 Oct 2008 14:03:10 +0000 Subject: [PATCH] Added a parser for the Reefnet Sensus Pro. --- src/Makefile.am | 2 +- src/libdivecomputer.symbols | 3 + src/parser.h | 3 +- src/reefnet_sensuspro.h | 11 +- src/reefnet_sensuspro_parser.c | 185 +++++++++++++++++++++++++++++++++ 5 files changed, 200 insertions(+), 4 deletions(-) create mode 100644 src/reefnet_sensuspro_parser.c diff --git a/src/Makefile.am b/src/Makefile.am index 3d65b35..fa2a3a8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -43,7 +43,7 @@ libdivecomputer_la_SOURCES = \ suunto_vyper2.h suunto_vyper2.c \ suunto_d9.h suunto_d9.c \ reefnet.h \ - reefnet_sensuspro.h reefnet_sensuspro.c \ + reefnet_sensuspro.h reefnet_sensuspro.c reefnet_sensuspro_parser.c \ reefnet_sensusultra.h reefnet_sensusultra.c \ uwatec.h \ uwatec_aladin.h uwatec_aladin.c \ diff --git a/src/libdivecomputer.symbols b/src/libdivecomputer.symbols index 271261f..7ab4dfb 100644 --- a/src/libdivecomputer.symbols +++ b/src/libdivecomputer.symbols @@ -3,6 +3,9 @@ parser_set_data parser_samples_foreach parser_destroy +reefnet_sensuspro_parser_create +reefnet_sensuspro_parser_set_calibration + device_close device_dump device_foreach diff --git a/src/parser.h b/src/parser.h index 0eb81de..50e71b9 100644 --- a/src/parser.h +++ b/src/parser.h @@ -27,7 +27,8 @@ extern "C" { #endif /* __cplusplus */ typedef enum parser_type_t { - PARSER_TYPE_NULL = 0 + PARSER_TYPE_NULL = 0, + PARSER_TYPE_REEFNET_SENSUSPRO } parser_type_t; typedef enum parser_status_t { diff --git a/src/reefnet_sensuspro.h b/src/reefnet_sensuspro.h index be1025d..9ca9bd0 100644 --- a/src/reefnet_sensuspro.h +++ b/src/reefnet_sensuspro.h @@ -22,12 +22,13 @@ #ifndef REEFNET_SENSUSPRO_H #define REEFNET_SENSUSPRO_H +#include "device.h" +#include "parser.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -#include "device.h" - #define REEFNET_SENSUSPRO_MEMORY_SIZE 56320 #define REEFNET_SENSUSPRO_HANDSHAKE_SIZE 10 @@ -43,6 +44,12 @@ reefnet_sensuspro_device_write_interval (device_t *device, unsigned char interva device_status_t reefnet_sensuspro_extract_dives (const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata, unsigned int timestamp); +parser_status_t +reefnet_sensuspro_parser_create (parser_t **parser); + +parser_status_t +reefnet_sensuspro_parser_set_calibration (parser_t *parser, double atmospheric, double hydrostatic); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/reefnet_sensuspro_parser.c b/src/reefnet_sensuspro_parser.c new file mode 100644 index 0000000..1011990 --- /dev/null +++ b/src/reefnet_sensuspro_parser.c @@ -0,0 +1,185 @@ +/* + * libdivecomputer + * + * Copyright (C) 2008 Jef Driesen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ + +#include +#include // memcmp +#include + +#include "reefnet_sensuspro.h" +#include "parser-private.h" +#include "units.h" +#include "utils.h" + +#define WARNING(expr) \ +{ \ + message ("%s:%d: %s\n", __FILE__, __LINE__, expr); \ +} + +typedef struct reefnet_sensuspro_parser_t reefnet_sensuspro_parser_t; + +struct reefnet_sensuspro_parser_t { + parser_t base; + // Depth calibration. + double atmospheric; + double hydrostatic; +}; + +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_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); +static parser_status_t reefnet_sensuspro_parser_destroy (parser_t *abstract); + +static const parser_backend_t reefnet_sensuspro_parser_backend = { + PARSER_TYPE_REEFNET_SENSUSPRO, + reefnet_sensuspro_parser_set_data, /* set_data */ + reefnet_sensuspro_parser_samples_foreach, /* samples_foreach */ + reefnet_sensuspro_parser_destroy /* destroy */ +}; + + +static int +parser_is_reefnet_sensuspro (parser_t *abstract) +{ + if (abstract == NULL) + return 0; + + return abstract->backend == &reefnet_sensuspro_parser_backend; +} + + +parser_status_t +reefnet_sensuspro_parser_create (parser_t **out) +{ + if (out == NULL) + return PARSER_STATUS_ERROR; + + // Allocate memory. + reefnet_sensuspro_parser_t *parser = malloc (sizeof (reefnet_sensuspro_parser_t)); + if (parser == NULL) { + WARNING ("Failed to allocate memory."); + return PARSER_STATUS_MEMORY; + } + + // Initialize the base class. + parser_init (&parser->base, &reefnet_sensuspro_parser_backend); + + // Set the default values. + parser->atmospheric = ATM; + parser->hydrostatic = 1025.0 * GRAVITY; + + *out = (parser_t*) parser; + + return PARSER_STATUS_SUCCESS; +} + + +static parser_status_t +reefnet_sensuspro_parser_destroy (parser_t *abstract) +{ + if (! parser_is_reefnet_sensuspro (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + // Free memory. + free (abstract); + + return PARSER_STATUS_SUCCESS; +} + + +static parser_status_t +reefnet_sensuspro_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size) +{ + if (! parser_is_reefnet_sensuspro (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + return PARSER_STATUS_SUCCESS; +} + + +parser_status_t +reefnet_sensuspro_parser_set_calibration (parser_t *abstract, double atmospheric, double hydrostatic) +{ + reefnet_sensuspro_parser_t *parser = (reefnet_sensuspro_parser_t*) abstract; + + if (! parser_is_reefnet_sensuspro (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + parser->atmospheric = atmospheric; + parser->hydrostatic = hydrostatic; + + return PARSER_STATUS_SUCCESS; +} + + +static parser_status_t +reefnet_sensuspro_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) +{ + reefnet_sensuspro_parser_t *parser = (reefnet_sensuspro_parser_t*) abstract; + + if (! parser_is_reefnet_sensuspro (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + const unsigned char header[4] = {0x00, 0x00, 0x00, 0x00}; + const unsigned char footer[2] = {0xFF, 0xFF}; + + const unsigned char *data = abstract->data; + unsigned int size = abstract->size; + + unsigned int offset = 0; + while (offset + sizeof (header) <= size) { + if (memcmp (data + offset, header, sizeof (header)) == 0) { + assert (offset + 10 <= size); + + unsigned int time = 0; + unsigned int interval = data[offset + 4] + (data[offset + 5] << 8); + + offset += 10; + while (offset + sizeof (footer) <= size && + memcmp (data + offset, footer, sizeof (footer)) != 0) + { + unsigned int value = data[offset + 0] + (data[offset + 1] << 8); + unsigned int depth = (value & 0x01FF); + unsigned int temperature = (value & 0xFE00) >> 9; + + parser_sample_value_t sample = {0}; + + // Time (seconds) + sample.time = time; + if (callback) callback (SAMPLE_TYPE_TIME, sample, userdata); + + // Temperature (°F) + sample.temperature = (temperature - 32.0) * (5.0 / 9.0); + if (callback) callback (SAMPLE_TYPE_TEMPERATURE, sample, userdata); + + // Depth (absolute pressure in fsw) + sample.depth = (depth * FSW - parser->atmospheric) / parser->hydrostatic; + if (callback) callback (SAMPLE_TYPE_DEPTH, sample, userdata); + + time += interval; + offset += 2; + } + break; + } else { + offset++; + } + } + + return PARSER_STATUS_SUCCESS; +}