Skip to content

Commit 6944956

Browse files
jefdriesenmikeller
authored andcommitted
Add support for the Cressi Archimede
The Cressi Archimede protocol is very similar to the existing Edy protocol, with a few smaller differences: - No init3 command and baudrate change - Smaller packet size (32 instead of 128 bytes) - Modified read command with a 1 byte address The most curious change is the fact that the nibbles of all bytes are reversed (little endian). To simplify the processing of the data, the nibbles are swapped again immediately after downloading.
1 parent 10ab01d commit 6944956

File tree

5 files changed

+73
-24
lines changed

5 files changed

+73
-24
lines changed

src/array.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ array_reverse_bits (unsigned char data[], unsigned int size)
5151
}
5252
}
5353

54+
void
55+
array_reverse_nibbles (unsigned char data[], unsigned int size)
56+
{
57+
for (unsigned int i = 0; i < size; ++i) {
58+
unsigned char tmp = data[i];
59+
data[i] = ((tmp & 0xF0) >> 4) | ((tmp & 0x0F) << 4);
60+
}
61+
}
5462

5563
int
5664
array_isequal (const unsigned char data[], unsigned int size, unsigned char value)

src/array.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ array_reverse_bytes (unsigned char data[], unsigned int size);
3535
void
3636
array_reverse_bits (unsigned char data[], unsigned int size);
3737

38+
void
39+
array_reverse_nibbles (unsigned char data[], unsigned int size);
40+
3841
int
3942
array_isequal (const unsigned char data[], unsigned int size, unsigned char value);
4043

src/cressi_edy.c

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@
3535

3636
#define MAXRETRIES 4
3737

38-
#define SZ_PACKET 0x80
39-
#define SZ_PAGE (SZ_PACKET / 4)
38+
#define SZ_PAGE 32
4039

4140
#define SZ_HEADER 32
4241

42+
#define ARCHIMEDE 0x01
4343
#define IQ700 0x05
4444
#define EDY 0x08
4545

@@ -60,6 +60,7 @@ typedef struct cressi_edy_device_t {
6060
const cressi_edy_layout_t *layout;
6161
unsigned char fingerprint[SZ_PAGE / 2];
6262
unsigned int model;
63+
unsigned int packetsize;
6364
} cressi_edy_device_t;
6465

6566
static dc_status_t cressi_edy_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
@@ -247,6 +248,7 @@ cressi_edy_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_t
247248
device->iostream = iostream;
248249
device->layout = NULL;
249250
device->model = 0;
251+
device->packetsize = 0;
250252
memset (device->fingerprint, 0, sizeof (device->fingerprint));
251253

