Skip to content

Commit

Permalink
Shearwater: Add time synchronisation.
Browse files Browse the repository at this point in the history
Add time synchronisation for Shearwater dive computers.
This synchronises the local time, which is all that is supported by all
Shearwater models except for the Teric.
Time synchronisation including the time zone for the Teric still has to
be added.

Signed-off-by: Michael Keller <[email protected]>
  • Loading branch information
mikeller committed May 20, 2023
1 parent 3a2dc6c commit 763fc68
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 2 deletions.
82 changes: 82 additions & 0 deletions src/shearwater_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@
#define ESC_END 0xDC
#define ESC_ESC 0xDD

// SIDs for CAN WDBI (Write Data By Identifier) as defined by ISO 14229-1
// (the RDBI command is implemented in shearwater_common_identifier)
#define CAN_WDBI_REQUEST_SID 0x2E
#define CAN_WDBI_RESPONSE_SID 0x6E

dc_status_t
shearwater_common_setup (shearwater_common_device_t *device, dc_context_t *context, dc_iostream_t *iostream)
{
Expand Down Expand Up @@ -548,3 +553,80 @@ shearwater_common_identifier (shearwater_common_device_t *device, dc_buffer_t *b

return rc;
}


dc_status_t shearwater_common_can_wdbi (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int id)
{
dc_device_t *abstract = (dc_device_t *)device;

unsigned n = 0;
char request_header[] = {
CAN_WDBI_REQUEST_SID,
(id >> 8) & 0xFF,
id & 0xFF
};
if (!dc_buffer_prepend(buffer, request_header, sizeof(request_header))) {
ERROR(abstract->context, "Insufficient buffer space available.");
return DC_STATUS_NOMEMORY;
}

char response[SZ_PACKET];
dc_status_t rc = shearwater_common_transfer(device, dc_buffer_get_data(buffer), dc_buffer_get_size(buffer), response, sizeof(response), &n);
if (rc != DC_STATUS_SUCCESS) {
return rc;
}

// Verify the response.
if (n < 3 || response[0] != CAN_WDBI_RESPONSE_SID || response[1] != request_header[1] || response[2] != request_header[2]) {
ERROR(abstract->context, "Unexpected response packet.");

return DC_STATUS_PROTOCOL;
}

return rc;
}


dc_status_t shearwater_common_device_timesync(dc_device_t *abstract, const dc_datetime_t *datetime)
{
shearwater_common_device_t *device = (shearwater_common_device_t *)abstract;

dc_datetime_t local_time;
memcpy(&local_time, datetime, sizeof(local_time));

// We need to supply a unix timestamp in _local_ time
local_time.timezone = DC_TIMEZONE_NONE;

dc_ticks_t unix_timestamp = dc_datetime_mktime(&local_time);
if (unix_timestamp == -1) {
ERROR(abstract->context, "Invalid date/time value specified.");

return DC_STATUS_INVALIDARGS;
}

char shearwater_timestamp[] = {
(unix_timestamp >> 24) & 0xFF,
(unix_timestamp >> 16) & 0xFF,
(unix_timestamp >> 8) & 0xFF,
unix_timestamp & 0xFF
};

dc_buffer_t *buffer = dc_buffer_new(WDBI_TIME_PACKET_SIZE);
if (buffer == NULL) {
ERROR(abstract->context, "Insufficient buffer space available.");
dc_buffer_free(buffer);

return DC_STATUS_NOMEMORY;
}

dc_buffer_append(buffer, shearwater_timestamp, 4);

dc_status_t rc = shearwater_common_can_wdbi(device, buffer, ID_TIME);
if (rc != DC_STATUS_SUCCESS) {
ERROR(abstract->context, "Failed to write the dive computer time.");
}

dc_buffer_free(buffer);

return rc;
}
7 changes: 7 additions & 0 deletions src/shearwater_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ extern "C" {
#define ID_FIRMWARE 0x8011
#define ID_LOGUPLOAD 0x8021
#define ID_HARDWARE 0x8050
#define ID_TIME 0x9030

#define WDBI_TIME_PACKET_SIZE 7

#define PREDATOR 2
#define PETREL 3
Expand Down Expand Up @@ -67,6 +70,10 @@ shearwater_common_download (shearwater_common_device_t *device, dc_buffer_t *buf
dc_status_t
shearwater_common_identifier (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int id);

dc_status_t shearwater_common_can_wdbi (shearwater_common_device_t *device, dc_buffer_t *buffer, unsigned int id);

dc_status_t shearwater_common_device_timesync(dc_device_t *abstract, const dc_datetime_t *datetime);

#ifdef __cplusplus
}
#endif /* __cplusplus */
Expand Down
12 changes: 11 additions & 1 deletion src/shearwater_petrel.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,16 @@ typedef struct shearwater_petrel_device_t {
unsigned char fingerprint[4];
} shearwater_petrel_device_t;


static dc_status_t shearwater_petrel_device_timesync(dc_device_t *abstract, const dc_datetime_t *datetime)
{
// The Teric will need a different implementation
// to properly support time zones

return shearwater_common_device_timesync(abstract, datetime);
}


static dc_status_t shearwater_petrel_device_set_fingerprint (dc_device_t *abstract, const unsigned char data[], unsigned int size);
static dc_status_t shearwater_petrel_device_foreach (dc_device_t *abstract, dc_dive_callback_t callback, void *userdata);
static dc_status_t shearwater_petrel_device_close (dc_device_t *abstract);
Expand All @@ -56,7 +66,7 @@ static const dc_device_vtable_t shearwater_petrel_device_vtable = {
NULL, /* write */
NULL, /* dump */
shearwater_petrel_device_foreach, /* foreach */
NULL, /* timesync */
shearwater_petrel_device_timesync,
shearwater_petrel_device_close /* close */
};

Expand Down
2 changes: 1 addition & 1 deletion src/shearwater_predator.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ static const dc_device_vtable_t shearwater_predator_device_vtable = {
NULL, /* write */
shearwater_predator_device_dump, /* dump */
shearwater_predator_device_foreach, /* foreach */
NULL, /* timesync */
shearwater_common_device_timesync,
NULL /* close */
};

Expand Down

0 comments on commit 763fc68

Please sign in to comment.