#include <stdio.h>
+#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "dive.h"
#include "file.h"
+#define DON
+
/*
* The Cochran file format is designed to be annoying to read. It's roughly:
*
return best;
}
-static void cochran_debug_write(int dive, const unsigned char *data, unsigned size)
+#define hexchar(n) ("0123456789abcdef"[(n)&15])
+
+static int show_line(unsigned offset, const unsigned char *data, unsigned size, int show_empty)
{
- char buffer[60];
- int fd;
-
- snprintf(buffer, sizeof(buffer), "cochran.%d.out", dive);
- fd = open(buffer, O_CREAT | O_TRUNC | O_WRONLY, 0666);
- if (fd >= 0) {
- write(fd, data, size);
- close(fd);
+ unsigned char bits;
+ int i, off;
+ char buffer[120];
+
+ if (size > 16)
+ size = 16;
+
+ bits = 0;
+ memset(buffer, ' ', sizeof(buffer));
+ off = sprintf(buffer, "%06x ", offset);
+ for (i = 0; i < size; i++) {
+ char *hex = buffer + off + 3*i;
+ char *asc = buffer + off + 50 + i;
+ unsigned char byte = data[i];
+
+ hex[0] = hexchar(byte>>4);
+ hex[1] = hexchar(byte);
+ bits |= byte;
+ if (byte < 32 || byte > 126)
+ byte = '.';
+ asc[0] = byte;
+ asc[1] = 0;
}
+
+ if (bits) {
+ puts(buffer);
+ return 1;
+ }
+ if (show_empty)
+ puts("...");
+ return 0;
+}
+
+static void cochran_debug_write(const char *filename, const unsigned char *data, unsigned size)
+{
+ int i, show = 1;
+
+ for (i = 0; i < size; i += 16)
+ show = show_line(i, data + i, size - i, show);
}
-static void parse_cochran_dive(int dive, const unsigned char *decode, unsigned mod,
+static void parse_cochran_header(const char *filename,
+ const unsigned char *decode, unsigned mod,
const unsigned char *in, unsigned size)
{
char *buf = malloc(size);
+ /* Do the "null decode" using a one-byte decode array of '\0' */
+ partial_decode(0 , 0x0b14, "", 0, 1, in, size, buf);
+
+ /*
+ * The header scrambling is different form the dive
+ * scrambling. Oh yay!
+ */
+ partial_decode(0x010e, 0x0b14, decode, 0, mod, in, size, buf);
+ partial_decode(0x0b14, 0x1b14, decode, 0, mod, in, size, buf);
+ partial_decode(0x1b14, 0x2b14, decode, 0, mod, in, size, buf);
+ partial_decode(0x2b14, 0x3b14, decode, 0, mod, in, size, buf);
+ partial_decode(0x3b14, 0x5414, decode, 0, mod, in, size, buf);
+ partial_decode(0x5414, size, decode, 0, mod, in, size, buf);
+
+ printf("\n%s, header\n\n", filename);
+ cochran_debug_write(filename, buf, size);
+
+ free(buf);
+}
+
+/*
+ * Cochran export files show that depths seem to be in
+ * quarter feet (rounded up to tenths).
+ *
+ * Temperature seems to be exported in Fahrenheit.
+ *
+ * Cylinder pressure seems to be in multiples of 4 psi.
+ *
+ * The data seems to be some byte-stream where the pattern
+ * appears to be that the two high bits indicate type of
+ * data.
+ *
+ * For '00', the low six bits seem to be positive
+ * values with a distribution towards zero, probably depth
+ * deltas. '0 0' exists, but is very rare ("surface"?). 63
+ * exists, but is rare.
+ *
+ * For '01', the low six bits seem to be a signed binary value,
+ * with the most common being 0, and 1 and -1 (63) being the
+ * next most common values.
+ *
+ * NOTE! Don's CAN data is different. It shows the reverse pattern
+ * for 00 and 01 above: 00 looks like signed data, with 01 looking
+ * like unsigned data.
+ *
+ * For '10', there seems to be another positive value distribution,
+ * but unlike '00' the value 0 is common, and I see examples of 63
+ * too ("overflow"?) and a spike at '7'.
+ *
+ * Again, Don's data is different.
+ *
+ * The values for '11' seem to be some exception case. Possibly
+ * overflow handling, possibly warning events. It doesn't have
+ * any clear distribution: values 0, 1, 16, 33, 35, 48, 51, 55
+ * and 63 are common.
+ *
+ * For David and Don's data, '01' is the most common, with '00'
+ * and '10' not uncommon. '11' is two orders of magnitude less
+ * common.
+ *
+ * For Alex, '00' is the most common, with 01 about a third as
+ * common, and 02 a third of that. 11 is least common.
+ *
+ * There clearly are variations in the format here. And Alex has
+ * a different data offset than Don/David too (see the #ifdef DON).
+ * Christ. Maybe I've misread the patterns entirely.
+ */
+static void cochran_profile_write(const unsigned char *buf, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ unsigned char c = buf[i];
+ printf("%d %d\n",
+ c >> 6, c & 0x3f);
+ }
+}
+
+static void parse_cochran_dive(const char *filename, int dive,
+ const unsigned char *decode, unsigned mod,
+ const unsigned char *in, unsigned size)
+{
+ char *buf = malloc(size);
+#ifdef DON
+ unsigned int offset = 0x4a14;
+#else
+ unsigned int offset = 0x4b14;
+#endif
+
/*
* The scrambling has odd boundaries. I think the boundaries
* match some data structure size, but I don't know. They were
* scrambled, but there seems to be size differences in the data,
* so this just descrambles part of it:
*/
- partial_decode(0x48ff, size, decode, 0, mod, in, size, buf);
+ partial_decode(0x48ff, offset, decode, 0, mod, in, size, buf);
+ partial_decode(offset, size, decode, 0, mod, in, size, buf);
- cochran_debug_write(dive, buf, size);
+ printf("\n%s, dive %d\n\n", filename, dive);
+ cochran_debug_write(filename, buf, size);
+ cochran_profile_write(buf + offset, size - offset);
free(buf);
}
mod = figure_out_modulus(decode, mem->buffer + dive1, dive2 - dive1);
+ parse_cochran_header(filename, decode, mod, mem->buffer + 0x40000, dive1 - 0x40000);
+
for (i = 0; i < 65534; i++) {
dive1 = offsets[i];
dive2 = offsets[i+1];
break;
if (dive2 > mem->size)
break;
- parse_cochran_dive(i, decode, mod, mem->buffer + dive1, dive2 - dive1);
+ parse_cochran_dive(filename, i+1, decode, mod, mem->buffer + dive1, dive2 - dive1);
}
- return 1;
+ exit(0);
}