suunto_nautic: decode multi-gas mixes and link tanks to gas + volume - #1
Merged
Conversation
The /Summary gas table is a 45-byte-stride array (base 0xC7), one record per configured gas: O2% at +1, He% at +2, PO2-max float at +5, cylinder water capacity float (m^3) at +9. The previous 4-byte stride only ever recovered the first gas because the PO2 float after gas 0 tripped the plausibility stop, so multi-gas dives lost every mix after the first and tanks were never linked to a gas. Parse gases at the correct stride, store each gas's cylinder volume, tag every tank with its cylinder-slot index (== GasNumber), and wire tank->gasmix plus DC_TANKVOLUME_METRIC volume in DC_FIELD_TANK. Reverse-engineered and validated against two real dual-transmitter dives (Air 12 L on gas 0 + NX26 5.7 L on gas 1): both mixes, per-tank gas linkage, and volumes now match the Suunto app export exactly. Resolves the multi-gas half of issues #33/#34; single-gas and profile-only captures are unaffected (stop at the first implausible slot, as before). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012VH1Magk9E9nWusjYQd4oe
This was referenced Sep 5, 2026
urbamax
added a commit
to urbamax/submersion
that referenced
this pull request
Sep 7, 2026
deepsealabs/libdivecomputer#1 cherry-picked onto submersion-patches: the /Summary gas table is a 45-byte-stride array (base 0xC7), not 4-byte, so the old parser stopped after gas 0 (it hit the PO2 float) and lost every mix on a multi-gas Nautic dive; tanks were never linked to a gas. Now each tank carries its gas index and per-gas cylinder volume. Also reconciles the earlier standalone cylinder-size read (bb1aa55) -- superseded by the per-gas volume -- and rebases the PO2-max read (bcd0542) onto Gas[0]+5. Single-gas dives, including every one in the local corpus, are unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The
/Summarygas table is a 45-byte-stride array (base0xC7), one record per configured gas: O2% at +1, He% at +2, PO2-max float at +5, cylinder water capacity float (m³) at +9. The previous 4-byte stride only ever recovered the first gas (the PO2 float after gas 0 tripped the plausibility stop), so multi-gas dives lost every mix after the first and tanks were never linked to a gas.This parses gases at the correct stride, stores each gas's cylinder volume, tags every tank with its cylinder-slot index (== GasNumber), and wires
tank->gasmixplusDC_TANKVOLUME_METRICvolume inDC_FIELD_TANK.Reverse-engineered and validated against two real dual-transmitter dives (Air 12 L on gas 0 + NX26 5.7 L on gas 1, deepsealabs/libdc-swift#29): both mixes, per-tank gas linkage, and volumes match the Suunto app export exactly. Resolves the multi-gas half of deepsealabs/libdc-swift#33/#34. Single-gas and profile-only captures are unaffected (stop at the first implausible slot, as before).
🤖 Generated with Claude Code