<div dir="ltr"><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Jan 29, 2016 at 4:55 AM,  <span dir="ltr"><<a href="mailto:john@vanostrand.com" target="_blank">john@vanostrand.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="background-color:rgb(255,255,255);line-height:initial" lang="en-US">                                                                                      <div style="width:100%;font-size:initial;font-family:Calibri,'Slate Pro',sans-serif,sans-serif;color:rgb(31,73,125);text-align:initial;background-color:rgb(255,255,255)"><br></div>                                                                                                                                     <div style="width:100%;font-size:initial;font-family:Calibri,'Slate Pro',sans-serif,sans-serif;color:rgb(31,73,125);text-align:initial;background-color:rgb(255,255,255)"><br style="display:initial"></div>                                                                                                                                                                                                   <div style="font-size:initial;font-family:Calibri,'Slate Pro',sans-serif,sans-serif;color:rgb(31,73,125);text-align:initial;background-color:rgb(255,255,255)">Sent from my BlackBerry 12 neural implant. </div>                                                                                                                                                                                  <table style="background-color:white;border-spacing:0px" width="100%"> <tbody><tr><td colspan="2" style="font-size:initial;text-align:initial;background-color:rgb(255,255,255)">                           <div style="border-style:solid none none;border-top-color:rgb(181,196,223);border-top-width:1pt;padding:3pt 0in 0in;font-family:Tahoma,'BB Alpha Sans','Slate Pro';font-size:10pt">  <div><b>From: </b>John Van Ostrand</div><div><b>Sent: </b>Wednesday, January 27, 2016 10:49 AM</div><div><b>To: </b>devel</div><div><b>Subject: </b>Re: Cochran Changes</div></div></td></tr></tbody></table><div style="border-style:solid none none;border-top-color:rgb(186,188,209);border-top-width:1pt;font-size:initial;text-align:initial;background-color:rgb(255,255,255)"></div><br><div><br><div dir="ltr"><div><div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jan 27, 2016 at 10:21 AM, Jef Driesen <span dir="ltr"><<a href="mailto:jef@libdivecomputer.org" target="_blank">jef@libdivecomputer.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span>On 2016-01-20 18:41, John Van Ostrand wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
I think this is a summary of where we left of:<br>
<br>
1. dc_context_t pointer doesn't need to be passed to cochran serial open a<br>
setup functions. (fixed with patch pending.)<br>
</blockquote>
<br></span>
Patch looks fine to me.<span><br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
2. Cochran can store more log entries than profiles. So when the profile<br>
ring buffer wraps earlier logs will point to profile data from other dives.<br>
Jef suggests processing dives in reverse chronological order, adding up<br>
profile data used and not processing profiles after it's processed a full<br>
ring-buffer of data. I have yet to work on this or consider alternatives.<br>
</blockquote>
<br></span>
The dc_device_foreach() function must return the dives in reverse chronological order. This is a requirement for the download only new dives feature. When dives are returned in reverse chronological order, an application (or libdivecomputer itself) can simply stop downloading dives as soon as a previously downloaded dive is recognized. Very simple and efficient.<br></blockquote><div><br></div><div>This is my loop in dc_device_foreach. <br><br>    int i;<br>    for (i = data->dive_count - 1; i > data->fp_dive_num; i--) {<br><br><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
Thus if we need to return the dives in reverse chronological order, it makes sense to process (and also download) the data in this order. Otherwise you'll end up with a rather inefficient implementation.<br>
<br>
I have to read through your documentation again, but processing the dives in reverse order might also make the recovery of corrupt dives easier. If the tail of a dive is missing, then it can run at most until the start of the next dive. And due the reverse order we already have that one.<span><br>
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
3. Corrupt dive handling. In some cases (like a low battery especially in<br>
cold water) the computer resets during a dive. This results in a<br>
"start-dive" block written but no valid "end-dive" block written. We know<br>
information from the start of a dive (like date/time, gasses, profile start<br>
pointer, etc.) but we don't know information accumulated during or at the<br>
end of a dive (like end-profile pointer, max depth, min temp, etc.) I've<br>
taken to guessing the end of a dive by starting with the next dive's<br>
pre-dive-profile-pointer and backing up until we think we have the previous<br>
dive's end. We haven't resolved our differences on this. It seems to down<br>
to the question: Do we present a partial or broken profile in the interest<br>
of giving the diver something or do we give nothing in the interest of<br>
being accurate?<br>
</blockquote>
<br></span>
That's a difficult question. In general, I prefer to be very strict and simply fail on unexpected data. Usually this is the correct thing to do, because such unexpected data often turns out to be an wrong assumption in the code. So being strict helps finding bugs. But sometimes the data is really wrong (due to a firmware bug, running out of battery during the dive, etc), and if it happens frequently, then a workaround might indeed be necessary.<br>
<br>
It also depends on where the data "corruption" is located. If the information needed to move from one dive to another is good, but we are unsure about the contents of the dive, then we can return the bogus dive to the application and let the parser deal with it. You might get incorrect data for that particular dive, or even a failure to parse the dive. This would ensure that we can still download the other dives. But if the primary structure is damaged and we can no longer safely move to the next dive, then I think we should fail.<span><font color="#888888"><br>
<br>
Jef<br>
</font></span></blockquote></div><br></div><div class="gmail_extra">I've been working on code to retrieve corrupt dives and it's becoming unwieldy. In working backwards from a future dive's profile I have to remove inter-dive events which vary in length. it's possible that two events might match the data and the code would have to decide which event to use. The code also needs to do range checking, like ensuring it doesn't exceed the malloc'ed memory and things like ring-buffer wrapping. I should also remove any surface time (the time the DC still stores samples in case you re-descend.)<br><br></div><div>There are ways to make this better but I think I'm going to have to think about it for a bit. I'm considering pulling that code. Any ideas on what I should do with the code so it isn't lost. An #ifdef maybe?</div><div><br></div></div></div><div><span style="line-height:initial">I've done some work and I may have a decent algorithm to backtrack over the inter-dive events to get to good data. It goes as far as removing good data in an effort to eliminate giving bad data. </span></div><div><span style="line-height:initial"><br></span></div><div><span style="line-height:initial">To refresh the issue: it has never been finding the beginning of data. The issue has been finding the end. ‎We do have the start of the next dive or, if no next dive, we have the ring buffer head pointer. What happens if we simply use those pointers is that interdive data, the data recorded between dives like power on events, is interpreted as profile data. The profile then looks erratic at the end. So the trick is to backtrack to find the real end of good data. Ideally wed be able to do that accurately but if we have to remove good data to be sure it would result in only loosing a few seconds of dive samples. </span></div><div><span style="line-height:initial"><br></span></div><div><span style="line-height:initial">Now that I've thought about the problem more and identified many of the issues I have a standalone test program that's doing a good job of backtracking to get to good data. I've used recursion to simplify the code and derive at an optimal solution.  In the dozen examples I'm using it's working on 11 of them well enough to remove all non profile data. The 12th leaves several seconds of non profile data. </span></div><span></span><br clear="all"></div></div></div></blockquote></div><br></div><div class="gmail_extra">Further to this I was thinking of another tactic. The profile data has a fairly normal pattern. Since depth samples are done every second and temp and ascent rate are every other second we don't expect to see huge changes in depth, temp or ascent rate. So we can do two things. Parse back as described above and in the event that it's not thorough enough we can watch for substantial changes in the data pattern and stop when it looks wrong. This would only be done with incomplete dives (incomplete is a better term than corrupt dives.)<br><br>If we can find a way to log that it was an incomplete dive there would be an easy way to reduce or easily eliminate bugs.<br></div><div class="gmail_extra"><br></div><div class="gmail_extra">-- <br><div><div dir="ltr"><div>John Van Ostrand<br></div><div>At large on sabbatical<br></div><br></div></div>
</div></div>