Avoid pointless calls to dive planner

Stupid Gtk. Seriously. So in order to get a notification if the user
selects the drop down for the gas with the mouse I need to connect to the
"changed" signal for the combobox. But that also fires whenever the user
types something into the GtkEntry. Which means we once again get called
for all kinds of silly partial names.

Instead we want to handle the manual entry in the "focus-out" callback
(the user has hit tab or something else to move away from the GtkEntry -
let's assume that this is the text he wants us to use) and only respond to
the changed signal on the combobox if the user selected something from the
dropdown.

The easiest way to do that (I think) is to check the text with the strings
stored in the model. If this indeed matches a string stored in the model
then most likely this is something the user selected from the dropdown.
But more importantly if it isn't in the model, then we KNOW that this is
just a partial string that was typed in. And we can ignore that one.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Fix gas handling in the planner

The dive will start with gas 0. If things change during the planned part
of the dive, this will be represented by an event. Use the last gas for
the ascent.

Obviously this still doesn't handle deco gases, but at least we now no
longer switch back to the first gas after the planned part of the dive.

This also adds quite a bit of debugging code to be able to trace what's
happening in the planner.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Rewrite of the deco code

o) Instead of using gradient factors as means of comparison, I now use
   pressure (as in: maximal ambient pressure).

o) tissue_tolerance_calc() now computes the maximal ambient pressure now
   respecting gradient factors. For this, it needs to know about the
   surface pressure (as refernce for GF_high), thus gets *dive as an
   argument. It is called from add_segment() which this also needs *dive
   as an additional argument.

o) This implies deco_allowed_depth is now mainly a ambient-pressure to
   depth conversion with decorations to avoid negative depth (i.e. no deco
   obliation), implementation of quantization (!smooth => multiples of 3m)
   and explicit setting of last deco depth (e.g. 6m for O2 deco).

o) gf_low_pressure_this_dive (slight change of name), the max depth in
   pressure units is updated in add_segment. I set the minimal value in
   buehlmann_config to the equivalent of 20m as otherwise good values of
   GF_low add a lot of deco to shallow dives which do not need deep stops
   in the first place.

o) The bogus loop is gone as well as actual_gradient_limit() and
   gradient_factor_calculation() and large parts of deco_allowed_depth()
   although I did not delete the code but put it in comments.

o) The meat is in the formula in lines 147-154 of deco.c. Here is the
   rationale:

   Without gradient factors, the M-value (i.e the maximal tissue pressure)
   at a given depth is given by ambient_pressure / buehlmann_b + a.

   According to "Clearing Up The Confusion About "Deep Stops" by Erik C.
   Baker (as found via google) the effect of the gradient factors is no
   replace this by a reduced affine relation (i.e. another line) such that
   at the surface the difference between M-value and ambient pressure is
   reduced by a factor GF_high and at the maximal depth by a factor
   GF_low.

   That is, we are looking for parameters alpha and beta such that

   alpha surface + beta = surface + gf_high * (surface/b + a - surface)

   and

   alpha max_p + beta = max_p + gf_low * (max_p/b + a - max_p)

   This can be solved for alpha and beta and then inverted to obtain the
   max ambient pressure given tissue loadings. The result is the above
   mentioned formula.

Signed-off-by: Robert C. Helling <helling@atdotde.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Clean up the rewritten deco.c

In commit a7902f279a57 "Rewrite of the deco code" Robert kept the old code
that he replaced around; I removed all that as it's in the git history if
we ever need to look at it again but doesn't really help us in the file as
it is.

I also removed constants, variables and config parameters that aren't used
in the new implementation and did some coding style / formatting changes
to make deco.c more consistent with the rest of Subsurface. I also updated
the comments at the top of the file to reflect reality.

