Merge branch 'release-0.3'

Integrate the bugfixes from the stable branch.
This commit is contained in:
Jef Driesen 2013-05-13 22:46:30 +02:00
commit ee8b4e36ad
13 changed files with 156 additions and 31 deletions

View File

@ -245,7 +245,7 @@ sample_cb (dc_sample_type_t type, dc_sample_value_t value, void *userdata)
"OLF", "PO2", "airtime", "rgbm", "heading", "tissue level warning", "OLF", "PO2", "airtime", "rgbm", "heading", "tissue level warning",
"gaschange2"}; "gaschange2"};
static const char *decostop[] = { static const char *decostop[] = {
"ndl", "deco", "deep", "safety"}; "ndl", "safety", "deco", "deep"};
sample_data_t *sampledata = (sample_data_t *) userdata; sample_data_t *sampledata = (sample_data_t *) userdata;

View File

@ -124,6 +124,9 @@ cressi_leonardo_device_open (dc_device_t **out, dc_context_t *context, const cha
return DC_STATUS_IO; return DC_STATUS_IO;
} }
serial_sleep (device->port, 100);
serial_flush (device->port, SERIAL_QUEUE_BOTH);
*out = (dc_device_t *) device; *out = (dc_device_t *) device;
return DC_STATUS_SUCCESS; return DC_STATUS_SUCCESS;
@ -268,6 +271,13 @@ cressi_leonardo_device_foreach (dc_device_t *abstract, dc_dive_callback_t callba
return rc; return rc;
} }
unsigned char *data = dc_buffer_get_data (buffer);
dc_event_devinfo_t devinfo;
devinfo.model = 0;
devinfo.firmware = 0;
devinfo.serial = array_uint32_le (data + 1);
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);
rc = cressi_leonardo_extract_dives (abstract, dc_buffer_get_data (buffer), rc = cressi_leonardo_extract_dives (abstract, dc_buffer_get_data (buffer),
dc_buffer_get_size (buffer), callback, userdata); dc_buffer_get_size (buffer), callback, userdata);
@ -328,7 +338,7 @@ cressi_leonardo_extract_dives (dc_device_t *abstract, const unsigned char data[]
if (header < RB_PROFILE_BEGIN || header + 2 > RB_PROFILE_END || if (header < RB_PROFILE_BEGIN || header + 2 > RB_PROFILE_END ||
footer < RB_PROFILE_BEGIN || footer + 2 > RB_PROFILE_END) footer < RB_PROFILE_BEGIN || footer + 2 > RB_PROFILE_END)
{ {
ERROR (abstract->context, "Invalid ringbuffer pointer detected."); ERROR (context, "Invalid ringbuffer pointer detected.");
free (buffer); free (buffer);
return DC_STATUS_DATAFORMAT; return DC_STATUS_DATAFORMAT;
} }
@ -337,7 +347,7 @@ cressi_leonardo_extract_dives (dc_device_t *abstract, const unsigned char data[]
unsigned int header2 = array_uint16_le (data + footer); unsigned int header2 = array_uint16_le (data + footer);
unsigned int footer2 = array_uint16_le (data + header); unsigned int footer2 = array_uint16_le (data + header);
if (header2 != header || footer2 != footer) { if (header2 != header || footer2 != footer) {
ERROR (abstract->context, "Invalid ringbuffer pointer detected."); ERROR (context, "Invalid ringbuffer pointer detected.");
free (buffer); free (buffer);
return DC_STATUS_DATAFORMAT; return DC_STATUS_DATAFORMAT;
} }

View File

@ -76,20 +76,33 @@ static const dc_descriptor_t g_descriptors[] = {
{"Suunto", "D4i", DC_FAMILY_SUUNTO_D9, 0x19}, {"Suunto", "D4i", DC_FAMILY_SUUNTO_D9, 0x19},
{"Suunto", "D6i", DC_FAMILY_SUUNTO_D9, 0x1A}, {"Suunto", "D6i", DC_FAMILY_SUUNTO_D9, 0x1A},
{"Suunto", "D9tx", DC_FAMILY_SUUNTO_D9, 0x1B}, {"Suunto", "D9tx", DC_FAMILY_SUUNTO_D9, 0x1B},
{"Suunto", "DX", DC_FAMILY_SUUNTO_D9, 0x1C},
/* Uwatec Aladin */ /* Uwatec Aladin */
{"Uwatec", "Aladin", DC_FAMILY_UWATEC_ALADIN, 0}, {"Uwatec", "Aladin Air Twin", DC_FAMILY_UWATEC_ALADIN, 0x1C},
{"Uwatec", "Aladin Sport Plus", DC_FAMILY_UWATEC_ALADIN, 0x3E},
{"Uwatec", "Aladin Pro", DC_FAMILY_UWATEC_ALADIN, 0x3F},
{"Uwatec", "Aladin Air Z", DC_FAMILY_UWATEC_ALADIN, 0x44},
{"Uwatec", "Aladin Air Z O2", DC_FAMILY_UWATEC_ALADIN, 0xA4},
{"Uwatec", "Aladin Air Z Nitrox", DC_FAMILY_UWATEC_ALADIN, 0xF4},
{"Uwatec", "Aladin Pro Ultra", DC_FAMILY_UWATEC_ALADIN, 0xFF},
/* Uwatec Memomouse */ /* Uwatec Memomouse */
{"Uwatec", "Memomouse", DC_FAMILY_UWATEC_MEMOMOUSE, 0}, {"Uwatec", "Memomouse", DC_FAMILY_UWATEC_MEMOMOUSE, 0},
/* Uwatec Smart */ /* Uwatec Smart */
#ifdef HAVE_IRDA #ifdef HAVE_IRDA
{"Uwatec", "Smart Pro", DC_FAMILY_UWATEC_SMART, 0x10}, {"Uwatec", "Smart Pro", DC_FAMILY_UWATEC_SMART, 0x10},
{"Uwatec", "Galileo", DC_FAMILY_UWATEC_SMART, 0x11}, {"Uwatec", "Galileo Sol", DC_FAMILY_UWATEC_SMART, 0x11},
{"Uwatec", "Galileo Luna", DC_FAMILY_UWATEC_SMART, 0x11},
{"Uwatec", "Galileo Terra", DC_FAMILY_UWATEC_SMART, 0x11},
{"Uwatec", "Aladin Tec", DC_FAMILY_UWATEC_SMART, 0x12}, {"Uwatec", "Aladin Tec", DC_FAMILY_UWATEC_SMART, 0x12},
{"Uwatec", "Aladin Prime", DC_FAMILY_UWATEC_SMART, 0x12},
{"Uwatec", "Aladin Tec 2G", DC_FAMILY_UWATEC_SMART, 0x13}, {"Uwatec", "Aladin Tec 2G", DC_FAMILY_UWATEC_SMART, 0x13},
{"Uwatec", "Aladin 2G", DC_FAMILY_UWATEC_SMART, 0x13},
{"Subgear","XP-10", DC_FAMILY_UWATEC_SMART, 0x13},
{"Uwatec", "Smart Com", DC_FAMILY_UWATEC_SMART, 0x14}, {"Uwatec", "Smart Com", DC_FAMILY_UWATEC_SMART, 0x14},
{"Uwatec", "Smart Tec", DC_FAMILY_UWATEC_SMART, 0x18}, {"Uwatec", "Smart Tec", DC_FAMILY_UWATEC_SMART, 0x18},
{"Uwatec", "Galileo Trimix",DC_FAMILY_UWATEC_SMART, 0x19}, {"Uwatec", "Galileo Trimix",DC_FAMILY_UWATEC_SMART, 0x19},
{"Uwatec", "Smart Z", DC_FAMILY_UWATEC_SMART, 0x1C}, {"Uwatec", "Smart Z", DC_FAMILY_UWATEC_SMART, 0x1C},
{"Subgear","XP Air", DC_FAMILY_UWATEC_SMART, 0x1C},
#endif #endif
/* Reefnet */ /* Reefnet */
{"Reefnet", "Sensus", DC_FAMILY_REEFNET_SENSUS, 1}, {"Reefnet", "Sensus", DC_FAMILY_REEFNET_SENSUS, 1},
@ -97,10 +110,12 @@ static const dc_descriptor_t g_descriptors[] = {
{"Reefnet", "Sensus Ultra", DC_FAMILY_REEFNET_SENSUSULTRA, 3}, {"Reefnet", "Sensus Ultra", DC_FAMILY_REEFNET_SENSUSULTRA, 3},
/* Oceanic VT Pro */ /* Oceanic VT Pro */
{"Oceanic", "Versa Pro", DC_FAMILY_OCEANIC_VTPRO, 0x4155}, {"Oceanic", "Versa Pro", DC_FAMILY_OCEANIC_VTPRO, 0x4155},
{"Aeris", "Atmos 2", DC_FAMILY_OCEANIC_VTPRO, 0x4158},
{"Oceanic", "Pro Plus 2", DC_FAMILY_OCEANIC_VTPRO, 0x4159}, {"Oceanic", "Pro Plus 2", DC_FAMILY_OCEANIC_VTPRO, 0x4159},
{"Aeris", "Atmos AI", DC_FAMILY_OCEANIC_VTPRO, 0x4244}, {"Aeris", "Atmos AI", DC_FAMILY_OCEANIC_VTPRO, 0x4244},
{"Oceanic", "VT Pro", DC_FAMILY_OCEANIC_VTPRO, 0x4245}, {"Oceanic", "VT Pro", DC_FAMILY_OCEANIC_VTPRO, 0x4245},
{"Sherwood", "Wisdom", DC_FAMILY_OCEANIC_VTPRO, 0x4246}, {"Sherwood", "Wisdom", DC_FAMILY_OCEANIC_VTPRO, 0x4246},
{"Aeris", "Elite", DC_FAMILY_OCEANIC_VTPRO, 0x424F},
/* Oceanic Veo 250 */ /* Oceanic Veo 250 */
{"Genesis", "React Pro", DC_FAMILY_OCEANIC_VEO250, 0x4247}, {"Genesis", "React Pro", DC_FAMILY_OCEANIC_VEO250, 0x4247},
{"Oceanic", "Veo 200", DC_FAMILY_OCEANIC_VEO250, 0x424B}, {"Oceanic", "Veo 200", DC_FAMILY_OCEANIC_VEO250, 0x424B},
@ -123,6 +138,7 @@ static const dc_descriptor_t g_descriptors[] = {
{"Oceanic", "OC1", DC_FAMILY_OCEANIC_ATOM2, 0x434E}, {"Oceanic", "OC1", DC_FAMILY_OCEANIC_ATOM2, 0x434E},
{"Sherwood", "Wisdom 2", DC_FAMILY_OCEANIC_ATOM2, 0x4350}, {"Sherwood", "Wisdom 2", DC_FAMILY_OCEANIC_ATOM2, 0x4350},
{"Sherwood", "Insight 2", DC_FAMILY_OCEANIC_ATOM2, 0x4353}, {"Sherwood", "Insight 2", DC_FAMILY_OCEANIC_ATOM2, 0x4353},
{"Genesis", "React Pro White", DC_FAMILY_OCEANIC_ATOM2, 0x4354},
{"Tusa", "Element II (IQ-750)", DC_FAMILY_OCEANIC_ATOM2, 0x4357}, {"Tusa", "Element II (IQ-750)", DC_FAMILY_OCEANIC_ATOM2, 0x4357},
{"Oceanic", "Veo 1.0", DC_FAMILY_OCEANIC_ATOM2, 0x4358}, {"Oceanic", "Veo 1.0", DC_FAMILY_OCEANIC_ATOM2, 0x4358},
{"Oceanic", "Veo 2.0", DC_FAMILY_OCEANIC_ATOM2, 0x4359}, {"Oceanic", "Veo 2.0", DC_FAMILY_OCEANIC_ATOM2, 0x4359},
@ -137,14 +153,18 @@ static const dc_descriptor_t g_descriptors[] = {
{"Oceanic", "Atom 3.0", DC_FAMILY_OCEANIC_ATOM2, 0x444C}, {"Oceanic", "Atom 3.0", DC_FAMILY_OCEANIC_ATOM2, 0x444C},
{"Hollis", "DG03", DC_FAMILY_OCEANIC_ATOM2, 0x444D}, {"Hollis", "DG03", DC_FAMILY_OCEANIC_ATOM2, 0x444D},
{"Oceanic", "OCS", DC_FAMILY_OCEANIC_ATOM2, 0x4450}, {"Oceanic", "OCS", DC_FAMILY_OCEANIC_ATOM2, 0x4450},
{"Oceanic", "OC1", DC_FAMILY_OCEANIC_ATOM2, 0x4451},
{"Oceanic", "VT 4.1", DC_FAMILY_OCEANIC_ATOM2, 0x4452}, {"Oceanic", "VT 4.1", DC_FAMILY_OCEANIC_ATOM2, 0x4452},
{"Aeris", "Epic", DC_FAMILY_OCEANIC_ATOM2, 0x4453}, {"Aeris", "Epic", DC_FAMILY_OCEANIC_ATOM2, 0x4453},
{"Aeris", "Elite T3", DC_FAMILY_OCEANIC_ATOM2, 0x4455}, {"Aeris", "Elite T3", DC_FAMILY_OCEANIC_ATOM2, 0x4455},
{"Oceanic", "Atom 3.1", DC_FAMILY_OCEANIC_ATOM2, 0x4456}, {"Oceanic", "Atom 3.1", DC_FAMILY_OCEANIC_ATOM2, 0x4456},
{"Aeris", "A300 AI", DC_FAMILY_OCEANIC_ATOM2, 0x4457}, {"Aeris", "A300 AI", DC_FAMILY_OCEANIC_ATOM2, 0x4457},
{"Sherwood", "Wisdom 3", DC_FAMILY_OCEANIC_ATOM2, 0x4458}, {"Sherwood", "Wisdom 3", DC_FAMILY_OCEANIC_ATOM2, 0x4458},
{"Oceanic", "Pro Plus 3", DC_FAMILY_OCEANIC_ATOM2, 0x4548},
/* Mares Nemo */ /* Mares Nemo */
{"Mares", "Nemo", DC_FAMILY_MARES_NEMO, 0}, {"Mares", "Nemo", DC_FAMILY_MARES_NEMO, 0},
{"Mares", "Nemo Steel", DC_FAMILY_MARES_NEMO, 0},
{"Mares", "Nemo Titanium",DC_FAMILY_MARES_NEMO, 0},
{"Mares", "Nemo Excel", DC_FAMILY_MARES_NEMO, 17}, {"Mares", "Nemo Excel", DC_FAMILY_MARES_NEMO, 17},
{"Mares", "Nemo Apneist", DC_FAMILY_MARES_NEMO, 18}, {"Mares", "Nemo Apneist", DC_FAMILY_MARES_NEMO, 18},
/* Mares Puck */ /* Mares Puck */

View File

@ -152,6 +152,8 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
dc_gasmix_t *gasmix = (dc_gasmix_t *) value; dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
unsigned int air = (p[0] & 0x02) == 0;
if (value) { if (value) {
switch (type) { switch (type) {
case DC_FIELD_DIVETIME: case DC_FIELD_DIVETIME:
@ -161,11 +163,27 @@ mares_iconhd_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsi
*((double *) value) = array_uint16_le (p + 0x04) / 10.0; *((double *) value) = array_uint16_le (p + 0x04) / 10.0;
break; break;
case DC_FIELD_GASMIX_COUNT: case DC_FIELD_GASMIX_COUNT:
*((unsigned int *) value) = 3; if (air) {
*((unsigned int *) value) = 1;
} else {
// Count the number of active gas mixes. The active gas
// mixes are always first, so we stop counting as soon
// as the first gas marked as disabled is found.
unsigned int i = 0;
while (i < 3) {
if (p[0x14 + i * 4 + 1] & 0x80)
break;
i++;
}
*((unsigned int *) value) = i;
}
break; break;
case DC_FIELD_GASMIX: case DC_FIELD_GASMIX:
if (air)
gasmix->oxygen = 0.21;
else
gasmix->oxygen = p[0x14 + flags * 4] / 100.0;
gasmix->helium = 0.0; gasmix->helium = 0.0;
gasmix->oxygen = p[0x14 + flags * 4] / 100.0;
gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium; gasmix->nitrogen = 1.0 - gasmix->oxygen - gasmix->helium;
break; break;
default: default:

View File

@ -89,6 +89,7 @@ static const oceanic_common_version_t oceanic_atom2b_version[] = {
{"ELEMENT2 \0\0 512K"}, {"ELEMENT2 \0\0 512K"},
{"OCEVEO20 \0\0 512K"}, {"OCEVEO20 \0\0 512K"},
{"TUSAZEN \0\0 512K"}, {"TUSAZEN \0\0 512K"},
{"PROPLUS3 \0\0 512K"},
}; };
static const oceanic_common_version_t oceanic_atom2c_version[] = { static const oceanic_common_version_t oceanic_atom2c_version[] = {
@ -124,6 +125,10 @@ static const oceanic_common_version_t oceanic_veo1_version[] = {
{"OCEVEO10 \0\0 8K"}, {"OCEVEO10 \0\0 8K"},
}; };
static const oceanic_common_version_t oceanic_reactpro_version[] = {
{"REACPRO2 \0\0 512K"},
};
static const oceanic_common_layout_t aeris_f10_layout = { static const oceanic_common_layout_t aeris_f10_layout = {
0x10000, /* memsize */ 0x10000, /* memsize */
0x0000, /* cf_devinfo */ 0x0000, /* cf_devinfo */
@ -241,6 +246,18 @@ static const oceanic_common_layout_t oceanic_veo1_layout = {
0 /* pt_mode_logbook */ 0 /* pt_mode_logbook */
}; };
static const oceanic_common_layout_t oceanic_reactpro_layout = {
0xFFF0, /* memsize */
0x0000, /* cf_devinfo */
0x0040, /* cf_pointers */
0x0400, /* rb_logbook_begin */
0x0600, /* rb_logbook_end */
8, /* rb_logbook_entry_size */
0x0600, /* rb_profile_begin */
0xFFF0, /* rb_profile_end */
1, /* pt_mode_global */
1 /* pt_mode_logbook */
};
static dc_status_t static dc_status_t
oceanic_atom2_send (oceanic_atom2_device_t *device, const unsigned char command[], unsigned int csize, unsigned char ack) oceanic_atom2_send (oceanic_atom2_device_t *device, const unsigned char command[], unsigned int csize, unsigned char ack)
@ -418,6 +435,8 @@ oceanic_atom2_device_open (dc_device_t **out, dc_context_t *context, const char
device->base.layout = &oceanic_oc1_layout; device->base.layout = &oceanic_oc1_layout;
} else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_veo1_version)) { } else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_veo1_version)) {
device->base.layout = &oceanic_veo1_layout; device->base.layout = &oceanic_veo1_layout;
} else if (OCEANIC_COMMON_MATCH (device->base.version, oceanic_reactpro_version)) {
device->base.layout = &oceanic_reactpro_layout;
} else { } else {
device->base.layout = &oceanic_default_layout; device->base.layout = &oceanic_default_layout;
} }

View File

@ -41,6 +41,7 @@
#define COMPUMASK 0x4348 #define COMPUMASK 0x4348
#define OC1A 0x434E #define OC1A 0x434E
#define F10 0x434D #define F10 0x434D
#define ELEMENT2 0x4357
#define VEO20 0x4359 #define VEO20 0x4359
#define VEO30 0x435A #define VEO30 0x435A
#define ZENAIR 0x4442 #define ZENAIR 0x4442
@ -51,10 +52,12 @@
#define ATOM3 0x444C #define ATOM3 0x444C
#define DG03 0x444D #define DG03 0x444D
#define OCS 0x4450 #define OCS 0x4450
#define OC1C 0x4451
#define VT41 0x4452 #define VT41 0x4452
#define EPICB 0x4453 #define EPICB 0x4453
#define ATOM31 0x4456 #define ATOM31 0x4456
#define A300AI 0x4457 #define A300AI 0x4457
#define PROPLUS3 0x4548
typedef struct oceanic_atom2_parser_t oceanic_atom2_parser_t; typedef struct oceanic_atom2_parser_t oceanic_atom2_parser_t;
@ -156,6 +159,7 @@ oceanic_atom2_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetim
switch (parser->model) { switch (parser->model) {
case OC1A: case OC1A:
case OC1B: case OC1B:
case OC1C:
case OCS: case OCS:
case VT4: case VT4:
case VT41: case VT41:
@ -262,7 +266,7 @@ oceanic_atom2_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, uns
if (parser->model == DATAMASK || parser->model == COMPUMASK || if (parser->model == DATAMASK || parser->model == COMPUMASK ||
parser->model == GEO || parser->model == GEO20 || parser->model == GEO || parser->model == GEO20 ||
parser->model == VEO20 || parser->model == VEO30 || parser->model == VEO20 || parser->model == VEO30 ||
parser->model == OCS) { parser->model == OCS || parser->model == PROPLUS3) {
headersize -= PAGESIZE; headersize -= PAGESIZE;
} else if (parser->model == VT4 || parser->model == VT41) { } else if (parser->model == VT4 || parser->model == VT41) {
headersize += PAGESIZE; headersize += PAGESIZE;
@ -353,7 +357,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
if (parser->model == DATAMASK || parser->model == COMPUMASK || if (parser->model == DATAMASK || parser->model == COMPUMASK ||
parser->model == GEO || parser->model == GEO20 || parser->model == GEO || parser->model == GEO20 ||
parser->model == VEO20 || parser->model == VEO30 || parser->model == VEO20 || parser->model == VEO30 ||
parser->model == OCS) { parser->model == OCS || parser->model == PROPLUS3) {
headersize -= PAGESIZE; headersize -= PAGESIZE;
} else if (parser->model == VT4 || parser->model == VT41) { } else if (parser->model == VT4 || parser->model == VT41) {
headersize += PAGESIZE; headersize += PAGESIZE;
@ -390,13 +394,14 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
} }
unsigned int samplesize = PAGESIZE / 2; unsigned int samplesize = PAGESIZE / 2;
if (parser->model == OC1A || parser->model == OC1B) if (parser->model == OC1A || parser->model == OC1B || parser->model == OC1C)
samplesize = PAGESIZE; samplesize = PAGESIZE;
else if (parser->model == F10) else if (parser->model == F10)
samplesize = 2; samplesize = 2;
unsigned int have_temperature = 1, have_pressure = 1; unsigned int have_temperature = 1, have_pressure = 1;
if (parser->model == VEO30 || parser->model == OCS) { if (parser->model == VEO30 || parser->model == OCS ||
parser->model == ELEMENT2) {
have_pressure = 0; have_pressure = 0;
} else if (parser->model == F10) { } else if (parser->model == F10) {
have_temperature = 0; have_temperature = 0;
@ -494,11 +499,12 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
} else { } else {
// Temperature (°F) // Temperature (°F)
if (have_temperature) { if (have_temperature) {
if (parser->model == GEO || parser->model == ATOM1) { if (parser->model == GEO || parser->model == ATOM1 ||
parser->model == ELEMENT2) {
temperature = data[offset + 6]; temperature = data[offset + 6];
} else if (parser->model == GEO20 || parser->model == VEO20 || } else if (parser->model == GEO20 || parser->model == VEO20 ||
parser->model == VEO30 || parser->model == OC1A || parser->model == VEO30 || parser->model == OC1A ||
parser->model == OC1B) { parser->model == OC1B || parser->model == OC1C) {
temperature = data[offset + 3]; temperature = data[offset + 3];
} else if (parser->model == OCS) { } else if (parser->model == OCS) {
temperature = data[offset + 1]; temperature = data[offset + 1];
@ -506,7 +512,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
temperature = ((data[offset + 7] & 0xF0) >> 4) | ((data[offset + 7] & 0x0C) << 2) | ((data[offset + 5] & 0x0C) << 4); temperature = ((data[offset + 7] & 0xF0) >> 4) | ((data[offset + 7] & 0x0C) << 2) | ((data[offset + 5] & 0x0C) << 4);
} else { } else {
unsigned int sign; unsigned int sign;
if (parser->model == DG03) if (parser->model == DG03 || parser->model == PROPLUS3)
sign = (~data[offset + 5] & 0x04) >> 2; sign = (~data[offset + 5] & 0x04) >> 2;
else if (parser->model == ATOM2 || parser->model == PROPLUS21 || else if (parser->model == ATOM2 || parser->model == PROPLUS21 ||
parser->model == EPICA || parser->model == EPICB) parser->model == EPICA || parser->model == EPICB)
@ -524,12 +530,12 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
// Tank Pressure (psi) // Tank Pressure (psi)
if (have_pressure) { if (have_pressure) {
if (parser->model == OC1A || parser->model == OC1B) if (parser->model == OC1A || parser->model == OC1B || parser->model == OC1C)
pressure = (data[offset + 10] + (data[offset + 11] << 8)) & 0x0FFF; pressure = (data[offset + 10] + (data[offset + 11] << 8)) & 0x0FFF;
else if (parser->model == VT4 || parser->model == VT41|| else if (parser->model == VT4 || parser->model == VT41||
parser->model == ATOM3 || parser->model == ATOM31 || parser->model == ATOM3 || parser->model == ATOM31 ||
parser->model == ZENAIR ||parser->model == A300AI || parser->model == ZENAIR ||parser->model == A300AI ||
parser->model == DG03) parser->model == DG03 || parser->model == PROPLUS3)
pressure = (((data[offset + 0] & 0x03) << 8) + data[offset + 1]) * 5; pressure = (((data[offset + 0] & 0x03) << 8) + data[offset + 1]) * 5;
else else
pressure -= data[offset + 1]; pressure -= data[offset + 1];
@ -542,7 +548,7 @@ oceanic_atom2_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_
unsigned int depth; unsigned int depth;
if (parser->model == GEO20 || parser->model == VEO20 || if (parser->model == GEO20 || parser->model == VEO20 ||
parser->model == VEO30 || parser->model == OC1A || parser->model == VEO30 || parser->model == OC1A ||
parser->model == OC1B) parser->model == OC1B || parser->model == OC1C)
depth = (data[offset + 4] + (data[offset + 5] << 8)) & 0x0FFF; depth = (data[offset + 4] + (data[offset + 5] << 8)) & 0x0FFF;
else if (parser->model == ATOM1) else if (parser->model == ATOM1)
depth = data[offset + 3] * 16; depth = data[offset + 3] * 16;

View File

@ -31,6 +31,11 @@
#define ISINSTANCE(parser) dc_parser_isinstance((parser), &oceanic_veo250_parser_vtable) #define ISINSTANCE(parser) dc_parser_isinstance((parser), &oceanic_veo250_parser_vtable)
#define REACTPRO 0x4247
#define VEO200 0x424B
#define VEO250 0x424C
#define REACTPROWHITE 0x4354
typedef struct oceanic_veo250_parser_t oceanic_veo250_parser_t; typedef struct oceanic_veo250_parser_t oceanic_veo250_parser_t;
struct oceanic_veo250_parser_t { struct oceanic_veo250_parser_t {
@ -128,8 +133,10 @@ oceanic_veo250_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *dateti
datetime->minute = p[2]; datetime->minute = p[2];
datetime->second = 0; datetime->second = 0;
if (parser->model == 0x424B || parser->model == 0x424C) if (parser->model == VEO200 || parser->model == VEO250)
datetime->year += 3; datetime->year += 3;
else if (parser->model == REACTPRO)
datetime->year += 2;
} }
return DC_STATUS_SUCCESS; return DC_STATUS_SUCCESS;
@ -194,6 +201,7 @@ oceanic_veo250_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, un
static dc_status_t static dc_status_t
oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata) oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
{ {
oceanic_veo250_parser_t *parser = (oceanic_veo250_parser_t *) abstract;
const unsigned char *data = abstract->data; const unsigned char *data = abstract->data;
unsigned int size = abstract->size; unsigned int size = abstract->size;
@ -202,7 +210,12 @@ oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
unsigned int time = 0; unsigned int time = 0;
unsigned int interval = 0; unsigned int interval = 0;
switch (data[0x27] & 0x03) { unsigned int interval_idx = data[0x27] & 0x03;
if (parser->model == REACTPRO || parser->model == REACTPROWHITE) {
interval_idx += 1;
interval_idx %= 4;
}
switch (interval_idx) {
case 0: case 0:
interval = 2; interval = 2;
break; break;
@ -244,7 +257,12 @@ oceanic_veo250_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback
if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata); if (callback) callback (DC_SAMPLE_DEPTH, sample, userdata);
// Temperature (°F) // Temperature (°F)
unsigned int temperature = data[offset + 7]; unsigned int temperature;
if (parser->model == REACTPRO || parser->model == REACTPROWHITE) {
temperature = data[offset + 6];
} else {
temperature = data[offset + 7];
}
sample.temperature = (temperature - 32.0) * (5.0 / 9.0); sample.temperature = (temperature - 32.0) * (5.0 / 9.0);
if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata); if (callback) callback (DC_SAMPLE_TEMPERATURE, sample, userdata);

View File

@ -65,9 +65,11 @@ static const dc_device_vtable_t oceanic_vtpro_device_vtable = {
static const oceanic_common_version_t oceanic_vtpro_version[] = { static const oceanic_common_version_t oceanic_vtpro_version[] = {
{"VERSAPRO \0\0 256K"}, {"VERSAPRO \0\0 256K"},
{"ATMOSTWO \0\0 256K"},
{"PROPLUS2 \0\0 256K"}, {"PROPLUS2 \0\0 256K"},
{"ATMOSAIR \0\0 256K"}, {"ATMOSAIR \0\0 256K"},
{"VTPRO r\0\0 256K"}, {"VTPRO r\0\0 256K"},
{"ELITE r\0\0 256K"},
}; };
static const oceanic_common_version_t oceanic_wisdom_version[] = { static const oceanic_common_version_t oceanic_wisdom_version[] = {

View File

@ -35,6 +35,8 @@
#include "parser-private.h" #include "parser-private.h"
#include "device-private.h" #include "device-private.h"
#define REACTPROWHITE 0x4354
dc_status_t dc_status_t
dc_parser_new (dc_parser_t **out, dc_device_t *device) dc_parser_new (dc_parser_t **out, dc_device_t *device)
{ {
@ -86,7 +88,10 @@ dc_parser_new (dc_parser_t **out, dc_device_t *device)
rc = oceanic_veo250_parser_create (&parser, context, device->devinfo.model); rc = oceanic_veo250_parser_create (&parser, context, device->devinfo.model);
break; break;
case DC_FAMILY_OCEANIC_ATOM2: case DC_FAMILY_OCEANIC_ATOM2:
rc = oceanic_atom2_parser_create (&parser, context, device->devinfo.model); if (device->devinfo.model == REACTPROWHITE)
rc = oceanic_veo250_parser_create (&parser, context, device->devinfo.model);
else
rc = oceanic_atom2_parser_create (&parser, context, device->devinfo.model);
break; break;
case DC_FAMILY_MARES_NEMO: case DC_FAMILY_MARES_NEMO:
case DC_FAMILY_MARES_PUCK: case DC_FAMILY_MARES_PUCK:

View File

@ -141,7 +141,7 @@ shearwater_predator_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *d
unsigned int ticks = array_uint32_be (data + 12); unsigned int ticks = array_uint32_be (data + 12);
if (!dc_datetime_localtime (datetime, ticks)) if (!dc_datetime_gmtime (datetime, ticks))
return DC_STATUS_DATAFORMAT; return DC_STATUS_DATAFORMAT;
return DC_STATUS_SUCCESS; return DC_STATUS_SUCCESS;

View File

@ -43,6 +43,7 @@
#define D4i 0x19 #define D4i 0x19
#define D6i 0x1A #define D6i 0x1A
#define D9tx 0x1B #define D9tx 0x1B
#define DX 0x1C
typedef struct suunto_d9_device_t { typedef struct suunto_d9_device_t {
suunto_common2_device_t base; suunto_common2_device_t base;
@ -81,6 +82,14 @@ static const suunto_common2_layout_t suunto_d9tx_layout = {
0xEBF0 /* rb_profile_end */ 0xEBF0 /* rb_profile_end */
}; };
static const suunto_common2_layout_t suunto_dx_layout = {
0x10000, /* memsize */
0x0017, /* fingerprint */
0x0024, /* serial */
0x019A, /* rb_profile_begin */
0xEBF0 /* rb_profile_end */
};
static dc_status_t static dc_status_t
suunto_d9_device_autodetect (suunto_d9_device_t *device, unsigned int model) suunto_d9_device_autodetect (suunto_d9_device_t *device, unsigned int model)
@ -93,7 +102,7 @@ suunto_d9_device_autodetect (suunto_d9_device_t *device, unsigned int model)
// Use the model number as a hint to speedup the detection. // Use the model number as a hint to speedup the detection.
unsigned int hint = 0; unsigned int hint = 0;
if (model == D4i || model == D6i || model == D9tx) if (model == D4i || model == D6i || model == D9tx || model == DX)
hint = 1; hint = 1;
for (unsigned int i = 0; i < C_ARRAY_SIZE(baudrates); ++i) { for (unsigned int i = 0; i < C_ARRAY_SIZE(baudrates); ++i) {
@ -188,6 +197,8 @@ suunto_d9_device_open (dc_device_t **out, dc_context_t *context, const char *nam
model = device->base.version[0]; model = device->base.version[0];
if (model == D4i || model == D6i || model == D9tx) if (model == D4i || model == D6i || model == D9tx)
device->base.layout = &suunto_d9tx_layout; device->base.layout = &suunto_d9tx_layout;
else if (model == DX)
device->base.layout = &suunto_dx_layout;
else else
device->base.layout = &suunto_d9_layout; device->base.layout = &suunto_d9_layout;

View File

@ -43,6 +43,7 @@
#define D4i 0x19 #define D4i 0x19
#define D6i 0x1A #define D6i 0x1A
#define D9tx 0x1B #define D9tx 0x1B
#define DX 0x1C
#define AIR 0 #define AIR 0
#define NITROX 1 #define NITROX 1
@ -132,7 +133,7 @@ suunto_d9_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
suunto_d9_parser_t *parser = (suunto_d9_parser_t*) abstract; suunto_d9_parser_t *parser = (suunto_d9_parser_t*) abstract;
unsigned int offset = 0x11; unsigned int offset = 0x11;
if (parser->model == HELO2) if (parser->model == HELO2 || parser->model == DX)
offset = 0x17; offset = 0x17;
else if (parser->model == D4i || parser->model == D6i || parser->model == D9tx) else if (parser->model == D4i || parser->model == D6i || parser->model == D9tx)
offset = 0x13; offset = 0x13;
@ -143,7 +144,8 @@ suunto_d9_parser_get_datetime (dc_parser_t *abstract, dc_datetime_t *datetime)
const unsigned char *p = abstract->data + offset; const unsigned char *p = abstract->data + offset;
if (datetime) { if (datetime) {
if (parser->model == D4i || parser->model == D6i || parser->model == D9tx) { if (parser->model == D4i || parser->model == D6i ||
parser->model == D9tx || parser->model == DX) {
datetime->year = p[0] + (p[1] << 8); datetime->year = p[0] + (p[1] << 8);
datetime->month = p[2]; datetime->month = p[2];
datetime->day = p[3]; datetime->day = p[3];
@ -189,6 +191,9 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne
} else if (parser->model == D9tx) { } else if (parser->model == D9tx) {
gasmix_offset = 0x87; gasmix_offset = 0x87;
gasmix_count = 8; gasmix_count = 8;
} else if (parser->model == DX) {
gasmix_offset = 0xC1;
gasmix_count = 11;
} }
// Offset to the configuration data. // Offset to the configuration data.
@ -196,7 +201,8 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne
if (parser->model == D4) { if (parser->model == D4) {
config += 1; config += 1;
} else if (parser->model == HELO2 || parser->model == D4i || } else if (parser->model == HELO2 || parser->model == D4i ||
parser->model == D6i || parser->model == D9tx) { parser->model == D6i || parser->model == D9tx ||
parser->model == DX) {
config = gasmix_offset + gasmix_count * 6; config = gasmix_offset + gasmix_count * 6;
} }
if (config + 1 > size) if (config + 1 > size)
@ -208,6 +214,8 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne
gasmodel_offset = 0x1F; gasmodel_offset = 0x1F;
else if (parser->model == D4i || parser->model == D6i || parser->model == D9tx) else if (parser->model == D4i || parser->model == D6i || parser->model == D9tx)
gasmodel_offset = 0x1D; gasmodel_offset = 0x1D;
else if (parser->model == DX)
gasmodel_offset = 0x21;
unsigned int gasmodel = data[gasmodel_offset]; unsigned int gasmodel = data[gasmodel_offset];
dc_gasmix_t *gasmix = (dc_gasmix_t *) value; dc_gasmix_t *gasmix = (dc_gasmix_t *) value;
@ -217,7 +225,8 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne
case DC_FIELD_DIVETIME: case DC_FIELD_DIVETIME:
if (parser->model == D4) if (parser->model == D4)
*((unsigned int *) value) = array_uint16_le (data + 0x0B); *((unsigned int *) value) = array_uint16_le (data + 0x0B);
else if (parser->model == D4i || parser->model == D6i || parser->model == D9tx) else if (parser->model == D4i || parser->model == D6i ||
parser->model == D9tx || parser->model == DX)
*((unsigned int *) value) = array_uint16_le (data + 0x0D); *((unsigned int *) value) = array_uint16_le (data + 0x0D);
else if (parser->model == HELO2) else if (parser->model == HELO2)
*((unsigned int *) value) = array_uint16_le (data + 0x0D) * 60; *((unsigned int *) value) = array_uint16_le (data + 0x0D) * 60;
@ -239,7 +248,8 @@ suunto_d9_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigne
gasmix->helium = 0.0; gasmix->helium = 0.0;
gasmix->oxygen = 0.21; gasmix->oxygen = 0.21;
} else if (parser->model == HELO2 || parser->model == D4i || } else if (parser->model == HELO2 || parser->model == D4i ||
parser->model == D6i || parser->model == D9tx) { parser->model == D6i || parser->model == D9tx ||
parser->model == DX) {
gasmix->helium = data[gasmix_offset + 6 * flags + 2] / 100.0; gasmix->helium = data[gasmix_offset + 6 * flags + 2] / 100.0;
gasmix->oxygen = data[gasmix_offset + 6 * flags + 1] / 100.0; gasmix->oxygen = data[gasmix_offset + 6 * flags + 1] / 100.0;
} else { } else {
@ -282,6 +292,9 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca
} else if (parser->model == D9tx) { } else if (parser->model == D9tx) {
gasmix_offset = 0x87; gasmix_offset = 0x87;
gasmix_count = 8; gasmix_count = 8;
} else if (parser->model == DX) {
gasmix_offset = 0xC1;
gasmix_count = 11;
} }
// Offset to the configuration data. // Offset to the configuration data.
@ -289,7 +302,8 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca
if (parser->model == D4) { if (parser->model == D4) {
config += 1; config += 1;
} else if (parser->model == HELO2 || parser->model == D4i || } else if (parser->model == HELO2 || parser->model == D4i ||
parser->model == D6i || parser->model == D9tx) { parser->model == D6i || parser->model == D9tx ||
parser->model == DX) {
config = gasmix_offset + gasmix_count * 6; config = gasmix_offset + gasmix_count * 6;
} }
if (config + 1 > size) if (config + 1 > size)
@ -297,7 +311,7 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca
// Number of parameters in the configuration data. // Number of parameters in the configuration data.
unsigned int nparams = data[config]; unsigned int nparams = data[config];
if (nparams > MAXPARAMS) if (nparams == 0 || nparams > MAXPARAMS)
return DC_STATUS_DATAFORMAT; return DC_STATUS_DATAFORMAT;
// Available divisor values. // Available divisor values.
@ -340,6 +354,8 @@ suunto_d9_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t ca
if (parser->model == HELO2 || parser->model == D4i || if (parser->model == HELO2 || parser->model == D4i ||
parser->model == D6i || parser->model == D9tx) parser->model == D6i || parser->model == D9tx)
interval_sample_offset = 0x1E; interval_sample_offset = 0x1E;
else if (parser->model == DX)
interval_sample_offset = 0x22;
unsigned int interval_sample = data[interval_sample_offset]; unsigned int interval_sample = data[interval_sample_offset];
if (interval_sample == 0) if (interval_sample == 0)
return DC_STATUS_DATAFORMAT; return DC_STATUS_DATAFORMAT;

View File

@ -584,7 +584,7 @@ uwatec_smart_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t
break; break;
case TEMPERATURE: case TEMPERATURE:
if (table[id].absolute) { if (table[id].absolute) {
temperature = value / 2.5; temperature = svalue / 2.5;
have_temperature = 1; have_temperature = 1;
} else { } else {
temperature += svalue / 2.5; temperature += svalue / 2.5;