Add a new sample with the active gas mix.

The new gasmix sample contains the index of the active gas mix.

This new sample is intended as a replacement for the existing gas change
events (SAMPLE_EVENT_GASCHANGE and SAMPLE_EVENT_GASCHANGE2). To maintain
backwards compatibility, the legacy events are marked as deprecated but
not removed yet.
This commit is contained in:
Jef Driesen 2015-01-04 08:56:10 +01:00
parent d839852953
commit 06e0de6712
15 changed files with 156 additions and 19 deletions

View File

@ -271,12 +271,8 @@ sample_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata)
fprintf (sampledata->fp, " <temperature>%.2f</temperature>\n", value.temperature);
break;
case DC_SAMPLE_EVENT:
if (value.event.type == SAMPLE_EVENT_GASCHANGE2) {
fprintf (sampledata->fp, " <gaschange o2=\"%u\" he=\"%u\" />\n",
value.event.value & 0xFFFF, (value.event.value >> 16) & 0xFFFF);
} else if (value.event.type == SAMPLE_EVENT_GASCHANGE) {
fprintf (sampledata->fp, " <gaschange o2=\"%u\" />\n",
value.event.value);
if (value.event.type == SAMPLE_EVENT_GASCHANGE || value.event.type == SAMPLE_EVENT_GASCHANGE2) {
// Ignore deprecated events.
} else {
fprintf (sampledata->fp, " <event type=\"%u\" time=\"%u\" flags=\"%u\" value=\"%u\">%s</event>\n",
value.event.type, value.event.time, value.event.flags, value.event.value, events[value.event.type]);
@ -310,6 +306,9 @@ sample_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata)
fprintf (sampledata->fp, " <deco time=\"%u\" depth=\"%.2f\">%s</deco>\n",
value.deco.time, value.deco.depth, decostop[value.deco.type]);
break;
case DC_SAMPLE_GASMIX:
fprintf (sampledata->fp, " <gasmix>%u</gasmix>\n", value.gasmix);
break;
default:
break;
}

View File

@ -43,7 +43,8 @@ typedef enum dc_sample_type_t {
DC_SAMPLE_SETPOINT,
DC_SAMPLE_PPO2,
DC_SAMPLE_CNS,
DC_SAMPLE_DECO
DC_SAMPLE_DECO,
DC_SAMPLE_GASMIX
} dc_sample_type_t;
typedef enum dc_field_type_t {
@ -74,7 +75,7 @@ typedef enum parser_sample_event_t {
SAMPLE_EVENT_BOOKMARK,
SAMPLE_EVENT_SURFACE,
SAMPLE_EVENT_SAFETYSTOP,
SAMPLE_EVENT_GASCHANGE, /* The event value contains the O2 percentage. */
SAMPLE_EVENT_GASCHANGE, /* Deprecated: replaced by DC_SAMPLE_GASMIX. */
SAMPLE_EVENT_SAFETYSTOP_VOLUNTARY,
SAMPLE_EVENT_SAFETYSTOP_MANDATORY,
SAMPLE_EVENT_DEEPSTOP,
@ -88,9 +89,7 @@ typedef enum parser_sample_event_t {
SAMPLE_EVENT_RGBM,
SAMPLE_EVENT_HEADING,
SAMPLE_EVENT_TISSUELEVEL,
SAMPLE_EVENT_GASCHANGE2, /* The event value contains the O2 and He
percentages, packed as two 16bit integers in
respectively the low and high part. */
SAMPLE_EVENT_GASCHANGE2, /* Deprecated: replaced by DC_SAMPLE_GASMIX. */
} parser_sample_event_t;
/* For backwards compatibility */
@ -211,6 +210,7 @@ typedef union dc_sample_value_t {
unsigned int time;
double depth;
} deco;
unsigned int gasmix; /* Gas mix index */
} dc_sample_value_t;
typedef struct dc_parser_t dc_parser_t;

View File

@ -1,5 +1,5 @@
AM_CPPFLAGS = -I$(top_builddir)/include -I$(top_srcdir)/include
AM_CFLAGS = $(LIBUSB_CFLAGS)
AM_CFLAGS = $(LIBUSB_CFLAGS) -DENABLE_DEPRECATED
lib_LTLIBRARIES = libdivecomputer.la

View File

@ -306,6 +306,9 @@ atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
ERROR (abstract->context, "Invalid gas mix index.");
return DC_STATUS_DATAFORMAT;
}
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
#ifdef ENABLE_DEPRECATED
unsigned int o2 = data[SZ_HEADER + SZ_GASMIX * idx + 4];
unsigned int he = data[SZ_HEADER + SZ_GASMIX * idx + 5];
sample.event.type = SAMPLE_EVENT_GASCHANGE2;
@ -313,6 +316,7 @@ atomics_cobalt_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
sample.event.flags = 0;
sample.event.value = o2 | (he << 16);
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
#endif
gasmix_previous = gasmix;
}

