From c3419542e0c33814e51edd66acee5e6424289c5d Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 31 Oct 2008 14:03:57 +0000 Subject: [PATCH] Added a parser for the Uwatec Memomouse. --- src/Makefile.am | 2 +- src/libdivecomputer.symbols | 1 + src/parser.h | 14 ++- src/uwatec_memomouse.h | 8 +- src/uwatec_memomouse_parser.c | 208 ++++++++++++++++++++++++++++++++++ 5 files changed, 227 insertions(+), 6 deletions(-) create mode 100644 src/uwatec_memomouse_parser.c diff --git a/src/Makefile.am b/src/Makefile.am index cd8f3ca..af5fcd5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -47,7 +47,7 @@ libdivecomputer_la_SOURCES = \ reefnet_sensusultra.h reefnet_sensusultra.c reefnet_sensusultra_parser.c \ uwatec.h \ uwatec_aladin.h uwatec_aladin.c \ - uwatec_memomouse.h uwatec_memomouse.c \ + uwatec_memomouse.h uwatec_memomouse.c uwatec_memomouse_parser.c \ oceanic.h \ oceanic_atom2.h oceanic_atom2.c \ ringbuffer.h ringbuffer.c \ diff --git a/src/libdivecomputer.symbols b/src/libdivecomputer.symbols index 5f77659..512cce0 100644 --- a/src/libdivecomputer.symbols +++ b/src/libdivecomputer.symbols @@ -7,6 +7,7 @@ reefnet_sensuspro_parser_create reefnet_sensuspro_parser_set_calibration reefnet_sensusultra_parser_create reefnet_sensusultra_parser_set_calibration +uwatec_memomouse_parser_create device_close device_dump diff --git a/src/parser.h b/src/parser.h index 6641cdb..6959b82 100644 --- a/src/parser.h +++ b/src/parser.h @@ -29,7 +29,8 @@ extern "C" { typedef enum parser_type_t { PARSER_TYPE_NULL = 0, PARSER_TYPE_REEFNET_SENSUSPRO, - PARSER_TYPE_REEFNET_SENSUSULTRA + PARSER_TYPE_REEFNET_SENSUSULTRA, + PARSER_TYPE_UWATEC_MEMOMOUSE } parser_type_t; typedef enum parser_status_t { @@ -52,7 +53,13 @@ typedef enum parser_sample_type_t { } parser_sample_type_t; typedef enum parser_sample_event_t { - SAMPLE_EVENT_NONE + SAMPLE_EVENT_NONE, + SAMPLE_EVENT_DECOSTOP, + SAMPLE_EVENT_RBT, + SAMPLE_EVENT_ASCENT, + SAMPLE_EVENT_CEILING, + SAMPLE_EVENT_WORKLOAD, + SAMPLE_EVENT_TRANSMITTER } parser_sample_event_t; typedef enum parser_sample_flags_t { @@ -60,7 +67,8 @@ typedef enum parser_sample_flags_t { } parser_sample_flags_t; typedef enum parser_sample_vendor_t { - SAMPLE_VENDOR_NONE + SAMPLE_VENDOR_NONE, + SAMPLE_VENDOR_UWATEC_ALADIN } parser_sample_vendor_t; typedef union parser_sample_value_t { diff --git a/src/uwatec_memomouse.h b/src/uwatec_memomouse.h index 55fc0ef..2380d27 100644 --- a/src/uwatec_memomouse.h +++ b/src/uwatec_memomouse.h @@ -22,12 +22,13 @@ #ifndef UWATEC_MEMOMOUSE_H #define UWATEC_MEMOMOUSE_H +#include "device.h" +#include "parser.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -#include "device.h" - device_status_t uwatec_memomouse_device_open (device_t **device, const char* name); @@ -37,6 +38,9 @@ uwatec_memomouse_device_set_timestamp (device_t *device, unsigned int timestamp) device_status_t uwatec_memomouse_extract_dives (const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata); +parser_status_t +uwatec_memomouse_parser_create (parser_t **parser); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/uwatec_memomouse_parser.c b/src/uwatec_memomouse_parser.c new file mode 100644 index 0000000..9d538d6 --- /dev/null +++ b/src/uwatec_memomouse_parser.c @@ -0,0 +1,208 @@ +/* + * 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 + +#include "uwatec_memomouse.h" +#include "parser-private.h" +#include "utils.h" + +#define WARNING(expr) \ +{ \ + message ("%s:%d: %s\n", __FILE__, __LINE__, expr); \ +} + +typedef struct uwatec_memomouse_parser_t uwatec_memomouse_parser_t; + +struct uwatec_memomouse_parser_t { + parser_t base; +}; + +static parser_status_t uwatec_memomouse_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); +static parser_status_t uwatec_memomouse_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); +static parser_status_t uwatec_memomouse_parser_destroy (parser_t *abstract); + +static const parser_backend_t uwatec_memomouse_parser_backend = { + PARSER_TYPE_UWATEC_MEMOMOUSE, + uwatec_memomouse_parser_set_data, /* set_data */ + uwatec_memomouse_parser_samples_foreach, /* samples_foreach */ + uwatec_memomouse_parser_destroy /* destroy */ +}; + + +static int +parser_is_uwatec_memomouse (parser_t *abstract) +{ + if (abstract == NULL) + return 0; + + return abstract->backend == &uwatec_memomouse_parser_backend; +} + + +parser_status_t +uwatec_memomouse_parser_create (parser_t **out) +{ + if (out == NULL) + return PARSER_STATUS_ERROR; + + // Allocate memory. + uwatec_memomouse_parser_t *parser = malloc (sizeof (uwatec_memomouse_parser_t)); + if (parser == NULL) { + WARNING ("Failed to allocate memory."); + return PARSER_STATUS_MEMORY; + } + + // Initialize the base class. + parser_init (&parser->base, &uwatec_memomouse_parser_backend); + + *out = (parser_t*) parser; + + return PARSER_STATUS_SUCCESS; +} + + +static parser_status_t +uwatec_memomouse_parser_destroy (parser_t *abstract) +{ + if (! parser_is_uwatec_memomouse (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + // Free memory. + free (abstract); + + return PARSER_STATUS_SUCCESS; +} + + +static parser_status_t +uwatec_memomouse_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size) +{ + if (! parser_is_uwatec_memomouse (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + return PARSER_STATUS_SUCCESS; +} + + +static parser_status_t +uwatec_memomouse_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) +{ + if (! parser_is_uwatec_memomouse (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + const unsigned char *data = abstract->data; + unsigned int size = abstract->size; + + if (size < 18) + return PARSER_STATUS_ERROR; + + unsigned int model = data[3]; + + int is_nitrox = 0, is_oxygen = 0, is_air = 0; + if ((model & 0xF0) == 0xF0) + is_nitrox = 1; + if ((model & 0xF0) == 0xA0) + is_oxygen = 1; + if ((model & 0xF0) % 4 == 0) + is_air = 1; + + unsigned int header = 22; + if (is_nitrox) + header += 2; + if (is_oxygen) + header += 3; + + unsigned int time = 20; + + unsigned int offset = header + 18; + while (offset + 2 <= size) { + parser_sample_value_t sample = {0}; + + unsigned int value = (data[offset + 0] << 8) + data[offset + 1]; + unsigned int depth = (value & 0xFFC0) >> 6; + unsigned int warnings = (value & 0x3F); + offset += 2; + + // Time (seconds) + sample.time = time; + if (callback) callback (SAMPLE_TYPE_TIME, sample, userdata); + + // Depth (meters) + sample.depth = depth * 10.0 / 64.0; + if (callback) callback (SAMPLE_TYPE_DEPTH, sample, userdata); + + // Warnings + for (unsigned int i = 0; i < 6; ++i) { + if (warnings & (1 << i)) { + sample.event.time = 0; + sample.event.flags = 0; + sample.event.value = 0; + switch (i) { + case 0: // Deco stop + sample.event.type = SAMPLE_EVENT_DECOSTOP; + break; + case 1: // Remaining bottom time too short (Air series only) + sample.event.type = SAMPLE_EVENT_RBT; + break; + case 2: // Ascent too fast + sample.event.type = SAMPLE_EVENT_ASCENT; + break; + case 3: // Ceiling violation of deco stop + sample.event.type = SAMPLE_EVENT_CEILING; + break; + case 4: // Work too hard (Air series only) + sample.event.type = SAMPLE_EVENT_WORKLOAD; + break; + case 5: // Transmit error of air pressure (always 1 unless Air series) + sample.event.type = SAMPLE_EVENT_TRANSMITTER; + break; + } + if (callback) callback (SAMPLE_TYPE_EVENT, sample, userdata); + } + } + + if (time % 60 == 0) { + sample.vendor.type = SAMPLE_VENDOR_UWATEC_ALADIN; + sample.vendor.size = 0; + sample.vendor.data = data + offset; + + // Decompression information. + assert (offset + 1 <= size); + sample.vendor.size++; + offset++; + + // Oxygen percentage (O2 series only). + if (is_oxygen) { + assert (offset + 1 <= size); + sample.vendor.size++; + offset++; + } + + if (callback) callback (SAMPLE_TYPE_VENDOR, sample, userdata); + } + + time += 20; + } + + return PARSER_STATUS_SUCCESS; +}