Compare commits
13 Commits
Subsurface
...
NG-test
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5f53eeb1f | ||
|
|
5a0f603770 | ||
|
|
6e71b174e0 | ||
|
|
b0d72cd74c | ||
|
|
72c99a6dcb | ||
|
|
9a38a1ac6d | ||
|
|
a6637442b7 | ||
|
|
0ae143e27f | ||
|
|
2d3b25cf8e | ||
|
|
bd1999134f | ||
|
|
927d272e0c | ||
|
|
820b3c0ff5 | ||
|
|
ee802410e3 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -82,3 +82,5 @@ Makefile.in
|
|||||||
/src/libdivecomputer.la
|
/src/libdivecomputer.la
|
||||||
/src/libdivecomputer.rc
|
/src/libdivecomputer.rc
|
||||||
/src/revision.h
|
/src/revision.h
|
||||||
|
|
||||||
|
/build
|
||||||
|
|||||||
10
configure.ac
10
configure.ac
@ -2,7 +2,7 @@
|
|||||||
m4_define([dc_version_major],[0])
|
m4_define([dc_version_major],[0])
|
||||||
m4_define([dc_version_minor],[7])
|
m4_define([dc_version_minor],[7])
|
||||||
m4_define([dc_version_micro],[0])
|
m4_define([dc_version_micro],[0])
|
||||||
m4_define([dc_version_suffix],[devel])
|
m4_define([dc_version_suffix],[devel-Subsurface-NG])
|
||||||
m4_define([dc_version],dc_version_major.dc_version_minor.dc_version_micro[]m4_ifset([dc_version_suffix],-[dc_version_suffix]))
|
m4_define([dc_version],dc_version_major.dc_version_minor.dc_version_micro[]m4_ifset([dc_version_suffix],-[dc_version_suffix]))
|
||||||
|
|
||||||
# Libtool versioning.
|
# Libtool versioning.
|
||||||
@ -175,19 +175,21 @@ AC_CHECK_FUNCS([getopt_long])
|
|||||||
|
|
||||||
# Checks for supported compiler options.
|
# Checks for supported compiler options.
|
||||||
AX_APPEND_COMPILE_FLAGS([ \
|
AX_APPEND_COMPILE_FLAGS([ \
|
||||||
-pedantic \
|
|
||||||
-Wall \
|
-Wall \
|
||||||
-Wextra \
|
|
||||||
-Wshadow \
|
-Wshadow \
|
||||||
-Wrestrict \
|
-Wrestrict \
|
||||||
-Wformat=2 \
|
-Wformat=2 \
|
||||||
-Wwrite-strings \
|
-Wwrite-strings \
|
||||||
-Wcast-qual \
|
|
||||||
-Wpointer-arith \
|
-Wpointer-arith \
|
||||||
-Wstrict-prototypes \
|
-Wstrict-prototypes \
|
||||||
-Wmissing-prototypes \
|
-Wmissing-prototypes \
|
||||||
-Wmissing-declarations \
|
-Wmissing-declarations \
|
||||||
-Wno-unused-parameter \
|
-Wno-unused-parameter \
|
||||||
|
-Wno-unused-function \
|
||||||
|
-Wno-unused-variable \
|
||||||
|
-Wno-unused-but-set-variable \
|
||||||
|
-Wno-pointer-sign \
|
||||||
|
-Wno-shadow \
|
||||||
])
|
])
|
||||||
|
|
||||||
# Windows specific compiler options.
|
# Windows specific compiler options.
|
||||||
|
|||||||
@ -400,6 +400,24 @@ dctool_xml_output_write (dctool_output_t *abstract, dc_parser_t *parser, const u
|
|||||||
convert_pressure(atmospheric, output->units));
|
convert_pressure(atmospheric, output->units));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message ("Parsing strings.\n");
|
||||||
|
int idx;
|
||||||
|
for (idx = 0; idx < 100; idx++) {
|
||||||
|
dc_field_string_t str = { NULL };
|
||||||
|
status = dc_parser_get_field(parser, DC_FIELD_STRING, idx, &str);
|
||||||
|
if (status != DC_STATUS_SUCCESS && status != DC_STATUS_UNSUPPORTED) {
|
||||||
|
ERROR ("Error parsing strings");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (status == DC_STATUS_UNSUPPORTED)
|
||||||
|
break;
|
||||||
|
if (!str.desc || !str.value)
|
||||||
|
break;
|
||||||
|
fprintf (output->ostream, "<extradata key='%s' value='%s' />\n",
|
||||||
|
str.desc, str.value);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Parse the sample data.
|
// Parse the sample data.
|
||||||
message ("Parsing the sample data.\n");
|
message ("Parsing the sample data.\n");
|
||||||
status = dc_parser_samples_foreach (parser, sample_cb, &sampledata);
|
status = dc_parser_samples_foreach (parser, sample_cb, &sampledata);
|
||||||
|
|||||||
@ -62,9 +62,13 @@ typedef enum dc_field_type_t {
|
|||||||
DC_FIELD_TEMPERATURE_MAXIMUM,
|
DC_FIELD_TEMPERATURE_MAXIMUM,
|
||||||
DC_FIELD_TANK_COUNT,
|
DC_FIELD_TANK_COUNT,
|
||||||
DC_FIELD_TANK,
|
DC_FIELD_TANK,
|
||||||
DC_FIELD_DIVEMODE
|
DC_FIELD_DIVEMODE,
|
||||||
|
DC_FIELD_STRING,
|
||||||
} dc_field_type_t;
|
} dc_field_type_t;
|
||||||
|
|
||||||
|
// Make it easy to test support compile-time with "#ifdef DC_FIELD_STRING"
|
||||||
|
#define DC_FIELD_STRING DC_FIELD_STRING
|
||||||
|
|
||||||
typedef enum parser_sample_event_t {
|
typedef enum parser_sample_event_t {
|
||||||
SAMPLE_EVENT_NONE,
|
SAMPLE_EVENT_NONE,
|
||||||
SAMPLE_EVENT_DECOSTOP,
|
SAMPLE_EVENT_DECOSTOP,
|
||||||
@ -92,17 +96,30 @@ typedef enum parser_sample_event_t {
|
|||||||
SAMPLE_EVENT_HEADING,
|
SAMPLE_EVENT_HEADING,
|
||||||
SAMPLE_EVENT_TISSUELEVEL,
|
SAMPLE_EVENT_TISSUELEVEL,
|
||||||
SAMPLE_EVENT_GASCHANGE2, /* Deprecated: replaced by DC_SAMPLE_GASMIX. */
|
SAMPLE_EVENT_GASCHANGE2, /* Deprecated: replaced by DC_SAMPLE_GASMIX. */
|
||||||
|
SAMPLE_EVENT_STRING,
|
||||||
} parser_sample_event_t;
|
} parser_sample_event_t;
|
||||||
|
|
||||||
|
/* To let the compile know we have this */
|
||||||
|
#define SAMPLE_EVENT_STRING SAMPLE_EVENT_STRING
|
||||||
|
|
||||||
/* For backwards compatibility */
|
/* For backwards compatibility */
|
||||||
#define SAMPLE_EVENT_UNKNOWN SAMPLE_EVENT_FLOOR
|
#define SAMPLE_EVENT_UNKNOWN SAMPLE_EVENT_FLOOR
|
||||||
|
|
||||||
typedef enum parser_sample_flags_t {
|
typedef enum parser_sample_flags_t {
|
||||||
SAMPLE_FLAGS_NONE = 0,
|
SAMPLE_FLAGS_NONE = 0,
|
||||||
SAMPLE_FLAGS_BEGIN = (1 << 0),
|
SAMPLE_FLAGS_BEGIN = (1 << 0),
|
||||||
SAMPLE_FLAGS_END = (1 << 1)
|
SAMPLE_FLAGS_END = (1 << 1),
|
||||||
|
SAMPLE_FLAGS_SEVERITY_MASK = (7 << 2),
|
||||||
} parser_sample_flags_t;
|
} parser_sample_flags_t;
|
||||||
|
|
||||||
|
#define SAMPLE_FLAGS_SEVERITY_SHIFT 2
|
||||||
|
|
||||||
|
#define SAMPLE_FLAGS_SEVERITY_MISSING (0 << SAMPLE_FLAGS_SEVERITY_SHIFT)
|
||||||
|
#define SAMPLE_FLAGS_SEVERITY_STATE (1 << SAMPLE_FLAGS_SEVERITY_SHIFT)
|
||||||
|
#define SAMPLE_FLAGS_SEVERITY_INFO (2 << SAMPLE_FLAGS_SEVERITY_SHIFT)
|
||||||
|
#define SAMPLE_FLAGS_SEVERITY_WARN (3 << SAMPLE_FLAGS_SEVERITY_SHIFT)
|
||||||
|
#define SAMPLE_FLAGS_SEVERITY_ALARM (4 << SAMPLE_FLAGS_SEVERITY_SHIFT)
|
||||||
|
|
||||||
typedef enum parser_sample_vendor_t {
|
typedef enum parser_sample_vendor_t {
|
||||||
SAMPLE_VENDOR_NONE,
|
SAMPLE_VENDOR_NONE,
|
||||||
SAMPLE_VENDOR_UWATEC_ALADIN,
|
SAMPLE_VENDOR_UWATEC_ALADIN,
|
||||||
@ -148,11 +165,16 @@ typedef struct dc_gasmix_t {
|
|||||||
|
|
||||||
#define DC_GASMIX_UNKNOWN 0xFFFFFFFF
|
#define DC_GASMIX_UNKNOWN 0xFFFFFFFF
|
||||||
|
|
||||||
typedef enum dc_tankvolume_t {
|
typedef unsigned int dc_tankinfo_t;
|
||||||
DC_TANKVOLUME_NONE,
|
#define DC_TANKINFO_METRIC 1
|
||||||
DC_TANKVOLUME_METRIC,
|
#define DC_TANKINFO_IMPERIAL 2
|
||||||
DC_TANKVOLUME_IMPERIAL,
|
#define DC_TANKINFO_CC_DILUENT 4
|
||||||
} dc_tankvolume_t;
|
#define DC_TANKINFO_CC_O2 8
|
||||||
|
|
||||||
|
// For backwards compatibility
|
||||||
|
#define DC_TANKVOLUME_NONE 0
|
||||||
|
#define DC_TANKVOLUME_METRIC DC_TANKINFO_METRIC
|
||||||
|
#define DC_TANKVOLUME_IMPERIAL DC_TANKINFO_IMPERIAL
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tank volume
|
* Tank volume
|
||||||
@ -179,13 +201,18 @@ typedef enum dc_tankvolume_t {
|
|||||||
|
|
||||||
typedef struct dc_tank_t {
|
typedef struct dc_tank_t {
|
||||||
unsigned int gasmix; /* Gas mix index, or DC_GASMIX_UNKNOWN */
|
unsigned int gasmix; /* Gas mix index, or DC_GASMIX_UNKNOWN */
|
||||||
dc_tankvolume_t type; /* Tank type */
|
dc_tankinfo_t type; /* Tank type - metric/imperial and oc/cc */
|
||||||
double volume; /* Volume (liter) */
|
double volume; /* Volume (liter) */
|
||||||
double workpressure; /* Work pressure (bar) */
|
double workpressure; /* Work pressure (bar) */
|
||||||
double beginpressure; /* Begin pressure (bar) */
|
double beginpressure; /* Begin pressure (bar) */
|
||||||
double endpressure; /* End pressure (bar) */
|
double endpressure; /* End pressure (bar) */
|
||||||
} dc_tank_t;
|
} dc_tank_t;
|
||||||
|
|
||||||
|
typedef struct dc_field_string_t {
|
||||||
|
const char *desc;
|
||||||
|
const char *value;
|
||||||
|
} dc_field_string_t;
|
||||||
|
|
||||||
typedef union dc_sample_value_t {
|
typedef union dc_sample_value_t {
|
||||||
unsigned int time;
|
unsigned int time;
|
||||||
double depth;
|
double depth;
|
||||||
@ -199,6 +226,7 @@ typedef union dc_sample_value_t {
|
|||||||
unsigned int time;
|
unsigned int time;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
unsigned int value;
|
unsigned int value;
|
||||||
|
const char *name;
|
||||||
} event;
|
} event;
|
||||||
unsigned int rbt;
|
unsigned int rbt;
|
||||||
unsigned int heartbeat;
|
unsigned int heartbeat;
|
||||||
|
|||||||
@ -20,6 +20,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <libdivecomputer/units.h>
|
#include <libdivecomputer/units.h>
|
||||||
|
|
||||||
@ -129,6 +135,9 @@ atomics_cobalt_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *dateti
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define BUFLEN 16
|
||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value)
|
atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value)
|
||||||
{
|
{
|
||||||
@ -143,6 +152,9 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un
|
|||||||
dc_tank_t *tank = (dc_tank_t *) value;
|
dc_tank_t *tank = (dc_tank_t *) value;
|
||||||
|
|
||||||
double atmospheric = 0.0;
|
double atmospheric = 0.0;
|
||||||
|
char buf[BUFLEN];
|
||||||
|
dc_field_string_t *string = (dc_field_string_t *) value;
|
||||||
|
|
||||||
if (parser->atmospheric)
|
if (parser->atmospheric)
|
||||||
atmospheric = parser->atmospheric;
|
atmospheric = parser->atmospheric;
|
||||||
else
|
else
|
||||||
@ -208,6 +220,29 @@ atomics_cobalt_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un
|
|||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case DC_FIELD_STRING:
|
||||||
|
switch(flags) {
|
||||||
|
case 0: // Serialnr
|
||||||
|
string->desc = "Serial";
|
||||||
|
snprintf(buf, BUFLEN, "%c%c%c%c-%c%c%c%c", p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11]);
|
||||||
|
break;
|
||||||
|
case 1: // Program Version
|
||||||
|
string->desc = "Program Version";
|
||||||
|
snprintf(buf, BUFLEN, "%.2f", array_uint16_le(p + 30) / 100.0);
|
||||||
|
break;
|
||||||
|
case 2: // Boot Version
|
||||||
|
string->desc = "Boot Version";
|
||||||
|
snprintf(buf, BUFLEN, "%.2f", array_uint16_le(p + 32) / 100.0);
|
||||||
|
break;
|
||||||
|
case 3: // Nofly
|
||||||
|
string->desc = "NoFly Time";
|
||||||
|
snprintf(buf, BUFLEN, "%0u:%02u", p[0x52], p[0x53]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return DC_STATUS_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
string->value = strdup(buf);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return DC_STATUS_UNSUPPORTED;
|
return DC_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,7 @@ dc_status_t
|
|||||||
hw_ostc_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
hw_ostc_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
hw_ostc_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int hwos);
|
hw_ostc_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int serial, unsigned int hwos);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,7 @@ dc_status_t
|
|||||||
hw_ostc3_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
hw_ostc3_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
hw_ostc3_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model);
|
hw_ostc3_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int serial, unsigned int model);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,12 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "libdivecomputer/units.h"
|
#include "libdivecomputer/units.h"
|
||||||
|
|
||||||
@ -61,8 +67,14 @@
|
|||||||
#define OSTC3_APNEA 3
|
#define OSTC3_APNEA 3
|
||||||
#define OSTC3_PSCR 4
|
#define OSTC3_PSCR 4
|
||||||
|
|
||||||
|
#define OSTC3_ZHL16 0
|
||||||
|
#define OSTC3_ZHL16_GF 1
|
||||||
|
#define OSTC4_VPM 2
|
||||||
|
|
||||||
#define OSTC4 0x3B
|
#define OSTC4 0x3B
|
||||||
|
|
||||||
|
#define UNSUPPORTED 0xFFFFFFFF
|
||||||
|
|
||||||
typedef struct hw_ostc_sample_info_t {
|
typedef struct hw_ostc_sample_info_t {
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
unsigned int divisor;
|
unsigned int divisor;
|
||||||
@ -78,7 +90,13 @@ typedef struct hw_ostc_layout_t {
|
|||||||
unsigned int salinity;
|
unsigned int salinity;
|
||||||
unsigned int duration;
|
unsigned int duration;
|
||||||
unsigned int temperature;
|
unsigned int temperature;
|
||||||
|
unsigned int battery;
|
||||||
|
unsigned int desat;
|
||||||
unsigned int firmware;
|
unsigned int firmware;
|
||||||
|
unsigned int deco_info1;
|
||||||
|
unsigned int deco_info2;
|
||||||
|
unsigned int decomode;
|
||||||
|
unsigned int battery_percentage;
|
||||||
} hw_ostc_layout_t;
|
} hw_ostc_layout_t;
|
||||||
|
|
||||||
typedef struct hw_ostc_gasmix_t {
|
typedef struct hw_ostc_gasmix_t {
|
||||||
@ -90,6 +108,7 @@ typedef struct hw_ostc_parser_t {
|
|||||||
dc_parser_t base;
|
dc_parser_t base;
|
||||||
unsigned int hwos;
|
unsigned int hwos;
|
||||||
unsigned int model;
|
unsigned int model;
|
||||||
|
unsigned int serial;
|
||||||
// Cached fields.
|
// Cached fields.
|
||||||
unsigned int cached;
|
unsigned int cached;
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
@ -127,7 +146,13 @@ static const hw_ostc_layout_t hw_ostc_layout_ostc = {
|
|||||||
43, /* salinity */
|
43, /* salinity */
|
||||||
47, /* duration */
|
47, /* duration */
|
||||||
13, /* temperature */
|
13, /* temperature */
|
||||||
|
34, /* battery volt after dive */
|
||||||
|
17, /* desat */
|
||||||
32, /* firmware */
|
32, /* firmware */
|
||||||
|
49, /* deco_info1 */
|
||||||
|
50, /* deco_info1 */
|
||||||
|
51, /* decomode */
|
||||||
|
0, /* battery percentage TBD */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const hw_ostc_layout_t hw_ostc_layout_frog = {
|
static const hw_ostc_layout_t hw_ostc_layout_frog = {
|
||||||
@ -139,7 +164,13 @@ static const hw_ostc_layout_t hw_ostc_layout_frog = {
|
|||||||
43, /* salinity */
|
43, /* salinity */
|
||||||
47, /* duration */
|
47, /* duration */
|
||||||
19, /* temperature */
|
19, /* temperature */
|
||||||
|
34, /* battery volt after dive */
|
||||||
|
23, /* desat */
|
||||||
32, /* firmware */
|
32, /* firmware */
|
||||||
|
49, /* deco_info1 */
|
||||||
|
50, /* deco_info2 */
|
||||||
|
51, /* decomode */
|
||||||
|
0, /* battery percentage TBD */
|
||||||
};
|
};
|
||||||
|
|
||||||
static const hw_ostc_layout_t hw_ostc_layout_ostc3 = {
|
static const hw_ostc_layout_t hw_ostc_layout_ostc3 = {
|
||||||
@ -151,7 +182,13 @@ static const hw_ostc_layout_t hw_ostc_layout_ostc3 = {
|
|||||||
70, /* salinity */
|
70, /* salinity */
|
||||||
75, /* duration */
|
75, /* duration */
|
||||||
22, /* temperature */
|
22, /* temperature */
|
||||||
|
50, /* battery volt after dive */
|
||||||
|
26, /* desat */
|
||||||
48, /* firmware */
|
48, /* firmware */
|
||||||
|
77, /* deco_info1 */
|
||||||
|
78, /* deco_info2 */
|
||||||
|
79, /* decomode */
|
||||||
|
59, /* battery percentage */
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned int
|
static unsigned int
|
||||||
@ -294,7 +331,7 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, unsigned int hwos, unsigned int model)
|
hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, unsigned int serial, unsigned int hwos, unsigned int model)
|
||||||
{
|
{
|
||||||
hw_ostc_parser_t *parser = NULL;
|
hw_ostc_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -324,6 +361,7 @@ hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, unsign
|
|||||||
parser->gasmix[i].oxygen = 0;
|
parser->gasmix[i].oxygen = 0;
|
||||||
parser->gasmix[i].helium = 0;
|
parser->gasmix[i].helium = 0;
|
||||||
}
|
}
|
||||||
|
parser->serial = serial;
|
||||||
|
|
||||||
*out = (dc_parser_t *) parser;
|
*out = (dc_parser_t *) parser;
|
||||||
|
|
||||||
@ -332,15 +370,15 @@ hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, unsign
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
hw_ostc_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int hwos)
|
hw_ostc_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int serial, unsigned int hwos)
|
||||||
{
|
{
|
||||||
return hw_ostc_parser_create_internal (out, context, hwos, 0);
|
return hw_ostc_parser_create_internal (out, context, serial, hwos, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
hw_ostc3_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
hw_ostc3_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int serial, unsigned int model)
|
||||||
{
|
{
|
||||||
return hw_ostc_parser_create_internal (out, context, 1, model);
|
return hw_ostc_parser_create_internal (out, context, serial, 1, model);
|
||||||
}
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
@ -428,6 +466,8 @@ hw_ostc_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define BUFLEN 32
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value)
|
hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value)
|
||||||
{
|
{
|
||||||
@ -452,9 +492,12 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned
|
|||||||
|
|
||||||
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
|
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
|
||||||
dc_salinity_t *water = (dc_salinity_t *) value;
|
dc_salinity_t *water = (dc_salinity_t *) value;
|
||||||
|
dc_field_string_t *string = (dc_field_string_t *) value;
|
||||||
|
|
||||||
unsigned int salinity = data[layout->salinity];
|
unsigned int salinity = data[layout->salinity];
|
||||||
if (version == 0x23 || version == 0x24)
|
if (version == 0x23 || version == 0x24)
|
||||||
salinity += 100;
|
salinity += 100;
|
||||||
|
char buf[BUFLEN];
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -550,6 +593,79 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned
|
|||||||
return DC_STATUS_UNSUPPORTED;
|
return DC_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case DC_FIELD_STRING:
|
||||||
|
switch(flags) {
|
||||||
|
case 0: /* serial */
|
||||||
|
string->desc = "Serial";
|
||||||
|
snprintf(buf, BUFLEN, "%u", parser->serial);
|
||||||
|
break;
|
||||||
|
case 1: /* battery */
|
||||||
|
string->desc = "Battery at end";
|
||||||
|
unsigned int percentage = (unsigned int) data[layout->battery_percentage];
|
||||||
|
if (percentage != 0xFF && (version == 0x23 || version == 0x24)) {
|
||||||
|
percentage = percentage>100? 100: percentage;
|
||||||
|
snprintf(buf, BUFLEN, "%.2fV, %u%% remaining",
|
||||||
|
array_uint16_le (data + layout->battery) / 1000.0,
|
||||||
|
percentage);
|
||||||
|
} else {
|
||||||
|
snprintf(buf, BUFLEN, "%.2fV", array_uint16_le (data + layout->battery) / 1000.0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2: /* desat */
|
||||||
|
string->desc = "Desat time";
|
||||||
|
snprintf(buf, BUFLEN, "%0u:%02u", array_uint16_le (data + layout->desat) / 60,
|
||||||
|
array_uint16_le (data + layout->desat) % 60);
|
||||||
|
break;
|
||||||
|
case 3: /* firmware */
|
||||||
|
string->desc = "FW Version";
|
||||||
|
/* OSTC4 stores firmware as XXXX XYYY YYZZ ZZZB, -> X.Y.Z beta? */
|
||||||
|
if (parser->model == OSTC4) {
|
||||||
|
int firmwareOnDevice = array_uint16_le (data + layout->firmware);
|
||||||
|
unsigned char X = 0, Y = 0, Z = 0, beta = 0;
|
||||||
|
X = (firmwareOnDevice & 0xF800) >> 11;
|
||||||
|
Y = (firmwareOnDevice & 0x07C0) >> 6;
|
||||||
|
Z = (firmwareOnDevice & 0x003E) >> 1;
|
||||||
|
beta = firmwareOnDevice & 0x0001;
|
||||||
|
|
||||||
|
snprintf(buf, BUFLEN, "%u.%u.%u%s\n", X, Y, Z, beta? "beta": "");
|
||||||
|
} else {
|
||||||
|
snprintf(buf, BUFLEN, "%0u.%02u", data[layout->firmware], data[layout->firmware + 1]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4: /* Deco model */
|
||||||
|
string->desc = "Deco model";
|
||||||
|
if (((version == 0x23 || version == 0x24) && data[layout->decomode] == OSTC3_ZHL16) ||
|
||||||
|
(version == 0x22 && data[layout->decomode] == FROG_ZHL16) ||
|
||||||
|
(version == 0x21 && (data[layout->decomode] == OSTC_ZHL16_OC || data[layout->decomode] == OSTC_ZHL16_CC)))
|
||||||
|
strncpy(buf, "ZH-L16", BUFLEN);
|
||||||
|
else if (((version == 0x23 || version == 0x24) && data[layout->decomode] == OSTC3_ZHL16_GF) ||
|
||||||
|
(version == 0x22 && data[layout->decomode] == FROG_ZHL16_GF) ||
|
||||||
|
(version == 0x21 && (data[layout->decomode] == OSTC_ZHL16_OC_GF || data[layout->decomode] == OSTC_ZHL16_CC_GF)))
|
||||||
|
strncpy(buf, "ZH-L16-GF", BUFLEN);
|
||||||
|
else if (((version == 0x24) && data[layout->decomode] == OSTC4_VPM))
|
||||||
|
strncpy(buf, "VPM", BUFLEN);
|
||||||
|
else
|
||||||
|
return DC_STATUS_DATAFORMAT;
|
||||||
|
break;
|
||||||
|
case 5: /* Deco model info */
|
||||||
|
string->desc = "Deco model info";
|
||||||
|
if (((version == 0x23 || version == 0x24) && data[layout->decomode] == OSTC3_ZHL16) ||
|
||||||
|
(version == 0x22 && data[layout->decomode] == FROG_ZHL16) ||
|
||||||
|
(version == 0x21 && (data[layout->decomode] == OSTC_ZHL16_OC || data[layout->decomode] == OSTC_ZHL16_CC)))
|
||||||
|
snprintf(buf, BUFLEN, "Saturation %u, Desaturation %u", layout->deco_info1, layout->deco_info2);
|
||||||
|
else if (((version == 0x23 || version == 0x24) && data[layout->decomode] == OSTC3_ZHL16_GF) ||
|
||||||
|
(version == 0x22 && data[layout->decomode] == FROG_ZHL16_GF) ||
|
||||||
|
(version == 0x21 && (data[layout->decomode] == OSTC_ZHL16_OC_GF || data[layout->decomode] == OSTC_ZHL16_CC_GF)))
|
||||||
|
snprintf(buf, BUFLEN, "GF %u/%u", data[layout->deco_info1], data[layout->deco_info2]);
|
||||||
|
else
|
||||||
|
return DC_STATUS_DATAFORMAT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return DC_STATUS_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
string->value = strdup(buf);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return DC_STATUS_UNSUPPORTED;
|
return DC_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,7 +37,7 @@ dc_status_t
|
|||||||
oceanic_atom2_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
|
oceanic_atom2_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
oceanic_atom2_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
oceanic_atom2_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model, unsigned int serial);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <libdivecomputer/units.h>
|
#include <libdivecomputer/units.h>
|
||||||
|
|
||||||
@ -102,6 +104,7 @@ struct oceanic_atom2_parser_t {
|
|||||||
unsigned int model;
|
unsigned int model;
|
||||||
unsigned int headersize;
|
unsigned int headersize;
|
||||||
unsigned int footersize;
|
unsigned int footersize;
|
||||||
|
unsigned int serial;
|
||||||
// Cached fields.
|
// Cached fields.
|
||||||
unsigned int cached;
|
unsigned int cached;
|
||||||
unsigned int header;
|
unsigned int header;
|
||||||
@ -131,7 +134,7 @@ static const dc_parser_vtable_t oceanic_atom2_parser_vtable = {
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial)
|
||||||
{
|
{
|
||||||
oceanic_atom2_parser_t *parser = NULL;
|
oceanic_atom2_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -176,6 +179,7 @@ oceanic_atom2_parser_create (dc_parser_t **out, dc_context_t *context, unsigned
|
|||||||
parser->headersize = 5 * PAGESIZE;
|
parser->headersize = 5 * PAGESIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parser->serial = serial;
|
||||||
parser->cached = 0;
|
parser->cached = 0;
|
||||||
parser->header = 0;
|
parser->header = 0;
|
||||||
parser->footer = 0;
|
parser->footer = 0;
|
||||||
@ -366,6 +370,7 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define BUF_LEN 16
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
oceanic_atom2_parser_cache (oceanic_atom2_parser_t *parser)
|
oceanic_atom2_parser_cache (oceanic_atom2_parser_t *parser)
|
||||||
@ -502,6 +507,9 @@ oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns
|
|||||||
|
|
||||||
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
|
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
|
||||||
dc_salinity_t *water = (dc_salinity_t *) value;
|
dc_salinity_t *water = (dc_salinity_t *) value;
|
||||||
|
dc_field_string_t *string = (dc_field_string_t *) value;
|
||||||
|
|
||||||
|
char buf[BUF_LEN];
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -557,6 +565,17 @@ oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns
|
|||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case DC_FIELD_STRING:
|
||||||
|
switch(flags) {
|
||||||
|
case 0: /* Serial */
|
||||||
|
string->desc = "Serial";
|
||||||
|
snprintf(buf, BUF_LEN, "%06u", parser->serial);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return DC_STATUS_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
string->value = strdup(buf);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return DC_STATUS_UNSUPPORTED;
|
return DC_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/parser.c
22
src/parser.c
@ -64,7 +64,7 @@
|
|||||||
#define REACTPROWHITE 0x4354
|
#define REACTPROWHITE 0x4354
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t family, unsigned int model, unsigned int devtime, dc_ticks_t systime)
|
dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t family, unsigned int model, unsigned int serial, unsigned int devtime, dc_ticks_t systime)
|
||||||
{
|
{
|
||||||
dc_status_t rc = DC_STATUS_SUCCESS;
|
dc_status_t rc = DC_STATUS_SUCCESS;
|
||||||
dc_parser_t *parser = NULL;
|
dc_parser_t *parser = NULL;
|
||||||
@ -87,7 +87,7 @@ dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t fa
|
|||||||
break;
|
break;
|
||||||
case DC_FAMILY_SUUNTO_VYPER2:
|
case DC_FAMILY_SUUNTO_VYPER2:
|
||||||
case DC_FAMILY_SUUNTO_D9:
|
case DC_FAMILY_SUUNTO_D9:
|
||||||
rc = suunto_d9_parser_create (&parser, context, model);
|
rc = suunto_d9_parser_create (&parser, context, model, serial);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_SUUNTO_EONSTEEL:
|
case DC_FAMILY_SUUNTO_EONSTEEL:
|
||||||
rc = suunto_eonsteel_parser_create(&parser, context, model);
|
rc = suunto_eonsteel_parser_create(&parser, context, model);
|
||||||
@ -120,7 +120,7 @@ dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t fa
|
|||||||
if (model == REACTPROWHITE)
|
if (model == REACTPROWHITE)
|
||||||
rc = oceanic_veo250_parser_create (&parser, context, model);
|
rc = oceanic_veo250_parser_create (&parser, context, model);
|
||||||
else
|
else
|
||||||
rc = oceanic_atom2_parser_create (&parser, context, model);
|
rc = oceanic_atom2_parser_create (&parser, context, model, serial);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_MARES_NEMO:
|
case DC_FAMILY_MARES_NEMO:
|
||||||
case DC_FAMILY_MARES_PUCK:
|
case DC_FAMILY_MARES_PUCK:
|
||||||
@ -133,11 +133,11 @@ dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t fa
|
|||||||
rc = mares_iconhd_parser_create (&parser, context, model);
|
rc = mares_iconhd_parser_create (&parser, context, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_HW_OSTC:
|
case DC_FAMILY_HW_OSTC:
|
||||||
rc = hw_ostc_parser_create (&parser, context, 0);
|
rc = hw_ostc_parser_create (&parser, context, serial, 0);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_HW_FROG:
|
case DC_FAMILY_HW_FROG:
|
||||||
case DC_FAMILY_HW_OSTC3:
|
case DC_FAMILY_HW_OSTC3:
|
||||||
rc = hw_ostc3_parser_create (&parser, context, model);
|
rc = hw_ostc3_parser_create (&parser, context, serial, model);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_CRESSI_EDY:
|
case DC_FAMILY_CRESSI_EDY:
|
||||||
case DC_FAMILY_ZEAGLE_N2ITION3:
|
case DC_FAMILY_ZEAGLE_N2ITION3:
|
||||||
@ -150,10 +150,10 @@ dc_parser_new_internal (dc_parser_t **out, dc_context_t *context, dc_family_t fa
|
|||||||
rc = atomics_cobalt_parser_create (&parser, context);
|
rc = atomics_cobalt_parser_create (&parser, context);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_SHEARWATER_PREDATOR:
|
case DC_FAMILY_SHEARWATER_PREDATOR:
|
||||||
rc = shearwater_predator_parser_create (&parser, context, model);
|
rc = shearwater_predator_parser_create (&parser, context, model, serial);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_SHEARWATER_PETREL:
|
case DC_FAMILY_SHEARWATER_PETREL:
|
||||||
rc = shearwater_petrel_parser_create (&parser, context, model);
|
rc = shearwater_petrel_parser_create (&parser, context, model, serial);
|
||||||
break;
|
break;
|
||||||
case DC_FAMILY_DIVERITE_NITEKQ:
|
case DC_FAMILY_DIVERITE_NITEKQ:
|
||||||
rc = diverite_nitekq_parser_create (&parser, context);
|
rc = diverite_nitekq_parser_create (&parser, context);
|
||||||
@ -183,7 +183,9 @@ dc_parser_new (dc_parser_t **out, dc_device_t *device)
|
|||||||
return DC_STATUS_INVALIDARGS;
|
return DC_STATUS_INVALIDARGS;
|
||||||
|
|
||||||
return dc_parser_new_internal (out, device->context,
|
return dc_parser_new_internal (out, device->context,
|
||||||
dc_device_get_type (device), device->devinfo.model,
|
dc_device_get_type (device),
|
||||||
|
device->devinfo.model,
|
||||||
|
device->devinfo.serial,
|
||||||
device->clock.devtime, device->clock.systime);
|
device->clock.devtime, device->clock.systime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +193,9 @@ dc_status_t
|
|||||||
dc_parser_new2 (dc_parser_t **out, dc_context_t *context, dc_descriptor_t *descriptor, unsigned int devtime, dc_ticks_t systime)
|
dc_parser_new2 (dc_parser_t **out, dc_context_t *context, dc_descriptor_t *descriptor, unsigned int devtime, dc_ticks_t systime)
|
||||||
{
|
{
|
||||||
return dc_parser_new_internal (out, context,
|
return dc_parser_new_internal (out, context,
|
||||||
dc_descriptor_get_type (descriptor), dc_descriptor_get_model (descriptor),
|
dc_descriptor_get_type (descriptor),
|
||||||
|
dc_descriptor_get_model (descriptor),
|
||||||
|
0,
|
||||||
devtime, systime);
|
devtime, systime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -212,25 +212,37 @@ shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t call
|
|||||||
unsigned int hardware = array_uint_be (dc_buffer_get_data (buffer), dc_buffer_get_size (buffer));
|
unsigned int hardware = array_uint_be (dc_buffer_get_data (buffer), dc_buffer_get_size (buffer));
|
||||||
unsigned int model = 0;
|
unsigned int model = 0;
|
||||||
switch (hardware) {
|
switch (hardware) {
|
||||||
case 0x0808: // Petrel 2
|
case 0x0101:
|
||||||
case 0x0909: // Petrel 1
|
case 0x0202:
|
||||||
case 0x0B0B: // Petrel 1 (newer hardware)
|
model = PREDATOR;
|
||||||
model = PETREL;
|
|
||||||
break;
|
break;
|
||||||
|
case 0x0606:
|
||||||
case 0x0A0A: // Nerd 1
|
case 0x0A0A: // Nerd 1
|
||||||
model = NERD;
|
model = NERD;
|
||||||
break;
|
break;
|
||||||
case 0x0E0D: // Nerd 2
|
case 0x0E0D: // Nerd 2
|
||||||
model = NERD2;
|
model = NERD2;
|
||||||
break;
|
break;
|
||||||
case 0x0707:
|
case 0x0404:
|
||||||
|
case 0x0909: // Petrel 1
|
||||||
|
case 0x0B0B: // Petrel 1 (newer hardware)
|
||||||
|
model = PETREL;
|
||||||
|
break;
|
||||||
|
case 0x0505:
|
||||||
|
case 0x0808: // Petrel 2
|
||||||
|
model = PETREL;
|
||||||
|
break;
|
||||||
|
case 0x0707: // documentation list 0C0D for both Perdix and Perdix AI :-(
|
||||||
model = PERDIX;
|
model = PERDIX;
|
||||||
break;
|
break;
|
||||||
|
case 0x0C0C:
|
||||||
case 0x0C0D:
|
case 0x0C0D:
|
||||||
|
case 0x0D0D:
|
||||||
model = PERDIXAI;
|
model = PERDIXAI;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
WARNING (abstract->context, "Unknown hardware type %04x.", hardware);
|
model = PETREL;
|
||||||
|
WARNING (abstract->context, "Unknown hardware type %04x. Assuming Petrel.", hardware);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit a device info event.
|
// Emit a device info event.
|
||||||
|
|||||||
@ -35,7 +35,7 @@ dc_status_t
|
|||||||
shearwater_petrel_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
shearwater_petrel_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
shearwater_petrel_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
shearwater_petrel_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model, unsigned int serial);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -35,7 +35,7 @@ dc_status_t
|
|||||||
shearwater_predator_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
shearwater_predator_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
shearwater_predator_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
shearwater_predator_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model, unsigned int serial);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <libdivecomputer/units.h>
|
#include <libdivecomputer/units.h>
|
||||||
|
|
||||||
@ -47,6 +54,7 @@
|
|||||||
#define IMPERIAL 1
|
#define IMPERIAL 1
|
||||||
|
|
||||||
#define NGASMIXES 10
|
#define NGASMIXES 10
|
||||||
|
#define MAXSTRINGS 32
|
||||||
|
|
||||||
#define PREDATOR 2
|
#define PREDATOR 2
|
||||||
#define PETREL 3
|
#define PETREL 3
|
||||||
@ -68,7 +76,11 @@ struct shearwater_predator_parser_t {
|
|||||||
unsigned int helium[NGASMIXES];
|
unsigned int helium[NGASMIXES];
|
||||||
unsigned int calibrated;
|
unsigned int calibrated;
|
||||||
double calibration[3];
|
double calibration[3];
|
||||||
|
unsigned int serial;
|
||||||
dc_divemode_t mode;
|
dc_divemode_t mode;
|
||||||
|
|
||||||
|
/* String fields */
|
||||||
|
dc_field_string_t strings[MAXSTRINGS];
|
||||||
};
|
};
|
||||||
|
|
||||||
static dc_status_t shearwater_predator_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
static dc_status_t shearwater_predator_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size);
|
||||||
@ -112,7 +124,7 @@ shearwater_predator_find_gasmix (shearwater_predator_parser_t *parser, unsigned
|
|||||||
|
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int petrel)
|
shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial, unsigned int petrel)
|
||||||
{
|
{
|
||||||
shearwater_predator_parser_t *parser = NULL;
|
shearwater_predator_parser_t *parser = NULL;
|
||||||
const dc_parser_vtable_t *vtable = NULL;
|
const dc_parser_vtable_t *vtable = NULL;
|
||||||
@ -140,6 +152,9 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig
|
|||||||
parser->model = model;
|
parser->model = model;
|
||||||
parser->petrel = petrel;
|
parser->petrel = petrel;
|
||||||
parser->samplesize = samplesize;
|
parser->samplesize = samplesize;
|
||||||
|
parser->serial = serial;
|
||||||
|
|
||||||
|
// Set the default values.
|
||||||
parser->cached = 0;
|
parser->cached = 0;
|
||||||
parser->logversion = 0;
|
parser->logversion = 0;
|
||||||
parser->headersize = 0;
|
parser->headersize = 0;
|
||||||
@ -162,16 +177,16 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig
|
|||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
shearwater_predator_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
shearwater_predator_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial)
|
||||||
{
|
{
|
||||||
return shearwater_common_parser_create (out, context, model, 0);
|
return shearwater_common_parser_create (out, context, model, serial, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
shearwater_petrel_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
shearwater_petrel_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial)
|
||||||
{
|
{
|
||||||
return shearwater_common_parser_create (out, context, model, 1);
|
return shearwater_common_parser_create (out, context, model, serial, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -219,6 +234,146 @@ shearwater_predator_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *d
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These string cache interfaces should be some generic
|
||||||
|
* library rather than copied for all the dive computers.
|
||||||
|
*
|
||||||
|
* This is just copied from the EON Steel code.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
add_string(shearwater_predator_parser_t *parser, const char *desc, const char *value)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAXSTRINGS; i++) {
|
||||||
|
dc_field_string_t *str = parser->strings+i;
|
||||||
|
if (str->desc)
|
||||||
|
continue;
|
||||||
|
str->desc = desc;
|
||||||
|
str->value = strdup(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_string_fmt(shearwater_predator_parser_t *parser, const char *desc, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
char buffer[256];
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We ignore the return value from vsnprintf, and we
|
||||||
|
* always NUL-terminate the destination buffer ourselves.
|
||||||
|
*
|
||||||
|
* That way we don't have to worry about random bad legacy
|
||||||
|
* implementations.
|
||||||
|
*/
|
||||||
|
va_start(ap, fmt);
|
||||||
|
buffer[sizeof(buffer)-1] = 0;
|
||||||
|
(void) vsnprintf(buffer, sizeof(buffer)-1, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return add_string(parser, desc, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Battery state is a big-endian word:
|
||||||
|
//
|
||||||
|
// ffff = not paired / no comms for 90 s
|
||||||
|
// fffe = no comms for 30 s
|
||||||
|
//
|
||||||
|
// Otherwise:
|
||||||
|
// - top four bits are battery state (0 - normal, 1 - critical, 2 - warning)
|
||||||
|
// - bottom 12 bits are pressure in 2 psi increments (0..8k psi)
|
||||||
|
//
|
||||||
|
// This returns the state as a bitmask (so you can see all states it had
|
||||||
|
// during the dive). Note that we currently do not report pairing and
|
||||||
|
// communication lapses. Todo?
|
||||||
|
static unsigned int
|
||||||
|
battery_state(const unsigned char *data)
|
||||||
|
{
|
||||||
|
unsigned int pressure = array_uint16_be(data);
|
||||||
|
unsigned int state;
|
||||||
|
|
||||||
|
if ((pressure & 0xFFF0) == 0xFFF0)
|
||||||
|
return 0;
|
||||||
|
state = pressure >> 12;
|
||||||
|
if (state > 2)
|
||||||
|
return 0;
|
||||||
|
return 1u << state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the battery state
|
||||||
|
//
|
||||||
|
// NOTE! Right now it only shows the most serious bit
|
||||||
|
// but the code is set up so that we could perhaps
|
||||||
|
// indicate that the battery is on the edge (ie it
|
||||||
|
// reported both "normal" _and_ "warning" during the
|
||||||
|
// dive - maybe that would be a "starting to warn")
|
||||||
|
//
|
||||||
|
// We could also report unpaired and comm errors.
|
||||||
|
static void
|
||||||
|
add_battery_info(shearwater_predator_parser_t *parser, const char *desc, unsigned int state)
|
||||||
|
{
|
||||||
|
if (state >= 1 && state <= 7) {
|
||||||
|
static const char *states[8] = {
|
||||||
|
"", // 000 - No state bits, not used
|
||||||
|
"normal", // 001 - only normal
|
||||||
|
"critical", // 010 - only critical
|
||||||
|
"critical", // 011 - both normal and critical
|
||||||
|
"warning", // 100 - only warning
|
||||||
|
"warning", // 101 - normal and warning
|
||||||
|
"critical", // 110 - warning and critical
|
||||||
|
"critical", // 111 - normal, warning and critical
|
||||||
|
};
|
||||||
|
add_string(parser, desc, states[state]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_deco_model(shearwater_predator_parser_t *parser, const unsigned char *data)
|
||||||
|
{
|
||||||
|
switch (data[67]) {
|
||||||
|
case 0:
|
||||||
|
add_string_fmt(parser, "Deco model", "GF %u/%u", data[4], data[5]);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
add_string_fmt(parser, "Deco model", "VPM-B +%u", data[68]);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
add_string_fmt(parser, "Deco model", "VPM-B/GFS +%u %u%%", data[68], data[85]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
add_string_fmt(parser, "Deco model", "Unknown model %d", data[67]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_battery_type(shearwater_predator_parser_t *parser, const unsigned char *data)
|
||||||
|
{
|
||||||
|
if (parser->logversion < 7)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (data[120]) {
|
||||||
|
case 1:
|
||||||
|
add_string(parser, "Battery type", "1.5V Alkaline");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
add_string(parser, "Battery type", "1.5V Lithium");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
add_string(parser, "Battery type", "1.2V NiMH");
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
add_string(parser, "Battery type", "3.6V Saft");
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
add_string(parser, "Battery type", "3.7V Li-Ion");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
add_string_fmt(parser, "Battery type", "unknown type %d", data[120]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
||||||
@ -243,6 +398,9 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
|||||||
unsigned int logversion = 6;
|
unsigned int logversion = 6;
|
||||||
if (data[127] > 6)
|
if (data[127] > 6)
|
||||||
logversion = data[127];
|
logversion = data[127];
|
||||||
|
INFO(abstract->context, "Shearwater log version %u\n", logversion);
|
||||||
|
|
||||||
|
memset(parser->strings, 0, sizeof(parser->strings));
|
||||||
|
|
||||||
// Adjust the footersize for the final block.
|
// Adjust the footersize for the final block.
|
||||||
if (parser->petrel || array_uint16_be (data + size - footersize) == 0xFFFD) {
|
if (parser->petrel || array_uint16_be (data + size - footersize) == 0xFFFD) {
|
||||||
@ -262,6 +420,9 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
|||||||
unsigned int helium[NGASMIXES] = {0};
|
unsigned int helium[NGASMIXES] = {0};
|
||||||
unsigned int o2_previous = 0, he_previous = 0;
|
unsigned int o2_previous = 0, he_previous = 0;
|
||||||
|
|
||||||
|
// Transmitter battery levels
|
||||||
|
unsigned int t1_battery = 0, t2_battery = 0;
|
||||||
|
|
||||||
unsigned int offset = headersize;
|
unsigned int offset = headersize;
|
||||||
unsigned int length = size - footersize;
|
unsigned int length = size - footersize;
|
||||||
while (offset < length) {
|
while (offset < length) {
|
||||||
@ -304,6 +465,13 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
|||||||
he_previous = he;
|
he_previous = he;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transmitter battery levels
|
||||||
|
if (logversion >= 7) {
|
||||||
|
// T1 at offset 27, T2 at offset 19
|
||||||
|
t1_battery |= battery_state(data + offset + 27);
|
||||||
|
t2_battery |= battery_state(data + offset + 19);
|
||||||
|
}
|
||||||
|
|
||||||
offset += parser->samplesize;
|
offset += parser->samplesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,6 +516,13 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
|||||||
parser->helium[i] = helium[i];
|
parser->helium[i] = helium[i];
|
||||||
}
|
}
|
||||||
parser->mode = mode;
|
parser->mode = mode;
|
||||||
|
add_string_fmt(parser, "Serial", "%08x", parser->serial);
|
||||||
|
add_string_fmt(parser, "FW Version", "%2x", data[19]);
|
||||||
|
add_deco_model(parser, data);
|
||||||
|
add_battery_type(parser, data);
|
||||||
|
add_string_fmt(parser, "Battery at end", "%.1f V", data[9] / 10.0);
|
||||||
|
add_battery_info(parser, "T1 battery", t1_battery);
|
||||||
|
add_battery_info(parser, "T2 battery", t2_battery);
|
||||||
parser->cached = 1;
|
parser->cached = 1;
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
@ -374,6 +549,7 @@ shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ
|
|||||||
|
|
||||||
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
|
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
|
||||||
dc_salinity_t *water = (dc_salinity_t *) value;
|
dc_salinity_t *water = (dc_salinity_t *) value;
|
||||||
|
dc_field_string_t *string = (dc_field_string_t *) value;
|
||||||
unsigned int density = 0;
|
unsigned int density = 0;
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
@ -409,6 +585,15 @@ shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ
|
|||||||
case DC_FIELD_DIVEMODE:
|
case DC_FIELD_DIVEMODE:
|
||||||
*((dc_divemode_t *) value) = parser->mode;
|
*((dc_divemode_t *) value) = parser->mode;
|
||||||
break;
|
break;
|
||||||
|
case DC_FIELD_STRING:
|
||||||
|
if (flags < MAXSTRINGS) {
|
||||||
|
dc_field_string_t *p = parser->strings + flags;
|
||||||
|
if (p->desc) {
|
||||||
|
*string = *p;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return DC_STATUS_UNSUPPORTED;
|
||||||
default:
|
default:
|
||||||
return DC_STATUS_UNSUPPORTED;
|
return DC_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
@ -440,6 +625,7 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
|||||||
unsigned int time = 0;
|
unsigned int time = 0;
|
||||||
unsigned int offset = parser->headersize;
|
unsigned int offset = parser->headersize;
|
||||||
unsigned int length = size - parser->footersize;
|
unsigned int length = size - parser->footersize;
|
||||||
|
|
||||||
while (offset < length) {
|
while (offset < length) {
|
||||||
dc_sample_value_t sample = {0};
|
dc_sample_value_t sample = {0};
|
||||||
|
|
||||||
@ -590,6 +776,5 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
|||||||
|
|
||||||
offset += parser->samplesize;
|
offset += parser->samplesize;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -36,7 +36,7 @@ dc_status_t
|
|||||||
suunto_d9_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
|
suunto_d9_device_open (dc_device_t **device, dc_context_t *context, dc_iostream_t *iostream, unsigned int model);
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
suunto_d9_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model);
|
suunto_d9_parser_create (dc_parser_t **parser, dc_context_t *context, unsigned int model, unsigned int serial);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h> // memcmp
|
#include <string.h> // memcmp, strdup
|
||||||
|
#include <stdio.h> // snprintf
|
||||||
|
|
||||||
#include "suunto_d9.h"
|
#include "suunto_d9.h"
|
||||||
#include "context-private.h"
|
#include "context-private.h"
|
||||||
@ -72,6 +73,7 @@ typedef struct suunto_d9_parser_t suunto_d9_parser_t;
|
|||||||
struct suunto_d9_parser_t {
|
struct suunto_d9_parser_t {
|
||||||
dc_parser_t base;
|
dc_parser_t base;
|
||||||
unsigned int model;
|
unsigned int model;
|
||||||
|
unsigned int serial;
|
||||||
// Cached fields.
|
// Cached fields.
|
||||||
unsigned int cached;
|
unsigned int cached;
|
||||||
unsigned int mode;
|
unsigned int mode;
|
||||||
@ -231,7 +233,7 @@ suunto_d9_parser_cache (suunto_d9_parser_t *parser)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dc_status_t
|
dc_status_t
|
||||||
suunto_d9_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model)
|
suunto_d9_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int serial)
|
||||||
{
|
{
|
||||||
suunto_d9_parser_t *parser = NULL;
|
suunto_d9_parser_t *parser = NULL;
|
||||||
|
|
||||||
@ -247,6 +249,7 @@ suunto_d9_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int
|
|||||||
|
|
||||||
// Set the default values.
|
// Set the default values.
|
||||||
parser->model = model;
|
parser->model = model;
|
||||||
|
parser->serial = serial;
|
||||||
parser->cached = 0;
|
parser->cached = 0;
|
||||||
parser->mode = AIR;
|
parser->mode = AIR;
|
||||||
parser->ngasmixes = 0;
|
parser->ngasmixes = 0;
|
||||||
@ -326,6 +329,7 @@ suunto_d9_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define BUFLEN 16
|
||||||
|
|
||||||
static dc_status_t
|
static dc_status_t
|
||||||
suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value)
|
suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value)
|
||||||
@ -341,6 +345,9 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne
|
|||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
|
dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
|
||||||
|
dc_field_string_t *string = (dc_field_string_t *) value;
|
||||||
|
|
||||||
|
char buf[BUFLEN];
|
||||||
|
|
||||||
if (value) {
|
if (value) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -388,6 +395,17 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne
|
|||||||
return DC_STATUS_DATAFORMAT;
|
return DC_STATUS_DATAFORMAT;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case DC_FIELD_STRING:
|
||||||
|
switch (flags) {
|
||||||
|
case 0: /* serial */
|
||||||
|
string->desc = "Serial";
|
||||||
|
snprintf(buf, BUFLEN, "%08u", parser->serial);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return DC_STATUS_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
string->value = strdup(buf);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return DC_STATUS_UNSUPPORTED;
|
return DC_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,8 +21,16 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/* Wow. MSC is truly crap */
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#define vsnprintf _vsnprintf
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "suunto_eonsteel.h"
|
#include "suunto_eonsteel.h"
|
||||||
#include "context-private.h"
|
#include "context-private.h"
|
||||||
@ -71,6 +79,7 @@ struct type_desc {
|
|||||||
|
|
||||||
#define MAXTYPE 512
|
#define MAXTYPE 512
|
||||||
#define MAXGASES 16
|
#define MAXGASES 16
|
||||||
|
#define MAXSTRINGS 32
|
||||||
|
|
||||||
typedef struct suunto_eonsteel_parser_t {
|
typedef struct suunto_eonsteel_parser_t {
|
||||||
dc_parser_t base;
|
dc_parser_t base;
|
||||||
@ -89,7 +98,8 @@ typedef struct suunto_eonsteel_parser_t {
|
|||||||
double lowsetpoint;
|
double lowsetpoint;
|
||||||
double highsetpoint;
|
double highsetpoint;
|
||||||
double customsetpoint;
|
double customsetpoint;
|
||||||
dc_tankvolume_t tankinfo[MAXGASES];
|
dc_field_string_t strings[MAXSTRINGS];
|
||||||
|
dc_tankinfo_t tankinfo[MAXGASES];
|
||||||
double tanksize[MAXGASES];
|
double tanksize[MAXGASES];
|
||||||
double tankworkingpressure[MAXGASES];
|
double tankworkingpressure[MAXGASES];
|
||||||
} cache;
|
} cache;
|
||||||
@ -97,11 +107,6 @@ typedef struct suunto_eonsteel_parser_t {
|
|||||||
|
|
||||||
typedef int (*eon_data_cb_t)(unsigned short type, const struct type_desc *desc, const unsigned char *data, int len, void *user);
|
typedef int (*eon_data_cb_t)(unsigned short type, const struct type_desc *desc, const unsigned char *data, int len, void *user);
|
||||||
|
|
||||||
typedef struct eon_event_t {
|
|
||||||
const char *name;
|
|
||||||
parser_sample_event_t type;
|
|
||||||
} eon_event_t;
|
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
enum eon_sample type;
|
enum eon_sample type;
|
||||||
@ -167,16 +172,6 @@ static enum eon_sample lookup_descriptor_type(suunto_eonsteel_parser_t *eon, str
|
|||||||
return ES_none;
|
return ES_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
static parser_sample_event_t lookup_event(const char *name, const eon_event_t events[], size_t n)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < n; ++i) {
|
|
||||||
if (!strcasecmp(name, events[i].name))
|
|
||||||
return events[i].type;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SAMPLE_EVENT_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *desc_type_name(enum eon_sample type)
|
static const char *desc_type_name(enum eon_sample type)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -681,26 +676,17 @@ static void sample_event_state_type(const struct type_desc *desc, struct sample_
|
|||||||
static void sample_event_state_value(const struct type_desc *desc, struct sample_data *info, unsigned char value)
|
static void sample_event_state_value(const struct type_desc *desc, struct sample_data *info, unsigned char value)
|
||||||
{
|
{
|
||||||
dc_sample_value_t sample = {0};
|
dc_sample_value_t sample = {0};
|
||||||
static const eon_event_t states[] = {
|
|
||||||
{"Wet Outside", SAMPLE_EVENT_NONE},
|
|
||||||
{"Below Wet Activation Depth", SAMPLE_EVENT_NONE},
|
|
||||||
{"Below Surface", SAMPLE_EVENT_NONE},
|
|
||||||
{"Dive Active", SAMPLE_EVENT_NONE},
|
|
||||||
{"Surface Calculation", SAMPLE_EVENT_NONE},
|
|
||||||
{"Tank pressure available", SAMPLE_EVENT_NONE},
|
|
||||||
{"Closed Circuit Mode", SAMPLE_EVENT_NONE},
|
|
||||||
};
|
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
name = info->state_type;
|
name = info->state_type;
|
||||||
if (!name)
|
if (!name)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sample.event.type = lookup_event(name, states, C_ARRAY_SIZE(states));
|
sample.event.type = SAMPLE_EVENT_STRING;
|
||||||
if (sample.event.type == SAMPLE_EVENT_NONE)
|
sample.event.name = name;
|
||||||
return;
|
|
||||||
|
|
||||||
sample.event.flags = value ? SAMPLE_FLAGS_BEGIN : SAMPLE_FLAGS_END;
|
sample.event.flags = value ? SAMPLE_FLAGS_BEGIN : SAMPLE_FLAGS_END;
|
||||||
|
sample.event.flags |= 1 << SAMPLE_FLAGS_SEVERITY_SHIFT;
|
||||||
|
|
||||||
if (info->callback) info->callback(DC_SAMPLE_EVENT, sample, info->userdata);
|
if (info->callback) info->callback(DC_SAMPLE_EVENT, sample, info->userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -712,25 +698,6 @@ static void sample_event_notify_type(const struct type_desc *desc, struct sample
|
|||||||
|
|
||||||
static void sample_event_notify_value(const struct type_desc *desc, struct sample_data *info, unsigned char value)
|
static void sample_event_notify_value(const struct type_desc *desc, struct sample_data *info, unsigned char value)
|
||||||
{
|
{
|
||||||
static const eon_event_t notifications[] = {
|
|
||||||
{"NoFly Time", SAMPLE_EVENT_NONE},
|
|
||||||
{"Depth", SAMPLE_EVENT_NONE},
|
|
||||||
{"Surface Time", SAMPLE_EVENT_NONE},
|
|
||||||
{"Tissue Level", SAMPLE_EVENT_TISSUELEVEL},
|
|
||||||
{"Deco", SAMPLE_EVENT_NONE},
|
|
||||||
{"Deco Window", SAMPLE_EVENT_NONE},
|
|
||||||
{"Safety Stop Ahead", SAMPLE_EVENT_NONE},
|
|
||||||
{"Safety Stop", SAMPLE_EVENT_SAFETYSTOP},
|
|
||||||
{"Safety Stop Broken", SAMPLE_EVENT_CEILING_SAFETYSTOP},
|
|
||||||
{"Deep Stop Ahead", SAMPLE_EVENT_NONE},
|
|
||||||
{"Deep Stop", SAMPLE_EVENT_DEEPSTOP},
|
|
||||||
{"Dive Time", SAMPLE_EVENT_DIVETIME},
|
|
||||||
{"Gas Available", SAMPLE_EVENT_NONE},
|
|
||||||
{"SetPoint Switch", SAMPLE_EVENT_NONE},
|
|
||||||
{"Diluent Hypoxia", SAMPLE_EVENT_NONE},
|
|
||||||
{"Air Time", SAMPLE_EVENT_NONE},
|
|
||||||
{"Tank Pressure", SAMPLE_EVENT_NONE},
|
|
||||||
};
|
|
||||||
dc_sample_value_t sample = {0};
|
dc_sample_value_t sample = {0};
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
@ -738,11 +705,11 @@ static void sample_event_notify_value(const struct type_desc *desc, struct sampl
|
|||||||
if (!name)
|
if (!name)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sample.event.type = lookup_event(name, notifications, C_ARRAY_SIZE(notifications));
|
sample.event.type = SAMPLE_EVENT_STRING;
|
||||||
if (sample.event.type == SAMPLE_EVENT_NONE)
|
sample.event.name = name;
|
||||||
return;
|
|
||||||
|
|
||||||
sample.event.flags = value ? SAMPLE_FLAGS_BEGIN : SAMPLE_FLAGS_END;
|
sample.event.flags = value ? SAMPLE_FLAGS_BEGIN : SAMPLE_FLAGS_END;
|
||||||
|
sample.event.flags |= 2 << SAMPLE_FLAGS_SEVERITY_SHIFT;
|
||||||
|
|
||||||
if (info->callback) info->callback(DC_SAMPLE_EVENT, sample, info->userdata);
|
if (info->callback) info->callback(DC_SAMPLE_EVENT, sample, info->userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -755,22 +722,6 @@ static void sample_event_warning_type(const struct type_desc *desc, struct sampl
|
|||||||
|
|
||||||
static void sample_event_warning_value(const struct type_desc *desc, struct sample_data *info, unsigned char value)
|
static void sample_event_warning_value(const struct type_desc *desc, struct sample_data *info, unsigned char value)
|
||||||
{
|
{
|
||||||
static const eon_event_t warnings[] = {
|
|
||||||
{"ICD Penalty", SAMPLE_EVENT_NONE},
|
|
||||||
{"Deep Stop Penalty", SAMPLE_EVENT_VIOLATION},
|
|
||||||
{"Mandatory Safety Stop", SAMPLE_EVENT_SAFETYSTOP_MANDATORY},
|
|
||||||
{"OTU250", SAMPLE_EVENT_NONE},
|
|
||||||
{"OTU300", SAMPLE_EVENT_NONE},
|
|
||||||
{"CNS80%", SAMPLE_EVENT_NONE},
|
|
||||||
{"CNS100%", SAMPLE_EVENT_NONE},
|
|
||||||
{"Max.Depth", SAMPLE_EVENT_MAXDEPTH},
|
|
||||||
{"Air Time", SAMPLE_EVENT_AIRTIME},
|
|
||||||
{"Tank Pressure", SAMPLE_EVENT_NONE},
|
|
||||||
{"Safety Stop Broken", SAMPLE_EVENT_CEILING_SAFETYSTOP},
|
|
||||||
{"Deep Stop Broken", SAMPLE_EVENT_CEILING_SAFETYSTOP},
|
|
||||||
{"Ceiling Broken", SAMPLE_EVENT_CEILING},
|
|
||||||
{"PO2 High", SAMPLE_EVENT_PO2},
|
|
||||||
};
|
|
||||||
dc_sample_value_t sample = {0};
|
dc_sample_value_t sample = {0};
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
@ -778,11 +729,11 @@ static void sample_event_warning_value(const struct type_desc *desc, struct samp
|
|||||||
if (!name)
|
if (!name)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sample.event.type = lookup_event(name, warnings, C_ARRAY_SIZE(warnings));
|
sample.event.type = SAMPLE_EVENT_STRING;
|
||||||
if (sample.event.type == SAMPLE_EVENT_NONE)
|
sample.event.name = name;
|
||||||
return;
|
|
||||||
|
|
||||||
sample.event.flags = value ? SAMPLE_FLAGS_BEGIN : SAMPLE_FLAGS_END;
|
sample.event.flags = value ? SAMPLE_FLAGS_BEGIN : SAMPLE_FLAGS_END;
|
||||||
|
sample.event.flags |= 3 << SAMPLE_FLAGS_SEVERITY_SHIFT;
|
||||||
|
|
||||||
if (info->callback) info->callback(DC_SAMPLE_EVENT, sample, info->userdata);
|
if (info->callback) info->callback(DC_SAMPLE_EVENT, sample, info->userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -795,27 +746,18 @@ static void sample_event_alarm_type(const struct type_desc *desc, struct sample_
|
|||||||
|
|
||||||
static void sample_event_alarm_value(const struct type_desc *desc, struct sample_data *info, unsigned char value)
|
static void sample_event_alarm_value(const struct type_desc *desc, struct sample_data *info, unsigned char value)
|
||||||
{
|
{
|
||||||
static const eon_event_t alarms[] = {
|
|
||||||
{"Mandatory Safety Stop Broken", SAMPLE_EVENT_CEILING_SAFETYSTOP},
|
|
||||||
{"Ascent Speed", SAMPLE_EVENT_ASCENT},
|
|
||||||
{"Diluent Hyperoxia", SAMPLE_EVENT_NONE},
|
|
||||||
{"Violated Deep Stop", SAMPLE_EVENT_VIOLATION},
|
|
||||||
{"Ceiling Broken", SAMPLE_EVENT_CEILING},
|
|
||||||
{"PO2 High", SAMPLE_EVENT_PO2},
|
|
||||||
{"PO2 Low", SAMPLE_EVENT_PO2},
|
|
||||||
};
|
|
||||||
dc_sample_value_t sample = {0};
|
|
||||||
const char *name;
|
const char *name;
|
||||||
|
dc_sample_value_t sample = {0};
|
||||||
|
|
||||||
name = info->alarm_type;
|
name = info->alarm_type;
|
||||||
if (!name)
|
if (!name)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sample.event.type = lookup_event(name, alarms, C_ARRAY_SIZE(alarms));
|
sample.event.type = SAMPLE_EVENT_STRING;
|
||||||
if (sample.event.type == SAMPLE_EVENT_NONE)
|
sample.event.name = name;
|
||||||
return;
|
|
||||||
|
|
||||||
sample.event.flags = value ? SAMPLE_FLAGS_BEGIN : SAMPLE_FLAGS_END;
|
sample.event.flags = value ? SAMPLE_FLAGS_BEGIN : SAMPLE_FLAGS_END;
|
||||||
|
sample.event.flags |= 4 << SAMPLE_FLAGS_SEVERITY_SHIFT;
|
||||||
|
|
||||||
if (info->callback) info->callback(DC_SAMPLE_EVENT, sample, info->userdata);
|
if (info->callback) info->callback(DC_SAMPLE_EVENT, sample, info->userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1026,6 +968,19 @@ suunto_eonsteel_parser_samples_foreach(dc_parser_t *abstract, dc_sample_callback
|
|||||||
return DC_STATUS_SUCCESS;
|
return DC_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static dc_status_t get_string_field(suunto_eonsteel_parser_t *eon, unsigned idx, dc_field_string_t *value)
|
||||||
|
{
|
||||||
|
if (idx < MAXSTRINGS) {
|
||||||
|
dc_field_string_t *res = eon->cache.strings+idx;
|
||||||
|
if (res->desc && res->value) {
|
||||||
|
*value = *res;
|
||||||
|
return DC_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return DC_STATUS_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
// Ugly define thing makes the code much easier to read
|
// Ugly define thing makes the code much easier to read
|
||||||
// I'd love to use __typeof__, but that's a gcc'ism
|
// I'd love to use __typeof__, but that's a gcc'ism
|
||||||
#define field_value(p, set) \
|
#define field_value(p, set) \
|
||||||
@ -1094,11 +1049,13 @@ suunto_eonsteel_parser_get_field(dc_parser_t *parser, dc_field_type_t type, unsi
|
|||||||
* We need to have workpressure and a valid tank. In that case,
|
* We need to have workpressure and a valid tank. In that case,
|
||||||
* a fractional tank size implies imperial.
|
* a fractional tank size implies imperial.
|
||||||
*/
|
*/
|
||||||
if (tank->workpressure && (tank->type == DC_TANKVOLUME_METRIC)) {
|
if (tank->workpressure && (tank->type & DC_TANKINFO_METRIC)) {
|
||||||
if (fabs(tank->volume - rint(tank->volume)) > 0.001)
|
if (fabs(tank->volume - rint(tank->volume)) > 0.001)
|
||||||
tank->type = DC_TANKVOLUME_IMPERIAL;
|
tank->type += DC_TANKINFO_IMPERIAL - DC_TANKINFO_METRIC;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case DC_FIELD_STRING:
|
||||||
|
return get_string_field(eon, flags, (dc_field_string_t *)value);
|
||||||
default:
|
default:
|
||||||
return DC_STATUS_UNSUPPORTED;
|
return DC_STATUS_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
@ -1149,7 +1106,7 @@ static void set_depth_field(suunto_eonsteel_parser_t *eon, unsigned short d)
|
|||||||
// "enum:0=Off,1=Primary,2=?,3=Diluent"
|
// "enum:0=Off,1=Primary,2=?,3=Diluent"
|
||||||
// "enum:0=Off,1=Primary,3=Diluent,4=Oxygen"
|
// "enum:0=Off,1=Primary,3=Diluent,4=Oxygen"
|
||||||
//
|
//
|
||||||
// We turn that into the DC_TANKVOLUME data here, but
|
// We turn that into the DC_TANKINFO data here, but
|
||||||
// initially consider all non-off tanks to me METRIC.
|
// initially consider all non-off tanks to me METRIC.
|
||||||
//
|
//
|
||||||
// We may later turn the METRIC tank size into IMPERIAL if we
|
// We may later turn the METRIC tank size into IMPERIAL if we
|
||||||
@ -1157,7 +1114,7 @@ static void set_depth_field(suunto_eonsteel_parser_t *eon, unsigned short d)
|
|||||||
static int add_gas_type(suunto_eonsteel_parser_t *eon, const struct type_desc *desc, unsigned char type)
|
static int add_gas_type(suunto_eonsteel_parser_t *eon, const struct type_desc *desc, unsigned char type)
|
||||||
{
|
{
|
||||||
int idx = eon->cache.ngases;
|
int idx = eon->cache.ngases;
|
||||||
dc_tankvolume_t tankinfo = DC_TANKVOLUME_METRIC;
|
dc_tankinfo_t tankinfo = DC_TANKINFO_METRIC;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
if (idx >= MAXGASES)
|
if (idx >= MAXGASES)
|
||||||
@ -1168,9 +1125,9 @@ static int add_gas_type(suunto_eonsteel_parser_t *eon, const struct type_desc *d
|
|||||||
if (!name)
|
if (!name)
|
||||||
DEBUG(eon->base.context, "Unable to look up gas type %u in %s", type, desc->format);
|
DEBUG(eon->base.context, "Unable to look up gas type %u in %s", type, desc->format);
|
||||||
else if (!strcasecmp(name, "Diluent"))
|
else if (!strcasecmp(name, "Diluent"))
|
||||||
;
|
tankinfo |= DC_TANKINFO_CC_DILUENT;
|
||||||
else if (!strcasecmp(name, "Oxygen"))
|
else if (!strcasecmp(name, "Oxygen"))
|
||||||
;
|
tankinfo |= DC_TANKINFO_CC_O2;
|
||||||
else if (!strcasecmp(name, "None"))
|
else if (!strcasecmp(name, "None"))
|
||||||
tankinfo = DC_TANKVOLUME_NONE;
|
tankinfo = DC_TANKVOLUME_NONE;
|
||||||
else if (strcasecmp(name, "Primary"))
|
else if (strcasecmp(name, "Primary"))
|
||||||
@ -1223,6 +1180,42 @@ static int add_gas_workpressure(suunto_eonsteel_parser_t *eon, float wp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int add_string(suunto_eonsteel_parser_t *eon, const char *desc, const char *value)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
eon->cache.initialized |= 1 << DC_FIELD_STRING;
|
||||||
|
for (i = 0; i < MAXSTRINGS; i++) {
|
||||||
|
dc_field_string_t *str = eon->cache.strings+i;
|
||||||
|
if (str->desc)
|
||||||
|
continue;
|
||||||
|
str->desc = desc;
|
||||||
|
str->value = strdup(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int add_string_fmt(suunto_eonsteel_parser_t *eon, const char *desc, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
char buffer[256];
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We ignore the return value from vsnprintf, and we
|
||||||
|
* always NUL-terminate the destination buffer ourselves.
|
||||||
|
*
|
||||||
|
* That way we don't have to worry about random bad legacy
|
||||||
|
* implementations.
|
||||||
|
*/
|
||||||
|
va_start(ap, fmt);
|
||||||
|
buffer[sizeof(buffer)-1] = 0;
|
||||||
|
(void) vsnprintf(buffer, sizeof(buffer)-1, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
return add_string(eon, desc, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
static float get_le32_float(const unsigned char *src)
|
static float get_le32_float(const unsigned char *src)
|
||||||
{
|
{
|
||||||
union {
|
union {
|
||||||
@ -1246,7 +1239,16 @@ static int traverse_device_fields(suunto_eonsteel_parser_t *eon, const struct ty
|
|||||||
const unsigned char *data, int len)
|
const unsigned char *data, int len)
|
||||||
{
|
{
|
||||||
const char *name = desc->desc + strlen("sml.DeviceLog.Device.");
|
const char *name = desc->desc + strlen("sml.DeviceLog.Device.");
|
||||||
|
if (!strcmp(name, "SerialNumber"))
|
||||||
|
return add_string(eon, "Serial", data);
|
||||||
|
if (!strcmp(name, "Info.HW"))
|
||||||
|
return add_string(eon, "HW Version", data);
|
||||||
|
if (!strcmp(name, "Info.SW"))
|
||||||
|
return add_string(eon, "FW Version", data);
|
||||||
|
if (!strcmp(name, "Info.BatteryAtStart"))
|
||||||
|
return add_string(eon, "Battery at start", data);
|
||||||
|
if (!strcmp(name, "Info.BatteryAtEnd"))
|
||||||
|
return add_string(eon, "Battery at end", data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1277,12 +1279,30 @@ static int traverse_gas_fields(suunto_eonsteel_parser_t *eon, const struct type_
|
|||||||
if (!strcmp(name, ".Gas.Helium"))
|
if (!strcmp(name, ".Gas.Helium"))
|
||||||
return add_gas_he(eon, data[0]);
|
return add_gas_he(eon, data[0]);
|
||||||
|
|
||||||
|
if (!strcmp(name, ".Gas.TransmitterID"))
|
||||||
|
return add_string(eon, "Transmitter ID", data);
|
||||||
|
|
||||||
if (!strcmp(name, ".Gas.TankSize"))
|
if (!strcmp(name, ".Gas.TankSize"))
|
||||||
return add_gas_size(eon, get_le32_float(data));
|
return add_gas_size(eon, get_le32_float(data));
|
||||||
|
|
||||||
if (!strcmp(name, ".Gas.TankFillPressure"))
|
if (!strcmp(name, ".Gas.TankFillPressure"))
|
||||||
return add_gas_workpressure(eon, get_le32_float(data));
|
return add_gas_workpressure(eon, get_le32_float(data));
|
||||||
|
|
||||||
|
// There is a bug with older transmitters, where the transmitter
|
||||||
|
// battery charge returns zero. Rather than returning that bogus
|
||||||
|
// data, just don't return any battery charge information at all.
|
||||||
|
//
|
||||||
|
// Make sure to add all non-battery-charge field checks above this
|
||||||
|
// test, so that it doesn't trigger for anything else.
|
||||||
|
if (!data[0])
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!strcmp(name, ".Gas.TransmitterStartBatteryCharge"))
|
||||||
|
return add_string_fmt(eon, "Transmitter Battery at start", "%d %%", data[0]);
|
||||||
|
|
||||||
|
if (!strcmp(name, ".Gas.TransmitterEndBatteryCharge"))
|
||||||
|
return add_string_fmt(eon, "Transmitter Battery at end", "%d %%", data[0]);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1339,12 +1359,22 @@ static int traverse_diving_fields(suunto_eonsteel_parser_t *eon, const struct ty
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!strcmp(name, "Algorithm"))
|
||||||
|
return add_string(eon, "Deco algorithm", data);
|
||||||
|
|
||||||
if (!strcmp(name, "DiveMode")) {
|
if (!strcmp(name, "DiveMode")) {
|
||||||
if (!strncmp((const char *)data, "CCR", 3)) {
|
if (!strncmp((const char *)data, "CCR", 3)) {
|
||||||
eon->cache.divemode = DC_DIVEMODE_CCR;
|
eon->cache.divemode = DC_DIVEMODE_CCR;
|
||||||
eon->cache.initialized |= 1 << DC_FIELD_DIVEMODE;
|
eon->cache.initialized |= 1 << DC_FIELD_DIVEMODE;
|
||||||
}
|
}
|
||||||
return 0;
|
return add_string(eon, "Dive Mode", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Signed byte of conservatism (-2 .. +2) */
|
||||||
|
if (!strcmp(name, "Conservatism")) {
|
||||||
|
int val = *(signed char *)data;
|
||||||
|
|
||||||
|
return add_string_fmt(eon, "Personal Adjustment", "P%d", val);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(name, "LowSetPoint")) {
|
if (!strcmp(name, "LowSetPoint")) {
|
||||||
@ -1359,6 +1389,18 @@ static int traverse_diving_fields(suunto_eonsteel_parser_t *eon, const struct ty
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Time recoded in seconds.
|
||||||
|
// Let's just agree to ignore seconds
|
||||||
|
if (!strcmp(name, "DesaturationTime")) {
|
||||||
|
unsigned int time = array_uint32_le(data) / 60;
|
||||||
|
return add_string_fmt(eon, "Desaturation Time", "%d:%02d", time / 60, time % 60);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(name, "SurfaceTime")) {
|
||||||
|
unsigned int time = array_uint32_le(data) / 60;
|
||||||
|
return add_string_fmt(eon, "Surface Time", "%d:%02d", time / 60, time % 60);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1385,6 +1427,8 @@ static int traverse_header_fields(suunto_eonsteel_parser_t *eon, const struct ty
|
|||||||
eon->cache.maxdepth = d;
|
eon->cache.maxdepth = d;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (!strcmp(name, "DateTime"))
|
||||||
|
return add_string(eon, "Dive ID", data);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -1428,6 +1472,8 @@ static int traverse_sample_fields(suunto_eonsteel_parser_t *eon, const struct ty
|
|||||||
set_depth_field(eon, array_uint16_le(data));
|
set_depth_field(eon, array_uint16_le(data));
|
||||||
data += 2;
|
data += 2;
|
||||||
continue;
|
continue;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user