Add support for the new iX3M APOS4 firmware
The new APOS4 firmware changed the data format and communication protocol. The size of the samples changed from 54 to 64 bytes, and in order to speedup the download, a single data packet contains 3 samples at once. If the number of samples is not an exact multiple of three, the last packet appears to contain garbage data. For parsing, the firmware version is available in the dive header. Unfortunately it can't be used for dives that are downloaded from a device with the new firmware, but which have been recorded with an older firmware. Such dives store the old firmware version in the dive header, but they also use the new sample format. As a workaround, we inspect the size of the dive.
This commit is contained in:
parent
2854453f26
commit
55b9307e19
@ -57,6 +57,7 @@ typedef struct divesystem_idive_commands_t {
|
||||
divesystem_idive_command_t range;
|
||||
divesystem_idive_command_t header;
|
||||
divesystem_idive_command_t sample;
|
||||
unsigned int nsamples;
|
||||
} divesystem_idive_commands_t;
|
||||
|
||||
typedef struct divesystem_idive_device_t {
|
||||
@ -86,6 +87,7 @@ static const divesystem_idive_commands_t idive = {
|
||||
{0x98, 0x04},
|
||||
{0xA0, 0x32},
|
||||
{0xA8, 0x2A},
|
||||
1,
|
||||
};
|
||||
|
||||
static const divesystem_idive_commands_t ix3m = {
|
||||
@ -93,6 +95,15 @@ static const divesystem_idive_commands_t ix3m = {
|
||||
{0x78, 0x04},
|
||||
{0x79, 0x36},
|
||||
{0x7A, 0x36},
|
||||
1,
|
||||
};
|
||||
|
||||
static const divesystem_idive_commands_t ix3m_apos4 = {
|
||||
{0x11, 0x1A},
|
||||
{0x78, 0x04},
|
||||
{0x79, 0x36},
|
||||
{0x7A, 0x40},
|
||||
3,
|
||||
};
|
||||
|
||||
dc_status_t
|
||||
@ -382,6 +393,14 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
|
||||
vendor.size = commands->id.size;
|
||||
device_event_emit (abstract, DC_EVENT_VENDOR, &vendor);
|
||||
|
||||
if (device->model >= IX3M_EASY && device->model <= IX3M_REB) {
|
||||
// Detect the APOS4 firmware.
|
||||
unsigned int apos4 = (devinfo.firmware / 10000000) >= 4;
|
||||
if (apos4) {
|
||||
commands = &ix3m_apos4;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char cmd_range[] = {commands->range.cmd, 0x8D};
|
||||
rc = divesystem_idive_transfer (device, cmd_range, sizeof(cmd_range), packet, commands->range.size);
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
@ -429,20 +448,28 @@ divesystem_idive_device_foreach (dc_device_t *abstract, dc_dive_callback_t callb
|
||||
dc_buffer_reserve(buffer, commands->header.size + commands->sample.size * nsamples);
|
||||
dc_buffer_append(buffer, packet, commands->header.size);
|
||||
|
||||
for (unsigned int j = 0; j < nsamples; ++j) {
|
||||
for (unsigned int j = 0; j < nsamples; j += commands->nsamples) {
|
||||
unsigned int idx = j + 1;
|
||||
unsigned char cmd_sample[] = {commands->sample.cmd,
|
||||
(idx ) & 0xFF,
|
||||
(idx >> 8) & 0xFF};
|
||||
rc = divesystem_idive_transfer (device, cmd_sample, sizeof(cmd_sample), packet, commands->sample.size);
|
||||
rc = divesystem_idive_transfer (device, cmd_sample, sizeof(cmd_sample), packet, commands->sample.size * commands->nsamples);
|
||||
if (rc != DC_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
// If the number of samples is not an exact multiple of the
|
||||
// number of samples per packet, then the last packet
|
||||
// appears to contain garbage data. Ignore those samples.
|
||||
unsigned int n = commands->nsamples;
|
||||
if (j + n > nsamples) {
|
||||
n = nsamples - j;
|
||||
}
|
||||
|
||||
// Update and emit a progress event.
|
||||
progress.current = i * NSTEPS + STEP(j + 2, nsamples + 1);
|
||||
progress.current = i * NSTEPS + STEP(j + n + 1, nsamples + 1);
|
||||
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
|
||||
|
||||
dc_buffer_append(buffer, packet, commands->sample.size);
|
||||
dc_buffer_append(buffer, packet, commands->sample.size * n);
|
||||
}
|
||||
|
||||
unsigned char *data = dc_buffer_get_data(buffer);
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
#define SZ_SAMPLE_IDIVE 0x2A
|
||||
#define SZ_HEADER_IX3M 0x36
|
||||
#define SZ_SAMPLE_IX3M 0x36
|
||||
#define SZ_SAMPLE_IX3M_APOS4 0x40
|
||||
|
||||
#define NGASMIXES 8
|
||||
|
||||
@ -53,8 +54,8 @@ typedef struct divesystem_idive_parser_t divesystem_idive_parser_t;
|
||||
|
||||
struct divesystem_idive_parser_t {
|
||||
dc_parser_t base;
|
||||
unsigned int model;
|
||||
unsigned int headersize;
|
||||
unsigned int samplesize;
|
||||
// Cached fields.
|
||||
unsigned int cached;
|
||||
unsigned int divemode;
|
||||
@ -97,12 +98,11 @@ divesystem_idive_parser_create (dc_parser_t **out, dc_context_t *context, unsign
|
||||
}
|
||||
|
||||
// Set the default values.
|
||||
parser->model = model;
|
||||
if (model >= IX3M_EASY && model <= IX3M_REB) {
|
||||
parser->headersize = SZ_HEADER_IX3M;
|
||||
parser->samplesize = SZ_SAMPLE_IX3M;
|
||||
} else {
|
||||
parser->headersize = SZ_HEADER_IDIVE;
|
||||
parser->samplesize = SZ_SAMPLE_IDIVE;
|
||||
}
|
||||
parser->cached = 0;
|
||||
parser->divemode = INVALID;
|
||||
@ -241,8 +241,27 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
unsigned int mode_previous = INVALID;
|
||||
unsigned int divemode = INVALID;
|
||||
|
||||
unsigned int nsamples = array_uint16_le (data + 1);
|
||||
unsigned int samplesize = SZ_SAMPLE_IDIVE;
|
||||
if (parser->model >= IX3M_EASY && parser->model <= IX3M_REB) {
|
||||
// Detect the APOS4 firmware.
|
||||
unsigned int firmware = array_uint32_le(data + 0x2A);
|
||||
unsigned int apos4 = (firmware / 10000000) >= 4;
|
||||
if (apos4) {
|
||||
// Dive downloaded and recorded with the APOS4 firmware.
|
||||
samplesize = SZ_SAMPLE_IX3M_APOS4;
|
||||
} else if (size == parser->headersize + nsamples * SZ_SAMPLE_IX3M_APOS4) {
|
||||
// Dive downloaded with the APOS4 firmware, but recorded
|
||||
// with an older firmware.
|
||||
samplesize = SZ_SAMPLE_IX3M_APOS4;
|
||||
} else {
|
||||
// Dive downloaded and recorded with an older firmware.
|
||||
samplesize = SZ_SAMPLE_IX3M;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int offset = parser->headersize;
|
||||
while (offset + parser->samplesize <= size) {
|
||||
while (offset + samplesize <= size) {
|
||||
dc_sample_value_t sample = {0};
|
||||
|
||||
// Time (seconds).
|
||||
@ -328,7 +347,7 @@ divesystem_idive_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callba
|
||||
sample.cns = cns / 100.0;
|
||||
if (callback) callback (DC_SAMPLE_CNS, sample, userdata);
|
||||
|
||||
offset += parser->samplesize;
|
||||
offset += samplesize;
|
||||
}
|
||||
|
||||
// Cache the data for later use.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user