View File

@ -227,11 +227,15 @@ cressi_edy_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
return DC_STATUS_DATAFORMAT;
}
if (idx != gasmix) {
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
#ifdef ENABLE_DEPRECATED
sample.event.type = SAMPLE_EVENT_GASCHANGE;
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = bcd2dec(data[0x17 - idx]);
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
#endif
gasmix = idx;
}
}

View File

@ -270,11 +270,15 @@ diverite_nitekq_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callbac
// Gas change
if (gasmix != gasmix_previous) {
sample.gasmix = gasmix;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
#ifdef ENABLE_DEPRECATED
sample.event.type = SAMPLE_EVENT_GASCHANGE2;
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = oxygen[gasmix] | (helium[gasmix] << 16);
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
#endif
gasmix_previous = gasmix;
}

View File

@ -275,11 +275,15 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
ngasmixes = i + 1;
}
sample.gasmix = i;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
#ifdef ENABLE_DEPRECATED
sample.event.type = SAMPLE_EVENT_GASCHANGE2;
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = o2 | (he << 16);
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
#endif
o2_previous = o2;
he_previous = he;
}

View File

@ -616,6 +616,9 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
// Initial gas mix.
if (time == samplerate && parser->initial != 0xFF) {
sample.gasmix = parser->initial;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
#ifdef ENABLE_DEPRECATED
unsigned int idx = parser->initial;
unsigned int o2 = parser->gasmix[idx].oxygen;
unsigned int he = parser->gasmix[idx].helium;
@ -624,6 +627,7 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
sample.event.flags = 0;
sample.event.value = o2 | (he << 16);
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
#endif
}
// Depth (mbar).
@ -708,11 +712,16 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
parser->gasmix[idx].helium = he;
parser->ngasmixes = idx + 1;
}
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
#ifdef ENABLE_DEPRECATED
sample.event.type = SAMPLE_EVENT_GASCHANGE2;
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = o2 | (he << 16);
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
#endif
offset += 2;
length -= 2;
}
@ -729,6 +738,9 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
return DC_STATUS_DATAFORMAT;
}
idx--; /* Convert to a zero based index. */
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
#ifdef ENABLE_DEPRECATED
unsigned int o2 = parser->gasmix[idx].oxygen;
unsigned int he = parser->gasmix[idx].helium;
sample.event.type = SAMPLE_EVENT_GASCHANGE2;
@ -736,6 +748,7 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
sample.event.flags = 0;
sample.event.value = o2 | (he << 16);
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
#endif
offset++;
length--;
}
@ -773,11 +786,15 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
parser->ngasmixes = idx + 1;
}
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
#ifdef ENABLE_DEPRECATED
sample.event.type = SAMPLE_EVENT_GASCHANGE2;
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = o2 | (he << 16);
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
#endif
offset += 2;
length -= 2;
}
@ -877,11 +894,15 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
parser->ngasmixes = idx + 1;
}
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
#ifdef ENABLE_DEPRECATED
sample.event.type = SAMPLE_EVENT_GASCHANGE2;
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = o2 | (he << 16);
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
#endif
offset += 2;
length -= 2;
}

View File

