[PATCH 1/2] Cochran: Merged logic to get for valid profiles in _foreach().
John Van Ostrand
john at vanostrand.com
Tue Mar 8 11:24:07 PST 2016
Previously cochran_check_profiles() was called to establish which
dive is the earliest one with a profile. Now logic in foreach()
counts profile data to detect when dives no longer have valid
profile data.
---
src/cochran_commander.c | 146 +++++++++++++++---------------------------------
src/cochran_commander.h | 4 +-
2 files changed, 46 insertions(+), 104 deletions(-)
diff --git a/src/cochran_commander.c b/src/cochran_commander.c
index 127518d..47ecebb 100644
--- a/src/cochran_commander.c
+++ b/src/cochran_commander.c
@@ -67,7 +67,7 @@ const cochran_device_info_t cochran_cmdr_device_info = {
const cochran_conf_offsets_t cochran_cmdr_conf_offsets = {
0x046, // dive_count
0x06e, // last_log
- 0x071, // last_interdive
+ 0x200, // last_interdive
0x0aa, // serial_number
};
@@ -202,8 +202,6 @@ cochran_read_id(dc_device_t *device, unsigned char *id, int size);
static dc_status_t
cochran_commander_read (dc_device_t *abstract, dc_event_progress_t *progress,
unsigned int address, unsigned char data[], unsigned int size);
-static void
-cochran_check_profiles(dc_device_t *abstract, cochran_data_t *data);
static dc_status_t
@@ -599,13 +597,17 @@ cochran_read_config (dc_device_t *abstract, cochran_data_t *data, dc_event_progr
dc_status_t rc;
unsigned char command[2] = { 0x96, 0x00 };
- rc = cochran_packet(device, progress, command, sizeof(command), data->config, sizeof(data->config), 0);
- if (rc != DC_STATUS_SUCCESS)
- return rc;
+ // Read two 512 byte blocks into one 1024 byte buffer
+ for (int i = 0; i < 2; i++) {
+ command[1] = i;
+ rc = cochran_packet(device, progress, command, sizeof(command), data->config + i * 512, sizeof(data->config) / 2, 0);
+ if (rc != DC_STATUS_SUCCESS)
+ return rc;
- vendor.data = data->config;
- vendor.size = sizeof(data->config);
- device_event_emit (abstract, DC_EVENT_VENDOR, &vendor);
+ vendor.data = data->config + i * 512;
+ vendor.size = sizeof(data->config) / 2;
+ device_event_emit (abstract, DC_EVENT_VENDOR, &vendor);
+ }
return DC_STATUS_SUCCESS;
}
@@ -806,9 +808,6 @@ cochran_commander_device_read_all (dc_device_t *abstract, cochran_data_t *data)
if (rc != DC_STATUS_SUCCESS)
return rc;
- // Determine logs that haven't had profile data overwritten
- cochran_check_profiles(abstract, data);
-
return DC_STATUS_SUCCESS;
}
@@ -919,6 +918,17 @@ cochran_commander_device_foreach (dc_device_t *abstract,
if (rc != DC_STATUS_SUCCESS)
return rc;
+ // Calculate profile RB effective head pointer
+ // Cochran seems to erase 8K chunks so round up.
+ int last_start_address = (array_uint32_le(data.config + device->conf_ptr->last_interdive) & 0xfffff000) + 0x2000;
+ if (last_start_address < device->info->rb_profile_begin || last_start_address > device->info->rb_profile_end) {
+ ERROR(abstract->context, "Invalid profile ringbuffer head pointer in Cochra config block.");
+ return DC_STATUS_DATAFORMAT;
+ }
+
+ // We track profile ringbuffer usage to determine which dives have profile data
+ int profile_capacity_remaining = device->info->rb_profile_end - device->info->rb_profile_begin;
+
// Loop through each dive
int i;
for (i = data.dive_count - 1; i > data.fp_dive_num; i--) {
@@ -940,19 +950,32 @@ cochran_commander_device_foreach (dc_device_t *abstract,
// Corrupt dive, guess the end address
sample_end_address = cochran_guess_sample_end_address(device, &data, i);
- sample = data.sample + sample_start_address - data.sample_data_offset;
+ // Determine if sample exists
+ if (profile_capacity_remaining > 0) {
+ // Subtract this dive's profile size including post-dive events
+ profile_capacity_remaining -= (last_start_address - sample_start_address);
+ // Adjust for a dive that wraps the buffer
+ if (sample_start_address > last_start_address)
+ profile_capacity_remaining -= device->info->rb_profile_end - device->info->rb_profile_begin;
+ }
+ last_start_address = sample_start_address;
- // Determine size of sample
- unsigned int dive_num =array_uint16_le(log_entry + device->log_ptr->dive_number);
- if (dive_num >= data.profile_tail)
- sample_size = sample_end_address - sample_start_address;
- else
+ if (profile_capacity_remaining < 0) {
+ // There is no profile for this dive
+ sample = NULL;
sample_size = 0;
+ WARNING(abstract->context, "Profile data for dive %d was overwritten by newer dives.",
+ array_uint16_le(log_entry + device->log_ptr->dive_number));
+ } else {
+ // Calculate the size of the profile only
+ sample = data.sample + sample_start_address - data.sample_data_offset;
+ sample_size = sample_end_address - sample_start_address;
- if (sample_size < 0)
- // Adjust for ring buffer wrap-around
- sample_size += device->info->rb_profile_end
- - device->info->rb_profile_begin;
+ if (sample_size < 0)
+ // Adjust for ring buffer wrap-around
+ sample_size += device->info->rb_profile_end
+ - device->info->rb_profile_begin;
+ }
fingerprint = log_entry; // Date bytes
@@ -990,82 +1013,3 @@ cochran_commander_device_foreach (dc_device_t *abstract,
return DC_STATUS_SUCCESS;
}
-
-
-/*
-* cochran_check_profiles(dc_device_t *abstract)
-*
-* Scan logs to identify which have valid profile data, i.e. the profiles
-* have not been overwritten in the ringbuffer.
-*
-*/
-
-static void
-cochran_check_profiles(dc_device_t *abstract, cochran_data_t *data) {
- cochran_device_t *device = (cochran_device_t *) abstract;
-
- // Find head log entry
- // Set handy point to first dive's dive number
- unsigned char *l = data->logbook + device->log_ptr->dive_number;
- int head;
- for (head = 0; head < device->info->logbook_entry_count - 1; head ++) {
- int this_dive = array_uint16_le(l);
- l += device->info->logbook_entry_size;
- int next_dive = array_uint16_le(l);
-
- if (next_dive < this_dive || next_dive == 0xFFFF)
- break;
- }
-
- // This is the last piece of data
- unsigned int head_ptr;
- if (device->info->endian == ENDIAN_LE)
- head_ptr = array_uint32_le(data->config + device->conf_ptr->last_log);
- else
- head_ptr = array_uint32_be(data->config + device->conf_ptr->last_log);
-
- // Cochran (commander at least) erases 8k blocks, so round up
- head_ptr = (head_ptr & 0xfffff000) + 0x2000;
-
- // Now move backwards until we find a profile that overlaps this one.
- // Wrap around the ring buffer if needed.
-
- int tail;
- int profile_wrap = 0;
- int n = head - 1;
- if (n < 0)
- n = MIN(device->info->logbook_entry_count - 1, head);
-
- while (n != head) {
- unsigned int start_dive_ptr = array_uint32_le(data->logbook + device->info->logbook_entry_size * n + device->log_ptr->profile_begin_offset);
- unsigned int end_dive_ptr = array_uint32_le(data->logbook + device->info->logbook_entry_size * n + device->log_ptr->profile_end_offset);
-
- if (start_dive_ptr == 0xFFFFFFFF || start_dive_ptr == 0) {
- n--;
- if (n < 0)
- n = MIN(device->info->logbook_entry_count - 1, head);
- continue;
- }
-
- tail = n;
-
- if (profile_wrap) {
- if (start_dive_ptr < head_ptr) {
- // We've found the last valid dive
- break;
- }
- } else {
- if (start_dive_ptr > end_dive_ptr)
- profile_wrap = 1;
- }
-
- n--;
- if (n < 0)
- n = MIN(device->info->logbook_entry_count - 1, head);
- }
-
- data->log_head = head;
- data->profile_head = head;
-
- data->profile_tail = tail;
-}
diff --git a/src/cochran_commander.h b/src/cochran_commander.h
index f6e3921..14cfedf 100644
--- a/src/cochran_commander.h
+++ b/src/cochran_commander.h
@@ -96,14 +96,12 @@ typedef struct cochran_log_offsets_t {
} cochran_log_offsets_t;
typedef struct cochran_data_t {
- unsigned char config[512];
+ unsigned char config[1024];
unsigned char *logbook;
unsigned char *sample;
unsigned short int dive_count;
int fp_dive_num;
- int log_head, log_tail; // head and tail for log ringbuffer
- int profile_head, profile_tail; // Entries that have valid profiles
unsigned int logbook_size;
--
2.4.3
More information about the devel
mailing list