Merge branch 'uemis-integration' of git://github.com/dirkhh/subsurface

* 'uemis-integration' of git://github.com/dirkhh/subsurface:
  Much nicer implementation of uemis sample parsing - and add events, too
  Add working pressure to uemis tank data
This commit is contained in:
Linus Torvalds 2011-10-03 13:19:23 -07:00
commit 9d469862af
2 changed files with 91 additions and 10 deletions

71
uemis.c
View file

@ -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;

30
uemis.h
View file

@ -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 */