[PATCH] Revisions requested
John Van Ostrand
john at vanostrand.com
Mon Oct 27 17:18:41 PDT 2014
Removed dependency on packed structure.
Removed extraneous close/opens.
Formated lines to 78 chars.
Merged EMC and Commander backends to common.
Change nanosleep() calls to serial_sleep().
Change cochran_common_dump to use dc_buffer properly.
---
examples/cochran_download.c | 165 +++++++++++++++++++++--------
examples/universal.c | 3 +-
include/libdivecomputer/cochran.h | 11 +-
include/libdivecomputer/common.h | 3 +-
src/Makefile.am | 6 +-
src/cochran_cmdr.c | 66 ------------
src/cochran_cmdr.h | 83 ---------------
src/cochran_cmdr_parser.c | 63 +++++------
src/cochran_common.c | 218 +++++++++++++++++++++++++++-----------
src/cochran_common.h | 62 +++++++++--
src/cochran_common_parser.c | 78 ++++++++++++--
src/cochran_common_parser.h | 43 +++++++-
src/cochran_emc.c | 67 ------------
src/cochran_emc.h | 180 -------------------------------
src/cochran_emc_parser.c | 84 +++++++--------
src/descriptor.c | 6 +-
src/device.c | 7 +-
src/parser.c | 7 +-
18 files changed, 515 insertions(+), 637 deletions(-)
delete mode 100644 src/cochran_cmdr.c
delete mode 100644 src/cochran_cmdr.h
delete mode 100644 src/cochran_emc.c
delete mode 100644 src/cochran_emc.h
diff --git a/examples/cochran_download.c b/examples/cochran_download.c
index b42eb91..a9253af 100644
--- a/examples/cochran_download.c
+++ b/examples/cochran_download.c
@@ -58,14 +58,9 @@ usage (const char *filename)
fprintf (stderr, "Usage:\n\n");
fprintf (stderr, " %s [options] devname\n\n", filename);
fprintf (stderr, "Options:\n\n");
- fprintf (stderr, " -b name Set backend name (required).\n");
fprintf (stderr, " -d dirname Dump data to dirname.\n");
fprintf (stderr, " -f Force dump despite download errors\n");
fprintf (stderr, " -h Show this help message.\n\n");
-
- fprintf (stderr, "Supported backends:\n\n");
- fprintf (stderr, " emc, Cochran EMC family\n");
- fprintf (stderr, " commander, Cochran Commander family\n");
fprintf (stderr, "\n\n");
}
@@ -108,20 +103,17 @@ search (dc_descriptor_t **out, const char *name, dc_family_t backend, unsigned i
}
static dc_status_t
-write_dump(dc_buffer_t *dump, const char *fname)
+write_dump(const char *dump, unsigned int size, const char *fname)
{
- int fd, size = 0, written;
-
- if (dump)
- size = dc_buffer_get_size(dump);
+ int fd, written;
if (size > 0) {
fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH );
if (fd == -1) {
- printf("unable to open %s for writing\n", fname);
+ printf("Unable to open %s for writing\n", fname);
exit;
}
- written = write(fd, dc_buffer_get_data(dump), size);
+ written = write(fd, dump, size);
if (written != size) {
printf("Error writing %s. Wrote %d expected %d.\n", fname, written, size);
return (DC_STATUS_UNSUPPORTED);
@@ -130,6 +122,59 @@ write_dump(dc_buffer_t *dump, const char *fname)
return (DC_STATUS_SUCCESS);
}
+#define hexchar(n) ("0123456789abcdef"[(n) & 15])
+
+static int show_line(unsigned offset, const unsigned char *data,
+ unsigned size, int show_empty)
+{
+ unsigned char bits;
+ int i, off;
+ char buffer[120];
+
+ if (size > 16)
+ size = 16;
+
+ bits = 0;
+ memset(buffer, ' ', sizeof(buffer));
+ off = sprintf(buffer, "%06x ", offset);
+ for (i = 0; i < size; i++) {
+ char *hex = buffer + off + 3 * i;
+ char *asc = buffer + off + 50 + i;
+ unsigned char byte = data[i];
+
+ hex[0] = hexchar(byte >> 4);
+ hex[1] = hexchar(byte);
+ bits |= byte;
+ if (byte < 32 || byte > 126)
+ byte = '.';
+ asc[0] = byte;
+ asc[1] = 0;
+ }
+
+ if (bits) {
+ puts(buffer);
+ return 1;
+ }
+ if (show_empty)
+ puts("...");
+ return 0;
+}
+
+static void cochran_debug_write(const unsigned char *data, unsigned size)
+{
+ return;
+
+ int show = 1, i;
+
+
+ for (i = 0; i < size; i += 16)
+ show = show_line(i, data + i, size - i, show);
+}
+
+
+#define array_uint32_le(p) ( (unsigned char) (p)[0] + ((unsigned char) (p)[1] << 8) \
+ + ((unsigned char) (p)[2] << 16) + ((unsigned char) (p)[3] << 24) )
+
static dc_status_t
dowork (dc_context_t *context, dc_descriptor_t *descriptor, const char *devname, const char *dirname, unsigned int force_flag)
{
@@ -154,62 +199,96 @@ dowork (dc_context_t *context, dc_descriptor_t *descriptor, const char *devname,
}
// Create directory if needed
- stat(dirname, &dstat);
+ int src;
+ src = stat(dirname, &dstat);
- if ( ! (dstat.st_mode & S_IFDIR) ) {
+ if ( src == -1 ) {
if (mkdir(dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)) {
printf("Unable to create directory\n");
exit;
}
}
-
// TODO Run dump and write files
- struct cochran_data_dump dump = {0};
- rc = dc_device_dump (device, (dc_buffer_t *) &dump);
+ dc_buffer_t *dump = dc_buffer_new(0);
+
+ rc = dc_device_dump (device, dump);
+
+ cochran_debug_write(dc_buffer_get_data(dump), dc_buffer_get_size(dump));
+ exit;
if (rc == DC_STATUS_SUCCESS || force_flag) {
char fname[128];
+ char *d = dc_buffer_get_data(dump);
+ unsigned int ptr = 0, start, size;
sprintf(fname, "%s/info-x05x9dxffx00x43x00.bin", dirname);
- write_dump(dump.id0, fname);
-
- if (dc_buffer_get_size(dump.id0) > 0)
+ start = array_uint32_le(d + ptr);
+ size = array_uint32_le(d + ptr + 5) - start;
+printf("%s, start = %d, size = %d\n", fname, start, size);
+ write_dump(d + start, size, fname);
+
+ ptr += 5;
+ start = array_uint32_le(d + ptr);
+ size = array_uint32_le(d + ptr + 5) - start;
+ if (*(d + ptr - 1) == 1)
sprintf(fname, "%s/info-xdbx7fxffx00x43x00.bin", dirname);
else
sprintf(fname, "%s/info-x05x9dxffx00x43x00.bin", dirname);
- write_dump(dump.id1, fname);
+ write_dump(d + start, size, fname);
+ ptr += 5;
+ start = array_uint32_le(d + ptr);
+ size = array_uint32_le(d + ptr + 5) - start;
sprintf(fname, "%s/config-x96x00.bin", dirname);
- write_dump(dump.config1, fname);
+printf("%s, start = %d, size = %d\n", fname, start, size);
+ write_dump(d + start, size, fname);
+ ptr += 5;
+ start = array_uint32_le(d + ptr);
+ size = array_uint32_le(d + ptr + 5) - start;
sprintf(fname, "%s/config-x96x01.bin", dirname);
- write_dump(dump.config2, fname);
+printf("%s, start = %d, size = %d\n", fname, start, size);
+ write_dump(d + start, size, fname);
+ ptr += 5;
+ start = array_uint32_le(d + ptr);
+ size = array_uint32_le(d + ptr + 5) - start;
sprintf(fname, "%s/config-x96x02.bin", dirname);
- write_dump(dump.config3, fname);
+printf("%s, start = %d, size = %d\n", fname, start, size);
+ write_dump(d + start, size, fname);
+ ptr += 5;
+ start = array_uint32_le(d + ptr);
+ size = array_uint32_le(d + ptr + 5) - start;
sprintf(fname, "%s/config-x96x03.bin", dirname);
- write_dump(dump.config4, fname);
+printf("%s, start = %d, size = %d\n", fname, start, size);
+ write_dump(d + start, size, fname);
+ ptr += 5;
+ start = array_uint32_le(d + ptr);
+ size = array_uint32_le(d + ptr + 5) - start;
sprintf(fname, "%s/misc-x89x05x00x00x00xdcx05.bin", dirname);
- write_dump(dump.misc, fname);
+printf("%s, start = %d, size = %d\n", fname, start, size);
+ write_dump(d + start, size, fname);
+ ptr += 5;
+ start = array_uint32_le(d + ptr);
+ size = array_uint32_le(d + ptr + 5) - start;
sprintf(fname, "%s/logbook.bin", dirname);
- write_dump(dump.logbook, fname);
+printf("%s, start = %d, size = %d\n", fname, start, size);
+ write_dump(d + start, size, fname);
+ ptr += 5;
+ start = array_uint32_le(d + ptr);
+ size = array_uint32_le(d + ptr + 5) - start;
sprintf(fname, "%s/sample.bin", dirname);
- write_dump(dump.sample, fname);
-
- dc_buffer_free (dump.id0);
- dc_buffer_free (dump.id1);
- dc_buffer_free (dump.config1);
- dc_buffer_free (dump.config2);
- dc_buffer_free (dump.config3);
- dc_buffer_free (dump.config4);
- dc_buffer_free (dump.misc);
- dc_buffer_free (dump.logbook);
- dc_buffer_free (dump.sample);
+printf("%s, start = %d, size = %d\n", fname, start, size);
+ write_dump(d + start, size, fname);
+
+ dc_buffer_free (dump);
+ } else {
+ printf("Dive computer read failure\n");
}
// Close the device.
@@ -230,7 +309,7 @@ main (int argc, char *argv[])
extern int optind, opterr, optopt;
// Default values.
- dc_family_t backend = DC_FAMILY_NULL;
+ dc_family_t backend = DC_FAMILY_COCHRAN;
// Command line arguments
const char *devname = NULL, *dirname;
@@ -239,14 +318,8 @@ main (int argc, char *argv[])
// Parse command-line options.
int opt = 0;
- while ((opt = getopt (argc, argv, "b:d:ls:h")) != -1) {
+ while ((opt = getopt (argc, argv, "d:ls:h")) != -1) {
switch (opt) {
- case 'b': // backend
- if ( ! strcmp ("emc", optarg) )
- backend = DC_FAMILY_COCHRAN_EMC;
- else if ( ! strcmp( "commander", optarg) )
- backend = DC_FAMILY_COCHRAN_COMMANDER;
- break;
case 'd': // dump data to directory
dirname = optarg;
break;
diff --git a/examples/universal.c b/examples/universal.c
index 56445b7..c7d36f7 100644
--- a/examples/universal.c
+++ b/examples/universal.c
@@ -102,8 +102,7 @@ static const backend_table_t g_backends[] = {
{"predator", DC_FAMILY_SHEARWATER_PREDATOR},
{"petrel", DC_FAMILY_SHEARWATER_PETREL},
{"nitekq", DC_FAMILY_DIVERITE_NITEKQ},
- {"commander", DC_FAMILY_COCHRAN_COMMANDER},
- {"emc", DC_FAMILY_COCHRAN_EMC},
+ {"cochran", DC_FAMILY_COCHRAN},
};
static dc_family_t
diff --git a/include/libdivecomputer/cochran.h b/include/libdivecomputer/cochran.h
index 27fdcc5..f7506d7 100644
--- a/include/libdivecomputer/cochran.h
+++ b/include/libdivecomputer/cochran.h
@@ -43,16 +43,11 @@ struct cochran_data_dump {
};
dc_status_t
-cochran_cmdr_device_open (dc_device_t **device, dc_context_t *context, const char *name);
+cochran_common_device_open (dc_device_t **device, dc_context_t *context,
+ const char *name);
dc_status_t
-cochran_cmdr_parser_create (dc_parser_t **parser, dc_context_t *context);
-
-dc_status_t
-cochran_emc_device_open (dc_device_t **device, dc_context_t *context, const char *name);
-
-dc_status_t
-cochran_emc_parser_create (dc_parser_t **parser, dc_context_t *context);
+cochran_common_parser_create (dc_parser_t **parser, dc_context_t *context);
#ifdef __cplusplus
}
diff --git a/include/libdivecomputer/common.h b/include/libdivecomputer/common.h
index ef86272..218548f 100644
--- a/include/libdivecomputer/common.h
+++ b/include/libdivecomputer/common.h
@@ -84,8 +84,7 @@ typedef enum dc_family_t {
/* Dive Rite */
DC_FAMILY_DIVERITE_NITEKQ = (11 << 16),
/* Cochran */
- DC_FAMILY_COCHRAN_COMMANDER = (12 << 16),
- DC_FAMILY_COCHRAN_EMC,
+ DC_FAMILY_COCHRAN = (12 << 16),
} dc_family_t;
#ifdef __cplusplus
diff --git a/src/Makefile.am b/src/Makefile.am
index d8098f6..33d4713 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -56,9 +56,9 @@ libdivecomputer_la_SOURCES = \
checksum.h checksum.c \
array.h array.c \
buffer.c \
- cochran_common.h cochran_common.c cochran_common_parser.h cochran_common_parser.c \
- cochran_cmdr.h cochran_cmdr.c cochran_cmdr_parser.c \
- cochran_emc.h cochran_emc.c cochran_emc_parser.c
+ cochran_common.h cochran_common.c \
+ cochran_common_parser.h cochran_common_parser.c \
+ cochran_cmdr_parser.c cochran_emc_parser.c
if OS_WIN32
libdivecomputer_la_SOURCES += serial.h serial_win32.c
diff --git a/src/cochran_cmdr.c b/src/cochran_cmdr.c
deleted file mode 100644
index fb6e1e0..0000000
--- a/src/cochran_cmdr.c
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * libdivecomputer
- *
- * Copyright (C) 2014 John Van Ostrand
- *
- * 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 <stdlib.h>
-#include <time.h>
-
-#include <libdivecomputer/cochran.h>
-
-#include "context-private.h"
-#include "device-private.h"
-#include "serial.h"
-
-#include "cochran_common.h"
-#include "cochran_cmdr.h"
-
-
-static const dc_device_vtable_t cochran_cmdr_device_vtable = {
- DC_FAMILY_COCHRAN_COMMANDER,
- cochran_common_device_set_fingerprint, /* set_fingerprint */
- cochran_common_device_read, /* read */
- NULL, /* write */
- cochran_common_device_dump, /* dump */
- cochran_common_device_foreach, /* foreach */
- cochran_common_device_close /* close */
-};
-
-
-dc_status_t
-cochran_cmdr_device_open (dc_device_t **out, dc_context_t *context, const char *name)
-{
- dc_status_t rc;
- rc = cochran_common_device_open(out, context, name, &cochran_cmdr_device_vtable);
- if (rc != DC_STATUS_SUCCESS)
- return rc;
-
- cochran_device_t *device = (cochran_device_t *) *out;
-
- // Check family
- if ((device->data.model & 0xFF0000) != COCHRAN_MODEL_COMMANDER_FAMILY) {
- ERROR (context, "Device not recognized.");
- serial_close (device->port);
- free (device->data.id);
- free (device);
- return DC_STATUS_UNSUPPORTED;
- }
-
- return DC_STATUS_SUCCESS;
-}
diff --git a/src/cochran_cmdr.h b/src/cochran_cmdr.h
deleted file mode 100644
index bac5f57..0000000
--- a/src/cochran_cmdr.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * libdivecomputer
- *
- * Copyright (C) 2014 John Van Ostrand
- *
- * 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
- */
-
-
-struct cochran_cmdr_log_t {
- // Pre-dive 128 bytes
- unsigned char minutes, seconds; // 3 bytes
- unsigned char day, hour, year, month; // 3 bytes
- unsigned char sample_start_offset[4]; // 4 bytes
- unsigned char start_timestamp[4]; // 4 bytes
- unsigned char pre_dive_timestamp[4]; // 4 bytes
- unsigned char unknown1[6]; // 6 bytes
- unsigned char water_conductivity; // 1 byte [0=low, 2=high]
- unsigned char unknown2[5]; // 5 bytes
-// 30
- unsigned char sample_pre_event_offset[4];// 4 bytes
- unsigned char unknown3[4]; // 4 bytes
- unsigned char start_battery_voltage[2]; // 2 bytes [/256]
-//40
- unsigned char unknown4[4]; // 4 bytes
- unsigned char entered_or_computed_po[2];// 2 bytes ???
- unsigned char unknown5[8]; // 8 bytes
- unsigned char start_depth[2]; // 2 byte [/4]
-//56
- unsigned char unknown6[12]; // 12 bytes
- unsigned char sit[2]; // 2 bytes
-//70
- unsigned char number[2]; // 2 bytes
- unsigned char unknown7[1]; // 1 byte
- unsigned char altitude; // 1 byte [/4 = kft]
- unsigned char unknown8[28]; // 27 bytes
- unsigned char alarm_depth[2]; // 2 bytes
- unsigned char unknown9[4]; // 5 bytes
-//108
- unsigned char repetitive_dive; // 1 byte
- unsigned char unknown10[3]; // 3 bytes
- unsigned char start_tissue_nsat[16]; // 16 bytes [/256]
-
- // Post-dive 128 bytes
- unsigned char sample_end_offset[4]; // 4 bytes
- unsigned char unknown11[21]; // 21 bytes
- unsigned char temp; // 1 byte
- unsigned char unknown12[12]; // 12 bytes
- unsigned char bt[2]; // 2 bytes [minutes]
- unsigned char max_depth[2]; // 2 bytes [/4]
- unsigned char avg_depth[2]; // 2 bytes
- unsigned char unknown13[38]; // 38 bytes
- unsigned char o2_percent[4][2]; // 8 bytes
- unsigned char unknown14[22]; // 22 bytes
- unsigned char end_tissue_nsat[16]; // 16 bytes [/256]
-} __attribute__((packed));
-
-
-typedef struct cochran_cmdr_log_t cochran_cmdr_log_t;
-
-
-struct cochran_cmdr_config1_t {
- unsigned char unknown1[209];
- unsigned short int dive_count;
- unsigned char unknown2[274];
- unsigned short int serial_num; // @170
- unsigned char unknown3[24];
-} __attribute__((packed));
-
-typedef struct cochran_emc_config1_t cochran_emc_config1_t;
diff --git a/src/cochran_cmdr_parser.c b/src/cochran_cmdr_parser.c
index 8c74705..8b94fcf 100644
--- a/src/cochran_cmdr_parser.c
+++ b/src/cochran_cmdr_parser.c
@@ -32,36 +32,18 @@
#include "array.h"
#include "cochran_common.h"
-#include "cochran_cmdr.h"
#include "cochran_common_parser.h"
-#define SZ_SAMPLE 2
-
-static dc_status_t cochran_cmdr_parser_get_field(dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
-static dc_status_t cochran_cmdr_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
-static const dc_parser_vtable_t cochran_cmdr_parser_vtable = {
- DC_FAMILY_COCHRAN_COMMANDER,
- cochran_common_parser_set_data, /* set_data */
- cochran_common_parser_get_datetime, /* datetime */
- cochran_cmdr_parser_get_field, /* fields */
- cochran_cmdr_parser_samples_foreach, /* samples_foreach */
- cochran_common_parser_destroy /* destroy */
-};
+#define SZ_SAMPLE 2
dc_status_t
-cochran_cmdr_parser_create (dc_parser_t **out, dc_context_t *context)
-{
- return cochran_common_parser_create(out, context, &cochran_cmdr_parser_vtable);
-}
-
-
-static dc_status_t
-cochran_cmdr_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value)
+cochran_cmdr_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
+ unsigned int flags, void *value)
{
cochran_data_t *data = (cochran_data_t *) abstract->data;
- cochran_cmdr_log_t *log = (cochran_cmdr_log_t *) data->current_log;
+ unsigned char *log = data->current_log;
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
dc_salinity_t *water = (dc_salinity_t *) value;
@@ -69,31 +51,34 @@ cochran_cmdr_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
if (value) {
switch (type) {
case DC_FIELD_TEMPERATURE:
- *((unsigned int*) value) = (log->temp - 32) / 1.8;
+ *((unsigned int*) value) = log[CMD_START_TEMP];
case DC_FIELD_DIVETIME:
- *((unsigned int *) value) = array_uint16_le (log->bt) * 60;
+ *((unsigned int *) value) = array_uint16_le (log + EMC_BT) * 60;
break;
case DC_FIELD_MAXDEPTH:
- *((double *) value) = array_uint16_le (log->max_depth) / 4 * FEET;
+ *((double *) value) = array_uint16_le (log + CMD_MAX_DEPTH) / 4 * FEET;
break;
case DC_FIELD_AVGDEPTH:
- *((double *) value) = array_uint16_le (log->avg_depth) / 4 * FEET;
+ *((double *) value) = array_uint16_le (log + CMD_AVG_DEPTH) / 4 * FEET;
break;
case DC_FIELD_GASMIX_COUNT:
*((unsigned int *) value) = 2;
break;
case DC_FIELD_GASMIX:
- gasmix->oxygen = (double) array_uint16_le ((char *)log->o2_percent + 2 * flags) / 256 / 100;
+ gasmix->oxygen = (double) array_uint16_le ((char *)log
+ + CMD_O2_PERCENT + 2 * flags) / 256 / 100;
gasmix->helium = 0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
break;
case DC_FIELD_SALINITY:
// 0 = low conductivity, 1 = high, maybe there's a 2?
- water->type = ( log->water_conductivity == 0 ? DC_WATER_FRESH : DC_WATER_SALT );
- water->density = 1000 + 12.5 * log->water_conductivity;
+ water->type = ( log[CMD_WATER_CONDUCTIVITY] == 0 ? DC_WATER_FRESH
+ : DC_WATER_SALT );
+ water->density = 1000 + 12.5 * log[CMD_WATER_CONDUCTIVITY];
break;
case DC_FIELD_ATMOSPHERIC:
- *(double *) value = ATM / BAR * pow(1 - 0.0000225577 * (double) log->altitude * 250 * FEET, 5.25588);
+ *(double *) value = ATM / BAR * pow(1 - 0.0000225577
+ * (double) log[CMD_ALTITUDE] * 250 * FEET, 5.25588);
break;
default:
return DC_STATUS_UNSUPPORTED;
@@ -104,12 +89,13 @@ cochran_cmdr_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
}
-static dc_status_t
-cochran_cmdr_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
+dc_status_t
+cochran_cmdr_parser_samples_foreach (dc_parser_t *abstract,
+ dc_sample_callback_t callback, void *userdata)
{
cochran_data_t *data = (cochran_data_t *)abstract->data;
unsigned char *sdata = data->current_sample;
- cochran_cmdr_log_t *log = (cochran_cmdr_log_t *) data->current_log;
+ unsigned char *log = data->current_log;
unsigned int size = data->current_sample_size;
unsigned char *s;
@@ -126,7 +112,7 @@ cochran_cmdr_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
// and temp ever other second.
// Prime values from the dive log section
- depth = array_uint16_le (log->start_depth) / 256;
+ depth = array_uint16_le (log + CMD_START_DEPTH) / 4;
last_sample_time = sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
@@ -134,7 +120,7 @@ cochran_cmdr_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
sample.depth = depth * FEET;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
- // TODO: sample.temperature = (log->start_temperature - 32) / 1.8;
+ // TODO: sample.temperature = (log + CMD_START_TEMP - 32) / 1.8;
// TODO: if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
while (offset < size) {
@@ -165,7 +151,8 @@ cochran_cmdr_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
// Check for event
if (s[0] & 0x80) {
- offset += cochran_common_handle_event(abstract, callback, userdata, s[0], offset, time);
+ offset += cochran_common_handle_event(abstract, callback, userdata,
+ s[0], offset, time);
if (s[0] == 0xC5)
deco_obligation = 1; // Deco obligation begins
else if (s[0] == 0xC8)
@@ -183,12 +170,12 @@ cochran_cmdr_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
// Ascent rate is logged in the 0th sample, temp in the 1st, repeat.
if (time % 2 == 0) {
// Ascent rate
- ascent_rate = (s[1] & 0x7f) / 4 * (s[0] & 0x80 ? 1 : -1);
+ ascent_rate = (s[1] & 0x7f) / 4 * (s[1] & 0x80 ? 1 : -1);
sample.ascent_rate = ascent_rate * FEET;
if (callback) callback (DC_SAMPLE_ASCENT_RATE, sample, userdata);
} else {
// Temperature logged in half degrees F above 20
- temperature = s[1] / 2 + 20;
+ temperature = (float) s[1] / 2 + 20;
sample.temperature = (temperature - 32.0) / 1.8;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
diff --git a/src/cochran_common.c b/src/cochran_common.c
index 877491d..7bbe277 100644
--- a/src/cochran_common.c
+++ b/src/cochran_common.c
@@ -39,9 +39,21 @@
rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
)
+static const dc_device_vtable_t cochran_common_device_vtable = {
+ DC_FAMILY_COCHRAN,
+ cochran_common_device_set_fingerprint, /* set_fingerprint */
+ cochran_common_device_read, /* read */
+ NULL, /* write */
+ cochran_common_device_dump, /* dump */
+ cochran_common_device_foreach, /* foreach */
+ cochran_common_device_close /* close */
+};
+
dc_status_t
-cochran_packet (cochran_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize, int high_speed)
+cochran_packet (cochran_device_t *device, const unsigned char command[],
+ unsigned int csize, unsigned char answer[], unsigned int asize,
+ int high_speed)
{
dc_device_t *abstract = (dc_device_t *) device;
unsigned int bytes_read = 0, n, read_size;
@@ -50,11 +62,9 @@ cochran_packet (cochran_device_t *device, const unsigned char command[], unsigne
if (device_is_cancelled (abstract))
return DC_STATUS_CANCELLED;
- struct timespec tr, ts = {0};
- ts.tv_nsec = 16 * 1000000; // 16 ms
// Send the command to the device, one byte at a time
for (ptr = 0; ptr < csize; ptr++) {
- if (ptr) nanosleep(&ts, &tr);
+ if (ptr) serial_sleep(device->port, 16); // 16 ms
n = serial_write(device->port, command + ptr, 1);
if (n != 1) {
ERROR (abstract->context, "Failed to send the command.");
@@ -63,9 +73,7 @@ cochran_packet (cochran_device_t *device, const unsigned char command[], unsigne
}
if (high_speed) {
- struct timespec tr, ts = {0};
- ts.tv_nsec = 45 * 1000000; // 45 ms
- nanosleep(&ts, &tr);
+ serial_sleep(device->port, 45);
// Weird but I only get the right result when I do it twice
// Rates are odd, like 825600 for the EMC, 115200 for commander
@@ -85,7 +93,8 @@ cochran_packet (cochran_device_t *device, const unsigned char command[], unsigne
n = serial_read (device->port, answer + bytes_read, read_size);
if (n != read_size) {
- ERROR (abstract->context, "Failed to receive data, expected %u, read %u.", read_size, n);
+ ERROR (abstract->context, "Failed to receive data, expected %u,"
+ "read %u.", read_size, n);
return EXITCODE (n);
}
@@ -101,16 +110,10 @@ cochran_packet (cochran_device_t *device, const unsigned char command[], unsigne
}
-dc_status_t
-cochran_common_serial_open(cochran_device_t *device, dc_context_t *context)
+static dc_status_t
+cochran_common_serial_setup (cochran_device_t *device, dc_context_t *context)
{
- // Open the device.
- int rc = serial_open (&device->port, context, device->name);
- if (rc == -1) {
- ERROR (context, "Failed to open the serial port.");
- free (device);
- return DC_STATUS_IO;
- }
+ int rc;
// Set the serial communication protocol (9600 8N2, no FC).
rc = serial_configure (device->port, 9600, 8, SERIAL_PARITY_NONE,
@@ -135,9 +138,7 @@ cochran_common_serial_open(cochran_device_t *device, dc_context_t *context)
serial_flush (device->port, SERIAL_QUEUE_INPUT);
serial_set_break(device->port, 1);
- struct timespec tr, ts = {0};
- ts.tv_nsec = 16 * 1000000; // 16ms
- nanosleep(&ts, &tr);
+ serial_sleep(device->port, 16);
serial_set_break(device->port, 0);
@@ -162,7 +163,23 @@ cochran_common_serial_open(cochran_device_t *device, dc_context_t *context)
dc_status_t
-cochran_common_device_open (dc_device_t **out, dc_context_t *context, const char *name, const dc_device_vtable_t *vtable)
+cochran_common_serial_open(cochran_device_t *device, dc_context_t *context)
+{
+ // Open the device.
+ int rc = serial_open (&device->port, context, device->name);
+ if (rc == -1) {
+ ERROR (context, "Failed to open the serial port.");
+ free (device);
+ return DC_STATUS_IO;
+ }
+
+ return cochran_common_serial_setup(device, context);
+}
+
+
+dc_status_t
+cochran_common_device_open (dc_device_t **out, dc_context_t *context,
+ const char *name)
{
dc_status_t rc;
@@ -170,14 +187,15 @@ cochran_common_device_open (dc_device_t **out, dc_context_t *context, const char
return DC_STATUS_INVALIDARGS;
// Allocate memory.
- cochran_device_t *device = (cochran_device_t *) malloc (sizeof (cochran_device_t));
+ cochran_device_t *device = (cochran_device_t *) malloc (
+ sizeof (cochran_device_t));
if (device == NULL) {
ERROR (context, "Failed to allocate memory.");
return DC_STATUS_NOMEMORY;
}
// Initialize the base class.
- device_init (&device->base, context, vtable);
+ device_init (&device->base, context, &cochran_common_device_vtable);
// Set the default values.
device->port = NULL;
@@ -187,7 +205,8 @@ cochran_common_device_open (dc_device_t **out, dc_context_t *context, const char
device->data.sample = NULL;
cochran_common_device_set_fingerprint((dc_device_t *) device, "", 0);
- if ((rc = cochran_common_serial_open(device, context)) != DC_STATUS_SUCCESS)
+ if ((rc = cochran_common_serial_open(device, context))
+ != DC_STATUS_SUCCESS)
return rc;
// Read ID from the device
@@ -202,6 +221,15 @@ cochran_common_device_open (dc_device_t **out, dc_context_t *context, const char
return rc;
}
+ // Check ID
+ if ((device->data.model & 0xFF0000) == COCHRAN_MODEL_UNKNOWN) {
+ ERROR (context, "Device not recognized.");
+ serial_close (device->port);
+ free (device->data.id);
+ free (device);
+ return DC_STATUS_UNSUPPORTED;
+ }
+
*out = (dc_device_t *) device;
return DC_STATUS_SUCCESS;
@@ -236,7 +264,8 @@ cochran_common_device_close (dc_device_t *abstract)
dc_status_t
-cochran_common_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size)
+cochran_common_device_set_fingerprint (dc_device_t *abstract,
+ const unsigned char data[], unsigned int size)
{
cochran_device_t *device = (cochran_device_t *) abstract;
cochran_data_t *d = &(device->data);
@@ -254,7 +283,8 @@ cochran_common_device_set_fingerprint (dc_device_t *abstract, const unsigned cha
dc_status_t
-cochran_common_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size)
+cochran_common_device_read (dc_device_t *abstract, unsigned int address,
+ unsigned char data[], unsigned int size)
{
cochran_device_t *device = (cochran_device_t*) abstract;
@@ -294,7 +324,8 @@ cochran_common_device_read (dc_device_t *abstract, unsigned int address, unsigne
}
// Read data at high speed
- dc_status_t rc = cochran_packet (device, command, command_size, data, size, 1);
+ dc_status_t rc = cochran_packet (device, command, command_size, data,
+ size, 1);
if (rc != DC_STATUS_SUCCESS)
return rc;
@@ -341,7 +372,7 @@ cochran_set_device_config (cochran_device_t *device)
device->data.address_length = COCHRAN_ADDRESS_LENGTH_32;
device->data.high_baud = 825600;
}
- else if (memcmp(device->data.id + 0x3B, "AM\x11\x32\x32\x31\x32\x02", 8) == 0)
+ else if (memcmp(device->data.id + 0x3B, "AM\x11""2212\x02", 8) == 0)
{
device->data.model = COCHRAN_MODEL_COMMANDER_AIR_NITROX;
device->data.log_size = 256;
@@ -558,13 +589,10 @@ cochran_read_logbook (dc_device_t *abstract)
device->progress->maximum = d->logbook_size;
device_event_emit (abstract, DC_EVENT_PROGRESS, device->progress);
- // We have to close and restart to get the DC's attention
- serial_close(device->port);
+ serial_sleep(device->port, 800);
- struct timespec tr, ts = {0, 800 * 1000000}; // 800ms
- nanosleep(&ts, &tr);
-
- cochran_common_serial_open(device, abstract->context);
+ // set back to 9600 baud
+ cochran_common_serial_setup(device, abstract->context);
// Request log book
rc = cochran_common_device_read(abstract, 0, d->logbook, d->logbook_size);
@@ -662,9 +690,6 @@ cochran_read_samples(dc_device_t *abstract)
return DC_STATUS_NOMEMORY;
}
- // We have to close the serial port to get the DC's attention
- serial_close(device->port);
-
// Enable progress notifications.
device->progress = malloc(sizeof(dc_event_progress_t));
if (device->progress == NULL) {
@@ -676,13 +701,14 @@ cochran_read_samples(dc_device_t *abstract)
device->progress->maximum = d->sample_size;
device_event_emit (abstract, DC_EVENT_PROGRESS, device->progress);
- struct timespec tr, ts = {0, 800* 1000000}; // 800 ms
- nanosleep(&ts, &tr);
+ serial_sleep(device->port, 800);
- cochran_common_serial_open(device, abstract->context);
+ // set back to 9600 baud
+ cochran_common_serial_setup(device, abstract->context);
// Read the sample data
- rc = cochran_common_device_read (abstract, d->sample_data_offset, d->sample, d->sample_size);
+ rc = cochran_common_device_read (abstract, d->sample_data_offset,
+ d->sample, d->sample_size);
if (rc != DC_STATUS_SUCCESS) {
free (device->progress);
ERROR (abstract->context, "Failed to read the sample data.");
@@ -724,13 +750,17 @@ cochran_common_device_read_all (dc_device_t *abstract)
}
+#define pack_uint32_array_le(d, i) ((d)[0] = (i) & 0xff, \
+ (d)[1] = ((i) >> 8) & 0xff, \
+ (d)[2] = ((i) >> 16) & 0xff, \
+ (d)[3] = ((i) >> 24) & 0xff)
+
dc_status_t
cochran_common_device_dump (dc_device_t *abstract, dc_buffer_t *data)
{
cochran_device_t *device = (cochran_device_t *) abstract;
cochran_data_t *d = (cochran_data_t *) &(device->data);
-
- struct cochran_data_dump *dump = (struct cochran_data_dump *) data;
+ int ptr = 0;
dc_status_t rc;
@@ -739,60 +769,119 @@ cochran_common_device_dump (dc_device_t *abstract, dc_buffer_t *data)
if (rc != DC_STATUS_SUCCESS)
return rc;
- // Copy data for permanency.
+ // Reserve space for pointers
+ dc_buffer_resize(data, 10 * 5);
+
+ pack_uint32_array_le(dc_buffer_get_data(data) + ptr,
+ dc_buffer_get_size(data));
if (d->id0) {
- dump->id0 = dc_buffer_new(67);
- dc_buffer_append (dump->id0, d->id0, 67);
+ dc_buffer_append(data, d->id0, 67);
+ *(dc_buffer_get_data(data) + ptr + 4) = 1;
+ } else {
+ dc_buffer_resize(data, dc_buffer_get_size(data) + 67);
}
+ ptr += 5;
+ pack_uint32_array_le(dc_buffer_get_data(data) + ptr,
+ dc_buffer_get_size(data));
+
if (d->id) {
- dump->id1 = dc_buffer_new(67);
- dc_buffer_append (dump->id1, d->id, 67);
+ dc_buffer_append (data, d->id, 67);
+ *(dc_buffer_get_data(data) + ptr + 4) = 1;
+ } else {
+ dc_buffer_resize(data, dc_buffer_get_size(data) + 67);
}
+ ptr += 5;
+ pack_uint32_array_le(dc_buffer_get_data(data) + ptr,
+ dc_buffer_get_size(data));
+
if (d->config1) {
- dump->config1 = dc_buffer_new(512);
- dc_buffer_append (dump->config1, d->config1, 512);
+ dc_buffer_append (data, d->config1, 512);
+ *(dc_buffer_get_data(data) + ptr + 4) = 1;
+ } else {
+ dc_buffer_resize(data, dc_buffer_get_size(data) + 512);
}
+ ptr += 5;
+ pack_uint32_array_le(dc_buffer_get_data(data) + ptr,
+ dc_buffer_get_size(data));
+
if (d->config2) {
- dump->config2 = dc_buffer_new(512);
- dc_buffer_append (dump->config2, d->config2, 512);
+ dc_buffer_append (data, d->config2, 512);
+ *(dc_buffer_get_data(data) + ptr + 4) = 1;
+ } else {
+ dc_buffer_resize(data, dc_buffer_get_size(data) + 512);
}
+ ptr += 5;
+ pack_uint32_array_le(dc_buffer_get_data(data) + ptr,
+ dc_buffer_get_size(data));
+
if (d->config3) {
- dump->config3 = dc_buffer_new(512);
- dc_buffer_append (dump->config3, d->config3, 512);
+ dc_buffer_append (data, d->config3, 512);
+ *(dc_buffer_get_data(data) + ptr + 4) = 1;
+ } else {
+ dc_buffer_resize(data, dc_buffer_get_size(data) + 512);
}
+ ptr += 5;
+ pack_uint32_array_le(dc_buffer_get_data(data) + ptr,
+ dc_buffer_get_size(data));
+
if (d->config4) {
- dump->config4 = dc_buffer_new(512);
- dc_buffer_append (dump->config4, d->config4, 512);
+ dc_buffer_append (data, d->config4, 512);
+ *(dc_buffer_get_data(data) + ptr + 4) = 1;
+ } else {
+ dc_buffer_resize(data, dc_buffer_get_size(data) + 512);
}
+ ptr += 5;
+ pack_uint32_array_le(dc_buffer_get_data(data) + ptr,
+ dc_buffer_get_size(data));
+
if (d->misc) {
- dump->misc = dc_buffer_new(1500);
- dc_buffer_append (dump->misc, d->misc, 1500);
+ dc_buffer_append (data, d->misc, 1500);
+ *(dc_buffer_get_data(data) + ptr + 4) = 1;
+ } else {
+ dc_buffer_resize(data, dc_buffer_get_size(data) + 1500);
}
+ ptr += 5;
+ pack_uint32_array_le(dc_buffer_get_data(data) + ptr,
+ dc_buffer_get_size(data));
+
if (d->logbook) {
- dump->logbook = dc_buffer_new(d->logbook_size);
- dc_buffer_append (dump->logbook, d->logbook, d->logbook_size);
+ dc_buffer_append (data, d->logbook, d->logbook_size);
+ *(dc_buffer_get_data(data) + ptr + 4) = 1;
+ } else {
+ dc_buffer_resize(data, dc_buffer_get_size(data) + d->logbook_size);
}
+ ptr += 5;
+ pack_uint32_array_le(dc_buffer_get_data(data) + ptr,
+ dc_buffer_get_size(data));
+
if (d->sample) {
- dump->sample = dc_buffer_new(d->sample_size);
- dc_buffer_append (dump->sample, d->sample, d->sample_size);
+ dc_buffer_append (data, d->sample, d->sample_size);
+ *(dc_buffer_get_data(data) + ptr + 4) = 1;
+ } else {
+ dc_buffer_resize(data, dc_buffer_get_size(data) + d->sample_size);
}
+ ptr += 5;
+ pack_uint32_array_le(dc_buffer_get_data(data) + ptr,
+ dc_buffer_get_size(data));
+
return DC_STATUS_SUCCESS;
}
dc_status_t
-cochran_common_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata)
+cochran_common_device_foreach (dc_device_t *abstract,
+ dc_dive_callback_t callback, void *userdata)
{
cochran_device_t *device = (cochran_device_t *) abstract;
cochran_data_t *d = &(device->data);
@@ -853,7 +942,8 @@ cochran_common_device_foreach (dc_device_t *abstract, dc_dive_callback_t callbac
}
d->current_dive_start_time = mktime(&t);
- if (callback && !callback ((unsigned char *) d, sizeof(device->data), d->current_fingerprint, sizeof (d->fingerprint), userdata))
+ if (callback && !callback ((unsigned char *) d, sizeof(device->data),
+ d->current_fingerprint, sizeof (d->fingerprint), userdata))
return DC_STATUS_SUCCESS;
}
diff --git a/src/cochran_common.h b/src/cochran_common.h
index 136f153..7bba3fb 100644
--- a/src/cochran_common.h
+++ b/src/cochran_common.h
@@ -96,14 +96,62 @@ typedef struct cochran_device_t {
const char *name; // serial port name
serial_t *port;
cochran_data_t data; // dive data used in parsing
- dc_event_progress_t *progress; // We have to do progress in the _read function
+ dc_event_progress_t *progress; // for progress in the _read function
} cochran_device_t;
-dc_status_t cochran_packet (cochran_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize, int high_speed);
-dc_status_t cochran_common_device_open (dc_device_t **out, dc_context_t *context, const char *name, const dc_device_vtable_t *vtable);
+
+// Commander log fields
+#define CMD_SEC 1
+#define CMD_MIN 0
+#define CMD_HOUR 3
+#define CMD_DAY 2
+#define CMD_MON 5
+#define CMD_YEAR 4
+#define CME_START_OFFSET 6 // 4 bytes
+#define CMD_WATER_CONDUCTIVITY 24 // 1 byte, 0=low, 2=high
+#define CMD_START_TEMP 45 // 1 byte, F
+#define CMD_START_DEPTH 56 // 2 byte, /4=ft
+#define CMD_ALTITUDE 73 // 1 byte, /4=Kilofeet
+#define CMD_END_OFFSET 128 // 4 bytes
+#define CMD_MIN_TEMP 153 // 1 byte, F
+#define CMD_BT 166 // 2 bytes, minutes
+#define CMD_MAX_DEPTH 168 // 2 bytes, /4=ft
+#define CMD_AVG_DEPTH 170 // 2 bytes, /4=ft
+#define CMD_O2_PERCENT 210 // 8 bytes, 4 x 2 byte, /256=%
+
+// EMC log fields
+#define EMC_SEC 0
+#define EMC_MIN 1
+#define EMC_HOUR 2
+#define EMC_DAY 3
+#define EMC_MON 4
+#define EMC_YEAR 5
+#define EMC_START_OFFSET 6 // 4 bytes
+#define EMC_WATER_CONDUCTIVITY 25 // 1 byte, 0=low, 2=high
+#define EMC_START_DEPTH 42 // 2 byte, /256=ft
+#define EMC_START_TEMP 55 // 1 byte, F
+#define EMC_ALTITUDE 89 // 1 byte, /4=Kilofeet
+#define EMC_O2_PERCENT 144 // 20 bytes, 10 x 2 bytes, /256=%
+#define EMC_HE_PERCENT 164 // 20 bytes, 10 x 2 bytes, /256=%
+#define EMC_END_OFFSET 256 // 4 bytes
+#define EMC_MIN_TEMP 293 // 1 byte, F
+#define EMC_BT 304 // 2 bytes, minutes
+#define EMC_MAX_DEPTH 306 // 2 bytes, /4=ft
+#define EMC_AVG_DEPTH 310 // 2 bytes, /4=ft
+
+
+dc_status_t cochran_packet (cochran_device_t *device,
+ const unsigned char command[], unsigned int csize,
+ unsigned char answer[], unsigned int asize, int high_speed);
+dc_status_t cochran_common_device_open (dc_device_t **out,
+ dc_context_t *context, const char *name);
dc_status_t cochran_common_device_close (dc_device_t *abstract);
-dc_status_t cochran_common_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
-dc_status_t cochran_common_device_read (dc_device_t *abstract, unsigned int address, unsigned char data[], unsigned int size);
+dc_status_t cochran_common_device_set_fingerprint (dc_device_t *abstract,
+ const unsigned char data[], unsigned int size);
+dc_status_t cochran_common_device_read (dc_device_t *abstract,
+ unsigned int address, unsigned char data[], unsigned int size);
static dc_status_t cochran_read_id (dc_device_t *abstract);
-dc_status_t cochran_common_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata);
-dc_status_t cochran_common_device_dump (dc_device_t *abstract, dc_buffer_t *data);
+dc_status_t cochran_common_device_foreach (dc_device_t *abstract,
+ dc_dive_callback_t callback, void *userdata);
+dc_status_t cochran_common_device_dump (dc_device_t *abstract,
+ dc_buffer_t *data);
diff --git a/src/cochran_common_parser.c b/src/cochran_common_parser.c
index 744e5e7..9cc4040 100644
--- a/src/cochran_common_parser.c
+++ b/src/cochran_common_parser.c
@@ -34,15 +34,34 @@
#include "cochran_common_parser.h"
-dc_status_t cochran_common_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
-dc_status_t cochran_common_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
-dc_status_t cochran_common_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
+dc_status_t cochran_common_parser_set_data (dc_parser_t *abstract,
+ const unsigned char *data, unsigned int size);
+dc_status_t cochran_common_parser_get_datetime (dc_parser_t *abstract,
+ dc_datetime_t *datetime);
+static dc_status_t cochran_common_parser_get_field (dc_parser_t *abstract,
+ dc_field_type_t type, unsigned int flags, void *value);
dc_status_t cochran_common_parser_destroy (dc_parser_t *abstract);
-int cochran_common_handle_event (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata, unsigned char code, unsigned int offset, unsigned int time);
+static dc_status_t cochran_common_parser_samples_foreach
+ (dc_parser_t *abstract, dc_sample_callback_t callback,
+ void *userdata);
+int cochran_common_handle_event (dc_parser_t *abstract,
+ dc_sample_callback_t callback, void *userdata, unsigned char code,
+ unsigned int offset, unsigned int time);
+
+
+static dc_parser_vtable_t cochran_common_parser_vtable = {
+ DC_FAMILY_COCHRAN,
+ cochran_common_parser_set_data, /* set_data */
+ cochran_common_parser_get_datetime, /* datetime */
+ cochran_common_parser_get_field, /* fields */
+ cochran_common_parser_samples_foreach, /* samples_foreach */
+ cochran_common_parser_destroy /* destroy */
+};
+
dc_status_t
-cochran_common_parser_create (dc_parser_t **out, dc_context_t *context, const dc_parser_vtable_t *vtable)
+cochran_common_parser_create (dc_parser_t **out, dc_context_t *context)
{
if (out == NULL)
return DC_STATUS_INVALIDARGS;
@@ -54,7 +73,7 @@ cochran_common_parser_create (dc_parser_t **out, dc_context_t *context, const dc
return DC_STATUS_NOMEMORY;
}
- parser_init (parser, context, vtable);
+ parser_init (parser, context, &cochran_common_parser_vtable);
*out = parser;
@@ -73,7 +92,8 @@ cochran_common_parser_destroy (dc_parser_t *abstract)
dc_status_t
-cochran_common_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size)
+cochran_common_parser_set_data (dc_parser_t *abstract,
+ const unsigned char *data, unsigned int size)
{
abstract->data = data;
abstract->size = size;
@@ -84,7 +104,8 @@ cochran_common_parser_set_data (dc_parser_t *abstract, const unsigned char *data
// There are two date formats used by Cochran
dc_status_t
-cochran_common_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
+cochran_common_parser_get_datetime (dc_parser_t *abstract,
+ dc_datetime_t *datetime)
{
cochran_data_t *data = (cochran_data_t *) abstract->data;
const unsigned char *log = data->current_log;
@@ -108,9 +129,48 @@ cochran_common_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *dateti
return DC_STATUS_SUCCESS;
}
+static dc_status_t
+cochran_common_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
+ unsigned int flags, void *value)
+{
+ cochran_data_t *data = (cochran_data_t *) abstract->data;
+
+ switch (data->model & 0xFF0000)
+ {
+ case COCHRAN_MODEL_COMMANDER_FAMILY:
+ return cochran_cmdr_parser_get_field(abstract, type, flags, value);
+ break;
+ case COCHRAN_MODEL_EMC_FAMILY:
+ return cochran_emc_parser_get_field(abstract, type, flags, value);
+ break;
+ }
+}
+
+static dc_status_t
+cochran_common_parser_samples_foreach (dc_parser_t *abstract,
+ dc_sample_callback_t callback, void *userdata)
+{
+ cochran_data_t *data = (cochran_data_t *) abstract->data;
+
+ switch (data->model & 0xFF0000)
+ {
+ case COCHRAN_MODEL_COMMANDER_FAMILY:
+ return cochran_cmdr_parser_samples_foreach(abstract, callback,
+ userdata);
+ break;
+ case COCHRAN_MODEL_EMC_FAMILY:
+ return cochran_emc_parser_samples_foreach(abstract, callback,
+ userdata);
+ break;
+ }
+}
+
+
int
-cochran_common_handle_event (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata, unsigned char code, unsigned int offset, unsigned int time)
+cochran_common_handle_event (dc_parser_t *abstract,
+ dc_sample_callback_t callback, void *userdata, unsigned char code,
+ unsigned int offset, unsigned int time)
{
cochran_data_t *data = (cochran_data_t *) abstract->data;
cochran_events_t *e = cochran_events;
diff --git a/src/cochran_common_parser.h b/src/cochran_common_parser.h
index d19a619..9c4a67d 100644
--- a/src/cochran_common_parser.h
+++ b/src/cochran_common_parser.h
@@ -36,6 +36,8 @@ static cochran_events_t cochran_events[] = {
SAMPLE_EVENT_NONE, SAMPLE_FLAGS_NONE },
{ 0xAD, 5, "Ceiling increase",
SAMPLE_EVENT_NONE, SAMPLE_FLAGS_NONE },
+ { 0xBD, 1, "Switched to nomal PO2 setting",
+ SAMPLE_EVENT_NONE, SAMPLE_FLAGS_NONE },
{ 0xC0, 1, "Switched to FO2 21% mode",
SAMPLE_EVENT_GASCHANGE, SAMPLE_FLAGS_NONE },
{ 0xC1, 1, "Ascent rate greater than limit",
@@ -50,20 +52,34 @@ static cochran_events_t cochran_events[] = {
SAMPLE_EVENT_DEEPSTOP, SAMPLE_FLAGS_BEGIN },
{ 0xC8, 1, "PO2 too high",
SAMPLE_EVENT_FLOOR, SAMPLE_FLAGS_BEGIN },
+ { 0xCC, 1, "Low Cylinder 1 pressure",
+ SAMPLE_EVENT_NONE, SAMPLE_FLAGS_BEGIN },
{ 0xCE, 1, "Non-decompression warning",
SAMPLE_EVENT_RBT, SAMPLE_FLAGS_BEGIN },
+ { 0xCD, 1, "Switched to deco blend",
+ SAMPLE_EVENT_NONE, SAMPLE_FLAGS_BEGIN },
+ { 0xD0, 1, "Breathing rate alarm",
+ SAMPLE_EVENT_NONE, SAMPLE_FLAGS_BEGIN },
+ { 0xD3, 1, "Low gas 1 flow rate",
+ SAMPLE_EVENT_NONE, SAMPLE_FLAGS_NONE },
{ 0xD6, 1, "Depth is less than ceiling",
SAMPLE_EVENT_CEILING, SAMPLE_FLAGS_BEGIN },
{ 0xD8, 1, "End decompression mode",
SAMPLE_EVENT_DEEPSTOP, SAMPLE_FLAGS_END },
{ 0xE1, 1, "End ascent rate warning",
SAMPLE_EVENT_ASCENT, SAMPLE_FLAGS_END },
+ { 0xE2, 1, "Low SBAT battery warning",
+ SAMPLE_EVENT_NONE, SAMPLE_FLAGS_NONE },
{ 0xE3, 1, "Switched to FO2 mode",
SAMPLE_EVENT_NONE, SAMPLE_FLAGS_NONE },
+ { 0xE5, 1, "Switched to PO2 mode",
+ SAMPLE_EVENT_NONE, SAMPLE_FLAGS_NONE },
{ 0xEE, 1, "End non-decompresison warning",
SAMPLE_EVENT_RBT, SAMPLE_FLAGS_END },
{ 0xEF, 1, "Switch to blend 2",
SAMPLE_EVENT_GASCHANGE2, SAMPLE_FLAGS_NONE },
+ { 0xF0, 1, "Breathing rate alarm",
+ SAMPLE_EVENT_NONE, SAMPLE_FLAGS_END },
{ 0xF3, 1, "Switch to blend 1",
SAMPLE_EVENT_GASCHANGE2, SAMPLE_FLAGS_NONE },
{ 0xF6, 1, "End Depth is less than ceiling",
@@ -73,8 +89,27 @@ static cochran_events_t cochran_events[] = {
};
-dc_status_t cochran_common_parser_create (dc_parser_t **out, dc_context_t *context, const dc_parser_vtable_t *vtable);
+// Common
+dc_status_t cochran_common_parser_create (dc_parser_t **out,
+ dc_context_t *context);
dc_status_t cochran_common_parser_destroy (dc_parser_t *abstract);
-dc_status_t cochran_common_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
-dc_status_t cochran_common_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime);
-int cochran_common_handle_event (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata, unsigned char code, unsigned int offset, unsigned int time);
+dc_status_t cochran_common_parser_set_data (dc_parser_t *abstract,
+ const unsigned char *data, unsigned int size);
+dc_status_t cochran_common_parser_get_datetime (dc_parser_t *abstract,
+ dc_datetime_t *datetime);
+int cochran_common_handle_event (dc_parser_t *abstract,
+ dc_sample_callback_t callback, void *userdata, unsigned char code,
+ unsigned int offset, unsigned int time);
+
+// EMC FAMILY
+dc_status_t cochran_emc_parser_get_field (dc_parser_t *abstract,
+ dc_field_type_t type, unsigned int flags, void *value);
+dc_status_t cochran_emc_parser_samples_foreach (dc_parser_t *abstract,
+ dc_sample_callback_t callback, void *userdata);
+
+// COMMANDER FAMILY
+dc_status_t cochran_cmdr_parser_get_field(dc_parser_t *abstract,
+ dc_field_type_t type, unsigned int flags, void *value);
+dc_status_t cochran_cmdr_parser_samples_foreach (dc_parser_t *abstract,
+ dc_sample_callback_t callback, void *userdata);
+
diff --git a/src/cochran_emc.c b/src/cochran_emc.c
deleted file mode 100644
index c4b0367..0000000
--- a/src/cochran_emc.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * libdivecomputer
- *
- * Copyright (C) 2014 John Van Ostrand
- *
- * 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 <stdlib.h>
-#include <time.h>
-
-#include <libdivecomputer/cochran.h>
-
-#include "context-private.h"
-#include "device-private.h"
-#include "serial.h"
-
-#include "cochran_common.h"
-#include "cochran_emc.h"
-
-
-static const dc_device_vtable_t cochran_emc_device_vtable = {
- DC_FAMILY_COCHRAN_EMC,
- cochran_common_device_set_fingerprint, /* set_fingerprint */
- cochran_common_device_read, /* read */
- NULL, /* write */
- cochran_common_device_dump, /* dump */
- cochran_common_device_foreach, /* foreach */
- cochran_common_device_close /* close */
-};
-
-
-dc_status_t
-cochran_emc_device_open (dc_device_t **out, dc_context_t *context, const char *name)
-{
- dc_status_t rc;
-
- rc = cochran_common_device_open(out, context, name, &cochran_emc_device_vtable);
- if (rc != DC_STATUS_SUCCESS)
- return rc;
-
- cochran_device_t *device = (cochran_device_t *) *out;
-
- // Check family
- if ((device->data.model & 0xFF0000) != COCHRAN_MODEL_EMC_FAMILY) {
- ERROR (context, "Device not recognized.");
- serial_close (device->port);
- free (device->data.id);
- free (device);
- return DC_STATUS_UNSUPPORTED;
- }
-
- return DC_STATUS_SUCCESS;
-}
diff --git a/src/cochran_emc.h b/src/cochran_emc.h
deleted file mode 100644
index e21036b..0000000
--- a/src/cochran_emc.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * libdivecomputer
- *
- * Copyright (C) 2014 John Van Ostrand
- *
- * 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
- */
-
-// 512 bytes for each dive in the log book
-struct cochran_emc_log_t {
- // Pre-dive 256 bytes
- unsigned char seconds, minutes, hour; // 3 bytes
- unsigned char day, month, year; // 3 bytes
- unsigned char sample_start_offset[4]; // 4 bytes
- unsigned char start_timestamp[4]; // 4 bytes [secs from jan 1,92]
- unsigned char pre_dive_timestamp[4]; // 4 bytes [secs from Jan 1,92]
- unsigned char unknown1[6]; // 6 bytes
- unsigned char water_conductivity; // 1 byte [0 =low, 2-high]
- unsigned char unknown2[5]; // 5 bytes
-//30
- unsigned char sample_pre_event_offset[4]; // 4 bytes
- unsigned char config_bitfield[6]; // 6 bytes
- unsigned char unknown3[2]; // 2 bytes
- unsigned char start_depth[2]; // 2 bytes [/256]
- unsigned char unknown4[2]; // 2 bytes
- unsigned char start_battery_voltage[2]; // 2 bytes [/256]
-//48
- unsigned char unknown5[7]; // 7 bytes
- unsigned char start_temperature; // 1 byte [F]
- unsigned char unknown6[28]; // 28 bytes
- unsigned char sit[2]; // 2 bytes [minutes]
- unsigned char number[2]; // 2 bytes
- unsigned char unknown7[1]; // 1 bytes
- unsigned char altitude; // 1 byte [/4 = kft]
- unsigned char start_nofly[2]; // 2 bytes [/256 = hours]
-//92
- unsigned char unknown8[18]; // 18 bytes
- unsigned char post_dive_sit[2]; // 2 bytes [seconds]
- unsigned char po2_set_point[9][2]; // 18 bytes [/256 = %]
- unsigned char unknown9[12]; // 12 bytes
- unsigned char po2_alarm[2]; // 2 bytes [/256 = %]
-//144
- unsigned char o2_percent[10][2]; // 20 bytes [/256 = %]
- unsigned char he_percent[10][2]; // 20 bytes [/256 = %]
- unsigned char alarm_depth[2]; // 2 bytes
- unsigned char unknown10[14]; // 14 bytes
- unsigned char conservatism; // 1 bytes [/256 = fraction]
- unsigned char unknown11[2]; // 2 bytes
- unsigned char repetitive_dive; // 1 byte
- unsigned char unknown12[12]; // 12 bytes
- unsigned char start_tissue_nsat[20][2]; // 40 bytes [/256]
-
- // Post-dive 256 bytes
- unsigned char sample_end_offset[4]; // 4 bytes
- unsigned char unknown13[33]; // 33 bytes
- unsigned char temp; // 1 byte [F]
- unsigned char unknown14[10]; // 10 bytes
-// 48
- unsigned char bt[2]; // 2 bytes [minutes]
- unsigned char max_depth[2]; // 2 bytes [/4 = ft]
- unsigned char unknown15[2]; // 2 bytes
- unsigned char avg_depth[2]; // 2 bytes [/4 = ft]
- unsigned char min_ndc[2]; // 2 bytes [minutes]
- unsigned char min_ndx_bt[2]; // 2 bytes [minutes]
- unsigned char max_forecast_deco[2]; // 2 bytes [minutes]
- unsigned char max_forecast_deco_bt[2]; // 2 bytes [minutes]
-//64
- unsigned char max_ceiling[2]; // 2 bytes [*10 = ft]
- unsigned char max_ceiling_bt[2]; // 2 bytes [minutes]
- unsigned char unknown16[10]; // 18 bytes
- unsigned char max_ascent_rate; // 1 byte [ft/min]
- unsigned char unknown17[3]; // 3 bytes
- unsigned char max_ascent_rate_bt[2]; // 2 bytes [seconds]
-//84
- unsigned char unknown18[54]; // 54 bytes
-//138
- unsigned char end_battery_voltage[2]; // 2 bytes [/256 = v]
- unsigned char unknown19[8]; // 8 bytes
- unsigned char min_temp_bt[2]; // 2 bytes [seconds]
-//150
- unsigned char unknown20[22]; // 22 bytes
-//172
- unsigned char end_nofly[2]; // 2 bytes [/256 = hours]
- unsigned char alarm_count[2]; // 2 byte
- unsigned char actual_deco_time[2]; // 2 bytes [seconds]
-//178
- unsigned char unknown21[38]; // 38 bytes
-//216
- unsigned char end_tissue_nsat[20][2]; // 40 bytes [/256 = fraction]
-} __attribute__((packed));
-
-typedef struct cochran_emc_log_t cochran_emc_log_t;
-
-typedef enum cochran_emc_bitfield_config_t {
- BF_TEMP_DEPENDENT_N2,
- BF_ASCENT_RATE_BAR_GRAPH,
- BF_BLEND_2_SWITCHING,
- BF_ALTITUDE_AS_ONE_ZONE,
- BF_DECOMPRESSION_TIME_DISPLAY,
- BF_BLEND_3_SWITCHING,
- BF_VARIABLE_ASCENT_RATE_ALARM,
- BF_ASCENT_RATE_RESPONSE,
- BF_REPETITIVE_DIVE_DEPENDENT_N2,
- BF_TRAINING_MODE,
- BF_CONSTANT_MODE_COMPUTATIONS,
- BF_DISPLAYED_UNITS,
- BF_AUDIBLE_ALARM,
- BF_CLOCK,
- BF_CEILING_DISPLAY_DIV_BY_10,
- BF_GAS_2_AS_FIRST_GAS,
- BF_ENABLE_HELIUM_COMPUTATIONS,
- BF_AUTOMATIC_PO2_FO2_SWITCHING,
- BF_TOUCH_PROGRAMMING_PO2_FO2_SWITCH,
-} cochran_emc_bitfield_config_t;
-
-
-typedef struct cochran_emc_bitfield_t {
- cochran_emc_bitfield_config_t config;
- unsigned char word;
- unsigned char byte;
- unsigned char mask;
- unsigned char shift;
-} cochran_emc_bitfield_t;
-
-static cochran_emc_bitfield_t cochran_emc_bits[] = {
-// Word BD
- { BF_TEMP_DEPENDENT_N2, 0xBD, 0, 0x40, 6 }, // 0=normal,
- // 1=reduced
- { BF_ASCENT_RATE_BAR_GRAPH, 0xBD, 0, 0x20, 5 }, // 0=fixed,
- // 1=proportional
- { BF_BLEND_2_SWITCHING, 0xBD, 0, 0x04, 2 }, // 0=dis, 1=ena
- { BF_ALTITUDE_AS_ONE_ZONE, 0xBD, 0, 0x02, 1}, // 0=off, 1=on
-
- { BF_DECOMPRESSION_TIME_DISPLAY, 0xBD, 1, 0xC0, 5}, // 111=both,
- // 011=stop,
- // 001=total
- { BF_BLEND_3_SWITCHING, 0xBD, 1, 0x10, 4 }, // 0=dis, 1=ena
- { BF_VARIABLE_ASCENT_RATE_ALARM, 0xBD, 1, 0x04, 3}, // 0=off, 1=on
- { BF_ASCENT_RATE_RESPONSE, 0xBD, 1, 0x07, 0},
-
-//WORD BE
- { BF_REPETITIVE_DIVE_DEPENDENT_N2, 0xBE, 0, 0x80, 7 }, // 0=off, 1=on
- { BF_TRAINING_MODE, 0xBE, 0, 0x04, 2 }, // 0=off, 1=on
- { BF_CONSTANT_MODE_COMPUTATIONS, 0xBE, 0, 0x04, 2 }, // 0=FO2, 1=PO2
- { BF_DISPLAYED_UNITS, 0xBE, 0, 0x01, 0 }, // 1=metric,
- // 0=imperial
-
-// WORD BF
- { BF_AUDIBLE_ALARM, 0xBF, 0, 0x40, 6 }, // 0=on, 1=off ***
- { BF_CLOCK, 0xBF, 0, 0x20, 5 }, // 0=off, 1=on
- { BF_CEILING_DISPLAY_DIV_BY_10, 0xBF, 0, 0x10, 4 }, // 0=off, 1=on
- { BF_GAS_2_AS_FIRST_GAS, 0xBF, 0, 0x02, 1 }, // 0=dis, 1=ena
- { BF_ENABLE_HELIUM_COMPUTATIONS, 0xBF, 0, 0x01, 0 }, // 0=dis, 1=ena
-
- { BF_AUTOMATIC_PO2_FO2_SWITCHING, 0xBF, 1, 0x04, 2 }, // 0=dis, 1=ena
- { BF_TOUCH_PROGRAMMING_PO2_FO2_SWITCH, 0xBF, 1, 0x02, 1 }, // 0=dis, 1=ena
-};
-
-struct cochran_emc_config1_t {
- unsigned char unknown1[209];
- unsigned short int dive_count;
- unsigned char unknown2[274];
- unsigned short int serial_num;
- unsigned char unknown3[24];
-} __attribute__((packed));
-
-typedef struct cochran_emc_config1_t cochran_emc_config1_t;
diff --git a/src/cochran_emc_parser.c b/src/cochran_emc_parser.c
index cf6e9af..f336e43 100644
--- a/src/cochran_emc_parser.c
+++ b/src/cochran_emc_parser.c
@@ -32,7 +32,6 @@
#include "array.h"
#include "cochran_common.h"
-#include "cochran_emc.h"
#include "cochran_common_parser.h"
@@ -44,33 +43,16 @@ struct dive_stats {
};
-static dc_status_t cochran_emc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
-static dc_status_t cochran_emc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
-static void cochran_emc_parse_dive_stats (dc_parser_t *abstract, struct dive_stats *stats);
-
-
-static dc_parser_vtable_t cochran_emc_parser_vtable = {
- DC_FAMILY_COCHRAN_EMC,
- cochran_common_parser_set_data, /* set_data */
- cochran_common_parser_get_datetime, /* datetime */
- cochran_emc_parser_get_field, /* fields */
- cochran_emc_parser_samples_foreach, /* samples_foreach */
- cochran_common_parser_destroy /* destroy */
-};
+static void cochran_emc_parse_dive_stats (dc_parser_t *abstract,
+ struct dive_stats *stats);
dc_status_t
-cochran_emc_parser_create (dc_parser_t **out, dc_context_t *context)
-{
- return cochran_common_parser_create(out, context, &cochran_emc_parser_vtable);
-}
-
-
-static dc_status_t
-cochran_emc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value)
+cochran_emc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
+ unsigned int flags, void *value)
{
cochran_data_t *data = (cochran_data_t *) abstract->data;
- cochran_emc_log_t *log = (cochran_emc_log_t *) data->current_log;
+ unsigned char *log = data->current_log;
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
dc_salinity_t *water = (dc_salinity_t *) value;
@@ -86,44 +68,50 @@ cochran_emc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsig
cochran_emc_parse_dive_stats(abstract, &stats);
*((unsigned int*) value) = min_temp;
} else
- *((unsigned int*) value) = (log->start_temperature - 32) / 1.8;
+ *((unsigned int*) value) = (log[EMC_START_TEMP] - 32) / 1.8;
break;
case DC_FIELD_DIVETIME:
if (data->corrupt_dive) {
cochran_emc_parse_dive_stats(abstract, &stats);
*((unsigned int*) value) = dive_time;
} else
- *((unsigned int *) value) = array_uint16_le (log->bt) * 60;
+ *((unsigned int *) value) = array_uint16_le (log + EMC_BT) * 60;
break;
case DC_FIELD_MAXDEPTH:
if (data->corrupt_dive) {
cochran_emc_parse_dive_stats(abstract, &stats);
*((unsigned int*) value) = max_depth;
} else
- *((double *) value) = array_uint16_le (log->max_depth) / 4 * FEET;
+ *((double *) value) = array_uint16_le (log + EMC_MAX_DEPTH) / 4
+ * FEET;
break;
case DC_FIELD_AVGDEPTH:
if (data->corrupt_dive) {
cochran_emc_parse_dive_stats(abstract, &stats);
*((unsigned int*) value) = avg_depth;
} else
- *((double *) value) = array_uint16_le (log->avg_depth) / 4 * FEET;
+ *((double *) value) = array_uint16_le (log + EMC_AVG_DEPTH) / 4
+ * FEET;
break;
case DC_FIELD_GASMIX_COUNT:
*((unsigned int *) value) = 10;
break;
case DC_FIELD_GASMIX:
- gasmix->oxygen = (double) array_uint16_le ((char *)log->o2_percent + 2 * flags) / 256 / 100;
- gasmix->helium = (double) array_uint16_le ((char *)log->he_percent + 2 * flags) / 256 / 100;
+ gasmix->oxygen = (double) array_uint16_le ((char *) log
+ + EMC_O2_PERCENT + 2 * flags) / 256 / 100;
+ gasmix->helium = (double) array_uint16_le ((char *) log
+ + EMC_HE_PERCENT + 2 * flags) / 256 / 100;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
break;
case DC_FIELD_SALINITY:
// 0 = low conductivity, 2 = high, maybe there's a 1?
- water->type = ( log->water_conductivity == 0 ? DC_WATER_FRESH : DC_WATER_SALT );
- water->density = 1000 + 12.5 * log->water_conductivity;
+ water->type = ( log[EMC_WATER_CONDUCTIVITY] == 0 ? DC_WATER_FRESH
+ : DC_WATER_SALT );
+ water->density = 1000 + 12.5 * log[EMC_WATER_CONDUCTIVITY];
break;
case DC_FIELD_ATMOSPHERIC:
- *(double *) value = ATM / BAR * pow(1 - 0.0000225577 * (double) log->altitude * 250 * FEET, 5.25588);
+ *(double *) value = ATM / BAR * pow(1 - 0.0000225577
+ * (double) log[EMC_ALTITUDE] * 250 * FEET, 5.25588);
break;
default:
return DC_STATUS_UNSUPPORTED;
@@ -172,12 +160,13 @@ cochran_emc_guess_sample_size(cochran_data_t *data)
-static dc_status_t
-cochran_emc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
+dc_status_t
+cochran_emc_parser_samples_foreach (dc_parser_t *abstract,
+ dc_sample_callback_t callback, void *userdata)
{
cochran_data_t *data = (cochran_data_t *) abstract->data;
unsigned char *sdata = data->current_sample;
- cochran_emc_log_t *log = (cochran_emc_log_t *) data->current_log;
+ unsigned char *log = data->current_log;
unsigned int size = data->current_sample_size;
unsigned char *s;
@@ -196,12 +185,15 @@ cochran_emc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
size = cochran_emc_guess_sample_size(data);
}
- // Cochran samples depth every second and varies between ascent rate
- // and temp ever other second.
- // In the 21st, 22nd, 23rd, 24th samples are NDL remaining, deco time and ceiling
+ /*
+ * Cochran samples depth every second and varies between ascent rate
+ * and temp ever other second.
+ * In the 21st, 22nd, 23rd, 24th samples are NDL remaining,
+ *deco time and ceiling
+ */
// Prime with values from the dive log section
- depth = array_uint16_le (log->start_depth) / 256;
+ depth = array_uint16_le (log + EMC_START_DEPTH) / 256;
last_sample_time = sample.time = time;
if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
@@ -209,7 +201,7 @@ cochran_emc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
sample.depth = depth * FEET;
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
- sample.temperature = (log->start_temperature - 32) / 1.8;
+ sample.temperature = (log[EMC_START_TEMP] - 32) / 1.8;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
while (offset < size) {
@@ -237,7 +229,8 @@ cochran_emc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
// Check for event
if (s[0] & 0x80) {
- offset += cochran_common_handle_event(abstract, callback, userdata, s[0], offset, time);
+ offset += cochran_common_handle_event(abstract, callback, userdata,
+ s[0], offset, time);
switch (s[0])
{
case 0xC5: // Deco obligation begins
@@ -276,12 +269,12 @@ cochran_emc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
// Ascent rate is logged in the 0th sample, temp in the 1st, repeat.
if (time % 2 == 0) {
// Ascent rate
- ascent_rate = (s[1] & 0x7f) / 4 * (s[0] & 0x80 ? 1 : -1);
+ ascent_rate = (s[1] & 0x7f) / 4 * (s[1] & 0x80 ? 1 : -1);
sample.ascent_rate = ascent_rate * FEET;
if (callback) callback (DC_SAMPLE_ASCENT_RATE, sample, userdata);
} else {
// Temperature logged in half degrees F above 20
- temperature = s[1] / 2 + 20;
+ temperature = (float) s[1] / 2 + 20;
sample.temperature = (temperature - 32.0) / 1.8;
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
@@ -323,11 +316,12 @@ cochran_emc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
return DC_STATUS_SUCCESS;
}
-void cochran_emc_parse_dive_stats (dc_parser_t *abstract, struct dive_stats *stats)
+void cochran_emc_parse_dive_stats (dc_parser_t *abstract,
+ struct dive_stats *stats)
{
cochran_data_t *data = (cochran_data_t *) abstract->data;
unsigned char *sdata = data->current_sample;
- cochran_emc_log_t *log = (cochran_emc_log_t *) data->current_log;
+ unsigned char *log = data->current_log;
unsigned int size = data->current_sample_size;
unsigned char *s;
unsigned int offset = 0;
diff --git a/src/descriptor.c b/src/descriptor.c
index 20f74e6..8836709 100644
--- a/src/descriptor.c
+++ b/src/descriptor.c
@@ -223,9 +223,9 @@ static const dc_descriptor_t g_descriptors[] = {
{"Shearwater", "Petrel", DC_FAMILY_SHEARWATER_PETREL, 3},
/* Dive Rite NiTek Q */
{"Dive Rite", "NiTek Q", DC_FAMILY_DIVERITE_NITEKQ, 0},
- {"Cochran", "Commander", DC_FAMILY_COCHRAN_COMMANDER, 0},
- {"Cochran", "EMC-20H", DC_FAMILY_COCHRAN_EMC, 0},
- {"Cochran", "EMC-16", DC_FAMILY_COCHRAN_EMC, 0},
+ {"Cochran", "Commander", DC_FAMILY_COCHRAN, 0},
+ {"Cochran", "EMC-16", DC_FAMILY_COCHRAN, 1},
+ {"Cochran", "EMC-20H", DC_FAMILY_COCHRAN, 2},
};
typedef struct dc_descriptor_iterator_t {
diff --git a/src/device.c b/src/device.c
index e8661b0..cdd41ab 100644
--- a/src/device.c
+++ b/src/device.c
@@ -155,11 +155,8 @@ dc_device_open (dc_device_t **out, dc_context_t *context, dc_descriptor_t *descr
case DC_FAMILY_DIVERITE_NITEKQ:
rc = diverite_nitekq_device_open (&device, context, name);
break;
- case DC_FAMILY_COCHRAN_COMMANDER:
- rc = cochran_cmdr_device_open (&device, context, name);
- break;
- case DC_FAMILY_COCHRAN_EMC:
- rc = cochran_emc_device_open (&device, context, name);
+ case DC_FAMILY_COCHRAN:
+ rc = cochran_common_device_open (&device, context, name);
break;
default:
return DC_STATUS_INVALIDARGS;
diff --git a/src/parser.c b/src/parser.c
index dc6655b..07e9d2d 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -132,11 +132,8 @@ dc_parser_new (dc_parser_t **out, dc_device_t *device)
case DC_FAMILY_DIVERITE_NITEKQ:
rc = diverite_nitekq_parser_create (&parser, context);
break;
- case DC_FAMILY_COCHRAN_COMMANDER:
- rc = cochran_cmdr_parser_create (&parser, context);
- break;
- case DC_FAMILY_COCHRAN_EMC:
- rc = cochran_emc_parser_create (&parser, context);
+ case DC_FAMILY_COCHRAN:
+ rc = cochran_common_parser_create (&parser, context);
break;
default:
return DC_STATUS_INVALIDARGS;
--
1.8.3.1
More information about the devel
mailing list