diff --git a/msvc/libdivecomputer.vcproj b/msvc/libdivecomputer.vcproj index 9ed1719..f97cf47 100644 --- a/msvc/libdivecomputer.vcproj +++ b/msvc/libdivecomputer.vcproj @@ -212,6 +212,10 @@ RelativePath="..\src\oceanic_atom2.c" > + + diff --git a/src/Makefile.am b/src/Makefile.am index f80d7ae..1dcca90 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -60,7 +60,7 @@ libdivecomputer_la_SOURCES = \ uwatec_memomouse.h uwatec_memomouse.c uwatec_memomouse_parser.c \ oceanic.h \ oceanic_common.h oceanic_common.c \ - oceanic_atom2.h oceanic_atom2.c \ + oceanic_atom2.h oceanic_atom2.c oceanic_atom2_parser.c \ oceanic_veo250.h oceanic_veo250.c \ oceanic_vtpro.h oceanic_vtpro.c \ mares.h \ diff --git a/src/libdivecomputer.symbols b/src/libdivecomputer.symbols index be6ec25..c1163b3 100644 --- a/src/libdivecomputer.symbols +++ b/src/libdivecomputer.symbols @@ -18,6 +18,7 @@ suunto_solution_parser_create suunto_spyder_parser_create suunto_d9_parser_create mares_nemo_parser_create +oceanic_atom2_parser_create device_close device_dump diff --git a/src/oceanic_atom2.h b/src/oceanic_atom2.h index 12ab620..9a1363d 100644 --- a/src/oceanic_atom2.h +++ b/src/oceanic_atom2.h @@ -22,12 +22,13 @@ #ifndef OCEANIC_ATOM2_H #define OCEANIC_ATOM2_H +#include "device.h" +#include "parser.h" + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ -#include "device.h" - #define OCEANIC_ATOM2_MEMORY_SIZE 0x10000 #define OCEANIC_ATOM2_PACKET_SIZE 0x10 @@ -37,6 +38,9 @@ oceanic_atom2_device_open (device_t **device, const char* name); device_status_t oceanic_atom2_device_keepalive (device_t *device); +parser_status_t +oceanic_atom2_parser_create (parser_t **parser); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/src/oceanic_atom2_parser.c b/src/oceanic_atom2_parser.c new file mode 100644 index 0000000..af1be38 --- /dev/null +++ b/src/oceanic_atom2_parser.c @@ -0,0 +1,198 @@ +/* + * 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 +#include + +#include "oceanic_atom2.h" +#include "parser-private.h" +#include "array.h" +#include "units.h" +#include "utils.h" + +typedef struct oceanic_atom2_parser_t oceanic_atom2_parser_t; + +struct oceanic_atom2_parser_t { + parser_t base; +}; + +static parser_status_t oceanic_atom2_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size); +static parser_status_t oceanic_atom2_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata); +static parser_status_t oceanic_atom2_parser_destroy (parser_t *abstract); + +static const parser_backend_t oceanic_atom2_parser_backend = { + PARSER_TYPE_OCEANIC_ATOM2, + oceanic_atom2_parser_set_data, /* set_data */ + oceanic_atom2_parser_samples_foreach, /* samples_foreach */ + oceanic_atom2_parser_destroy /* destroy */ +}; + + +static int +parser_is_oceanic_atom2 (parser_t *abstract) +{ + if (abstract == NULL) + return 0; + + return abstract->backend == &oceanic_atom2_parser_backend; +} + + +parser_status_t +oceanic_atom2_parser_create (parser_t **out) +{ + if (out == NULL) + return PARSER_STATUS_ERROR; + + // Allocate memory. + oceanic_atom2_parser_t *parser = (oceanic_atom2_parser_t *) malloc (sizeof (oceanic_atom2_parser_t)); + if (parser == NULL) { + WARNING ("Failed to allocate memory."); + return PARSER_STATUS_MEMORY; + } + + // Initialize the base class. + parser_init (&parser->base, &oceanic_atom2_parser_backend); + + *out = (parser_t*) parser; + + return PARSER_STATUS_SUCCESS; +} + + +static parser_status_t +oceanic_atom2_parser_destroy (parser_t *abstract) +{ + if (! parser_is_oceanic_atom2 (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + // Free memory. + free (abstract); + + return PARSER_STATUS_SUCCESS; +} + + +static parser_status_t +oceanic_atom2_parser_set_data (parser_t *abstract, const unsigned char *data, unsigned int size) +{ + if (! parser_is_oceanic_atom2 (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + return PARSER_STATUS_SUCCESS; +} + + +static parser_status_t +oceanic_atom2_parser_samples_foreach (parser_t *abstract, sample_callback_t callback, void *userdata) +{ + if (! parser_is_oceanic_atom2 (abstract)) + return PARSER_STATUS_TYPE_MISMATCH; + + const unsigned char *data = abstract->data; + unsigned int size = abstract->size; + + if (size < 11 * OCEANIC_ATOM2_PACKET_SIZE / 2) + return PARSER_STATUS_ERROR; + + unsigned int time = 0; + unsigned interval = 0; + switch (data[0x17] & 0x03) { + case 0: + interval = 2; + break; + case 1: + interval = 15; + break; + case 2: + interval = 30; + break; + case 3: + interval = 60; + break; + } + + int complete = 1; + + unsigned int tank = 0; + unsigned int pressure = data[0x42] + (data[0x42 + 1] << 8); + unsigned int temperature = data[0x47]; + + unsigned int offset = 9 * OCEANIC_ATOM2_PACKET_SIZE / 2; + while (offset + OCEANIC_ATOM2_PACKET_SIZE / 2 <= size - OCEANIC_ATOM2_PACKET_SIZE) { + parser_sample_value_t sample = {0}; + + // Ignore empty samples. + if (array_isequal (data + offset, OCEANIC_ATOM2_PACKET_SIZE / 2, 0x00)) { + offset += OCEANIC_ATOM2_PACKET_SIZE / 2; + continue; + } + + // Time. + if (complete) { + time += interval; + sample.time = time; + if (callback) callback (SAMPLE_TYPE_TIME, sample, userdata); + } + + // Vendor specific data + sample.vendor.type = SAMPLE_VENDOR_OCEANIC_ATOM2; + sample.vendor.size = OCEANIC_ATOM2_PACKET_SIZE / 2; + sample.vendor.data = data + offset; + if (callback) callback (SAMPLE_TYPE_VENDOR, sample, userdata); + + // Check for a tank switch sample. + if (data[offset + 0] == 0xAA) { + // Tank Number (one based index) + tank = (data[offset + 1] & 0x03) - 1; + + // Tank Pressure (2 psi) + pressure = (((data[offset + 4] << 8) + data[offset + 5]) & 0x0FFF) * 2; + + complete = 0; + } else { + // Temperature (°F) + if (data[offset + 0] & 0x80) + temperature += (data[offset + 7] & 0xFC) >> 2; + else + temperature -= (data[offset + 7] & 0xFC) >> 2; + sample.temperature = (temperature - 32.0) * (5.0 / 9.0); + if (callback) callback (SAMPLE_TYPE_TEMPERATURE, sample, userdata); + + // Tank Pressure (psi) + pressure -= data[offset + 1]; + sample.pressure.tank = tank; + sample.pressure.value = pressure * PSI / BAR; + if (callback && pressure != 10000) callback (SAMPLE_TYPE_PRESSURE, sample, userdata); + + // Depth (1/16 ft) + unsigned int depth = (data[offset + 2] + (data[offset + 3] << 8)) & 0x0FFF; + sample.depth = depth / 16.0 * FEET; + if (callback) callback (SAMPLE_TYPE_DEPTH, sample, userdata); + + complete = 1; + } + + offset += OCEANIC_ATOM2_PACKET_SIZE / 2; + } + + return PARSER_STATUS_SUCCESS; +} diff --git a/src/parser.h b/src/parser.h index 9da7024..2afa45f 100644 --- a/src/parser.h +++ b/src/parser.h @@ -37,7 +37,8 @@ typedef enum parser_type_t { PARSER_TYPE_REEFNET_SENSUSULTRA, PARSER_TYPE_UWATEC_MEMOMOUSE, PARSER_TYPE_UWATEC_SMART, - PARSER_TYPE_MARES_NEMO + PARSER_TYPE_MARES_NEMO, + PARSER_TYPE_OCEANIC_ATOM2 } parser_type_t; typedef enum parser_status_t { @@ -96,7 +97,8 @@ typedef enum parser_sample_flags_t { typedef enum parser_sample_vendor_t { SAMPLE_VENDOR_NONE, SAMPLE_VENDOR_UWATEC_ALADIN, - SAMPLE_VENDOR_UWATEC_SMART + SAMPLE_VENDOR_UWATEC_SMART, + SAMPLE_VENDOR_OCEANIC_ATOM2 } parser_sample_vendor_t; typedef union parser_sample_value_t { diff --git a/src/units.h b/src/units.h index 9308f70..f1c6a44 100644 --- a/src/units.h +++ b/src/units.h @@ -23,12 +23,15 @@ #define UNITS_H +#define POUND 0.45359237 #define FEET 0.3048 +#define INCH 0.0254 #define GRAVITY 9.80665 #define ATM 101325.0 #define BAR 100000.0 #define FSW (ATM / 33.0) #define MSW (BAR / 10.0) +#define PSI ((POUND * GRAVITY) / (INCH * INCH)) #endif /* UNITS_H */