Skip to content

Commit 5d36cc0

Browse files
committed
Remove disabled gas mixes
Returning disabled gas mixes to the application mainly results in lots of unnecessary information. Therefore, remove all disabled gas mixes, unless they are actively used. Many other dive computers do not even include disabled gas mixes in the data. The removal of the disabled gas mixes requires a two pass approach for parsing the profile data. The first pass is only used to discover which gas mixes are actively used during the dive. Next, all disabled and not actively used gas mixes are removed from the list. Since removing one or more gas mixes also invalidates the index of the remaining gas mixes, the profile needs to be parsed again to report the new index in the gas switch samples. The original one based index is used as the stable gas mix id, used for looking up the new gas mix index.
1 parent 993283d commit 5d36cc0

File tree

1 file changed

+79
-20
lines changed

1 file changed

+79
-20
lines changed

src/hw_ostc_parser.c

Lines changed: 79 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ typedef struct hw_ostc_parser_t {
124124
const hw_ostc_layout_t *layout;
125125
unsigned int ngasmixes;
126126
unsigned int nfixed;
127+
unsigned int ndisabled;
127128
unsigned int initial;
128129
unsigned int initial_setpoint;
129130
unsigned int initial_cns;
@@ -134,6 +135,8 @@ static dc_status_t hw_ostc_parser_get_datetime (dc_parser_t *abstract, dc_dateti
134135
static dc_status_t hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned int flags, void *value);
135136
static dc_status_t hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata);
136137

