]> git.tdb.fi Git - ext/subsurface.git/commitdiff
Much nicer implementation of uemis sample parsing - and add events, too
authorDirk Hohndel <dirk@hohndel.org>
Mon, 3 Oct 2011 19:27:14 +0000 (12:27 -0700)
committerDirk Hohndel <dirk@hohndel.org>
Mon, 3 Oct 2011 19:31:56 +0000 (12:31 -0700)
This is something I wanted to do for a while. Every uemis sample is simply
a packed structure with no padding. Instead of grabbing random bytes from
the middle of an unstructured data blob let's just define the structure
and access its members.

And while we do that, add support for the more useful uemis events as
well.

A couple of the warnings are disabled by default (compile time flag) as
they are just crazy - any normal dive will give you dozens and dozens of
speed warnings. Same goes for the PO2 green warning (I haven't looked but
this seems to trigger on a PO2 over 1.0 or something). Completely useless
and just hides actually useful info.

I still want to redo the way we visualize events in general - just
printing the text ontop of the profile really is suboptimal. Especially as
the uemis really seems to love to repeat several of the warnings quite
frequently.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
uemis.c
uemis.h

diff --git a/uemis.c b/uemis.c
index 46878e22a89c0632ad0be203f41ea3bbbcc8bfda..dc11a6deced6882077f2aec614b87f124c52bb9e 100644 (file)
--- a/uemis.c
+++ b/uemis.c
@@ -119,6 +119,59 @@ bail:
        return datalen;
 }
 
+/* Create events from the flag bits;
+ * These bits basically represent what is displayed on screen at sample time.
+ * Many of these 'warnings' are way hyper-active and seriously clutter the
+ * profile plot - so these are disabled by default
+ */
+void uemis_event(struct dive *dive, struct sample *sample, uemis_sample_t *u_sample)
+{
+       uint8_t *flags = u_sample->flags;
+
+       if (flags[1] & 0x01)
+               add_event(dive, sample->time.seconds, 0, 0, 0, "Safety Stop Violation");
+       if (flags[1] & 0x08)
+               add_event(dive, sample->time.seconds, 0, 0, 0, "Speed Alarm");
+#if WANT_CRAZY_WARNINGS
+       if (flags[1] & 0x06) /* both bits 1 and 2 are a warning */
+               add_event(dive, sample->time.seconds, 0, 0, 0, "Speed Warning");
+       if (flags[1] & 0x10)
+               add_event(dive, sample->time.seconds, 0, 0, 0, "PO2 Green Warning");
+#endif
+       if (flags[1] & 0x20)
+               add_event(dive, sample->time.seconds, 0, 0, 0, "PO2 Ascend Warning");
+       if (flags[1] & 0x40)
+               add_event(dive, sample->time.seconds, 0, 0, 0, "PO2 Ascend Alarm");
+       /* flags[2] reflects the deco / time bar
+        * flags[3] reflects more display details on deco and pO2 */
+       if (flags[4] & 0x01)
+               add_event(dive, sample->time.seconds, 0, 0, 0, "Tank Pressure Info");
+       if (flags[4] & 0x04)
+               add_event(dive, sample->time.seconds, 0, 0, 0, "RGT Warning");
+       if (flags[4] & 0x08)
+               add_event(dive, sample->time.seconds, 0, 0, 0, "RGT Alert");
+       if (flags[4] & 0x40)
+               add_event(dive, sample->time.seconds, 0, 0, 0, "Tank Change Suggest");
+       if (flags[4] & 0x80)
+               add_event(dive, sample->time.seconds, 0, 0, 0, "Depth Limit Exceeded");
+       if (flags[5] & 0x01)
+               add_event(dive, sample->time.seconds, 0, 0, 0, "Max Deco Time Warning");
+       if (flags[5] & 0x04)
+               add_event(dive, sample->time.seconds, 0, 0, 0, "Dive Time Info");
+       if (flags[5] & 0x08)
+               add_event(dive, sample->time.seconds, 0, 0, 0, "Dive Time Alert");
+       if (flags[5] & 0x10)
+               add_event(dive, sample->time.seconds, 0, 0, 0, "Marker");
+       if (flags[6] & 0x02)
+               add_event(dive, sample->time.seconds, 0, 0, 0, "No Tank Data");
+       if (flags[6] & 0x04)
+               add_event(dive, sample->time.seconds, 0, 0, 0, "Low Battery Warning");
+       if (flags[6] & 0x08)
+               add_event(dive, sample->time.seconds, 0, 0, 0, "Low Battery Alert");
+       /* flags[7] reflects the little on screen icons that remind of previous
+        * warnings / alerts - not useful for events */
+}
+
 /*
  * parse uemis base64 data blob into struct dive
  */
