diff --git a/src/Makefile.am b/src/Makefile.am index af5fcd5..f1addce 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -39,7 +39,7 @@ libdivecomputer_la_SOURCES = \ suunto.h \ suunto_common.h suunto_common.c \ suunto_eon.h suunto_eon.c \ - suunto_vyper.h suunto_vyper.c \ + suunto_vyper.h suunto_vyper.c suunto_vyper_parser.c \ suunto_vyper2.h suunto_vyper2.c \ suunto_d9.h suunto_d9.c \ reefnet.h \ diff --git a/src/libdivecomputer.symbols b/src/libdivecomputer.symbols index 512cce0..74ae8f1 100644 --- a/src/libdivecomputer.symbols +++ b/src/libdivecomputer.symbols @@ -8,6 +8,7 @@ reefnet_sensuspro_parser_set_calibration reefnet_sensusultra_parser_create reefnet_sensusultra_parser_set_calibration uwatec_memomouse_parser_create +suunto_vyper_parser_create device_close device_dump diff --git a/src/parser.h b/src/parser.h index 6959b82..71bc19c 100644 --- a/src/parser.h +++ b/src/parser.h @@ -28,6 +28,7 @@ extern "C" { typedef enum parser_type_t { PARSER_TYPE_NULL = 0, + PARSER_TYPE_SUUNTO_VYPER, PARSER_TYPE_REEFNET_SENSUSPRO, PARSER_TYPE_REEFNET_SENSUSULTRA, PARSER_TYPE_UWATEC_MEMOMOUSE @@ -59,7 +60,12 @@ typedef enum parser_sample_event_t { SAMPLE_EVENT_ASCENT, SAMPLE_EVENT_CEILING, SAMPLE_EVENT_WORKLOAD, - SAMPLE_EVENT_TRANSMITTER + SAMPLE_EVENT_TRANSMITTER, + SAMPLE_EVENT_VIOLATION, + SAMPLE_EVENT_BOOKMARK, + SAMPLE_EVENT_SURFACE, + SAMPLE_EVENT_SAFETYSTOP, + SAMPLE_EVENT_GASCHANGE } parser_sample_event_t; typedef enum parser_sample_flags_t { diff --git a/src/suunto_vyper.h b/src/suunto_vyper.h index d6ae32f..e0042f2 100644 --- a/src/suunto_vyper.h +++ b/src/suunto_vyper.h @@ -22,12 +22,13 @@ #ifndef SUUNTO_VYPER_H #define SUUNTO_VYPER_H +#include "device.h" +#include "parser.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -#include "device.h" - #define SUUNTO_VYPER_MEMORY_SIZE 0x2000 #define SUUNTO_VYPER_PACKET_SIZE 32 @@ -46,6 +47,9 @@ suunto_vyper_extract_dives (const unsigned char data[], unsigned int size, dive_ device_status_t suunto_spyder_extract_dives (const unsigned char data[], unsigned int size, dive_callback_t callback, void *userdata); +parser_status_t +suunto_vyper_parser_create (parser_t **parser); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/suunto_vyper_parser.c b/src/suunto_vyper_parser.c new file mode 100644 index 0000000..a2a58eb --- /dev/null +++ b/src/suunto_vyper_parser.c @@ -0,0 +1,179 @@ +/* + * 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 "suunto_vyper.h" +#include "parser-private.h" +#include "units.h" +#include "utils.h" + +#define WARNING(expr) \ +{ \ + message ("%s:%d: %s\n", __FILE__, __LINE__, expr); \ +} + +typedef struct suunto_vyper_parser_t suunto_vyper_parser_t; + +struct suunto_vyper_parser_t { + parser_t base; +}; + +static parser_status_t suunto_vyper_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); +static parser_status_t suunto_vyper_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); +static parser_status_t suunto_vyper_parser_destroy (parser_t *abstract); + +static const parser_backend_t suunto_vyper_parser_backend = { + PARSER_TYPE_SUUNTO_VYPER, + suunto_vyper_parser_set_data, /* set_data */ + suunto_vyper_parser_samples_foreach, /* samples_foreach */ + suunto_vyper_parser_destroy /* destroy */ +}; + + +static int +parser_is_suunto_vyper (parser_t *abstract) +{ + if (abstract == NULL) + return 0; + + return abstract->backend == &suunto_vyper_parser_backend; +} + + +parser_status_t +suunto_vyper_parser_create (parser_t **out) +{ + if (out == NULL) + return PARSER_STATUS_ERROR; + + // Allocate memory. + suunto_vyper_parser_t *parser = malloc (sizeof (suunto_vyper_parser_t)); + if (parser == NULL) { + WARNING ("Failed to allocate memory."); + return PARSER_STATUS_MEMORY; + } + + // Initialize the base class. + parser_init (&parser->base, &suunto_vyper_parser_backend); + + *out = (parser_t*) parser; + + return PARSER_STATUS_SUCCESS; +} + + +static parser_status_t +suunto_vyper_parser_destroy (parser_t *abstract) +{ + if (! parser_is_suunto_vyper (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + // Free memory. + free (abstract); + + return PARSER_STATUS_SUCCESS; +} + + +static parser_status_t +suunto_vyper_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size) +{ + if (! parser_is_suunto_vyper (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + return PARSER_STATUS_SUCCESS; +} + + +static parser_status_t +suunto_vyper_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) +{ + if (! parser_is_suunto_vyper (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 time = 0, depth = 0; + unsigned int interval = data[3]; + + unsigned int offset = 14; + while (offset < size && data[offset] != 0x80) { + parser_sample_value_t sample = {0}; + unsigned char value = data[offset++]; + if (value < 0x79 || value > 0x87) { + // Time (seconds). + time += interval; + sample.time = time; + if (callback) callback (SAMPLE_TYPE_TIME, sample, userdata); + + // Depth (ft). + depth += (signed char) value; + sample.depth = depth * FEET; + if (callback) callback (SAMPLE_TYPE_DEPTH, sample, userdata); + } else { + // Event. + sample.event.time = 0; + sample.event.flags = 0; + sample.event.value = 0; + switch (value) { + case 0x7a: // Slow + sample.event.type = SAMPLE_EVENT_ASCENT; + break; + case 0x7b: // Violation + sample.event.type = SAMPLE_EVENT_VIOLATION; + break; + case 0x7c: // Bookmark + sample.event.type = SAMPLE_EVENT_BOOKMARK; + break; + case 0x7d: // Surface + sample.event.type = SAMPLE_EVENT_SURFACE; + break; + case 0x7e: // Deco + sample.event.type = SAMPLE_EVENT_DECOSTOP; + break; + case 0x7f: // Ceiling (Deco Violation) + sample.event.type = SAMPLE_EVENT_CEILING; + break; + case 0x81: // Safety Stop + sample.event.type = SAMPLE_EVENT_SAFETYSTOP; + break; + case 0x87: // Gas Change + assert (offset < size); + sample.event.type = SAMPLE_EVENT_GASCHANGE; + sample.event.value = data[offset++]; + break; + default: // Unknown + WARNING ("Unknown event"); + break; + } + + if (callback) callback (SAMPLE_TYPE_EVENT, sample, userdata); + } + } + + return PARSER_STATUS_SUCCESS; +}