138+
static dc_status_t hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t callback, void *userdata);
139+
137140
static const dc_parser_vtable_t hw_ostc_parser_vtable = {
138141
sizeof(hw_ostc_parser_t),
139142
DC_FAMILY_HW_OSTC,
@@ -194,7 +197,7 @@ static const hw_ostc_layout_t hw_ostc_layout_ostc3 = {
194197
static unsigned int
195198
hw_ostc_find_gasmix_manual (hw_ostc_parser_t *parser, unsigned int o2, unsigned int he, unsigned int dil)
196199
{
197-
unsigned int offset = parser->nfixed;
200+
unsigned int offset = parser->nfixed - parser->ndisabled;
198201
unsigned int count = parser->ngasmixes;
199202

200203
unsigned int i = offset;
@@ -207,6 +210,22 @@ hw_ostc_find_gasmix_manual (hw_ostc_parser_t *parser, unsigned int o2, unsigned
207210
return i;
208211
}
209212

213+
static unsigned int
214+
hw_ostc_find_gasmix_fixed (hw_ostc_parser_t *parser, unsigned int id)
215+
{
216+
unsigned int offset = 0;
217+
unsigned int count = parser->nfixed - parser->ndisabled;
218+
219+
unsigned int i = offset;
220+
while (i < count) {
221+
if (id == parser->gasmix[i].id)
222+
break;
223+
i++;
224+
}
225+
226+
return i;
227+
}
228+
210229
static unsigned int
211230
hw_ostc_is_ccr (unsigned int divemode, unsigned int version)
212231
{
@@ -341,7 +360,6 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
341360
ERROR(abstract->context, "Invalid initial gas mix.");
342361
return DC_STATUS_DATAFORMAT;
343362
}
344-
initial--; /* Convert to a zero based index. */
345363
} else {
346364
WARNING(abstract->context, "No initial gas mix available.");
347365
}
@@ -352,6 +370,7 @@ hw_ostc_parser_cache (hw_ostc_parser_t *parser)
352370
parser->layout = layout;
353371
parser->ngasmixes = ngasmixes;
354372
parser->nfixed = ngasmixes;
373+
parser->ndisabled = 0;
355374
parser->initial = initial;
356375
parser->initial_setpoint = initial_setpoint;
357376
parser->initial_cns = initial_cns;
@@ -387,6 +406,7 @@ hw_ostc_parser_create_internal (dc_parser_t **out, dc_context_t *context, const
387406
parser->layout = NULL;
388407
parser->ngasmixes = 0;
389408
parser->nfixed = 0;
409+
parser->ndisabled = 0;
390410
parser->initial = 0;
391411
parser->initial_setpoint = 0;
392412
parser->initial_cns = 0;
@@ -491,7 +511,7 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned
491511

492512
// Cache the profile data.
493513
if (parser->cached < PROFILE) {
494-
rc = hw_ostc_parser_samples_foreach (abstract, NULL, NULL);
514+
rc = hw_ostc_parser_internal_foreach (parser, NULL, NULL);
495515
if (rc != DC_STATUS_SUCCESS)
496516
return rc;
497517
}
@@ -679,17 +699,12 @@ hw_ostc_parser_get_field (dc_parser_t *abstract, dc_field_type_t type, unsigned
679699

680700

681701
static dc_status_t
682-
hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
702+
hw_ostc_parser_internal_foreach (hw_ostc_parser_t *parser, dc_sample_callback_t callback, void *userdata)
683703
{
684-
hw_ostc_parser_t *parser = (hw_ostc_parser_t *) abstract;
704+
dc_parser_t *abstract = (dc_parser_t *) parser;
685705
const unsigned char *data = abstract->data;
686706
unsigned int size = abstract->size;
687707

688-
// Cache the parser data.
689-
dc_status_t rc = hw_ostc_parser_cache (parser);
690-
if (rc != DC_STATUS_SUCCESS)
691-
return rc;
692-
693708
unsigned int version = parser->version;
694709
unsigned int header = parser->header;
695710
const hw_ostc_layout_t *layout = parser->layout;
@@ -795,7 +810,7 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
795810

796811
unsigned int time = 0;
797812
unsigned int nsamples = 0;
798-
unsigned int tank = parser->initial != UNDEFINED ? parser->initial : 0;
813+
unsigned int tank = parser->initial != UNDEFINED ? parser->initial - 1 : 0;
799814

800815
unsigned int offset = header;
801816
if (version == 0x23 || version == 0x24)
@@ -812,8 +827,9 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
812827

813828
// Initial gas mix.
814829
if (time == samplerate && parser->initial != UNDEFINED) {
815-
parser->gasmix[parser->initial].active = 1;
816-
sample.gasmix = parser->initial;
830+
unsigned int idx = hw_ostc_find_gasmix_fixed (parser, parser->initial);
831+
parser->gasmix[idx].active = 1;
832+
sample.gasmix = idx;
817833
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
818834
}
819835

@@ -929,20 +945,20 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
929945
ERROR (abstract->context, "Buffer overflow detected!");
930946
return DC_STATUS_DATAFORMAT;
931947
}
932-
unsigned int idx = data[offset];
933-
if (parser->model == OSTC4 && ccr && idx > parser->nfixed) {
948+
unsigned int id = data[offset];
949+
if (parser->model == OSTC4 && ccr && id > parser->nfixed) {
934950
// Fix the OSTC4 diluent index.
935-
idx -= parser->nfixed;
951+
id -= parser->nfixed;
936952
}
937-
if (idx < 1 || idx > parser->nfixed) {
938-
ERROR(abstract->context, "Invalid gas mix (%u).", idx);
953+
if (id < 1 || id > parser->nfixed) {
954+
ERROR(abstract->context, "Invalid gas mix (%u).", id);
939955
return DC_STATUS_DATAFORMAT;
940956
}
941-
idx--; /* Convert to a zero based index. */
957+
unsigned int idx = hw_ostc_find_gasmix_fixed (parser, id);
942958
parser->gasmix[idx].active = 1;
943959
sample.gasmix = idx;
944960
if (callback) callback (DC_SAMPLE_GASMIX, &sample, userdata);
945-
tank = idx;
961+
tank = id - 1;
946962
offset++;
947963
length--;
948964
}
@@ -1141,7 +1157,50 @@ hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t call
11411157
return DC_STATUS_DATAFORMAT;
11421158
}
11431159

1160+
// Remove the disabled gas mixes from the fixed gas mixes.
1161+
unsigned int ndisabled = 0, nenabled = 0;
1162+
unsigned int count = parser->nfixed - parser->ndisabled;
1163+
for (unsigned int i = 0; i < count; ++i) {
1164+
if (parser->gasmix[i].enabled || parser->gasmix[i].active) {
1165+
// Move the fixed gas mix.
1166+
parser->gasmix[nenabled] = parser->gasmix[i];
1167+
nenabled++;
1168+
} else {
1169+
ndisabled++;
1170+
}
1171+
}
1172+
1173+
// Move all the manual gas mixes.
1174+
memmove (parser->gasmix + nenabled, parser->gasmix + count,
1175+
(parser->ngasmixes - count) * sizeof (hw_ostc_gasmix_t));
1176+
memset (parser->gasmix + parser->ngasmixes - ndisabled, 0,
1177+
ndisabled * sizeof (hw_ostc_gasmix_t));
1178+
1179+
// Adjust the counts.
1180+
parser->ngasmixes -= ndisabled;
1181+
parser->ndisabled += ndisabled;
1182+
11441183
parser->cached = PROFILE;
11451184

11461185
return DC_STATUS_SUCCESS;
11471186
}
1187+
1188+
static dc_status_t
1189+
hw_ostc_parser_samples_foreach (dc_parser_t *abstract, dc_sample_callback_t callback, void *userdata)
1190+
{
1191+
hw_ostc_parser_t *parser = (hw_ostc_parser_t *) abstract;
1192+
1193+
// Cache the header data.
1194+
dc_status_t rc = hw_ostc_parser_cache (parser);
1195+
if (rc != DC_STATUS_SUCCESS)
1196+
return rc;
1197+
1198+
// Cache the profile data.
1199+
if (parser->cached < PROFILE) {
1200+
rc = hw_ostc_parser_internal_foreach (parser, NULL, NULL);
1201+
if (rc != DC_STATUS_SUCCESS)
1202+
return rc;
1203+
}
1204+
1205+
return hw_ostc_parser_internal_foreach (parser, callback, userdata);
1206+
}

0 commit comments

Comments
 (0)