I did one change that actually affects the code. In the explanation of his
changes Robert said that gf_low_pressure_this_dive is initialized to the
exquivalent of 20m, yet his code added the surface pressure twice. I
decided to change the default config value from 3 (bar) to 2 so that this
indeed reflects (about) 20m (as in the code below surface_pressure is
added to this value).

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Fix deco planning for low oxygen mixes

Not sure about the future of the current planner.c as we have new
approaches now but as this annoyed me for some days now I just decided
to come up with this trivial stuff to make my life easier.

More a cosmetic fix than a patch, but actually it fixes a bug one might
face planing a dive using low oxygen mixes and where stop levels at just
90m, 60m, 30m and nothing in between will not allow subsurface to finish
a deco ceiling which ends before the universe collapses. Allows to plan
20min@130m using a 10/70 now (f.i.).

Signed-off-by: Jan Schubert / Jan.Schubert@GMX.li
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Fix deco display bug for dives with multiple samples at the same time

While one might argue that multiple samples with the same time are 'odd'
that still shouldn't be an excuse to incorrectly reset the ceiling value
for them back to 0.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Really prevent time travel in planner dive edit

Commit c92e4535a6de "Prevent time travel in planner dive edit" almost got
it right but had a stupid think-o. This commit should fix it the right
way. If the duration that is passed in is before the previous timestamp,
then this is most likely intended to be a relative time.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Minor cleanups

Coding style in deco.c.
Unneccessary if clause in profile.c (the loop starts with i = 1)

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Improve travel logic code for the ascent in the planner

This shouldn't change the the actual stops we do or the travel time how we
get there, but it makes the code more logical. From the end depth of the
planned dive we have ONE transition to the first stop depth (which may be
the surface). And then for every stop we (potentially) have a wait and
travel to the next stop.

Once we are in the while loop, we know that we are at a stop level, so
there is no point to keep checking if we first need to transition to the
stop.

It does create one additional improvement: if we don't need any stops at
all, then we don't transition to the first stop and then from there to the
surface. We do it in one step. The overall profile / traveltime remains
the same, we just drop one intermediate sample on the way.

This also improves a few ugly (and in one case, wrong) debug statements.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Fix the deco calculation in the dive planner

The existing code incorrectly started all calculation at the depth at the
end of the first segment. So if you went to 50m in 5min in your first
segment, you incorrectly got 5 minutes at 50m (instead of a progression
from 0 to 50m, over 5 minutes).

This commit fixes that and now gives us planned dives that then match what
is shown in the profile.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Do planned deco stops in multiples of 1 minute

We may want to make this configurable, but I haven't seen any software
that doesn't do deco stops in full minutes.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Set a default surface pressure for dive plan and allow simplistic print

This commit makes sure we have a reasonable default surface pressure (we
need an input field for that).

It also adjusts the debug level settings so that compiling this with
make CLCFLAGS=-DDEBUG_PLAN=3
will print out an almost usable dive plan.

