Merge branch 'shearwater'
This commit is contained in:
commit
bedd6180f1
12
src/array.c
12
src/array.c
@ -160,6 +160,18 @@ array_convert_str2num (const unsigned char data[], unsigned int size)
|
||||
return value;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
array_convert_bcd2dec (const unsigned char data[], unsigned int size)
|
||||
{
|
||||
unsigned int value = 0;
|
||||
for (unsigned int i = 0; i < size; ++i) {
|
||||
value *= 100;
|
||||
value += bcd2dec(data[i]);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
array_uint_be (const unsigned char data[], unsigned int n)
|
||||
{
|
||||
|
||||
@ -52,6 +52,9 @@ array_convert_hex2bin (const unsigned char input[], unsigned int isize, unsigned
|
||||
unsigned int
|
||||
array_convert_str2num (const unsigned char data[], unsigned int size);
|
||||
|
||||
unsigned int
|
||||
array_convert_bcd2dec (const unsigned char data[], unsigned int size);
|
||||
|
||||
unsigned int
|
||||
array_uint_be (const unsigned char data[], unsigned int n);
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libdivecomputer/units.h>
|
||||
|
||||
@ -52,6 +53,7 @@
|
||||
#define LOG_RECORD_CLOSING_6 0x26
|
||||
#define LOG_RECORD_CLOSING_7 0x27
|
||||
#define LOG_RECORD_INFO_EVENT 0x30
|
||||
#define LOG_RECORD_DIVE_SAMPLE_EXT 0xE1
|
||||
#define LOG_RECORD_FINAL 0xFF
|
||||
|
||||
#define INFO_EVENT_TAG_LOG 38
|
||||
@ -67,15 +69,25 @@
|
||||
#define SC 0x08
|
||||
#define OC 0x10
|
||||
|
||||
#define M_CC 0
|
||||
#define M_OC_TEC 1
|
||||
#define M_GAUGE 2
|
||||
#define M_PPO2 3
|
||||
#define M_SC 4
|
||||
#define M_CC2 5
|
||||
#define M_OC_REC 6
|
||||
#define M_FREEDIVE 7
|
||||
|
||||
#define METRIC 0
|
||||
#define IMPERIAL 1
|
||||
|
||||
#define NGASMIXES 10
|
||||
#define NTANKS 2
|
||||
#define NTANKS 4
|
||||
#define NRECORDS 8
|
||||
|
||||
#define PREDATOR 2
|
||||
#define PETREL 3
|
||||
#define TERIC 8
|
||||
|
||||
#define UNDEFINED 0xFFFFFFFF
|
||||
|
||||
@ -88,8 +100,13 @@ typedef struct shearwater_predator_gasmix_t {
|
||||
|
||||
typedef struct shearwater_predator_tank_t {
|
||||
unsigned int enabled;
|
||||
unsigned int active;
|
||||
unsigned int beginpressure;
|
||||
unsigned int endpressure;
|
||||
unsigned int pressure_max;
|
||||
unsigned int pressure_reserve;
|
||||
unsigned int serial;
|
||||
char name[2];
|
||||
} shearwater_predator_tank_t;
|
||||
|
||||
struct shearwater_predator_parser_t {
|
||||
@ -113,7 +130,7 @@ struct shearwater_predator_parser_t {
|
||||
unsigned int tankidx[NTANKS];
|
||||
unsigned int calibrated;
|
||||
double calibration[3];
|
||||
dc_divemode_t mode;
|
||||
unsigned int divemode;
|
||||
unsigned int units;
|
||||
unsigned int atmospheric;
|
||||
unsigned int density;
|
||||
@ -208,15 +225,20 @@ shearwater_common_parser_create (dc_parser_t **out, dc_context_t *context, unsig
|
||||
parser->ntanks = 0;
|
||||
for (unsigned int i = 0; i < NTANKS; ++i) {
|
||||
parser->tank[i].enabled = 0;
|
||||
parser->tank[i].active = 0;
|
||||
parser->tank[i].beginpressure = 0;
|
||||
parser->tank[i].endpressure = 0;
|
||||
parser->tank[i].pressure_max = 0;
|
||||
parser->tank[i].pressure_reserve = 0;
|
||||
parser->tank[i].serial = 0;
|
||||
memset (parser->tank[i].name, 0, sizeof (parser->tank[i].name));
|
||||
parser->tankidx[i] = i;
|
||||
}
|
||||
parser->calibrated = 0;
|
||||
for (unsigned int i = 0; i < 3; ++i) {
|
||||
parser->calibration[i] = 0.0;
|
||||
}
|
||||
parser->mode = DC_DIVEMODE_OC;
|
||||
parser->divemode = M_OC_TEC;
|
||||
parser->units = METRIC;
|
||||
parser->density = 1025;
|
||||
parser->atmospheric = ATM / (BAR / 1000);
|
||||
@ -265,15 +287,20 @@ shearwater_predator_parser_set_data (dc_parser_t *abstract, const unsigned char
|
||||
parser->ntanks = 0;
|
||||
for (unsigned int i = 0; i < NTANKS; ++i) {
|
||||
parser->tank[i].enabled = 0;
|
||||
parser->tank[i].active = 0;
|
||||
parser->tank[i].beginpressure = 0;
|
||||
parser->tank[i].endpressure = 0;
|
||||
parser->tank[i].pressure_max = 0;
|
||||
parser->tank[i].pressure_reserve = 0;
|
||||
parser->tank[i].serial = 0;
|
||||
memset (parser->tank[i].name, 0, sizeof (parser->tank[i].name));
|
||||
parser->tankidx[i] = i;
|
||||
}
|
||||
parser->calibrated = 0;
|
||||
for (unsigned int i = 0; i < 3; ++i) {
|
||||
parser->calibration[i] = 0.0;
|
||||
}
|
||||
parser->mode = DC_DIVEMODE_OC;
|
||||
parser->divemode = M_OC_TEC;
|
||||
parser->units = METRIC;
|
||||
parser->density = 1025;
|
||||
parser->atmospheric = ATM / (BAR / 1000);
|
||||
@ -298,7 +325,13 @@ shearwater_predator_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *d
|
||||
if (!dc_datetime_gmtime (datetime, ticks))
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
|
||||
datetime->timezone = DC_TIMEZONE_NONE;
|
||||
if (parser->model == TERIC && parser->logversion >= 9 && parser->opening[5] != UNDEFINED) {
|
||||
int utc_offset = (int) array_uint32_be (data + parser->opening[5] + 26);
|
||||
int dst = data[parser->opening[5] + 30];
|
||||
datetime->timezone = utc_offset * 60 + dst * 3600;
|
||||
} else {
|
||||
datetime->timezone = DC_TIMEZONE_NONE;
|
||||
}
|
||||
|
||||
return DC_STATUS_SUCCESS;
|
||||
}
|
||||
@ -357,7 +390,7 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
||||
// byte opening and closing block. To minimize the differences
|
||||
// with the PNF format, all record offsets are assigned the same
|
||||
// value here.
|
||||
for (unsigned int i = 0; i < NRECORDS; ++i) {
|
||||
for (unsigned int i = 0; i <= 4; ++i) {
|
||||
parser->opening[i] = 0;
|
||||
parser->closing[i] = size - footersize;
|
||||
}
|
||||
@ -367,7 +400,7 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
||||
}
|
||||
|
||||
// Default dive mode.
|
||||
dc_divemode_t mode = DC_DIVEMODE_OC;
|
||||
unsigned int divemode = M_OC_TEC;
|
||||
|
||||
// Get the gas mixes.
|
||||
unsigned int ngasmixes = 0;
|
||||
@ -391,7 +424,7 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
||||
// Status flags.
|
||||
unsigned int status = data[offset + 11 + pnf];
|
||||
if ((status & OC) == 0) {
|
||||
mode = DC_DIVEMODE_CCR;
|
||||
divemode = status & SC ? M_SC : M_CC;
|
||||
}
|
||||
|
||||
// Gaschange.
|
||||
@ -423,8 +456,8 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
||||
|
||||
// Tank pressure
|
||||
if (logversion >= 7) {
|
||||
const unsigned int idx[NTANKS] = {27, 19};
|
||||
for (unsigned int i = 0; i < NTANKS; ++i) {
|
||||
const unsigned int idx[2] = {27, 19};
|
||||
for (unsigned int i = 0; i < 2; ++i) {
|
||||
// Values above 0xFFF0 are special codes:
|
||||
// 0xFFFF AI is off
|
||||
// 0xFFFE No comms for 90 seconds+
|
||||
@ -436,8 +469,8 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
||||
unsigned int pressure = array_uint16_be (data + offset + pnf + idx[i]);
|
||||
if (pressure < 0xFFF0) {
|
||||
pressure &= 0x0FFF;
|
||||
if (!tank[i].enabled) {
|
||||
tank[i].enabled = 1;
|
||||
if (!tank[i].active) {
|
||||
tank[i].active = 1;
|
||||
tank[i].beginpressure = pressure;
|
||||
tank[i].endpressure = pressure;
|
||||
}
|
||||
@ -445,16 +478,82 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (type == LOG_RECORD_DIVE_SAMPLE_EXT) {
|
||||
// Tank pressure
|
||||
if (logversion >= 13) {
|
||||
for (unsigned int i = 0; i < 2; ++i) {
|
||||
unsigned int pressure = array_uint16_be (data + offset + pnf + i * 2);
|
||||
if (pressure < 0xFFF0) {
|
||||
pressure &= 0x0FFF;
|
||||
if (!tank[i + 2].active) {
|
||||
tank[i + 2].active = 1;
|
||||
tank[i + 2].beginpressure = pressure;
|
||||
tank[i + 2].endpressure = pressure;
|
||||
}
|
||||
tank[i + 2].endpressure = pressure;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (type == LOG_RECORD_FREEDIVE_SAMPLE) {
|
||||
// Freedive record
|
||||
mode = DC_DIVEMODE_FREEDIVE;
|
||||
divemode = M_FREEDIVE;
|
||||
} else if (type >= LOG_RECORD_OPENING_0 && type <= LOG_RECORD_OPENING_7) {
|
||||
// Opening record
|
||||
parser->opening[type - LOG_RECORD_OPENING_0] = offset;
|
||||
|
||||
// Log version
|
||||
if (type == LOG_RECORD_OPENING_4) {
|
||||
// Log version
|
||||
logversion = data[offset + 16];
|
||||
|
||||
// Air integration mode
|
||||
if (logversion >= 7) {
|
||||
unsigned int airmode = data[offset + 28];
|
||||
if (logversion < 13) {
|
||||
if (airmode == 1 || airmode == 2) {
|
||||
tank[airmode - 1].enabled = 1;
|
||||
} else if (airmode == 3) {
|
||||
tank[0].enabled = 1;
|
||||
tank[1].enabled = 1;
|
||||
}
|
||||
}
|
||||
if (airmode == 4) {
|
||||
tank[0].enabled = 1;
|
||||
tank[1].enabled = 1;
|
||||
}
|
||||
}
|
||||
} else if (type == LOG_RECORD_OPENING_5) {
|
||||
if (logversion >= 9) {
|
||||
tank[0].serial = array_convert_bcd2dec (data + offset + 1, 3);
|
||||
tank[0].pressure_max = array_uint16_be(data + offset + 6);
|
||||
tank[0].pressure_reserve = array_uint16_be(data + offset + 8);
|
||||
|
||||
tank[1].serial = array_convert_bcd2dec(data + offset + 10, 3);
|
||||
tank[1].pressure_max = array_uint16_be(data + offset + 15);
|
||||
tank[1].pressure_reserve = array_uint16_be(data + offset + 17);
|
||||
}
|
||||
} else if (type == LOG_RECORD_OPENING_6) {
|
||||
if (logversion >= 13) {
|
||||
tank[0].enabled = data[offset + 19];
|
||||
memcpy (tank[0].name, data + offset + 20, sizeof (tank[0].name));
|
||||
|
||||
tank[1].enabled = data[offset + 22];
|
||||
memcpy (tank[1].name, data + offset + 23, sizeof (tank[1].name));
|
||||
|
||||
tank[2].serial = array_convert_bcd2dec(data + offset + 25, 3);
|
||||
tank[2].pressure_max = array_uint16_be(data + offset + 28);
|
||||
tank[2].pressure_reserve = array_uint16_be(data + offset + 30);
|
||||
}
|
||||
} else if (type == LOG_RECORD_OPENING_7) {
|
||||
if (logversion >= 13) {
|
||||
tank[2].enabled = data[offset + 1];
|
||||
memcpy (tank[2].name, data + offset + 2, sizeof (tank[2].name));
|
||||
|
||||
tank[3].serial = array_convert_bcd2dec(data + offset + 4, 3);
|
||||
tank[3].pressure_max = array_uint16_be(data + offset + 7);
|
||||
tank[3].pressure_reserve = array_uint16_be(data + offset + 9);
|
||||
tank[3].enabled = data[offset + 11];
|
||||
memcpy (tank[3].name, data + offset + 12, sizeof (tank[3].name));
|
||||
}
|
||||
}
|
||||
} else if (type >= LOG_RECORD_CLOSING_0 && type <= LOG_RECORD_CLOSING_7) {
|
||||
// Closing record
|
||||
@ -510,6 +609,26 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
||||
parser->calibrated = data[base];
|
||||
}
|
||||
|
||||
// Get the dive mode from the header (if available).
|
||||
if (logversion >= 8) {
|
||||
divemode = data[parser->opening[4] + (pnf ? 1 : 112)];
|
||||
}
|
||||
|
||||
// Get the correct model number from the final block.
|
||||
if (parser->final != UNDEFINED) {
|
||||
parser->model = data[parser->final + 13];
|
||||
}
|
||||
|
||||
// Fix the Teric tank serial number.
|
||||
if (parser->model == TERIC) {
|
||||
for (unsigned int i = 0; i < NTANKS; ++i) {
|
||||
tank[i].serial =
|
||||
((tank[i].serial / 10000) % 100) +
|
||||
((tank[i].serial / 100) % 100) * 100 +
|
||||
((tank[i].serial ) % 100) * 10000;
|
||||
}
|
||||
}
|
||||
|
||||
// Cache the data for later use.
|
||||
parser->pnf = pnf;
|
||||
parser->logversion = logversion;
|
||||
@ -521,7 +640,7 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
||||
}
|
||||
parser->ntanks = 0;
|
||||
for (unsigned int i = 0; i < NTANKS; ++i) {
|
||||
if (tank[i].enabled) {
|
||||
if (tank[i].active) {
|
||||
parser->tankidx[i] = parser->ntanks;
|
||||
parser->tank[parser->ntanks] = tank[i];
|
||||
parser->ntanks++;
|
||||
@ -529,7 +648,7 @@ shearwater_predator_parser_cache (shearwater_predator_parser_t *parser)
|
||||
parser->tankidx[i] = UNDEFINED;
|
||||
}
|
||||
}
|
||||
parser->mode = mode;
|
||||
parser->divemode = divemode;
|
||||
parser->units = data[parser->opening[0] + 8];
|
||||
parser->atmospheric = array_uint16_be (data + parser->opening[1] + (parser->pnf ? 16 : 47));
|
||||
parser->density = array_uint16_be (data + parser->opening[3] + (parser->pnf ? 3 : 83));
|
||||
@ -600,7 +719,28 @@ shearwater_predator_parser_get_field (dc_parser_t *abstract, dc_field_type_t typ
|
||||
*((double *) value) = parser->atmospheric / 1000.0;
|
||||
break;
|
||||
case DC_FIELD_DIVEMODE:
|
||||
*((dc_divemode_t *) value) = parser->mode;
|
||||
switch (parser->divemode) {
|
||||
case M_CC:
|
||||
case M_CC2:
|
||||
*((dc_divemode_t *) value) = DC_DIVEMODE_CCR;
|
||||
break;
|
||||
case M_SC:
|
||||
*((dc_divemode_t *) value) = DC_DIVEMODE_SCR;
|
||||
break;
|
||||
case M_OC_TEC:
|
||||
case M_OC_REC:
|
||||
*((dc_divemode_t *) value) = DC_DIVEMODE_OC;
|
||||
break;
|
||||
case M_GAUGE:
|
||||
case M_PPO2:
|
||||
*((dc_divemode_t *) value) = DC_DIVEMODE_GAUGE;
|
||||
break;
|
||||
case M_FREEDIVE:
|
||||
*((dc_divemode_t *) value) = DC_DIVEMODE_FREEDIVE;
|
||||
break;
|
||||
default:
|
||||
return DC_STATUS_DATAFORMAT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return DC_STATUS_UNSUPPORTED;
|
||||
@ -758,8 +898,8 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
||||
// for logversion 7 and newer (introduced for Perdix AI)
|
||||
// detect tank pressure
|
||||
if (parser->logversion >= 7) {
|
||||
const unsigned int idx[NTANKS] = {27, 19};
|
||||
for (unsigned int i = 0; i < NTANKS; ++i) {
|
||||
const unsigned int idx[2] = {27, 19};
|
||||
for (unsigned int i = 0; i < 2; ++i) {
|
||||
// Tank pressure
|
||||
// Values above 0xFFF0 are special codes:
|
||||
// 0xFFFF AI is off
|
||||
@ -790,6 +930,19 @@ shearwater_predator_parser_samples_foreach (dc_parser_t *abstract, dc_sample_cal
|
||||
if (callback) callback (DC_SAMPLE_RBT, sample, userdata);
|
||||
}
|
||||
}
|
||||
} else if (type == LOG_RECORD_DIVE_SAMPLE_EXT) {
|
||||
// Tank pressure
|
||||
if (parser->logversion >= 13) {
|
||||
for (unsigned int i = 0; i < 2; ++i) {
|
||||
unsigned int pressure = array_uint16_be (data + offset + pnf + i * 2);
|
||||
if (pressure < 0xFFF0) {
|
||||
pressure &= 0x0FFF;
|
||||
sample.pressure.tank = parser->tankidx[i + 2];
|
||||
sample.pressure.value = pressure * 2 * PSI / BAR;
|
||||
if (callback) callback (DC_SAMPLE_PRESSURE, sample, userdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (type == LOG_RECORD_FREEDIVE_SAMPLE) {
|
||||
// A freedive record is actually 4 samples, each 8-bytes,
|
||||
// packed into a standard 32-byte sized record. At the end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user