@@ -127,6 +180,7 @@ void uemis_parse_divelog_binary(char *base64, void *datap) {
        int i;
        uint8_t *data;
        struct sample *sample;
+       uemis_sample_t *u_sample;
        struct dive **divep = datap;
        struct dive *dive = *divep;
        int template, gasoffset;
@@ -160,22 +214,25 @@ void uemis_parse_divelog_binary(char *base64, void *datap) {
        }
        /* first byte of divelog data is at offset 0x123 */
        i = 0x123;
-       while ((i < datalen) && (*(uint16_t *)(data+i))) {
+       u_sample = (uemis_sample_t *)(data + i);
+       while ((i < datalen) && (u_sample->dive_time)) {
                /* it seems that a dive_time of 0 indicates the end of the valid readings */
                /* the SDA usually records more samples after the end of the dive --
                 * we want to discard those, but not cut the dive short; sadly the dive
                 * duration in the header is a) in minutes and b) up to 3 minutes short */
-               if (*(uint16_t *)(data+i) > dive->duration.seconds + 180)
+               if (u_sample->dive_time > dive->duration.seconds + 180)
                        break;
                sample = prepare_sample(divep);
                dive = *divep; /* prepare_sample might realloc the dive */
-               sample->time.seconds = *(uint16_t *)(data+i);
-               sample->depth.mm = pressure_to_depth(*(uint16_t *)(data+i+2));
-               sample->temperature.mkelvin = (*(uint16_t *)(data+i+4) * 100) + 273150;
-               sample->cylinderpressure.mbar= *(uint16_t *)(data+i+23) * 10;
-               sample->cylinderindex = *(uint8_t *)(data+i+22);
+               sample->time.seconds = u_sample->dive_time;
+               sample->depth.mm = pressure_to_depth(u_sample->water_pressure);
+               sample->temperature.mkelvin = (u_sample->dive_temperature * 100) + 273150;
+               sample->cylinderindex = u_sample->active_tank;
+               sample->cylinderpressure.mbar= u_sample->tank_pressure * 10;
+               uemis_event(dive, sample, u_sample);
                finish_sample(dive, sample);
                i += 0x25;
+               u_sample++;
        }
        dive->duration.seconds = sample->time.seconds - 1;
        return;
diff --git a/uemis.h b/uemis.h
index e4e8532c21c429680a059041cfac0a3eadd2f822..29a168f5d3449a04efd066b6803e50e78a3be086 100644 (file)
--- a/uemis.h
+++ b/uemis.h
@@ -1,10 +1,34 @@
-#ifndef UEMIS_H
-#define UEMIS_H
-
 /*
  * defines and prototypes for the uemis Zurich SDA file parser
  */
 
+#ifndef UEMIS_H
+#define UEMIS_H
+
+#include <stdint.h>
+
 void uemis_parse_divelog_binary(char *base64, void *divep);
 
+typedef struct {
+       uint16_t        dive_time;
+       uint16_t        water_pressure;         // (in cbar)
+       uint16_t        dive_temperature;       // (in dC)
+       uint8_t         ascent_speed;           // (units unclear)
+       uint8_t         work_fact;
+       uint8_t         cold_fact;
+       uint8_t         bubble_fact;
+       uint16_t        ascent_time;
+       uint16_t        ascent_time_opt;
+       uint16_t        p_amb_tol;
+       uint16_t        satt;
+       uint16_t        hold_depth;
+       uint16_t        hold_time;
+       uint8_t         active_tank;
+       uint16_t        tank_pressure;          // (in cbar)
+       uint16_t        consumption;            // (units unclear)
+       uint8_t         rgt;                    // (remaining gas time in minutes)
+       uint8_t         cns;
+       uint8_t         flags[8]; 
+} __attribute((packed)) uemis_sample_t;
+
 #endif /* DIVE_H */