This is of course still lacking air consumption calculations and will show
deco stops that we just transit through (if the ceiling lifts far enough
during the transition to an intended stop that this stop can be skipped;
this sometimes happens for the first stop (haven't seen it for a later
one). But it's better than nothing, I guess.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Undo unintentional change to deco.c

In commit d163a68ac69e "Clean up the rewritten deco.c" I apparently made
one more change than I intended - I changed the last deco stop back to 3m
instead of allowing the smooth mode to go all the way back to 0 without
any discrete steps.

This fixes that mistake.

Reported-by: Robert C. Helling <helling@lmu.de>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Allow special entries in diveplan for available gases

An entry with no time is considered special and not considered when
constructing the profile.

This should allow us to add support for two different ways of adding
information about available gas:

changedepth 0 gasmix
0 0 gasmix @ po2

The first syntax basically says "during the ascent, switch to this gas at
this depth.
The second one says "switch to this gas once the pO2 allows for it"

Neither of these are implemented, yet, but this commit is necessary in
order for the rest of the code to ignore entries with a time field of 0.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Add support to planner to use additional gases during the ascent

This change ended up being quite a bit bigger than expected as it
uncovered a number of bugs in the existing code.

The planner now handles gas changes correctly by creating (and later
parsing) events in the simulated divecomputer. At the end of the dive
specified in the input form the algorithm starts with the deepest
interesting depth: either the first stop below our ceiling or the deepest
depth at which we can change gases. It then traverses all the stop and all
the gas change depth and at each stage ensures that we are allowed to
ascend further before going on.

Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Clean up duplicated depth interpolation

We have several places where we interpolate the depth based on two
samples and the time between them. Some of them use floating point, some
of them don't, some of them meant to do it but didn't.

Just use a common helper function for it. I seriously doubt the floating
point here really matters, since doing it in integers is not going to
overflow unless we're interpolating between two samples that are hours
apart at hundreds of meters of depth, but hey, it gives that rounding to
the nearest millimeter. Which I'm sure matters.

Anyway, we can probably just get rid of the rounding and the floating
point math, but it won't really hurt either, so at least do it
consistently.

The interpolation could be for other things than just depth, but we
probably don't have anything else we'd want to interpolate. But make the
function naming generic just in case.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Rename 'dcnicknamelist' struct as 'device_info'

We'll start recording more than just nicknames in it, like serial
numbers and firmware version etc.  Start off just renaming it, and
re-ordering the members to reflect how the nickname is not the primary
issue.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Move device_info handling into a new 'device.c' file

The legacy nickname wrappers (that use the device_info structure) are
left in gtk-gui.c.  We can slowly start moving away from them, we don't
want to start exporting that thing as some kind of generic interface.

This isn't a pure code movement - because we leave the legacy interfaces
alone, there are a few new interfaces in device.c (like "create a new
device_info entry") that were embedded into the legacy "create nickname"
code, and needed to be abstracted out.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Assemble the actual Suunto serial number

It turns out that the serial number returned by libdivecomputer isn't
really the serial number as interpreted by the vendor. Those tend to be
strings, but libdivecomputer gives us a 32bit number.

Some experimenting showed that for the Suunto devies tested the serial
number is encoded in that 32bit number:

It so happens that the Suunto serial number strings are strings that have
all numbers, but they aren't *one* number. They are four bytes
representing two numbers each, and the "23500027" string is actually the
four bytes 23 50 00 27 (0x17 0x32 0x00 0x1b). And libdivecomputer has
incorrectly parsed those four bytes as one number, not as the encoded
serial number string it is. So the value 389152795 is actually hex
0x1732001b, which is 0x17 0x32 0x00 0x1b, which is - 23 50 00 27.

This should be done by libdivecomputer, but hey, in the meantime this at
least shows the concept. And helps test the XML save/restore code.

It depends on the two patches that create the whole "device.c"
infrastructure, of course. With this, my dive file ends up having the
settings section look like this:

  <divecomputerid model='Suunto Vyper Air' deviceid='d4629110'
serial='01201094' firmware='1.1.22'/>
  <divecomputerid model='Suunto HelO2' deviceid='995dd566'
serial='23500027' firmware='1.0.4'/>

where the format of the firmware version is something I guessed at,
but it was the obvious choice (again, it's byte-based, I'm ignoring
the high byte that is zero for both of my Suuntos).

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
Adjust GFlow to apply at deepest ceiling instead of at max depth

This moves the point where GF_low applies up which implies that at all
shallower depth (i.e. during deco) a lower GF results which makes the deco
longer compared to the previous implementation.

Of course, "GF_low" applies at first deco stop is a bit tricky since the
depth of the first deco stop again depends on GF_low, i.e. there is
another equation to solve. You can do this by inverting the equation for
the ambient pressure and use GF_low as the gradient factor. This yields

amb = (b * M_value_corrected - GF_low * a * b) / ((1-b) * GF_low + b)

Signed-off-by: Robert C. Helling helling@atdotde.de
Signed-off-by: Dirk Hohndel <dirk@hohndel.org>