diff --git a/msvc/libdivecomputer.vcproj b/msvc/libdivecomputer.vcproj index 2d9d954..b9507b7 100644 --- a/msvc/libdivecomputer.vcproj +++ b/msvc/libdivecomputer.vcproj @@ -220,6 +220,10 @@ RelativePath="..\src\reefnet_sensus.c" > + + diff --git a/src/Makefile.am b/src/Makefile.am index b57bc76..766850c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -50,7 +50,7 @@ libdivecomputer_la_SOURCES = \ suunto_vyper2.h suunto_vyper2.c \ suunto_d9.h suunto_d9.c suunto_d9_parser.c \ reefnet.h \ - reefnet_sensus.h reefnet_sensus.c \ + reefnet_sensus.h reefnet_sensus.c reefnet_sensus_parser.c \ reefnet_sensuspro.h reefnet_sensuspro.c reefnet_sensuspro_parser.c \ reefnet_sensusultra.h reefnet_sensusultra.c reefnet_sensusultra_parser.c \ uwatec.h \ diff --git a/src/libdivecomputer.symbols b/src/libdivecomputer.symbols index 3a05a1e..ad15ae5 100644 --- a/src/libdivecomputer.symbols +++ b/src/libdivecomputer.symbols @@ -3,6 +3,8 @@ parser_set_data parser_samples_foreach parser_destroy +reefnet_sensus_parser_create +reefnet_sensus_parser_set_calibration reefnet_sensuspro_parser_create reefnet_sensuspro_parser_set_calibration reefnet_sensusultra_parser_create diff --git a/src/parser.h b/src/parser.h index 8ad9f6d..9da7024 100644 --- a/src/parser.h +++ b/src/parser.h @@ -32,6 +32,7 @@ typedef enum parser_type_t { PARSER_TYPE_SUUNTO_SPYDER, PARSER_TYPE_SUUNTO_VYPER, PARSER_TYPE_SUUNTO_D9, + PARSER_TYPE_REEFNET_SENSUS, PARSER_TYPE_REEFNET_SENSUSPRO, PARSER_TYPE_REEFNET_SENSUSULTRA, PARSER_TYPE_UWATEC_MEMOMOUSE, diff --git a/src/reefnet_sensus.h b/src/reefnet_sensus.h index 8f3c438..42577c1 100644 --- a/src/reefnet_sensus.h +++ b/src/reefnet_sensus.h @@ -23,6 +23,7 @@ #define REEFNET_SENSUS_H #include "device.h" +#include "parser.h" #ifdef __cplusplus extern "C" { @@ -37,6 +38,12 @@ reefnet_sensus_device_open (device_t **device, const char* name); device_status_t reefnet_sensus_extract_dives (const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata); +parser_status_t +reefnet_sensus_parser_create (parser_t **parser); + +parser_status_t +reefnet_sensus_parser_set_calibration (parser_t *parser, double atmospheric, double hydrostatic); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/reefnet_sensus_parser.c b/src/reefnet_sensus_parser.c new file mode 100644 index 0000000..b3a9bc4 --- /dev/null +++ b/src/reefnet_sensus_parser.c @@ -0,0 +1,194 @@ +/* + * libdivecomputer + * + * Copyright (C) 2009 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 // malloc, free +#include // assert + +#include "reefnet_sensus.h" +#include "parser-private.h" +#include "units.h" +#include "utils.h" + +#define WARNING(expr) \ +{ \ + message ("%s:%d: %s\n", __FILE__, __LINE__, expr); \ +} + +#define SAMPLE_DEPTH_ADJUST 13 + +typedef struct reefnet_sensus_parser_t reefnet_sensus_parser_t; + +struct reefnet_sensus_parser_t { + parser_t base; + // Depth calibration. + double atmospheric; + double hydrostatic; +}; + +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_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); +static parser_status_t reefnet_sensus_parser_destroy (parser_t *abstract); + +static const parser_backend_t reefnet_sensus_parser_backend = { + PARSER_TYPE_REEFNET_SENSUS, + reefnet_sensus_parser_set_data, /* set_data */ + reefnet_sensus_parser_samples_foreach, /* samples_foreach */ + reefnet_sensus_parser_destroy /* destroy */ +}; + + +static int +parser_is_reefnet_sensus (parser_t *abstract) +{ + if (abstract == NULL) + return 0; + + return abstract->backend == &reefnet_sensus_parser_backend; +} + + +parser_status_t +reefnet_sensus_parser_create (parser_t **out) +{ + if (out == NULL) + return PARSER_STATUS_ERROR; + + // Allocate memory. + reefnet_sensus_parser_t *parser = (reefnet_sensus_parser_t *) malloc (sizeof (reefnet_sensus_parser_t)); + if (parser == NULL) { + WARNING ("Failed to allocate memory."); + return PARSER_STATUS_MEMORY; + } + + // Initialize the base class. + parser_init (&parser->base, &reefnet_sensus_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_sensus_parser_destroy (parser_t *abstract) +{ + if (! parser_is_reefnet_sensus (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + // Free memory. + free (abstract); + + return PARSER_STATUS_SUCCESS; +} + + +static parser_status_t +reefnet_sensus_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size) +{ + if (! parser_is_reefnet_sensus (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + return PARSER_STATUS_SUCCESS; +} + + +parser_status_t +reefnet_sensus_parser_set_calibration (parser_t *abstract, double atmospheric, double hydrostatic) +{ + reefnet_sensus_parser_t *parser = (reefnet_sensus_parser_t*) abstract; + + if (! parser_is_reefnet_sensus (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + parser->atmospheric = atmospheric; + parser->hydrostatic = hydrostatic; + + return PARSER_STATUS_SUCCESS; +} + + +static parser_status_t +reefnet_sensus_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) +{ + reefnet_sensus_parser_t *parser = (reefnet_sensus_parser_t*) abstract; + + if (! parser_is_reefnet_sensus (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + const unsigned char *data = abstract->data; + unsigned int size = abstract->size; + + unsigned int offset = 0; + while (offset + 7 <= size) { + if (data[offset] == 0xFF && data[offset + 6] == 0xFE) { + + unsigned int time = 0; + unsigned int interval = data[offset + 1]; + unsigned int nsamples = 0, count = 0; + + offset += 7; + while (offset + 1 <= size) { + parser_sample_value_t sample = {0}; + + // Time (seconds) + sample.time = time; + if (callback) callback (SAMPLE_TYPE_TIME, sample, userdata); + + // Depth (adjusted feet of seawater). + unsigned int depth = data[offset++]; + sample.depth = ((depth + 33.0 - (double) SAMPLE_DEPTH_ADJUST) * FSW - parser->atmospheric) / parser->hydrostatic; + if (callback) callback (SAMPLE_TYPE_DEPTH, sample, userdata); + + // Temperature (degrees Fahrenheit) + if ((nsamples % 6) == 0) { + assert (offset + 1 <= size); + unsigned int temperature = data[offset++]; + sample.temperature = (temperature - 32.0) * (5.0 / 9.0); + if (callback) callback (SAMPLE_TYPE_TEMPERATURE, sample, userdata); + } + + // Current sample is complete. + nsamples++; + time += interval; + + // 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; + } + } + break; + } else { + offset++; + } + } + + return PARSER_STATUS_SUCCESS; +}