@ -510,10 +510,14 @@ mares_iconhd_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
return DC_STATUS_DATAFORMAT;
}
if (gasmix != gasmix_previous) {
sample.gasmix = gasmix;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
#ifdef ENABLE_DEPRECATED
sample.event.type = SAMPLE_EVENT_GASCHANGE;
sample.event.time = 0;
sample.event.value = parser->oxygen[gasmix];
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
#endif
gasmix_previous = gasmix;
}
}

View File

@ -777,6 +777,9 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
ERROR (abstract->context, "Invalid gas mix index (%u).", gasmix);
return DC_STATUS_DATAFORMAT;
}
sample.gasmix = gasmix - 1;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
#ifdef ENABLE_DEPRECATED
unsigned int o2 = parser->oxygen[gasmix - 1];
unsigned int he = parser->helium[gasmix - 1];
sample.event.type = SAMPLE_EVENT_GASCHANGE2;
@ -784,6 +787,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
sample.event.flags = 0;
sample.event.value = o2 | (he << 16);
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
#endif
gasmix_previous = gasmix;
}

View File

@ -88,6 +88,20 @@ static const dc_parser_vtable_t shearwater_petrel_parser_vtable = {
};
static unsigned int
shearwater_predator_find_gasmix (shearwater_predator_parser_t *parser, unsigned int o2, unsigned int he)
{
unsigned int i = 0;
while (i < parser->ngasmixes) {
if (o2 == parser->oxygen[i] && he == parser->helium[i])
break;
i++;
}
return i;
}
dc_status_t
shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int petrel)
{
@ -418,11 +432,21 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
unsigned int o2 = data[offset + 7];
unsigned int he = data[offset + 8];
if (o2 != o2_previous || he != he_previous) {
unsigned int idx = shearwater_predator_find_gasmix (parser, o2, he);
if (idx >= parser->ngasmixes) {
ERROR (abstract->context, "Invalid gas mix.");
return DC_STATUS_DATAFORMAT;
}
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
#ifdef ENABLE_DEPRECATED
sample.event.type = SAMPLE_EVENT_GASCHANGE2;
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = o2 | (he << 16);
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
#endif
o2_previous = o2;
he_previous = he;
}

View File

@ -94,6 +94,19 @@ static const dc_parser_vtable_t suunto_d9_parser_vtable = {
suunto_d9_parser_destroy /* destroy */
};
static unsigned int
suunto_d9_parser_find_gasmix (suunto_d9_parser_t *parser, unsigned int o2, unsigned int he)
{
// Find the gasmix in the list.
unsigned int i = 0;
while (i < parser->ngasmixes) {
if (o2 == parser->oxygen[i] && he == parser->helium[i])
break;
i++;
}
return i;
}
static dc_status_t
suunto_d9_parser_cache (suunto_d9_parser_t *parser)
@ -487,12 +500,16 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca
ERROR (abstract->context, "Invalid initial gas mix.");
return DC_STATUS_DATAFORMAT;
}
sample.gasmix = parser->gasmix;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
#ifdef ENABLE_DEPRECATED
unsigned int he = parser->helium[parser->gasmix];
unsigned int o2 = parser->oxygen[parser->gasmix];
sample.event.type = SAMPLE_EVENT_GASCHANGE2;
sample.event.time = 0;
sample.event.value = o2 | (he << 16);
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
#endif
}
// Events
@ -501,7 +518,7 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca
unsigned int event = data[offset++];
unsigned int seconds, type, unknown, heading;
unsigned int current, next;
unsigned int he, o2;
unsigned int he, o2, idx;
unsigned int length;
sample.event.type = SAMPLE_EVENT_NONE;
@ -668,10 +685,19 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca
}
o2 = data[offset + 0];
seconds = data[offset + 1];
idx = suunto_d9_parser_find_gasmix(parser, o2, 0);
if (idx >= parser->ngasmixes) {
ERROR (abstract->context, "Invalid gas mix.");
return DC_STATUS_DATAFORMAT;
}
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
#ifdef ENABLE_DEPRECATED
sample.event.type = SAMPLE_EVENT_GASCHANGE;
sample.event.time = seconds;
sample.event.value = o2;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
#endif
offset += 2;
break;
case 0x06: // Gas Change
@ -691,10 +717,19 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca
} else {
seconds = data[offset + 3];
}
idx = suunto_d9_parser_find_gasmix(parser, o2, he);
if (idx >= parser->ngasmixes) {
ERROR (abstract->context, "Invalid gas mix.");
return DC_STATUS_DATAFORMAT;
}
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
#ifdef ENABLE_DEPRECATED
sample.event.type = SAMPLE_EVENT_GASCHANGE2;
sample.event.time = seconds;
sample.event.value = o2 | (he << 16);
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
#endif
offset += length;
break;
default:

