Add support for parsing the event bytes.

Right now only gas switch and bookmark events are supported, because
none of the other uwatec events can easily be mapped onto the existing
libdivecomputer events. But the basic infrastructure for supporting more
events is in place now.
This commit is contained in:
Jef Driesen 2015-07-09 20:13:25 +02:00
parent 0158739bcf
commit efe7e52bbe

View File

@ -49,6 +49,7 @@
#define UNSUPPORTED 0xFFFFFFFF #define UNSUPPORTED 0xFFFFFFFF
#define NEVENTS 3
#define NGASMIXES 10 #define NGASMIXES 10
#define HEADER 1 #define HEADER 1
@ -71,6 +72,16 @@ typedef enum {
UNKNOWN2, UNKNOWN2,
} uwatec_smart_sample_t; } uwatec_smart_sample_t;
typedef enum {
EV_WARNING, /* Warning (yellow buzzer) */
EV_ALARM, /* Alarm (red buzzer) */
EV_WORKLOAD, /* Workload */
EV_WORKLOAD_WARNING, /* Increased workload (lung symbol) */
EV_BOOKMARK, /* Bookmark / safety stop timer started */
EV_GASMIX, /* Active gasmix */
EV_UNKNOWN,
} uwatec_smart_event_t;
typedef struct uwatec_smart_header_info_t { typedef struct uwatec_smart_header_info_t {
unsigned int maxdepth; unsigned int maxdepth;
unsigned int divetime; unsigned int divetime;
@ -93,6 +104,12 @@ typedef struct uwatec_smart_sample_info_t {
unsigned int extrabytes; unsigned int extrabytes;
} uwatec_smart_sample_info_t; } uwatec_smart_sample_info_t;
typedef struct uwatec_smart_event_info_t {
uwatec_smart_event_t type;
unsigned int mask;
unsigned int shift;
} uwatec_smart_event_info_t;
typedef struct uwatec_smart_gasmix_t { typedef struct uwatec_smart_gasmix_t {
unsigned int id; unsigned int id;
unsigned int oxygen; unsigned int oxygen;
@ -117,6 +134,8 @@ struct uwatec_smart_parser_t {
const uwatec_smart_header_info_t *header; const uwatec_smart_header_info_t *header;
unsigned int headersize; unsigned int headersize;
unsigned int nsamples; unsigned int nsamples;
const uwatec_smart_event_info_t *events[NEVENTS];
unsigned int nevents[NEVENTS];
// Cached fields. // Cached fields.
unsigned int cached; unsigned int cached;
unsigned int trimix; unsigned int trimix;
@ -303,6 +322,57 @@ uwatec_smart_sample_info_t uwatec_smart_tec_samples[] = {
{RBT, 1, 0, 14, 1, 1}, // 11111111 111110dd dddddddd {RBT, 1, 0, 14, 1, 1}, // 11111111 111110dd dddddddd
}; };
static const
uwatec_smart_event_info_t uwatec_smart_tec_events_0[] = {
{EV_WARNING, 0x01, 0},
{EV_ALARM, 0x02, 1},
{EV_WORKLOAD_WARNING, 0x04, 2},
{EV_WORKLOAD, 0x38, 3},
{EV_UNKNOWN, 0xC0, 6},
};
static const
uwatec_smart_event_info_t uwatec_smart_aladintec_events_0[] = {
{EV_WARNING, 0x01, 0},
{EV_ALARM, 0x02, 1},
{EV_BOOKMARK, 0x04, 2},
{EV_UNKNOWN, 0x08, 3},
};
static const
uwatec_smart_event_info_t uwatec_smart_aladintec2g_events_0[] = {
{EV_WARNING, 0x01, 0},
{EV_ALARM, 0x02, 1},
{EV_BOOKMARK, 0x04, 2},
{EV_UNKNOWN, 0x08, 3},
};
static const
uwatec_smart_event_info_t uwatec_smart_aladintec2g_events_1[] = {
{EV_UNKNOWN, 0x07, 0},
{EV_GASMIX, 0x18, 3},
};
static const
uwatec_smart_event_info_t uwatec_smart_galileo_events_0[] = {
{EV_WARNING, 0x01, 0},
{EV_ALARM, 0x02, 1},
{EV_WORKLOAD_WARNING, 0x04, 2},
{EV_BOOKMARK, 0x08, 3},
};
static const
uwatec_smart_event_info_t uwatec_smart_galileo_events_1[] = {
{EV_WORKLOAD, 0x07, 0},
{EV_UNKNOWN, 0x18, 3},
{EV_GASMIX, 0x60, 5},
{EV_UNKNOWN, 0x80, 7},
};
static const
uwatec_smart_event_info_t uwatec_smart_galileo_events_2[] = {
{EV_UNKNOWN, 0xFF, 0},
};
static unsigned int static unsigned int
uwatec_smart_find_gasmix (uwatec_smart_parser_t *parser, unsigned int id) uwatec_smart_find_gasmix (uwatec_smart_parser_t *parser, unsigned int id)
@ -444,12 +514,18 @@ uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i
parser->model = model; parser->model = model;
parser->devtime = devtime; parser->devtime = devtime;
parser->systime = systime; parser->systime = systime;
for (unsigned int i = 0; i < NEVENTS; ++i) {
parser->events[i] = NULL;
parser->nevents[i] = 0;
}
switch (model) { switch (model) {
case SMARTPRO: case SMARTPRO:
parser->headersize = 92; parser->headersize = 92;
parser->header = &uwatec_smart_pro_header; parser->header = &uwatec_smart_pro_header;
parser->samples = uwatec_smart_pro_samples; parser->samples = uwatec_smart_pro_samples;
parser->nsamples = C_ARRAY_SIZE (uwatec_smart_pro_samples); parser->nsamples = C_ARRAY_SIZE (uwatec_smart_pro_samples);
parser->events[0] = uwatec_smart_tec_events_0;
parser->nevents[0] = C_ARRAY_SIZE (uwatec_smart_tec_events_0);
break; break;
case GALILEO: case GALILEO:
case GALILEOTRIMIX: case GALILEOTRIMIX:
@ -460,24 +536,38 @@ uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i
parser->header = &uwatec_smart_galileo_header; parser->header = &uwatec_smart_galileo_header;
parser->samples = uwatec_smart_galileo_samples; parser->samples = uwatec_smart_galileo_samples;
parser->nsamples = C_ARRAY_SIZE (uwatec_smart_galileo_samples); parser->nsamples = C_ARRAY_SIZE (uwatec_smart_galileo_samples);
parser->events[0] = uwatec_smart_galileo_events_0;
parser->events[1] = uwatec_smart_galileo_events_1;
parser->events[2] = uwatec_smart_galileo_events_2;
parser->nevents[0] = C_ARRAY_SIZE (uwatec_smart_galileo_events_0);
parser->nevents[1] = C_ARRAY_SIZE (uwatec_smart_galileo_events_1);
parser->nevents[2] = C_ARRAY_SIZE (uwatec_smart_galileo_events_2);
break; break;
case ALADINTEC: case ALADINTEC:
parser->headersize = 108; parser->headersize = 108;
parser->header = &uwatec_smart_aladin_tec_header; parser->header = &uwatec_smart_aladin_tec_header;
parser->samples = uwatec_smart_aladin_samples; parser->samples = uwatec_smart_aladin_samples;
parser->nsamples = C_ARRAY_SIZE (uwatec_smart_aladin_samples); parser->nsamples = C_ARRAY_SIZE (uwatec_smart_aladin_samples);
parser->events[0] = uwatec_smart_aladintec_events_0;
parser->nevents[0] = C_ARRAY_SIZE (uwatec_smart_aladintec_events_0);
break; break;
case ALADINTEC2G: case ALADINTEC2G:
parser->headersize = 116; parser->headersize = 116;
parser->header = &uwatec_smart_aladin_tec2g_header; parser->header = &uwatec_smart_aladin_tec2g_header;
parser->samples = uwatec_smart_aladin_samples; parser->samples = uwatec_smart_aladin_samples;
parser->nsamples = C_ARRAY_SIZE (uwatec_smart_aladin_samples); parser->nsamples = C_ARRAY_SIZE (uwatec_smart_aladin_samples);
parser->events[0] = uwatec_smart_aladintec2g_events_0;
parser->events[1] = uwatec_smart_aladintec2g_events_1;
parser->nevents[0] = C_ARRAY_SIZE (uwatec_smart_aladintec2g_events_0);
parser->nevents[1] = C_ARRAY_SIZE (uwatec_smart_aladintec2g_events_1);
break; break;
case SMARTCOM: case SMARTCOM:
parser->headersize = 100; parser->headersize = 100;
parser->header = &uwatec_smart_com_header; parser->header = &uwatec_smart_com_header;
parser->samples = uwatec_smart_com_samples; parser->samples = uwatec_smart_com_samples;
parser->nsamples = C_ARRAY_SIZE (uwatec_smart_com_samples); parser->nsamples = C_ARRAY_SIZE (uwatec_smart_com_samples);
parser->events[0] = uwatec_smart_tec_events_0;
parser->nevents[0] = C_ARRAY_SIZE (uwatec_smart_tec_events_0);
break; break;
case SMARTTEC: case SMARTTEC:
case SMARTZ: case SMARTZ:
@ -485,6 +575,8 @@ uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i
parser->header = &uwatec_smart_tec_header; parser->header = &uwatec_smart_tec_header;
parser->samples = uwatec_smart_tec_samples; parser->samples = uwatec_smart_tec_samples;
parser->nsamples = C_ARRAY_SIZE (uwatec_smart_tec_samples); parser->nsamples = C_ARRAY_SIZE (uwatec_smart_tec_samples);
parser->events[0] = uwatec_smart_tec_events_0;
parser->nevents[0] = C_ARRAY_SIZE (uwatec_smart_tec_events_0);
break; break;
default: default:
free (parser); free (parser);
@ -775,6 +867,7 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
unsigned int heartrate = 0; unsigned int heartrate = 0;
unsigned int bearing = 0; unsigned int bearing = 0;
unsigned char alarms[3] = {0, 0, 0}; unsigned char alarms[3] = {0, 0, 0};
unsigned int bookmark = 0;
// Previous gas mix - initialize with impossible value // Previous gas mix - initialize with impossible value
unsigned int gasmix_previous = 0xFFFFFFFF; unsigned int gasmix_previous = 0xFFFFFFFF;
@ -841,7 +934,10 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
signed int svalue = uwatec_smart_fixsignbit (value, nbits); signed int svalue = uwatec_smart_fixsignbit (value, nbits);
// Parse the value. // Parse the value.
unsigned int idx = 0;
unsigned int subtype = 0; unsigned int subtype = 0;
unsigned int nevents = 0;
const uwatec_smart_event_info_t *events = NULL;
switch (table[id].type) { switch (table[id].type) {
case PRESSURE_DEPTH: case PRESSURE_DEPTH:
pressure += ((signed char) ((svalue >> NBITS) & 0xFF)) / 4.0; pressure += ((signed char) ((svalue >> NBITS) & 0xFF)) / 4.0;
@ -907,11 +1003,27 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
case ALARMS: case ALARMS:
alarms[table[id].index] = value; alarms[table[id].index] = value;
have_alarms = 1; have_alarms = 1;
if (table[id].index == 1) { idx = table[id].index;
if (parser->model == ALADINTEC || parser->model == ALADINTEC2G) { if (idx >= NEVENTS || parser->events[idx] == NULL) {
gasmix = (value & 0x18) >> 3; ERROR (abstract->context, "Unexpected event index.");
} else { return DC_STATUS_DATAFORMAT;
gasmix = (value & 0x60) >> 5; }
events = parser->events[idx];
nevents = parser->nevents[idx];
for (unsigned int i = 0; i < nevents; ++i) {
uwatec_smart_event_t ev_type = events[i].type;
unsigned int ev_value = (value & events[i].mask) >> events[i].shift;
switch (ev_type) {
case EV_BOOKMARK:
bookmark = ev_value;
break;
case EV_GASMIX:
gasmix = ev_value;
break;
default:
break;
} }
} }
break; break;
@ -945,7 +1057,7 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
unsigned int endpressure = array_uint16_le (data + offset + 7); unsigned int endpressure = array_uint16_le (data + offset + 7);
if (o2 != 0 || he != 0) { if (o2 != 0 || he != 0) {
unsigned int idx = uwatec_smart_find_gasmix (parser, mixid); idx = uwatec_smart_find_gasmix (parser, mixid);
if (idx >= parser->ngasmixes) { if (idx >= parser->ngasmixes) {
if (idx >= NGASMIXES) { if (idx >= NGASMIXES) {
ERROR (abstract->context, "Maximum number of gas mixes reached."); ERROR (abstract->context, "Maximum number of gas mixes reached.");
@ -960,7 +1072,7 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
} }
if (beginpressure != 0 || endpressure != 0) { if (beginpressure != 0 || endpressure != 0) {
unsigned int idx = uwatec_smart_find_tank (parser, mixid); idx = uwatec_smart_find_tank (parser, mixid);
if (idx >= parser->ntanks) { if (idx >= parser->ntanks) {
if (idx >= NGASMIXES) { if (idx >= NGASMIXES) {
ERROR (abstract->context, "Maximum number of tanks reached."); ERROR (abstract->context, "Maximum number of tanks reached.");
@ -987,7 +1099,7 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
if (callback) callback (DC_SAMPLE_TIME, sample, userdata); if (callback) callback (DC_SAMPLE_TIME, sample, userdata);
if (parser->ngasmixes && gasmix != gasmix_previous) { if (parser->ngasmixes && gasmix != gasmix_previous) {
unsigned int idx = uwatec_smart_find_gasmix (parser, gasmix); idx = uwatec_smart_find_gasmix (parser, gasmix);
if (idx >= parser->ngasmixes) { if (idx >= parser->ngasmixes) {
ERROR (abstract->context, "Invalid gas mix index."); ERROR (abstract->context, "Invalid gas mix index.");
return DC_STATUS_DATAFORMAT; return DC_STATUS_DATAFORMAT;
@ -1007,6 +1119,14 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata); if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);
} }
if (bookmark) {
sample.event.type = SAMPLE_EVENT_BOOKMARK;
sample.event.time = 0;
sample.event.flags = 0;
sample.event.value = 0;
if (callback) callback (DC_SAMPLE_EVENT, sample, userdata);
}
if (have_alarms) { if (have_alarms) {
sample.vendor.type = SAMPLE_VENDOR_UWATEC_SMART; sample.vendor.type = SAMPLE_VENDOR_UWATEC_SMART;
sample.vendor.size = nalarms; sample.vendor.size = nalarms;