252254
// Set the serial communication protocol (1200 8N1).
@@ -284,19 +286,26 @@ cressi_edy_device_open (dc_device_t **out, dc_context_t *context, dc_iostream_t
284286
// Send the init commands.
285287
cressi_edy_init1 (device);
286288
cressi_edy_init2 (device);
287-
cressi_edy_init3 (device);
289+
if (device->model != ARCHIMEDE) {
290+
cressi_edy_init3 (device);
291+
}
292+
293+
device->packetsize = device->model == ARCHIMEDE ?
294+
SZ_PAGE : SZ_PAGE * 4;
288295

289-
if (device->model == IQ700) {
296+
if (device->model == IQ700 || device->model == ARCHIMEDE) {
290297
device->layout = &tusa_iq700_layout;
291298
} else {
292299
device->layout = &cressi_edy_layout;
293300
}
294301

295-
// Set the serial communication protocol (4800 8N1).
296-
status = dc_iostream_configure (device->iostream, 4800, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
297-
if (status != DC_STATUS_SUCCESS) {
298-
ERROR (context, "Failed to set the terminal attributes.");
299-
goto error_free;
302+
if (device->model != ARCHIMEDE) {
303+
// Set the serial communication protocol (4800 8N1).
304+
status = dc_iostream_configure (device->iostream, 4800, 8, DC_PARITY_NONE, DC_STOPBITS_ONE, DC_FLOWCONTROL_NONE);
305+
if (status != DC_STATUS_SUCCESS) {
306+
ERROR (context, "Failed to set the terminal attributes.");
307+
goto error_free;
308+
}
300309
}
301310

302311
// Make sure everything is in a sane state.
@@ -337,22 +346,33 @@ cressi_edy_device_read (dc_device_t *abstract, unsigned int address, unsigned ch
337346
cressi_edy_device_t *device = (cressi_edy_device_t*) abstract;
338347

339348
if ((address % SZ_PAGE != 0) ||
340-
(size % SZ_PACKET != 0))
349+
(size % device->packetsize != 0))
341350
return DC_STATUS_INVALIDARGS;
342351

343352
unsigned int nbytes = 0;
344353
while (nbytes < size) {
345354
// Read the package.
346355
unsigned int number = address / SZ_PAGE;
347-
unsigned char command[3] = {0x52,
348-
(number >> 8) & 0xFF, // high
349-
(number ) & 0xFF}; // low
350-
status = cressi_edy_transfer (device, command, sizeof (command), data + nbytes, SZ_PACKET, 1);
356+
unsigned char command[3] = {0};
357+
if (device->model == ARCHIMEDE) {
358+
command[0] = 0x45;
359+
command[1] = 0x52;
360+
command[2] = number & 0xFF;
361+
} else {
362+
command[0] = 0x52;
363+
command[1] = (number >> 8) & 0xFF; // high;
364+
command[2] = (number ) & 0xFF; // low
365+
}
366+
status = cressi_edy_transfer (device, command, sizeof (command), data + nbytes, device->packetsize, 1);
351367
if (status != DC_STATUS_SUCCESS)
352368
return status;
353369

354-
nbytes += SZ_PACKET;
355-
address += SZ_PACKET;
370+
nbytes += device->packetsize;
371+
address += device->packetsize;
372+
}
373+
374+
if (device->model == ARCHIMEDE) {
375+
array_reverse_nibbles (data, size);
356376
}
357377

358378
return status;
@@ -395,7 +415,7 @@ cressi_edy_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
395415
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);
396416

397417
return device_dump_read (abstract, 0, dc_buffer_get_data (buffer),
398-
dc_buffer_get_size (buffer), SZ_PACKET);
418+
dc_buffer_get_size (buffer), device->packetsize);
399419
}
400420

401421

@@ -407,7 +427,7 @@ cressi_edy_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
407427

408428
// Enable progress notifications.
409429
dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
410-
progress.maximum = SZ_PACKET +
430+
progress.maximum = 4 * SZ_PAGE +
411431
(layout->rb_profile_end - layout->rb_profile_begin);
412432
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
413433

@@ -419,7 +439,7 @@ cressi_edy_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
419439
device_event_emit (abstract, DC_EVENT_DEVINFO, &devinfo);
420440

421441
// Read the logbook data.
422-
unsigned char logbook[SZ_PACKET] = {0};
442+
unsigned char logbook[4 * SZ_PAGE] = {0};
423443
dc_status_t rc = cressi_edy_device_read (abstract, layout->rb_logbook_offset, logbook, sizeof (logbook));
424444
if (rc != DC_STATUS_SUCCESS) {
425445
ERROR (abstract->context, "Failed to read the logbook data.");
@@ -481,13 +501,13 @@ cressi_edy_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, v
481501
}
482502

483503
// Update and emit a progress event.
484-
progress.current += SZ_PACKET;
485-
progress.maximum = SZ_PACKET + total;
504+
progress.current += 4 * SZ_PAGE;
505+
progress.maximum = 4 * SZ_PAGE + total;
486506
device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
487507

488508
// Create the ringbuffer stream.
489509
dc_rbstream_t *rbstream = NULL;
490-
rc = dc_rbstream_new (&rbstream, abstract, SZ_PAGE, SZ_PACKET, layout->rb_profile_begin, layout->rb_profile_end, eop, DC_RBSTREAM_BACKWARD);
510+
rc = dc_rbstream_new (&rbstream, abstract, SZ_PAGE, device->packetsize, layout->rb_profile_begin, layout->rb_profile_end, eop, DC_RBSTREAM_BACKWARD);
491511
if (rc != DC_STATUS_SUCCESS) {
492512
ERROR (abstract->context, "Failed to create the ringbuffer stream.");
493513
return rc;

src/cressi_edy_parser.c

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#define ISINSTANCE(parser) dc_parser_isinstance((parser), &cressi_edy_parser_vtable)
3030

31+
#define ARCHIMEDE 0x01
3132
#define IQ700 0x05
3233
#define EDY 0x08
3334

@@ -80,6 +81,17 @@ static const cressi_edy_layout_t edy = {
8081
46, 3, /* gasmix */
8182
};
8283

84+
static const cressi_edy_layout_t archimede = {
85+
2, /* datetime_y */
86+
5, /* datetime_md */
87+
25, /* datetime_hm */
88+
22, /* avgdepth */
89+
9, /* maxdepth */
90+
45, /* temperature */
91+
29, /* divetime */
92+
43, 1, /* gasmix */
93+
};
94+
8395
static unsigned int
8496
decode (const unsigned char data[], unsigned int offset, unsigned int n)
8597
{
@@ -136,7 +148,12 @@ cressi_edy_parser_create (dc_parser_t **out, dc_context_t *context, const unsign
136148

137149
// Set the default values.
138150
parser->model = model;
139-
parser->layout = &edy;
151+
152+
if (model == ARCHIMEDE) {
153+
parser->layout = &archimede;
154+
} else {
155+
parser->layout = &edy;
156+
}
140157

141158
*out = (dc_parser_t*) parser;
142159

@@ -260,7 +277,7 @@ cressi_edy_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t c
260277
// Current gasmix
261278
if (ngasmixes) {
262279
unsigned int idx = (data[offset + 0] & 0x60) >> 5;
263-
if (parser->model == IQ700)
280+
if (parser->model == IQ700 || parser->model == ARCHIMEDE)
264281
idx = 0; /* FIXME */
265282
if (idx >= ngasmixes) {
266283
ERROR (abstract->context, "Invalid gas mix index.");

src/descriptor.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ static const dc_descriptor_t g_descriptors[] = {
344344
{"Heinrichs Weikamp", "OSTC Sport", DC_FAMILY_HW_OSTC3, 0x13, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH | DC_TRANSPORT_BLE, dc_filter_hw},
345345
{"Heinrichs Weikamp", "OSTC 2 TR", DC_FAMILY_HW_OSTC3, 0x33, DC_TRANSPORT_SERIAL | DC_TRANSPORT_BLUETOOTH | DC_TRANSPORT_BLE, dc_filter_hw},
346346
/* Cressi Edy */
347+
{"Cressi", "Archimede", DC_FAMILY_CRESSI_EDY, 0x01, DC_TRANSPORT_SERIAL, NULL},
347348
{"Tusa", "IQ-700", DC_FAMILY_CRESSI_EDY, 0x05, DC_TRANSPORT_SERIAL, NULL},
348349
{"Cressi", "Edy", DC_FAMILY_CRESSI_EDY, 0x08, DC_TRANSPORT_SERIAL, NULL},
349350
/* Cressi Leonardo */

0 commit comments

Comments
 (0)