<div dir="ltr">This patch is incomplete. Please excuse my lack of git-worthiness. I'll see if I can have a complete one in a few minutes.<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Oct 17, 2014 at 8:41 PM, John Van Ostrand <span dir="ltr"><<a href="mailto:john@vanostrand.com" target="_blank">john@vanostrand.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I fixed up the decode and finished the parse for Cochran<br>
EMC, Commander and Gemini computers. I suspect that this<br>
code may only work with files from certain versions of<br>
Cochran Analyst. It works with my own CAN files and with the<br>
samples that came with Analyst v4.01v.<br>
<br>
A seemingly arbitrary offset of 0x4914 is needed to access data.<br>
The previous code uses 0x4a14 and 0x4b14. I suspect these are from<br>
different version of Analyst.<br>
<br>
Signed-off-by: John Van Ostrand <<a href="mailto:john@vanostrand.com">john@vanostrand.com</a>><br>
---<br>
 cochran_cmdr.h |  88 ++++++++++++++++++++++++++++<br>
 cochran_emc.h  | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++<br>
 2 files changed, 268 insertions(+)<br>
 create mode 100644 cochran_cmdr.h<br>
 create mode 100644 cochran_emc.h<br>
<br>
diff --git a/cochran_cmdr.h b/cochran_cmdr.h<br>
new file mode 100644<br>
index 0000000..6c66165<br>
--- /dev/null<br>
+++ b/cochran_cmdr.h<br>
@@ -0,0 +1,88 @@<br>
+/*<br>
+ * subsurface<br>
+ *<br>
+ * Copyright (C) 2014 John Van Ostrand<br>
+ *<br>
+ * This library is free software; you can redistribute it and/or<br>
+ * modify it under the terms of the GNU Lesser General Public<br>
+ * License as published by the Free Software Foundation; either<br>
+ * version 2.1 of the License, or (at your option) any later version.<br>
+ *<br>
+ * This library is distributed in the hope that it will be useful,<br>
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU<br>
+ * Lesser General Public License for more details.<br>
+ *<br>
+ * You should have received a copy of the GNU Lesser General Public<br>
+ * License along with this library; if not, write to the Free Software<br>
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,<br>
+ * MA 02110-1301 USA<br>
+ */<br>
+<br>
+<br>
+struct cochran_cmdr_log_t {<br>
+       // Pre-dive 128 bytes<br>
+       unsigned char minutes, seconds;                 // 2 bytes<br>
+       unsigned char day, hour, year, month;   // 4 bytes<br>
+       unsigned char sample_start_offset[4];   // 4 bytes<br>
+       unsigned char start_timestamp[4];               // 4 bytes<br>
+       unsigned char pre_dive_timestamp[4];    // 4 bytes<br>
+       unsigned char unknown1[6];                              // 6 bytes<br>
+       unsigned char water_conductivity;               // 1 byte [0=low, 2=high]<br>
+       unsigned char unknown2[5];                              // 5 bytes<br>
+//30<br>
+       unsigned char sample_pre_event_offset[4];// 4 bytes<br>
+       unsigned char unknown3[4];                              // 4 bytes<br>
+       unsigned char start_battery_voltage[2]; // 2 bytes [/256]<br>
+//40<br>
+       unsigned char unknown4[2];                              // 2 bytes<br>
+       unsigned char start_sgc[2];                             // 2 bytes<br>
+       unsigned char entered_or_computed_po[2];// 2 bytes ???<br>
+       unsigned char unknown5[10];                             // 10 bytes<br>
+//56<br>
+       unsigned char start_depth[2];                   // 2 byte [/4]<br>
+       unsigned char unknown6[4];                              // 3 bytes<br>
+       unsigned char start_psi[2];                             // 2 bytes LE<br>
+       unsigned char unknown7[4];                              // 4 bytes<br>
+       unsigned char sit[2];                                   // 2 bytes<br>
+//70<br>
+       unsigned char number[2];                                // 2 bytes<br>
+       unsigned char unknown8[1];                              // 1 byte<br>
+       unsigned char altitude;                                 // 1 byte [/4 = kft]<br>
+       unsigned char unknown9[28];                             // 27 bytes<br>
+       unsigned char alarm_depth[2];                   // 2 bytes<br>
+       unsigned char unknown10[4];                             // 5 bytes<br>
+//108<br>
+       unsigned char repetitive_dive;                  // 1 byte<br>
+       unsigned char unknown11[3];                             // 3 bytes<br>
+       unsigned char start_tissue_nsat[16];    // 16 bytes [/256]<br>
+<br>
+       // Post-dive 128 bytes<br>
+       unsigned char sample_end_offset[4];             // 4 bytes<br>
+       unsigned char unknown12[21];                    // 21 bytes<br>
+       unsigned char temp;                                             // 1 byte<br>
+       unsigned char unknown13[12];                    // 12 bytes<br>
+       unsigned char bt[2];                                    // 2 bytes [minutes]<br>
+//168<br>
+       unsigned char max_depth[2];                             // 2 bytes [/4]<br>
+       unsigned char avg_depth[2];                             // 2 bytes<br>
+       unsigned char unknown14[38];                    // 38 bytes<br>
+//210<br>
+       unsigned char o2_percent[4][2];                 // 8 bytes<br>
+       unsigned char unknown15[22];                    // 22 bytes<br>
+       unsigned char end_tissue_nsat[16];              // 16 bytes [/256]<br>
+} __attribute__((packed));<br>
+<br>
+<br>
+typedef struct cochran_cmdr_log_t cochran_cmdr_log_t;<br>
+<br>
+<br>
+struct cochran_cmdr_config1_t {<br>
+       unsigned char unknown1[209];<br>
+       unsigned short int dive_count;<br>
+       unsigned char unknown2[274];<br>
+       unsigned short int serial_num; // @170<br>
+       unsigned char unknown3[24];<br>
+} __attribute__((packed));<br>
+<br>
+typedef struct cochran_emc_config1_t cochran_emc_config1_t;<br>
diff --git a/cochran_emc.h b/cochran_emc.h<br>
new file mode 100644<br>
index 0000000..33c4757<br>
--- /dev/null<br>
+++ b/cochran_emc.h<br>
@@ -0,0 +1,180 @@<br>
+/*<br>
+ * subsurface<br>
+ *<br>
+ * Copyright (C) 2014 John Van Ostrand<br>
+ *<br>
+ * This library is free software; you can redistribute it and/or<br>
+ * modify it under the terms of the GNU Lesser General Public<br>
+ * License as published by the Free Software Foundation; either<br>
+ * version 2.1 of the License, or (at your option) any later version.<br>
+ *<br>
+ * This library is distributed in the hope that it will be useful,<br>
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU<br>
+ * Lesser General Public License for more details.<br>
+ *<br>
+ * You should have received a copy of the GNU Lesser General Public<br>
+ * License along with this library; if not, write to the Free Software<br>
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,<br>
+ * MA 02110-1301 USA<br>
+ */<br>
+<br>
+// 512 bytes for each dive in the log book<br>
+struct cochran_emc_log_t {<br>
+       // Pre-dive 256 bytes<br>
+       unsigned char seconds, minutes, hour;           // 3 bytes<br>
+       unsigned char day, month, year;                         // 3 bytes<br>
+       unsigned char sample_start_offset[4];           // 4 bytes<br>
+       unsigned char start_timestamp[4];                       // 4 bytes [secs from jan 1,92]<br>
+       unsigned char pre_dive_timestamp[4];            // 4 bytes [secs from Jan 1,92]<br>
+       unsigned char unknown1[6];                                      // 6 bytes<br>
+       unsigned char water_conductivity;                       // 1 byte  [0 =low, 2-high]<br>
+       unsigned char unknown2[5];                                      // 5 bytes<br>
+//30<br>
+       unsigned char sample_pre_event_offset[4];       // 4 bytes<br>
+       unsigned char config_bitfield[6];                       // 6 bytes<br>
+       unsigned char unknown3[2];                                      // 2 bytes<br>
+       unsigned char start_depth[2];                           // 2 bytes [/256]<br>
+       unsigned char unknown4[2];                                      // 2 bytes<br>
+       unsigned char start_battery_voltage[2];         // 2 bytes [/256]<br>
+//48<br>
+       unsigned char unknown5[7];                                      // 7 bytes<br>
+       unsigned char start_temperature;                        // 1 byte  [F]<br>
+       unsigned char unknown6[28];                                     // 28 bytes<br>
+       unsigned char sit[2];                                           // 2 bytes [minutes]<br>
+       unsigned char number[2];                                        // 2 bytes<br>
+       unsigned char unknown7[1];                                      // 1 bytes<br>
+       unsigned char altitude;                                         // 1 byte [/4 = kft]<br>
+       unsigned char start_nofly[2];                           // 2 bytes [/256 = hours]<br>
+//92<br>
+       unsigned char unknown8[18];                             // 18 bytes<br>
+       unsigned char post_dive_sit[2];                         // 2 bytes  [seconds]<br>
+       unsigned char po2_set_point[9][2];                      // 18 bytes     [/256 = %]<br>
+       unsigned char unknown9[12];                             // 12 bytes<br>
+       unsigned char po2_alarm[2];                             // 2 bytes  [/256 = %]<br>
+//144<br>
+       unsigned char o2_percent[10][2];                        // 20 bytes     [/256 = %]<br>
+       unsigned char he_percent[10][2];                        // 20 bytes     [/256 = %]<br>
+       unsigned char alarm_depth[2];                           // 2 bytes<br>
+       unsigned char unknown10[14];                            // 14 bytes<br>
+       unsigned char conservatism;                                     // 1 bytes [/256 = fraction]<br>
+       unsigned char unknown11[2];                                     // 2 bytes<br>
+       unsigned char repetitive_dive;                          // 1 byte<br>
+       unsigned char unknown12[12];                            // 12 bytes<br>
+       unsigned char start_tissue_nsat[20][2];         // 40 bytes [/256]<br>
+<br>
+       // Post-dive 256 bytes<br>
+       unsigned char sample_end_offset[4];                     // 4 bytes<br>
+       unsigned char unknown13[33];                            // 33 bytes<br>
+       unsigned char temp;                                                     // 1 byte  [F]<br>
+       unsigned char unknown14[10];                            // 10 bytes<br>
+// 48<br>
+       unsigned char bt[2];                                            // 2 bytes [minutes]<br>
+       unsigned char max_depth[2];                                     // 2 bytes [/4 = ft]<br>
+       unsigned char unknown15[2];                                     // 2 bytes<br>
+       unsigned char avg_depth[2];                                     // 2 bytes [/4 = ft]<br>
+       unsigned char min_ndc[2];                                       // 2 bytes [minutes]<br>
+       unsigned char min_ndx_bt[2];                            // 2 bytes [minutes]<br>
+       unsigned char max_forecast_deco[2];                     // 2 bytes [minutes]<br>
+       unsigned char max_forecast_deco_bt[2];          // 2 bytes [minutes]<br>
+//64<br>
+       unsigned char max_ceiling[2];                           // 2 bytes [*10 = ft]<br>
+       unsigned char max_ceiling_bt[2];                        // 2 bytes [minutes]<br>
+       unsigned char unknown16[10];                            // 18 bytes<br>
+       unsigned char max_ascent_rate;                          // 1 byte  [ft/min]<br>
+       unsigned char unknown17[3];                                     // 3 bytes<br>
+       unsigned char max_ascent_rate_bt[2];            // 2 bytes [seconds]<br>
+//84<br>
+       unsigned char unknown18[54];                            // 54 bytes<br>
+//138<br>
+       unsigned char end_battery_voltage[2];           // 2 bytes [/256 = v]<br>
+       unsigned char unknown19[8];                                     // 8 bytes<br>
+       unsigned char min_temp_bt[2];                           // 2 bytes [seconds]<br>
+//150<br>
+       unsigned char unknown20[22];                            // 22 bytes<br>
+//172<br>
+       unsigned char end_nofly[2];                                     // 2 bytes      [/256 = hours]<br>
+       unsigned char alarm_count[2];                           // 2 byte<br>
+       unsigned char actual_deco_time[2];                      // 2 bytes [seconds]<br>
+//178<br>
+       unsigned char unknown21[38];                            // 38 bytes<br>
+//216<br>
+       unsigned char end_tissue_nsat[20][2];           // 40 bytes [/256 = fraction]<br>
+} __attribute__((packed));<br>
+<br>
+typedef struct cochran_emc_log_t cochran_emc_log_t;<br>
+<br>
+typedef enum cochran_emc_bitfield_config_t {<br>
+       BF_TEMP_DEPENDENT_N2,<br>
+       BF_ASCENT_RATE_BAR_GRAPH,<br>
+       BF_BLEND_2_SWITCHING,<br>
+       BF_ALTITUDE_AS_ONE_ZONE,<br>
+       BF_DECOMPRESSION_TIME_DISPLAY,<br>
+       BF_BLEND_3_SWITCHING,<br>
+       BF_VARIABLE_ASCENT_RATE_ALARM,<br>
+       BF_ASCENT_RATE_RESPONSE,<br>
+       BF_REPETITIVE_DIVE_DEPENDENT_N2,<br>
+       BF_TRAINING_MODE,<br>
+       BF_CONSTANT_MODE_COMPUTATIONS,<br>
+       BF_DISPLAYED_UNITS,<br>
+       BF_AUDIBLE_ALARM,<br>
+       BF_CLOCK,<br>
+       BF_CEILING_DISPLAY_DIV_BY_10,<br>
+       BF_GAS_2_AS_FIRST_GAS,<br>
+       BF_ENABLE_HELIUM_COMPUTATIONS,<br>
+       BF_AUTOMATIC_PO2_FO2_SWITCHING,<br>
+       BF_TOUCH_PROGRAMMING_PO2_FO2_SWITCH,<br>
+} cochran_emc_bitfield_config_t;<br>
+<br>
+<br>
+typedef struct cochran_emc_bitfield_t {<br>
+       cochran_emc_bitfield_config_t config;<br>
+       unsigned char word;<br>
+       unsigned char byte;<br>
+       unsigned char mask;<br>
+       unsigned char shift;<br>
+} cochran_emc_bitfield_t;<br>
+<br>
+static cochran_emc_bitfield_t cochran_emc_bits[] = {<br>
+// Word BD<br>
+       { BF_TEMP_DEPENDENT_N2, 0xBD, 0, 0x40, 6 },                     // 0=normal,<br>
+                                                                                                                       // 1=reduced<br>
+       { BF_ASCENT_RATE_BAR_GRAPH, 0xBD, 0, 0x20, 5 },                 // 0=fixed,<br>
+                                                                                                                       // 1=proportional<br>
+       { BF_BLEND_2_SWITCHING, 0xBD, 0, 0x04, 2 },                             // 0=dis, 1=ena<br>
+       { BF_ALTITUDE_AS_ONE_ZONE, 0xBD, 0, 0x02, 1},                   // 0=off, 1=on<br>
+<br>
+       { BF_DECOMPRESSION_TIME_DISPLAY, 0xBD, 1, 0xC0, 5},             // 111=both,<br>
+                                                                                                                       // 011=stop,<br>
+                                                                                                                       // 001=total<br>
+       { BF_BLEND_3_SWITCHING, 0xBD, 1, 0x10, 4 },                             // 0=dis, 1=ena<br>
+       { BF_VARIABLE_ASCENT_RATE_ALARM, 0xBD, 1, 0x04, 3},             // 0=off, 1=on<br>
+       { BF_ASCENT_RATE_RESPONSE, 0xBD, 1, 0x07, 0},<br>
+<br>
+//WORD BE<br>
+       { BF_REPETITIVE_DIVE_DEPENDENT_N2, 0xBE, 0, 0x80, 7 },  // 0=off, 1=on<br>
+       { BF_TRAINING_MODE, 0xBE, 0, 0x04, 2 },                                 // 0=off, 1=on<br>
+       { BF_CONSTANT_MODE_COMPUTATIONS, 0xBE, 0, 0x04, 2 },    // 0=FO2, 1=PO2<br>
+       { BF_DISPLAYED_UNITS, 0xBE, 0, 0x01, 0 },                               // 1=metric,<br>
+                                                                                                                       // 0=imperial<br>
+<br>
+// WORD BF<br>
+       { BF_AUDIBLE_ALARM, 0xBF, 0, 0x40, 6 },                                 // 0=on, 1=off ***<br>
+       { BF_CLOCK, 0xBF, 0, 0x20, 5 },                                                 // 0=off, 1=on<br>
+       { BF_CEILING_DISPLAY_DIV_BY_10, 0xBF, 0, 0x10, 4 },             // 0=off, 1=on<br>
+       { BF_GAS_2_AS_FIRST_GAS, 0xBF, 0, 0x02, 1 },                    // 0=dis, 1=ena<br>
+       { BF_ENABLE_HELIUM_COMPUTATIONS, 0xBF, 0, 0x01, 0 },    // 0=dis, 1=ena<br>
+<br>
+       { BF_AUTOMATIC_PO2_FO2_SWITCHING, 0xBF, 1, 0x04, 2 },   // 0=dis, 1=ena<br>
+       { BF_TOUCH_PROGRAMMING_PO2_FO2_SWITCH, 0xBF, 1, 0x02, 1 },      // 0=dis, 1=ena<br>
+};<br>
+<br>
+struct cochran_emc_config1_t {<br>
+       unsigned char unknown1[209];<br>
+       unsigned short int dive_count;<br>
+       unsigned char unknown2[274];<br>
+       unsigned short int serial_num;<br>
+       unsigned char unknown3[24];<br>
+} __attribute__((packed));<br>
+<br>
+typedef struct cochran_emc_config1_t cochran_emc_config1_t;<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.8.3.1<br>
<br>
</font></span></blockquote></div><br><br clear="all"><br>-- <br><div dir="ltr"><div>John Van Ostrand<br></div><div>At large on sabbatical<br></div><br></div>
</div>