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;