diff --git a/src/Makefile.am b/src/Makefile.am index fa2a3a8..cd8f3ca 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -44,7 +44,7 @@ libdivecomputer_la_SOURCES = \ suunto_d9.h suunto_d9.c \ reefnet.h \ reefnet_sensuspro.h reefnet_sensuspro.c reefnet_sensuspro_parser.c \ - reefnet_sensusultra.h reefnet_sensusultra.c \ + reefnet_sensusultra.h reefnet_sensusultra.c reefnet_sensusultra_parser.c \ uwatec.h \ uwatec_aladin.h uwatec_aladin.c \ uwatec_memomouse.h uwatec_memomouse.c \ diff --git a/src/libdivecomputer.symbols b/src/libdivecomputer.symbols index 7ab4dfb..5f77659 100644 --- a/src/libdivecomputer.symbols +++ b/src/libdivecomputer.symbols @@ -5,6 +5,8 @@ parser_destroy reefnet_sensuspro_parser_create reefnet_sensuspro_parser_set_calibration +reefnet_sensusultra_parser_create +reefnet_sensusultra_parser_set_calibration device_close device_dump diff --git a/src/parser.h b/src/parser.h index 50e71b9..0e94a55 100644 --- a/src/parser.h +++ b/src/parser.h @@ -28,7 +28,8 @@ extern "C" { typedef enum parser_type_t { PARSER_TYPE_NULL = 0, - PARSER_TYPE_REEFNET_SENSUSPRO + PARSER_TYPE_REEFNET_SENSUSPRO, + PARSER_TYPE_REEFNET_SENSUSULTRA } parser_type_t; typedef enum parser_status_t { diff --git a/src/reefnet_sensusultra.h b/src/reefnet_sensusultra.h index dfdb641..d284bc0 100644 --- a/src/reefnet_sensusultra.h +++ b/src/reefnet_sensusultra.h @@ -22,12 +22,13 @@ #ifndef REEFNET_SENSUSULTRA_H #define REEFNET_SENSUSULTRA_H +#include "device.h" +#include "parser.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -#include "device.h" - #define REEFNET_SENSUSULTRA_PACKET_SIZE 512 #define REEFNET_SENSUSULTRA_MEMORY_USER_SIZE 16384 /* 32 PAGES */ #define REEFNET_SENSUSULTRA_MEMORY_DATA_SIZE 2080768 /* 4064 PAGES */ @@ -68,6 +69,12 @@ reefnet_sensusultra_device_sense (device_t *device, unsigned char *data, unsigne device_status_t reefnet_sensusultra_extract_dives (const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata, unsigned int timestamp); +parser_status_t +reefnet_sensusultra_parser_create (parser_t **parser); + +parser_status_t +reefnet_sensusultra_parser_set_calibration (parser_t *parser, double atmospheric, double hydrostatic); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/reefnet_sensusultra_parser.c b/src/reefnet_sensusultra_parser.c new file mode 100644 index 0000000..ddf5eb1 --- /dev/null +++ b/src/reefnet_sensusultra_parser.c @@ -0,0 +1,183 @@ +/* + * 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_sensusultra.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_sensusultra_parser_t reefnet_sensusultra_parser_t; + +struct reefnet_sensusultra_parser_t { + parser_t base; + // Depth calibration. + double atmospheric; + double hydrostatic; +}; + +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_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); +static parser_status_t reefnet_sensusultra_parser_destroy (parser_t *abstract); + +static const parser_backend_t reefnet_sensusultra_parser_backend = { + PARSER_TYPE_REEFNET_SENSUSULTRA, + reefnet_sensusultra_parser_set_data, /* set_data */ + reefnet_sensusultra_parser_samples_foreach, /* samples_foreach */ + reefnet_sensusultra_parser_destroy /* destroy */ +}; + + +static int +parser_is_reefnet_sensusultra (parser_t *abstract) +{ + if (abstract == NULL) + return 0; + + return abstract->backend == &reefnet_sensusultra_parser_backend; +} + + +parser_status_t +reefnet_sensusultra_parser_create (parser_t **out) +{ + if (out == NULL) + return PARSER_STATUS_ERROR; + + // Allocate memory. + reefnet_sensusultra_parser_t *parser = malloc (sizeof (reefnet_sensusultra_parser_t)); + if (parser == NULL) { + WARNING ("Failed to allocate memory."); + return PARSER_STATUS_MEMORY; + } + + // Initialize the base class. + parser_init (&parser->base, &reefnet_sensusultra_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_sensusultra_parser_destroy (parser_t *abstract) +{ + if (! parser_is_reefnet_sensusultra (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + // Free memory. + free (abstract); + + return PARSER_STATUS_SUCCESS; +} + + +static parser_status_t +reefnet_sensusultra_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size) +{ + if (! parser_is_reefnet_sensusultra (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + return PARSER_STATUS_SUCCESS; +} + + +parser_status_t +reefnet_sensusultra_parser_set_calibration (parser_t *abstract, double atmospheric, double hydrostatic) +{ + reefnet_sensusultra_parser_t *parser = (reefnet_sensusultra_parser_t*) abstract; + + if (! parser_is_reefnet_sensusultra (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + parser->atmospheric = atmospheric; + parser->hydrostatic = hydrostatic; + + return PARSER_STATUS_SUCCESS; +} + + +static parser_status_t +reefnet_sensusultra_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) +{ + reefnet_sensusultra_parser_t *parser = (reefnet_sensusultra_parser_t*) abstract; + + if (! parser_is_reefnet_sensusultra (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + const unsigned char header[4] = {0x00, 0x00, 0x00, 0x00}; + const unsigned char footer[4] = {0xFF, 0xFF, 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 + 16 <= size); + + unsigned int time = 0; + unsigned int interval = data[offset + 8] + (data[offset + 9] << 8); + + offset += 16; + while (offset + sizeof (footer) <= size && + memcmp (data + offset, footer, sizeof (footer)) != 0) + { + parser_sample_value_t sample = {0}; + + // Time (seconds) + sample.time = time; + if (callback) callback (SAMPLE_TYPE_TIME, sample, userdata); + + // Temperature (0.01 °K) + unsigned int temperature = data[offset + 0] + (data[offset + 1] << 8); + sample.temperature = temperature / 100.0 - 273.15; + if (callback) callback (SAMPLE_TYPE_TEMPERATURE, sample, userdata); + + // Depth (absolute pressure in millibar) + unsigned int depth = data[offset + 2] + (data[offset + 3] << 8); + sample.depth = (depth * BAR / 1000.0 - parser->atmospheric) / parser->hydrostatic; + if (callback) callback (SAMPLE_TYPE_DEPTH, sample, userdata); + + time += interval; + offset += 4; + } + break; + } else { + offset++; + } + } + + return PARSER_STATUS_SUCCESS; +}