View File

@ -557,19 +557,22 @@ static void sample_gas_switch_event(struct sample_data *info, unsigned short idx
{
suunto_eonsteel_parser_t *eon = info->eon;
dc_sample_value_t sample = {0};
int o2, he;
if (idx < 1 || idx > eon->cache.ngases)
return;
// Horrible, broken, gas change events
o2 = 100 * eon->cache.gasmix[idx-1].oxygen;
he = 100 * eon->cache.gasmix[idx-1].helium;
sample.gasmix = idx - 1;
if (info->callback) info->callback(DC_SAMPLE_GASMIX, sample, info->userdata);
#ifdef ENABLE_DEPRECATED
unsigned int o2 = 100 * eon->cache.gasmix[idx-1].oxygen;
unsigned int he = 100 * eon->cache.gasmix[idx-1].helium;
sample.event.type = SAMPLE_EVENT_GASCHANGE2;
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = o2 | (he << 16);
if (info->callback) info->callback(DC_SAMPLE_EVENT, sample, info->userdata);
#endif
}
/*

View File

@ -59,6 +59,18 @@ static const dc_parser_vtable_t suunto_vyper_parser_vtable = {
suunto_vyper_parser_destroy /* destroy */
};
static unsigned int
suunto_vyper_parser_find_gasmix (suunto_vyper_parser_t *parser, unsigned int o2)
{
unsigned int i = 0;
while (i < parser->ngasmixes) {
if (o2 == parser->oxygen[i])
break;
i++;
}
return i;
}
static dc_status_t
suunto_vyper_parser_cache (suunto_vyper_parser_t *parser)
@ -353,6 +365,7 @@ suunto_vyper_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
complete = 1;
} else {
// Event.
unsigned int o2 = 0, idx = 0;
sample.event.type = SAMPLE_EVENT_NONE;
sample.event.time = 0;
sample.event.flags = 0;
@ -382,8 +395,22 @@ suunto_vyper_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
case 0x87: // Gas Change
if (offset + 1 > size)
return DC_STATUS_DATAFORMAT;
o2 = data[offset++];
idx = suunto_vyper_parser_find_gasmix (parser, o2);
if (idx >= parser->ngasmixes) {
ERROR (abstract->context, "Maximum number of gas mixes reached.");
return DC_STATUS_DATAFORMAT;
}
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
#ifdef ENABLE_DEPRECATED
sample.event.type = SAMPLE_EVENT_GASCHANGE;
sample.event.value = data[offset++];
sample.event.value = o2;
#else
sample.event.type = SAMPLE_EVENT_NONE;
#endif
break;
default: // Unknown
WARNING (abstract->context, "Unknown event");

View File

@ -1115,6 +1115,9 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
ERROR (abstract->context, "Invalid gas mix index.");
return DC_STATUS_DATAFORMAT;
}
sample.gasmix = idx;
if (callback) callback (DC_SAMPLE_GASMIX, sample, userdata);
#ifdef ENABLE_DEPRECATED
unsigned int o2 = parser->gasmix[idx].oxygen;
unsigned int he = parser->gasmix[idx].helium;
sample.event.type = SAMPLE_EVENT_GASCHANGE2;
@ -1122,6 +1125,7 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
sample.event.flags = 0;
sample.event.value = o2 | (he << 16);
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
#endif
gasmix_previous = gasmix;
}