From 8da80ea0a22f31079d0fca4de642c1ab77a76136 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 17 Oct 2013 19:03:12 +0200 Subject: [PATCH 1/6] Store the pointers to the tables in the device handle. Because for selecting the correct header and sample tables (and associated data) only the model number is necessary, they can easily be stored inside the device handle. The main benefit is less duplicated code. --- src/uwatec_smart_parser.c | 464 ++++++++++++++++++-------------------- 1 file changed, 225 insertions(+), 239 deletions(-) diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index b4d7508..5f571bb 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -31,8 +31,9 @@ #define ISINSTANCE(parser) dc_parser_isinstance((parser), &uwatec_smart_parser_vtable) +#define C_ARRAY_SIZE(array) (sizeof (array) / sizeof *(array)) + #define NBITS 8 -#define NELEMENTS(x) ( sizeof(x) / sizeof((x)[0]) ) #define SMARTPRO 0x10 #define GALILEO 0x11 @@ -45,6 +46,36 @@ #define SMARTZ 0x1C #define MERIDIAN 0x20 +typedef enum { + PRESSURE_DEPTH, + RBT, + TEMPERATURE, + PRESSURE, + DEPTH, + HEARTRATE, + BEARING, + ALARMS, + TIME, + UNKNOWN1, + UNKNOWN2, +} uwatec_smart_sample_t; + +typedef struct uwatec_smart_header_info_t { + unsigned int maxdepth; + unsigned int divetime; + unsigned int gasmix; + unsigned int ngases; +} uwatec_smart_header_info_t; + +typedef struct uwatec_smart_sample_info_t { + uwatec_smart_sample_t type; + unsigned int absolute; + unsigned int index; + unsigned int ntypebits; + unsigned int ignoretype; + unsigned int extrabytes; +} uwatec_smart_sample_info_t; + typedef struct uwatec_smart_parser_t uwatec_smart_parser_t; struct uwatec_smart_parser_t { @@ -52,6 +83,10 @@ struct uwatec_smart_parser_t { unsigned int model; unsigned int devtime; dc_ticks_t systime; + const uwatec_smart_sample_info_t *samples; + const uwatec_smart_header_info_t *header; + unsigned int headersize; + unsigned int nsamples; }; static dc_status_t uwatec_smart_parser_set_data (dc_parser_t *abstract, const unsigned char *data, unsigned int size); @@ -69,6 +104,138 @@ static const dc_parser_vtable_t uwatec_smart_parser_vtable = { uwatec_smart_parser_destroy /* destroy */ }; +static const +uwatec_smart_header_info_t uwatec_smart_pro_header = { + 18, + 20, + 24, 1 +}; + +static const +uwatec_smart_header_info_t uwatec_smart_galileo_header = { + 22, + 26, + 44, 3 +}; + +static const +uwatec_smart_header_info_t uwatec_smart_aladin_tec_header = { + 22, + 24, + 30, 1 +}; + +static const +uwatec_smart_header_info_t uwatec_smart_aladin_tec2g_header = { + 22, + 26, + 32, 3 +}; + +static const +uwatec_smart_header_info_t uwatec_smart_com_header = { + 18, + 20, + 24, 1 +}; + +static const +uwatec_smart_header_info_t uwatec_smart_tec_header = { + 18, + 20, + 28, 3 +}; + +static const +uwatec_smart_header_info_t uwatec_smart_z_header = { + 18, + 20, + 28, 1 +}; + +static const +uwatec_smart_sample_info_t uwatec_smart_pro_samples[] = { + {DEPTH, 0, 0, 1, 0, 0}, // 0ddddddd + {TEMPERATURE, 0, 0, 2, 0, 0}, // 10dddddd + {TIME, 1, 0, 3, 0, 0}, // 110ddddd + {ALARMS, 1, 0, 4, 0, 0}, // 1110dddd + {DEPTH, 0, 0, 5, 0, 1}, // 11110ddd dddddddd + {TEMPERATURE, 0, 0, 6, 0, 1}, // 111110dd dddddddd + {DEPTH, 1, 0, 7, 1, 2}, // 1111110d dddddddd dddddddd + {TEMPERATURE, 1, 0, 8, 0, 2}, // 11111110 dddddddd dddddddd +}; + +static const +uwatec_smart_sample_info_t uwatec_smart_galileo_samples[] = { + {DEPTH, 0, 0, 1, 0, 0}, // 0ddd dddd + {RBT, 0, 0, 3, 0, 0}, // 100d dddd + {PRESSURE, 0, 0, 4, 0, 0}, // 1010 dddd + {TEMPERATURE, 0, 0, 4, 0, 0}, // 1011 dddd + {TIME, 1, 0, 4, 0, 0}, // 1100 dddd + {HEARTRATE, 0, 0, 4, 0, 0}, // 1101 dddd + {ALARMS, 1, 0, 4, 0, 0}, // 1110 dddd + {ALARMS, 1, 1, 8, 0, 1}, // 1111 0000 dddddddd + {DEPTH, 1, 0, 8, 0, 2}, // 1111 0001 dddddddd dddddddd + {RBT, 1, 0, 8, 0, 1}, // 1111 0010 dddddddd + {TEMPERATURE, 1, 0, 8, 0, 2}, // 1111 0011 dddddddd dddddddd + {PRESSURE, 1, 0, 8, 0, 2}, // 1111 0100 dddddddd dddddddd + {PRESSURE, 1, 1, 8, 0, 2}, // 1111 0101 dddddddd dddddddd + {PRESSURE, 1, 2, 8, 0, 2}, // 1111 0110 dddddddd dddddddd + {HEARTRATE, 1, 0, 8, 0, 1}, // 1111 0111 dddddddd + {BEARING, 1, 0, 8, 0, 2}, // 1111 1000 dddddddd dddddddd + {ALARMS, 1, 2, 8, 0, 1}, // 1111 1001 dddddddd + {UNKNOWN1, 1, 0, 8, 0, 0}, // 1111 1010 (8 bytes) + {UNKNOWN2, 1, 0, 8, 0, 1}, // 1111 1011 dddddddd (n-1 bytes) +}; + + +static const +uwatec_smart_sample_info_t uwatec_smart_aladin_samples[] = { + {DEPTH, 0, 0, 1, 0, 0}, // 0ddddddd + {TEMPERATURE, 0, 0, 2, 0, 0}, // 10dddddd + {TIME, 1, 0, 3, 0, 0}, // 110ddddd + {ALARMS, 1, 0, 4, 0, 0}, // 1110dddd + {DEPTH, 0, 0, 5, 0, 1}, // 11110ddd dddddddd + {TEMPERATURE, 0, 0, 6, 0, 1}, // 111110dd dddddddd + {DEPTH, 1, 0, 7, 1, 2}, // 1111110d dddddddd dddddddd + {TEMPERATURE, 1, 0, 8, 0, 2}, // 11111110 dddddddd dddddddd + {ALARMS, 1, 1, 9, 0, 0}, // 11111111 0ddddddd +}; + +static const +uwatec_smart_sample_info_t uwatec_smart_com_samples[] = { + {PRESSURE_DEPTH, 0, 0, 1, 0, 1}, // 0ddddddd dddddddd + {RBT, 0, 0, 2, 0, 0}, // 10dddddd + {TEMPERATURE, 0, 0, 3, 0, 0}, // 110ddddd + {PRESSURE, 0, 0, 4, 0, 1}, // 1110dddd dddddddd + {DEPTH, 0, 0, 5, 0, 1}, // 11110ddd dddddddd + {TEMPERATURE, 0, 0, 6, 0, 1}, // 111110dd dddddddd + {ALARMS, 1, 0, 7, 1, 1}, // 1111110d dddddddd + {TIME, 1, 0, 8, 0, 1}, // 11111110 dddddddd + {DEPTH, 1, 0, 9, 1, 2}, // 11111111 0ddddddd dddddddd dddddddd + {PRESSURE, 1, 0, 10, 1, 2}, // 11111111 10dddddd dddddddd dddddddd + {TEMPERATURE, 1, 0, 11, 1, 2}, // 11111111 110ddddd dddddddd dddddddd + {RBT, 1, 0, 12, 1, 1}, // 11111111 1110dddd dddddddd +}; + +static const +uwatec_smart_sample_info_t uwatec_smart_tec_samples[] = { + {PRESSURE_DEPTH, 0, 0, 1, 0, 1}, // 0ddddddd dddddddd + {RBT, 0, 0, 2, 0, 0}, // 10dddddd + {TEMPERATURE, 0, 0, 3, 0, 0}, // 110ddddd + {PRESSURE, 0, 0, 4, 0, 1}, // 1110dddd dddddddd + {DEPTH, 0, 0, 5, 0, 1}, // 11110ddd dddddddd + {TEMPERATURE, 0, 0, 6, 0, 1}, // 111110dd dddddddd + {ALARMS, 1, 0, 7, 1, 1}, // 1111110d dddddddd + {TIME, 1, 0, 8, 0, 1}, // 11111110 dddddddd + {DEPTH, 1, 0, 9, 1, 2}, // 11111111 0ddddddd dddddddd dddddddd + {TEMPERATURE, 1, 0, 10, 1, 2}, // 11111111 10dddddd dddddddd dddddddd + {PRESSURE, 1, 0, 11, 1, 2}, // 11111111 110ddddd dddddddd dddddddd + {PRESSURE, 1, 1, 12, 1, 2}, // 11111111 1110dddd dddddddd dddddddd + {PRESSURE, 1, 2, 13, 1, 2}, // 11111111 11110ddd dddddddd dddddddd + {RBT, 1, 0, 14, 1, 1}, // 11111111 111110dd dddddddd +}; + dc_status_t uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned int model, unsigned int devtime, dc_ticks_t systime) @@ -90,6 +257,56 @@ uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i parser->model = model; parser->devtime = devtime; parser->systime = systime; + switch (model) { + case SMARTPRO: + parser->headersize = 92; + parser->header = &uwatec_smart_pro_header; + parser->samples = uwatec_smart_pro_samples; + parser->nsamples = C_ARRAY_SIZE (uwatec_smart_pro_samples); + break; + case GALILEO: + case GALILEOTRIMIX: + case ALADIN2G: + case MERIDIAN: + parser->headersize = 152; + parser->header = &uwatec_smart_galileo_header; + parser->samples = uwatec_smart_galileo_samples; + parser->nsamples = C_ARRAY_SIZE (uwatec_smart_galileo_samples); + break; + case ALADINTEC: + parser->headersize = 108; + parser->header = &uwatec_smart_aladin_tec_header; + parser->samples = uwatec_smart_aladin_samples; + parser->nsamples = C_ARRAY_SIZE (uwatec_smart_aladin_samples); + break; + case ALADINTEC2G: + parser->headersize = 116; + parser->header = &uwatec_smart_aladin_tec2g_header; + parser->samples = uwatec_smart_aladin_samples; + parser->nsamples = C_ARRAY_SIZE (uwatec_smart_aladin_samples); + break; + case SMARTCOM: + parser->headersize = 100; + parser->header = &uwatec_smart_com_header; + parser->samples = uwatec_smart_com_samples; + parser->nsamples = C_ARRAY_SIZE (uwatec_smart_com_samples); + break; + case SMARTTEC: + parser->headersize = 132; + parser->header = &uwatec_smart_tec_header; + parser->samples = uwatec_smart_tec_samples; + parser->nsamples = C_ARRAY_SIZE (uwatec_smart_tec_samples); + break; + case SMARTZ: + parser->headersize = 132; + parser->header = &uwatec_smart_z_header; + parser->samples = uwatec_smart_tec_samples; + parser->nsamples = C_ARRAY_SIZE (uwatec_smart_tec_samples); + break; + default: + free (parser); + return DC_STATUS_INVALIDARGS; + } *out = (dc_parser_t*) parser; @@ -132,61 +349,6 @@ uwatec_smart_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime return DC_STATUS_SUCCESS; } -typedef struct uwatec_smart_header_info_t { - unsigned int maxdepth; - unsigned int divetime; - unsigned int gasmix; - unsigned int ngases; -} uwatec_smart_header_info_t; - -static const -uwatec_smart_header_info_t uwatec_smart_pro_header = { - 18, - 20, - 24, 1 -}; - -static const -uwatec_smart_header_info_t uwatec_smart_aladin_header = { - 22, - 24, - 30, 1 -}; - -static const -uwatec_smart_header_info_t uwatec_smart_aladin_tec2g_header = { - 22, - 26, - 32, 3 -}; - -static const -uwatec_smart_header_info_t uwatec_smart_com_header = { - 18, - 20, - 24, 1 -}; - -static const -uwatec_smart_header_info_t uwatec_smart_tec_header = { - 18, - 20, - 28, 3 -}; - -static const -uwatec_smart_header_info_t uwatec_smart_z_header = { - 18, - 20, - 28, 1 -}; - -static const -uwatec_smart_header_info_t uwatec_galileo_sol_header = { - 22, - 26, - 44, 3 -}; static dc_status_t uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value) @@ -196,49 +358,15 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi const unsigned char *data = abstract->data; unsigned int size = abstract->size; - unsigned int header = 0; + const uwatec_smart_header_info_t *table = parser->header; + unsigned int header = parser->headersize; unsigned int trimix = 0; - const uwatec_smart_header_info_t *table = NULL; - // Load the correct table. - switch (parser->model) { - case SMARTPRO: - header = 92; - table = &uwatec_smart_pro_header; - break; - case GALILEO: - case GALILEOTRIMIX: - case ALADIN2G: - case MERIDIAN: - header = 152; + if (parser->model == GALILEOTRIMIX) { if (data[43] & 0x80) { header = 0xB1; trimix = 1; } - table = &uwatec_galileo_sol_header; - break; - case ALADINTEC: - header = 108; - table = &uwatec_smart_aladin_header; - break; - case ALADINTEC2G: - header = 116; - table = &uwatec_smart_aladin_tec2g_header; - break; - case SMARTCOM: - header = 100; - table = &uwatec_smart_com_header; - break; - case SMARTTEC: - header = 132; - table = &uwatec_smart_tec_header; - break; - case SMARTZ: - header = 132; - table = &uwatec_smart_z_header; - break; - default: - return DC_STATUS_DATAFORMAT; } if (size < header) @@ -331,111 +459,6 @@ uwatec_smart_fixsignbit (unsigned int x, unsigned int n) } -typedef enum { - PRESSURE_DEPTH, - RBT, - TEMPERATURE, - PRESSURE, - DEPTH, - HEARTRATE, - BEARING, - ALARMS, - TIME, - UNKNOWN1, - UNKNOWN2, -} uwatec_smart_sample_t; - -typedef struct uwatec_smart_sample_info_t { - uwatec_smart_sample_t type; - unsigned int absolute; - unsigned int index; - unsigned int ntypebits; - unsigned int ignoretype; - unsigned int extrabytes; -} uwatec_smart_sample_info_t; - -static const -uwatec_smart_sample_info_t uwatec_smart_pro_table [] = { - {DEPTH, 0, 0, 1, 0, 0}, // 0ddddddd - {TEMPERATURE, 0, 0, 2, 0, 0}, // 10dddddd - {TIME, 1, 0, 3, 0, 0}, // 110ddddd - {ALARMS, 1, 0, 4, 0, 0}, // 1110dddd - {DEPTH, 0, 0, 5, 0, 1}, // 11110ddd dddddddd - {TEMPERATURE, 0, 0, 6, 0, 1}, // 111110dd dddddddd - {DEPTH, 1, 0, 7, 1, 2}, // 1111110d dddddddd dddddddd - {TEMPERATURE, 1, 0, 8, 0, 2}, // 11111110 dddddddd dddddddd -}; - -static const -uwatec_smart_sample_info_t uwatec_smart_aladin_table [] = { - {DEPTH, 0, 0, 1, 0, 0}, // 0ddddddd - {TEMPERATURE, 0, 0, 2, 0, 0}, // 10dddddd - {TIME, 1, 0, 3, 0, 0}, // 110ddddd - {ALARMS, 1, 0, 4, 0, 0}, // 1110dddd - {DEPTH, 0, 0, 5, 0, 1}, // 11110ddd dddddddd - {TEMPERATURE, 0, 0, 6, 0, 1}, // 111110dd dddddddd - {DEPTH, 1, 0, 7, 1, 2}, // 1111110d dddddddd dddddddd - {TEMPERATURE, 1, 0, 8, 0, 2}, // 11111110 dddddddd dddddddd - {ALARMS, 1, 1, 9, 0, 0}, // 11111111 0ddddddd -}; - -static const -uwatec_smart_sample_info_t uwatec_smart_com_table [] = { - {PRESSURE_DEPTH, 0, 0, 1, 0, 1}, // 0ddddddd dddddddd - {RBT, 0, 0, 2, 0, 0}, // 10dddddd - {TEMPERATURE, 0, 0, 3, 0, 0}, // 110ddddd - {PRESSURE, 0, 0, 4, 0, 1}, // 1110dddd dddddddd - {DEPTH, 0, 0, 5, 0, 1}, // 11110ddd dddddddd - {TEMPERATURE, 0, 0, 6, 0, 1}, // 111110dd dddddddd - {ALARMS, 1, 0, 7, 1, 1}, // 1111110d dddddddd - {TIME, 1, 0, 8, 0, 1}, // 11111110 dddddddd - {DEPTH, 1, 0, 9, 1, 2}, // 11111111 0ddddddd dddddddd dddddddd - {PRESSURE, 1, 0, 10, 1, 2}, // 11111111 10dddddd dddddddd dddddddd - {TEMPERATURE, 1, 0, 11, 1, 2}, // 11111111 110ddddd dddddddd dddddddd - {RBT, 1, 0, 12, 1, 1}, // 11111111 1110dddd dddddddd -}; - -static const -uwatec_smart_sample_info_t uwatec_smart_tec_table [] = { - {PRESSURE_DEPTH, 0, 0, 1, 0, 1}, // 0ddddddd dddddddd - {RBT, 0, 0, 2, 0, 0}, // 10dddddd - {TEMPERATURE, 0, 0, 3, 0, 0}, // 110ddddd - {PRESSURE, 0, 0, 4, 0, 1}, // 1110dddd dddddddd - {DEPTH, 0, 0, 5, 0, 1}, // 11110ddd dddddddd - {TEMPERATURE, 0, 0, 6, 0, 1}, // 111110dd dddddddd - {ALARMS, 1, 0, 7, 1, 1}, // 1111110d dddddddd - {TIME, 1, 0, 8, 0, 1}, // 11111110 dddddddd - {DEPTH, 1, 0, 9, 1, 2}, // 11111111 0ddddddd dddddddd dddddddd - {TEMPERATURE, 1, 0, 10, 1, 2}, // 11111111 10dddddd dddddddd dddddddd - {PRESSURE, 1, 0, 11, 1, 2}, // 11111111 110ddddd dddddddd dddddddd - {PRESSURE, 1, 1, 12, 1, 2}, // 11111111 1110dddd dddddddd dddddddd - {PRESSURE, 1, 2, 13, 1, 2}, // 11111111 11110ddd dddddddd dddddddd - {RBT, 1, 0, 14, 1, 1}, // 11111111 111110dd dddddddd -}; - -static const -uwatec_smart_sample_info_t uwatec_galileo_sol_table [] = { - {DEPTH, 0, 0, 1, 0, 0}, // 0ddd dddd - {RBT, 0, 0, 3, 0, 0}, // 100d dddd - {PRESSURE, 0, 0, 4, 0, 0}, // 1010 dddd - {TEMPERATURE, 0, 0, 4, 0, 0}, // 1011 dddd - {TIME, 1, 0, 4, 0, 0}, // 1100 dddd - {HEARTRATE, 0, 0, 4, 0, 0}, // 1101 dddd - {ALARMS, 1, 0, 4, 0, 0}, // 1110 dddd - {ALARMS, 1, 1, 8, 0, 1}, // 1111 0000 dddddddd - {DEPTH, 1, 0, 8, 0, 2}, // 1111 0001 dddddddd dddddddd - {RBT, 1, 0, 8, 0, 1}, // 1111 0010 dddddddd - {TEMPERATURE, 1, 0, 8, 0, 2}, // 1111 0011 dddddddd dddddddd - {PRESSURE, 1, 0, 8, 0, 2}, // 1111 0100 dddddddd dddddddd - {PRESSURE, 1, 1, 8, 0, 2}, // 1111 0101 dddddddd dddddddd - {PRESSURE, 1, 2, 8, 0, 2}, // 1111 0110 dddddddd dddddddd - {HEARTRATE, 1, 0, 8, 0, 1}, // 1111 0111 dddddddd - {BEARING, 1, 0, 8, 0, 2}, // 1111 1000 dddddddd dddddddd - {ALARMS, 1, 2, 8, 0, 1}, // 1111 1001 dddddddd - {UNKNOWN1, 1, 0, 8, 0, 0}, // 1111 1010 (8 bytes) - {UNKNOWN2, 1, 0, 8, 0, 1}, // 1111 1011 dddddddd (n-1 bytes) -}; - static dc_status_t uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata) { @@ -444,53 +467,16 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t const unsigned char *data = abstract->data; unsigned int size = abstract->size; - const uwatec_smart_sample_info_t *table = NULL; - unsigned int entries = 0; - unsigned int header = 0; + const uwatec_smart_sample_info_t *table = parser->samples; + unsigned int entries = parser->nsamples; + unsigned int header = parser->headersize; unsigned int trimix = 0; - // Load the correct table. - switch (parser->model) { - case SMARTPRO: - header = 92; - table = uwatec_smart_pro_table; - entries = NELEMENTS (uwatec_smart_pro_table); - break; - case GALILEO: - case GALILEOTRIMIX: - case ALADIN2G: - case MERIDIAN: - header = 152; + if (parser->model == GALILEOTRIMIX) { if (data[43] & 0x80) { header = 0xB1; trimix = 1; } - table = uwatec_galileo_sol_table; - entries = NELEMENTS (uwatec_galileo_sol_table); - break; - case ALADINTEC: - header = 108; - table = uwatec_smart_aladin_table; - entries = NELEMENTS (uwatec_smart_aladin_table); - break; - case ALADINTEC2G: - header = 116; - table = uwatec_smart_aladin_table; - entries = NELEMENTS (uwatec_smart_aladin_table); - break; - case SMARTCOM: - header = 100; - table = uwatec_smart_com_table; - entries = NELEMENTS (uwatec_smart_com_table); - break; - case SMARTTEC: - case SMARTZ: - header = 132; - table = uwatec_smart_tec_table; - entries = NELEMENTS (uwatec_smart_tec_table); - break; - default: - return DC_STATUS_DATAFORMAT; } // Get the maximum number of alarm bytes. From 3536086015ac07b4104d2d0aee7ca3ee067bd8a1 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Sat, 19 Oct 2013 21:48:00 +0200 Subject: [PATCH 2/6] Check the buffer size before using the data. For the Galileo Trimix, the header length isn't fixed. The actual length depends on whether the dive has the trimix setting enabled or not. Because at this point we're still trying to determine the length of the header, it hasn't been checked yet and an extra check is necessary. --- src/uwatec_smart_parser.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index 5f571bb..addc295 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -363,6 +363,9 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi unsigned int trimix = 0; if (parser->model == GALILEOTRIMIX) { + if (size < 44) + return DC_STATUS_DATAFORMAT; + if (data[43] & 0x80) { header = 0xB1; trimix = 1; @@ -473,6 +476,9 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t unsigned int trimix = 0; if (parser->model == GALILEOTRIMIX) { + if (size < 44) + return DC_STATUS_DATAFORMAT; + if (data[43] & 0x80) { header = 0xB1; trimix = 1; From b9e8fdcb529ef429c41dc6ea877d40953b271454 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Mon, 21 Oct 2013 20:56:15 +0200 Subject: [PATCH 3/6] Use the same tables for the Uwatec Smart Tec and Z. Internal, these two models use exactly the same data format. For those features which are only available on one of the models, the corresponding data fields are set to their unused values. For example, the Smart Tec supports up to three gasmixes, while the Smart Z supports only one gasmix. But although the Smart Z has storage reserved for up to three gas mixes, only the first one is ever used. --- src/uwatec_smart_parser.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index addc295..6d6df03 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -146,13 +146,6 @@ uwatec_smart_header_info_t uwatec_smart_tec_header = { 28, 3 }; -static const -uwatec_smart_header_info_t uwatec_smart_z_header = { - 18, - 20, - 28, 1 -}; - static const uwatec_smart_sample_info_t uwatec_smart_pro_samples[] = { {DEPTH, 0, 0, 1, 0, 0}, // 0ddddddd @@ -292,14 +285,9 @@ uwatec_smart_parser_create (dc_parser_t **out, dc_context_t *context, unsigned i parser->nsamples = C_ARRAY_SIZE (uwatec_smart_com_samples); break; case SMARTTEC: - parser->headersize = 132; - parser->header = &uwatec_smart_tec_header; - parser->samples = uwatec_smart_tec_samples; - parser->nsamples = C_ARRAY_SIZE (uwatec_smart_tec_samples); - break; case SMARTZ: parser->headersize = 132; - parser->header = &uwatec_smart_z_header; + parser->header = &uwatec_smart_tec_header; parser->samples = uwatec_smart_tec_samples; parser->nsamples = C_ARRAY_SIZE (uwatec_smart_tec_samples); break; From 48661ce7a8a203729dc1761fe98d551b273412b0 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 22 Oct 2013 21:35:56 +0200 Subject: [PATCH 4/6] Fix the gasmix offset for the Aladin Tec 2G. --- src/uwatec_smart_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index 6d6df03..1d4b715 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -129,7 +129,7 @@ static const uwatec_smart_header_info_t uwatec_smart_aladin_tec2g_header = { 22, 26, - 32, 3 + 34, 3 }; static const From 68f97e907a036dc207058b83d46e4cedde3ddf0d Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 22 Oct 2013 22:19:28 +0200 Subject: [PATCH 5/6] Use only one byte for the oxygen percentage. One byte is already more than sufficient to store an oxygen percentage. Using two bytes doesn't cause any problems for some models, because the upper byte is always zero, but for other models that's not the case. Most likely this upper byte is used to store something else. --- src/uwatec_smart_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index 1d4b715..104481e 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -381,7 +381,7 @@ uwatec_smart_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi break; case DC_FIELD_GASMIX: gasmix->helium = 0.0; - gasmix->oxygen = array_uint16_le (data + table->gasmix + flags * 2) / 100.0; + gasmix->oxygen = data[table->gasmix + flags * 2] / 100.0; gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium; break; default: From 861b5652e0d42d08126e1c7f05fefa52d8401c88 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 23 Jan 2014 13:36:02 +0100 Subject: [PATCH 6/6] Add support for parsing gas changes. Parsing the gas switch events is somewhat complicated, because depending on the actual model, they can be stored in different ways. The table below lists the number of gas mixes (G), tanks (T) and alarm bytes (A) supported by each model. Note that only the representative model in each group is listed. Model | G | T | A ==============|===|===|=== Pro | 1 | 0 | 1 Com | 1 | 1 | 1 Tec | 3 | 3 | 1 Aladin Tec | 1 | 0 | 2 Aladin Tec 2G | 3 | 0 | 2 Galileo | 3 | 3 | 3 Models without support for multiple gasmixes only need to set the initial gas mix correctly. Models with support for one or more tank pressure sensors can link the gas switches to the tank switches. Models with at least two alarm bytes can store a gas switch event in the second alarm byte. As can be observed from the table, some models can use several different methods to store the gas switches. The current implementation supports all of them. In the case of a conflict, the last used method always takes precedence. That's simply due to the fact that each method just sets the gasmix index, and only the final value is used. If this approach turns out to produce wrong results, it can always be fixed later. The initial gasmix is always assumed to be the first configured gasmix. --- src/uwatec_smart_parser.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/uwatec_smart_parser.c b/src/uwatec_smart_parser.c index 104481e..dd4734e 100644 --- a/src/uwatec_smart_parser.c +++ b/src/uwatec_smart_parser.c @@ -483,12 +483,20 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t } } + // Get all the gas mixes. + unsigned int oxygen[3] = {0}; + unsigned int ngasmix = (trimix ? 0 : parser->header->ngases); + for (unsigned int i = 0; i < ngasmix; ++i) { + oxygen[i] = data[parser->header->gasmix + i * 2]; + } + int complete = 0; int calibrated = 0; unsigned int time = 0; unsigned int rbt = 99; unsigned int tank = 0; + unsigned int gasmix = 0; double depth = 0, depth_calibration = 0; double temperature = 0; double pressure = 0; @@ -496,6 +504,9 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t unsigned int bearing = 0; unsigned char alarms[3] = {0, 0, 0}; + // Previous gas mix - initialize with impossible value + unsigned int gasmix_previous = 0xFFFFFFFF; + int have_depth = 0, have_temperature = 0, have_pressure = 0, have_rbt = 0, have_heartrate = 0, have_alarms = 0, have_bearing = 0; @@ -587,6 +598,7 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t pressure = value / 4.0; } have_pressure = 1; + gasmix = tank; } else { pressure += svalue / 4.0; } @@ -619,6 +631,13 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t case ALARMS: alarms[table[id].index] = value; have_alarms = 1; + if (table[id].index == 1) { + if (parser->model == ALADINTEC || parser->model == ALADINTEC2G) { + gasmix = (value & 0x18) >> 3; + } else { + gasmix = (value & 0x30) >> 4; + } + } break; case TIME: complete = value; @@ -646,6 +665,17 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t sample.time = time; if (callback) callback (DC_SAMPLE_TIME, sample, userdata); + if (gasmix != gasmix_previous && !trimix) { + if (gasmix >= ngasmix) + return DC_STATUS_DATAFORMAT; + sample.event.type = SAMPLE_EVENT_GASCHANGE; + sample.event.time = 0; + sample.event.flags = 0; + sample.event.value = oxygen[gasmix]; + if (callback) callback (DC_SAMPLE_EVENT, sample, userdata); + gasmix_previous = gasmix; + } + if (have_temperature) { sample.temperature = temperature; if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);