From 0c343f2a476a9e7ee86d491b5fba5376b746a042 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Mon, 3 Oct 2011 12:27:14 -0700 Subject: [PATCH] Much nicer implementation of uemis sample parsing - and add events, too 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 --- uemis.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++------ uemis.h | 30 +++++++++++++++++++++--- 2 files changed, 91 insertions(+), 10 deletions(-) diff --git a/uemis.c b/uemis.c index 46878e2..dc11a6d 100644 --- 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 e4e8532..29a168f 100644 --- 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 + 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 */ -- 2.43.0