[PATCH 005/007] Cochran: Using structs now to switch layouts for different DCs.

John Van Ostrand john at vanostrand.com
Fri Jan 8 11:23:47 PST 2016


I removed the conf member from the data struct, that's not being
carried around any more. Each function that needs layout information
will be call cochran_commander_get_layout to obtain the layout to use
in parsing the data.
---
 src/cochran_commander.c        | 320 ++++++++++++++++++++++-------------------
 src/cochran_commander.h        |  54 +++++--
 src/cochran_commander_parser.c |  19 +--
 3 files changed, 224 insertions(+), 169 deletions(-)

diff --git a/src/cochran_commander.c b/src/cochran_commander.c
index 2287541..036ca6c 100644
--- a/src/cochran_commander.c
+++ b/src/cochran_commander.c
@@ -38,6 +38,105 @@
 	rc == -1 ? DC_STATUS_IO : DC_STATUS_TIMEOUT \
 )
 
+
+/*
+*  Hardware and data layout information for various Cochran models.
+*
+*  EMC models are identical except for the size of logbook and profile
+*  memory.
+*/
+static cochran_layout_t cochran_layout_cmdr = {
+	 COCHRAN_MODEL_COMMANDER_AIR_NITROX,	/* model */
+	 ENDIAN_BE,			/* endian */
+	 DATE_MSDHYM,		/* date_format */
+	 ADDRESS_24_BIT,	/* address_size */
+	 115200,			/* high_baud_rate */
+
+	 0x00000000,		/* rb_logbook_begin */
+	 0x00020000,		/* rb_logbook_end */
+	 256,				/* rb_log_size */
+	 0x00020000,		/* rb_profile_begin */
+	 0x00100000,		/* rb_profile_end */
+
+	 0x006,				/* pt_log_profile_begin */
+	 0x01e,				/* pt_log_profile_pre */
+	 0x046,				/* pt_log_dive_number */
+	 0x080,				/* pt_log_profile_end */
+
+	 0x046,				/* pt_conf_dive_count */
+	 0x06e,				/* pt_conf_last_log */
+	 0x0a7,				/* pt_conf_last_interdive */
+};
+
+static cochran_layout_t cochran_layout_emc20 = {
+	 COCHRAN_MODEL_EMC_20,	/* model */
+	 ENDIAN_LE,			/* endian */
+	 DATE_SMHDMY,		/* date_format */
+	 ADDRESS_32_BIT,	/* address_size */
+	 825600,			/* high_baud_rate */
+
+	 0x00000000,		/* rb_logbook_begin */
+	 0x00080000,		/* rb_logbook_end */
+	 512,				/* rb_log_size */
+	 0x00094000,		/* rb_profile_begin */
+	 0x01000000,		/* rb_profile_end */
+
+	 0x006,				/* pt_log_profile_begin */
+	 0x01e,				/* pt_log_profile_pre */
+	 0x056,				/* pt_log_dive_number */
+	 0x100,				/* pt_log_profile_end */
+
+	 0x0d2,				/* pt_conf_dive_count */
+	 0x142,				/* pt_conf_last_log */
+	 0x13e,				/* pt_conf_last_interdive */
+};
+
+static cochran_layout_t cochran_layout_emc16 = {
+	 COCHRAN_MODEL_EMC_16,	/* model */
+	 ENDIAN_LE,			/* endian */
+	 DATE_SMHDMY,		/* date_format */
+	 ADDRESS_32_BIT,	/* address_size */
+	 825600,			/* high_baud_rate */
+
+	 0x00000000,		/* rb_logbook_begin */
+	 0x00080000,		/* rb_logbook_end */
+	 512,				/* rb_log_size */
+	 0x00094000,		/* rb_profile_begin */
+	 0x00800000,		/* rb_profile_end */
+
+	 0x006,				/* pt_log_profile_begin */
+	 0x01e,				/* pt_log_profile_pre */
+	 0x056,				/* pt_log_dive_number */
+	 0x100,				/* pt_log_profile_end */
+
+	 0x0d2,				/* pt_conf_dive_count */
+	 0x142,				/* pt_conf_last_log */
+	 0x13e,				/* pt_conf_last_interdive */
+};
+
+static cochran_layout_t cochran_layout_emc14 = {
+	 COCHRAN_MODEL_EMC_14,	/* model */
+	 ENDIAN_LE,			/* endian */
+	 DATE_SMHDMY,		/* date_format */
+	 ADDRESS_32_BIT,	/* address_size */
+	 825600,			/* high_baud_rate */
+
+	 0x00000000,		/* rb_logbook_begin */
+	 0x00020000,		/* rb_logbook_end */
+	 512,				/* rb_log_size */
+	 0x00022000,		/* rb_profile_begin */
+	 0x00200000,		/* rb_profile_end */
+
+	 0x006,				/* pt_log_profile_begin */
+	 0x01e,				/* pt_log_profile_pre */
+	 0x056,				/* pt_log_dive_number */
+	 0x100,				/* pt_log_profile_end */
+
+	 0x0d2,				/* pt_conf_dive_count */
+	 0x142,				/* pt_conf_last_log */
+	 0x13e,				/* pt_conf_last_interdive */
+};
+
 static const dc_device_vtable_t cochran_commander_device_vtable = {
 	DC_FAMILY_COCHRAN_COMMANDER,
 	cochran_commander_device_set_fingerprint,	/* set_fingerprint */
@@ -83,7 +182,8 @@ cochran_packet (cochran_device_t *device, dc_event_progress_t *progress,
 		serial_sleep(device->port, 45);
 
 		// Rates are odd, like 825600 for the EMC, 115200 for commander
-		rc = serial_configure(device->port, device->data.conf.high_baud, 8,
+		cochran_layout_t *layout = cochran_commander_get_layout(device->model_string);
+		rc = serial_configure(device->port, layout->high_baud_rate, 8,
 						SERIAL_PARITY_NONE, 2, SERIAL_FLOWCONTROL_NONE);
 		if (rc == -1) {
 			ERROR (abstract->context, "Failed to set the high baud rate.");
@@ -142,7 +242,7 @@ cochran_commander_serial_setup (cochran_device_t *device, dc_context_t *context)
 
 	serial_set_break(device->port, 1);
 	serial_sleep(device->port, 16);
-	
+
 	serial_set_break(device->port, 0);
 
 	// Set the timeout for receiving data (5000 ms).
@@ -185,6 +285,7 @@ cochran_commander_device_open (dc_device_t **out, dc_context_t *context,
 		const char *name)
 {
 	dc_status_t rc;
+	cochran_layout_t *layout;
 
 	if (out == NULL)
 		return DC_STATUS_INVALIDARGS;
@@ -222,14 +323,18 @@ cochran_commander_device_open (dc_device_t **out, dc_context_t *context,
 		return rc;
 	}
 
+	memcpy(device->model_string, device->data.id + 0x3b, 8);
+	device->model_string[8] = 0;
+	layout = cochran_commander_get_layout(device->model_string);
+
 	// Check ID
-	if ((device->data.conf.model & 0xFF0000) == COCHRAN_MODEL_UNKNOWN) {
+	if ((layout->model & 0xFF0000) == COCHRAN_MODEL_UNKNOWN) {
 		ERROR (context,
 			"Unknown Cochran model %02x %02x %02x %02x %02x %02x %02x %02x",
-			*(device->data.id + 0x3B),     *(device->data.id + 0x3B + 1),
-			*(device->data.id + 0x3B + 2), *(device->data.id + 0x3B + 3),
-			*(device->data.id + 0x3B + 4), *(device->data.id + 0x3B + 5),
-			*(device->data.id + 0x3B + 6), *(device->data.id + 0x3B + 7));
+			device->model_string[0], device->model_string[1],
+			device->model_string[2], device->model_string[3],
+			device->model_string[4], device->model_string[5],
+			device->model_string[6], device->model_string[7]);
 		serial_close (device->port);
 		free (device);
 		return DC_STATUS_UNSUPPORTED;
@@ -293,14 +398,15 @@ cochran_commander_read (dc_device_t *abstract, dc_event_progress_t *progress,
 		unsigned int address, unsigned char data[], unsigned int size)
 {
 	cochran_device_t *device = (cochran_device_t*) abstract;
+	cochran_layout_t *layout = cochran_commander_get_layout(device->model_string);
 
 	// Build the command
 	unsigned char command[10];
 	unsigned char command_size;
 
-	switch (device->data.conf.address_length)
+	switch (layout->address_size)
 	{
-	case COCHRAN_ADDRESS_LENGTH_32:
+	case ADDRESS_32_BIT:
 		// EMC uses 32 bit addressing
 		command[0] = 0x15;
 		command[1] = (address      ) & 0xff;
@@ -314,7 +420,7 @@ cochran_commander_read (dc_device_t *abstract, dc_event_progress_t *progress,
 		command[9] = 0x05;
 		command_size = 10;
 		break;
-	case COCHRAN_ADDRESS_LENGTH_24:
+	case ADDRESS_24_BIT:
 		// Commander uses 24 byte addressing
 		command[0] = 0x15;
 		command[1] = (address      ) & 0xff;
@@ -339,89 +445,28 @@ cochran_commander_read (dc_device_t *abstract, dc_event_progress_t *progress,
 }
 
 
-void
-cochran_commander_get_config (const unsigned char *model,
-		cochran_config_t *conf)
+cochran_layout_t *
+cochran_commander_get_layout (const unsigned char *model)
 {
 	// Determine model
 	if (memcmp(model, "AM2315\xA3\x71", 8) == 0)
 	{
-		conf->model = COCHRAN_MODEL_EMC_20;
-		conf->log_size = 512;
-		conf->sample_memory_start_address = 0x94000;
-		conf->sample_memory_end_address = 0x1000000;	// 16MB
-		conf->dive_num_ptr = 0x56;
-		conf->dive_count_ptr = 0xD2;
-		conf->dive_count_endian = COCHRAN_LE_TYPE;
-		conf->sample_end_ptr = 256;
-		conf->log_pre_dive_ptr = 30;
-		conf->log_end_dive_ptr = 256;
-		conf->last_interdive_ptr = 233;
-		conf->last_entry_ptr = 194;
-		conf->date_format = COCHRAN_DATE_FORMAT_SMHDMY;
-		conf->address_length = COCHRAN_ADDRESS_LENGTH_32;
-		conf->high_baud = 825600;
+		return &cochran_layout_emc20;
 	}
 	else if (memcmp(model, "AMA315\xC3\xC5", 8) == 0)
 	{
-		conf->model = COCHRAN_MODEL_EMC_16;
-		conf->log_size = 512;
-		conf->sample_memory_start_address = 0x94000;
-		conf->sample_memory_end_address = 0x800000;	// 8MB, a guess
-		conf->dive_num_ptr = 0x56;
-		conf->dive_count_ptr = 0xD2;
-		conf->dive_count_endian = COCHRAN_LE_TYPE;
-		conf->sample_end_ptr = 256;
-		conf->log_pre_dive_ptr = 30;
-		conf->log_end_dive_ptr = 256;
-		conf->last_interdive_ptr = 233;
-		conf->last_entry_ptr = 194;
-		conf->date_format = COCHRAN_DATE_FORMAT_SMHDMY;
-		conf->address_length = COCHRAN_ADDRESS_LENGTH_32;
-		conf->high_baud = 825600;
+		return &cochran_layout_emc16;
 	}
 	else if (memcmp(model, "AM7303\x8b\x43", 8) == 0)
 	{
-		conf->model = COCHRAN_MODEL_EMC_14;
-		conf->log_size = 512;
-		conf->sample_memory_start_address = 0x22000;
-		conf->sample_memory_end_address = 0x200000;	// 2MB, a guess
-		conf->dive_num_ptr = 0x56;
-		conf->dive_count_ptr = 0xD2;
-		conf->dive_count_endian = COCHRAN_LE_TYPE;
-		conf->sample_end_ptr = 256;
-		conf->log_pre_dive_ptr = 30;
-		conf->log_end_dive_ptr = 256;
-		conf->last_interdive_ptr = 233;
-		conf->last_entry_ptr = 194;
-		conf->date_format = COCHRAN_DATE_FORMAT_SMHDMY;
-		conf->address_length = COCHRAN_ADDRESS_LENGTH_32;
-		conf->high_baud = 825600;
+		return &cochran_layout_emc14;
 	}
 	else if (memcmp(model, "AM\x11""2212\x02", 8) == 0)
 	{
-		conf->model = COCHRAN_MODEL_COMMANDER_AIR_NITROX;
-		conf->log_size = 256;
-		conf->sample_memory_start_address = 0x20000;
-		conf->sample_memory_end_address = 0x100000;
-		conf->dive_num_ptr = 0x46;
-		conf->dive_count_ptr = 0x46;
-		conf->dive_count_endian = COCHRAN_BE_TYPE;
-		conf->sample_end_ptr = 256;
-		conf->log_pre_dive_ptr = 30;
-		conf->log_end_dive_ptr = 128;
-		conf->last_interdive_ptr = 167;
-		conf->last_entry_ptr = -1;
-		conf->date_format = COCHRAN_DATE_FORMAT_MSDHYM;
-		conf->address_length = COCHRAN_ADDRESS_LENGTH_24;
-		conf->high_baud = 115200;
-	}
-	else
-	{
-		conf->model = 0;
+		return &cochran_layout_cmdr;
 	}
 
-	return;
+	return NULL;
 }
 
 
@@ -449,9 +494,6 @@ cochran_read_id (dc_device_t *abstract)
 			return rc;
 	}
 
-	cochran_commander_get_config(device->data.id + 0x3B, &device->data.conf);
-
-
 	return DC_STATUS_SUCCESS;
 }
 
@@ -488,10 +530,11 @@ cochran_read_misc (dc_device_t *abstract, dc_event_progress_t *progress)
 	cochran_device_t *device = (cochran_device_t *) abstract;
 	dc_status_t rc;
 	dc_event_vendor_t vendor;
+	cochran_layout_t *layout = cochran_commander_get_layout(device->model_string);
 
 	unsigned char command[7] = { 0x89, 0x05, 0x00, 0x00, 0x00, 0xDC, 0x05 };
 
-	switch (device->data.conf.model & 0xFF0000)
+	switch (layout->model & 0xFF0000)
 	{
 	case COCHRAN_MODEL_COMMANDER_FAMILY:
 		command[2] = 0xCA;
@@ -563,14 +606,14 @@ cochran_find_fingerprint(dc_device_t *abstract)
 {
 	cochran_device_t *device = (cochran_device_t *) abstract;
 	cochran_data_t *d = (cochran_data_t *) &device->data;
-	cochran_config_t *conf = &d->conf;
+	cochran_layout_t *layout = cochran_commander_get_layout(device->model_string);
 
 	// Skip to fingerprint to reduce time
 	d->fp_dive_num = d->dive_count - 1;
 
 	while (d->fp_dive_num >= 0 && memcmp(&d->fingerprint,
-						 d->logbook + d->fp_dive_num * conf->log_size
-						+ conf->dive_num_ptr,
+						 d->logbook + d->fp_dive_num * layout->rb_log_size
+						+ layout->pt_log_dive_number,
 						 sizeof(d->fingerprint)))
 		d->fp_dive_num--;
 }
@@ -581,9 +624,9 @@ cochran_get_sample_parms(dc_device_t *abstract)
 {
 	cochran_device_t *device = (cochran_device_t *) abstract;
 	cochran_data_t *d = (cochran_data_t *) &device->data;
-	cochran_config_t *conf = &d->conf;
 	unsigned int pre_dive_offset = 0, end_dive_offset = 0;
 	unsigned int low_offset, high_offset;
+	cochran_layout_t *layout = cochran_commander_get_layout(device->model_string);
 
 	// Find lowest and highest offsets into sample data
 	low_offset = 0xFFFFFFFF;
@@ -591,15 +634,15 @@ cochran_get_sample_parms(dc_device_t *abstract)
 
 	int i;
 	for (i = d->fp_dive_num + 1; i < d->dive_count; i++) {
-		pre_dive_offset = array_uint32_le (&(d->logbook[i * conf->log_size
-				+ conf->log_pre_dive_ptr]));
-		end_dive_offset = array_uint32_le (&(d->logbook[i * conf->log_size
-				+ conf->log_end_dive_ptr]));
+		pre_dive_offset = array_uint32_le (&(d->logbook[i * layout->rb_log_size
+				+ layout->pt_log_profile_pre]));
+		end_dive_offset = array_uint32_le (&(d->logbook[i * layout->rb_log_size
+				+ layout->pt_log_profile_begin]));
 
 		// Check for ring buffer wrap-around.
 		if (pre_dive_offset > end_dive_offset)
 			break;
-	
+
 		if (pre_dive_offset < low_offset)
 			low_offset = pre_dive_offset;
 		if (end_dive_offset > high_offset && end_dive_offset != 0xFFFFFFFF )
@@ -611,8 +654,8 @@ cochran_get_sample_parms(dc_device_t *abstract)
 		// I'll round to 128K, dives longer than 12 hrs aren't likely
 		// and memory in sizes not rounded to 128K might be odd.
 		high_offset = ((pre_dive_offset - 1) & 0xE0000) + 0x20000;
-		conf->sample_memory_end_address = high_offset;
-		low_offset = conf->sample_memory_start_address;
+		layout->rb_profile_end = high_offset;
+		low_offset = layout->rb_profile_begin;
 		d->sample_data_offset = low_offset;
 		d->sample_size = high_offset - low_offset;
 	} else if (low_offset < 0xFFFFFFFF && high_offset > 0) {
@@ -668,25 +711,19 @@ cochran_commander_device_read_all (dc_device_t *abstract)
 {
 	cochran_device_t *device = (cochran_device_t *) abstract;
 	cochran_data_t *d = (cochran_data_t *) &device->data;
-	cochran_config_t *conf = &d->conf;
 	dc_event_progress_t progress = {0};
+	cochran_layout_t *layout = cochran_commander_get_layout(device->model_string);
 
 	dc_status_t rc;
-	int sample_size;
-	int max_config, max_misc, max_logbook, max_sample;
+	int max_config, max_logbook, max_sample;
 
-	if ((conf->model & 0xFFFF0000) == COCHRAN_MODEL_COMMANDER_FAMILY)
-		sample_size = 2;
-	else
-		sample_size = 3;
-
-	max_config = 512 * 4; 					// max config page size
-	max_misc = 1500;						// misc size
-	max_logbook = 1024 * conf->log_size; 	// max logbook size
-	max_sample = 1450 * 3600 * sample_size;	// max sample size
+	// Calculate max data sizes
+	max_config = 512 * 2;
+	max_logbook =layout->rb_logbook_end - layout->rb_logbook_begin;
+	max_sample = layout->rb_profile_end - layout->rb_profile_begin;
 
 	progress.current = 0;
-	progress.maximum = max_config + max_misc + max_logbook + max_sample;
+	progress.maximum = max_config + max_logbook + max_sample;
 	device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
 
 	// Read config
@@ -694,21 +731,13 @@ cochran_commander_device_read_all (dc_device_t *abstract)
 	if (rc != DC_STATUS_SUCCESS)
 		return rc;
 
-	// Update max based on what's read
-	progress.maximum -=  max_config - progress.current;
-	device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
-
-	rc = cochran_read_misc(abstract, &progress);
-	if (rc != DC_STATUS_SUCCESS)
-		return rc;
-
 	// Determine size of dive list to read. Round up to nearest 16K
-	if (conf->dive_count_endian == COCHRAN_LE_TYPE)
-		d->dive_count = array_uint16_le (d->config[0] + conf->dive_count_ptr);
-	else 
-		d->dive_count = array_uint16_be (d->config[0] + conf->dive_count_ptr);
-	
-	d->logbook_size = ((d->dive_count * conf->log_size) & 0xFFFFC000)
+	if (layout->endian == ENDIAN_LE)
+		d->dive_count = array_uint16_le (d->config[0] + layout->pt_conf_dive_count);
+	else
+		d->dive_count = array_uint16_be (d->config[0] + layout->pt_conf_dive_count);
+
+	d->logbook_size = ((d->dive_count * layout->rb_log_size) & 0xFFFFC000)
 		 + 0x4000;
 
 	progress.maximum -= max_logbook - d->logbook_size;
@@ -719,7 +748,7 @@ cochran_commander_device_read_all (dc_device_t *abstract)
 		return rc;
 
 	// Determine sample memory to read
-	cochran_find_fingerprint(abstract);	
+	cochran_find_fingerprint(abstract);
 	cochran_get_sample_parms(abstract);
 
 	progress.maximum -= max_sample - d->sample_size;
@@ -745,6 +774,7 @@ cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *data)
 	cochran_data_t *d = (cochran_data_t *) &device->data;
 	dc_event_progress_t progress = {0};
 	dc_event_vendor_t vendor;
+	cochran_layout_t *layout = cochran_commander_get_layout(device->model_string);
 
 	dc_status_t rc;
 	int size;
@@ -756,7 +786,7 @@ cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *data)
 	}
 
 	// Determine size for progress
-	size = 512 + 512 + 1500 + d->conf.sample_memory_end_address;
+	size = 512 + 512 + 1500 + layout->rb_profile_end;
 
 	progress.current = 0;
 	progress.maximum = size;
@@ -776,7 +806,7 @@ cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *data)
 	rc = cochran_read_config (abstract, &progress);
 	if (rc != DC_STATUS_SUCCESS)
 		return rc;
-	
+
 	rc = cochran_read_misc (abstract, &progress);
 	if (rc != DC_STATUS_SUCCESS)
 		return rc;
@@ -784,7 +814,7 @@ cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *data)
 	// Read logbook and sample memory
 
 	// Reserve space
-	if (!dc_buffer_resize(data, d->conf.sample_memory_end_address)) {
+	if (!dc_buffer_resize(data, layout->rb_profile_end)) {
 		ERROR(abstract->context, "Insufficient buffer space available.");
 		return DC_STATUS_NOMEMORY;
 	}
@@ -795,8 +825,8 @@ cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *data)
 	cochran_commander_serial_setup(device, abstract->context);
 
 	// Read the sample data, from 0 to sample end will include logbook
-	rc = cochran_commander_read (abstract, &progress, 0, 
-			dc_buffer_get_data(data), d->conf.sample_memory_end_address);
+	rc = cochran_commander_read (abstract, &progress, 0,
+			dc_buffer_get_data(data), layout->rb_profile_end);
 	if (rc != DC_STATUS_SUCCESS) {
 		ERROR (abstract->context, "Failed to read the sample data.");
 		return rc;
@@ -813,18 +843,17 @@ cochran_commander_device_dump (dc_device_t *abstract, dc_buffer_t *data)
 */
 
 static unsigned int
-cochran_guess_sample_end_address(cochran_data_t *data, unsigned int log_num)
+cochran_guess_sample_end_address(cochran_layout_t *layout, cochran_data_t *data, unsigned int log_num)
 {
-	cochran_config_t *conf = &data->conf;
-	const unsigned char *log = data->logbook + data->conf.log_size * log_num;
+	const unsigned char *log = data->logbook + layout->rb_log_size * log_num;
 
 	if (log_num == data->dive_count)
 		// Return next usable address from config0 page
 		return array_uint32_le(data->config[0]
-			+ conf->sample_memory_end_address);
+			+ layout->rb_profile_end);
 
 	// Next log's start address
-	return array_uint32_le(log + conf->log_size + 6);
+	return array_uint32_le(log + layout->rb_log_size + 6);
 }
 
 
@@ -834,7 +863,7 @@ cochran_commander_device_foreach (dc_device_t *abstract,
 {
 	cochran_device_t *device = (cochran_device_t *) abstract;
 	cochran_data_t *data = &device->data;
-	cochran_config_t *conf = &data->conf;
+	cochran_layout_t *layout = cochran_commander_get_layout(device->model_string);
 
 	unsigned int sample_start_address, sample_end_address;
 	dc_status_t rc;
@@ -850,14 +879,14 @@ cochran_commander_device_foreach (dc_device_t *abstract,
 	// Loop through each dive
 	int i;
 	for (i = data->dive_count - 1; i > data->fp_dive_num; i--) {
-		log = data->logbook + i * conf->log_size;
+		log = data->logbook + i * layout->rb_log_size;
 
 		sample_start_address = array_uint32_le (log + 6);
-		sample_end_address = array_uint32_le (log + conf->log_size / 2);
+		sample_end_address = array_uint32_le (log + layout->rb_log_size / 2);
 
 		if (sample_end_address == 0xFFFFFFFF)
 			// Corrupt dive, guess the end address
-			sample_end_address = cochran_guess_sample_end_address(data, i);
+			sample_end_address = cochran_guess_sample_end_address(layout, data, i);
 
 		sample = data->sample + sample_start_address - data->sample_data_offset;
 
@@ -865,28 +894,29 @@ cochran_commander_device_foreach (dc_device_t *abstract,
 		sample_size = sample_end_address - sample_start_address;
 		if (sample_size < 0)
 			// Adjust for ring buffer wrap-around
-			sample_size += conf->sample_memory_end_address
-				- conf->sample_memory_start_address;
+			sample_size += layout->rb_profile_end
+				- layout->rb_profile_begin;
 
-		fingerprint = log + conf->dive_num_ptr;
+		fingerprint = log + layout->pt_log_dive_number;
 
 		// Build dive blob
-		dive_size = COCHRAN_MODEL_SIZE + conf->log_size + sample_size;
+		dive_size = COCHRAN_MODEL_SIZE + layout->rb_log_size + sample_size;
 		dive = malloc(dive_size);
 		if (dive == NULL)
 			return DC_STATUS_NOMEMORY;
 
-		memcpy(dive, data->id + 0x3B, 8);	// model string
-		memcpy(dive + COCHRAN_MODEL_SIZE, log, conf->log_size);
+		memcpy(dive, data->id + 0x3B, 8);       // model string
+		memcpy(dive + COCHRAN_MODEL_SIZE, log, layout->rb_log_size);
+
 		if (sample_start_address <= sample_end_address) {
-			memcpy(dive + COCHRAN_MODEL_SIZE + conf->log_size, sample,
+			memcpy(dive + COCHRAN_MODEL_SIZE + layout->rb_log_size, sample,
 				sample_size);
 		} else {
 			// It wrapped the buffer, copy two sections
-			unsigned int size = conf->sample_memory_end_address
+			unsigned int size = layout->rb_profile_end
 				- sample_start_address;
-			memcpy(dive + COCHRAN_MODEL_SIZE + conf->log_size, sample, size);
-			memcpy(dive + COCHRAN_MODEL_SIZE + conf->log_size + size,
+			memcpy(dive + COCHRAN_MODEL_SIZE + layout->rb_log_size, sample, size);
+			memcpy(dive + COCHRAN_MODEL_SIZE + layout->rb_log_size + size,
 				data->sample, sample_size - size);
 		}
 
diff --git a/src/cochran_commander.h b/src/cochran_commander.h
index 57962d8..f9d09ec 100644
--- a/src/cochran_commander.h
+++ b/src/cochran_commander.h
@@ -32,15 +32,6 @@
 #define COCHRAN_CMDR_LOG_SIZE		256
 #define COCHRAN_CMDR_SAMPLE_SIZE	2
 
-#define COCHRAN_LE_TYPE 0
-#define COCHRAN_BE_TYPE 1
-
-#define COCHRAN_DATE_FORMAT_SMHDMY 0
-#define COCHRAN_DATE_FORMAT_MSDHYM 1
-
-#define COCHRAN_ADDRESS_LENGTH_32 0
-#define COCHRAN_ADDRESS_LENGTH_24 1
-
 typedef enum cochran_model_t {
 	COCHRAN_MODEL_UNKNOWN = 0,
 	COCHRAN_MODEL_EMC_FAMILY = 1 << 16,
@@ -51,7 +42,46 @@ typedef enum cochran_model_t {
 	COCHRAN_MODEL_COMMANDER_AIR_NITROX,
 } cochran_model_t;
 
+typedef enum cochran_endian_t {
+	ENDIAN_LE,
+	ENDIAN_BE,
+} cochran_endian_t;
+
+typedef enum cochran_dateformat_t {
+	DATE_SMHDMY,
+	DATE_MSDHYM,
+} cochran_dateformat_t;
+
+typedef enum cochran_addresssize_t {
+	ADDRESS_24_BIT,
+	ADDRESS_32_BIT,
+} cochran_addresssize_t;
+
+typedef struct cochran_layout_t {
+	cochran_model_t model;
+	cochran_endian_t endian;
+	cochran_dateformat_t date_format;
+	cochran_addresssize_t address_size;
+	unsigned int high_baud_rate;
+
+	unsigned int rb_logbook_begin;
+	unsigned int rb_logbook_end;
+	unsigned int rb_log_size;
+	unsigned int rb_profile_begin;
+	unsigned int rb_profile_end;
+
+	unsigned int pt_log_profile_begin;
+	unsigned int pt_log_profile_pre;
+	unsigned int pt_log_dive_number;
+	unsigned int pt_log_profile_end;
+
+	unsigned int pt_conf_dive_count;
+	unsigned int pt_conf_last_log;
+	unsigned int pt_conf_last_interdive;
+} cochran_layout_t;
+
 // Device configuration items
+/*
 typedef struct cochran_config_t {
 	cochran_model_t model;
 	int log_size;
@@ -69,6 +99,7 @@ typedef struct cochran_config_t {
 	int address_length;
 	int high_baud; 			// baud rate to switch to for log/sample download
 } cochran_config_t;
+*/
 
 typedef struct cochran_data_t {
 	unsigned char id0[67];
@@ -89,14 +120,13 @@ typedef struct cochran_data_t {
 
 	unsigned int sample_data_offset;
 	unsigned int sample_size;
-
-	cochran_config_t conf;
 } cochran_data_t;
 
 typedef struct cochran_device_t {
 	dc_device_t base;
 	const char *name;				// serial port name
 	serial_t *port;
+	unsigned char model_string[COCHRAN_MODEL_SIZE + 1];
 	cochran_data_t data;			// dive data used in parsing
 } cochran_device_t;
 
@@ -156,4 +186,4 @@ dc_status_t cochran_commander_device_foreach (dc_device_t *abstract,
 		dc_dive_callback_t callback, void *userdata);
 dc_status_t cochran_commander_device_dump (dc_device_t *abstract,
 		dc_buffer_t *data);
-void cochran_commander_get_config(const unsigned char *model, cochran_config_t *conf);
+cochran_layout_t *cochran_commander_get_layout(const unsigned char *model);
diff --git a/src/cochran_commander_parser.c b/src/cochran_commander_parser.c
index 8db87cf..434d332 100644
--- a/src/cochran_commander_parser.c
+++ b/src/cochran_commander_parser.c
@@ -109,11 +109,10 @@ cochran_commander_parser_get_datetime (dc_parser_t *abstract,
 {
 	const unsigned char *data = abstract->data;
 	const unsigned char *log = data + COCHRAN_MODEL_SIZE;
-	cochran_config_t conf;
+	// abstract->data is prefixed by the model string
+	cochran_layout_t *layout = cochran_commander_get_layout(data);
 
-	cochran_commander_get_config(data, &conf);
-
-	if (conf.date_format == COCHRAN_DATE_FORMAT_SMHDMY) {
+	if (layout->date_format == DATE_SMHDMY) {
 		datetime->second = log[0];
 		datetime->minute = log[1];
 		datetime->hour = log[2];
@@ -136,11 +135,9 @@ static dc_status_t
 cochran_commander_parser_get_field (dc_parser_t *abstract, dc_field_type_t type,
 			unsigned int flags, void *value)
 {
-	cochran_config_t conf;
-
-	cochran_commander_get_config(abstract->data, &conf);
+	cochran_layout_t *layout = cochran_commander_get_layout(abstract->data);
 
-	switch (conf.model & 0xFF0000)
+	switch (layout->model & 0xFF0000)
 	{
 	case COCHRAN_MODEL_COMMANDER_FAMILY:
 		return cochran_cmdr_parser_get_field(abstract, type, flags, value);
@@ -157,11 +154,9 @@ static dc_status_t
 cochran_commander_parser_samples_foreach (dc_parser_t *abstract,
 			dc_sample_callback_t callback, void *userdata)
 {
-	cochran_config_t conf;
-
-	cochran_commander_get_config(abstract->data, &conf);
+	cochran_layout_t *layout = cochran_commander_get_layout(abstract->data);
 
-	switch (conf.model & 0xFF0000)
+	switch (layout->model & 0xFF0000)
 	{
 	case COCHRAN_MODEL_COMMANDER_FAMILY:
 		return cochran_cmdr_parser_samples_foreach(abstract, callback,
-- 
2.4.3



More information about the devel mailing list