Mercurial > public > ostc4
annotate Discovery/Src/logbook.c @ 173:05c770dc2911 max-depth
Bugfix: make max depth move with current depth (part 1)
The display in dive mode of the max depth was updated before the actual
depth, which looks very strange. The reason for this was conceptually
simple. The depth value was averaged over a set of depth samples, but
the current depth was only taken from the current sample. So, per
definition, on an initial descend, the current depth is always bigger
(deeper) than any average from previous shallower samples.
This part 1 commit introduces a new function that is used immediate
after reception of the new sample from the RTE. This function does the
trivial average of a set of samples. Notice that also the surface and
ambient mbar pressures are taken into account (which are used heavily
over the entire code). This is a consistency thing. We should base any
further calculation from the data presented in the UI, instead of
presenting A, and use A' for further calculations.
Signed-off-by: Jan Mulder <jlmulder@xs4all.nl>
author | Jan Mulder <jlmulder@xs4all.nl> |
---|---|
date | Mon, 11 Mar 2019 19:48:57 +0100 |
parents | e1d66bc78f9a |
children | f23b9055436f |
rev | line source |
---|---|
38 | 1 /** |
2 ****************************************************************************** | |
3 * @copyright heinrichs weikamp | |
4 * @file logbook.c | |
5 * @author heinrichs weikamp gmbh and heinrichs weikamp gmbh | |
6 * @date 22-Apr-2014 | |
7 * @version V0.0.3 | |
8 * @since 03-Feb-2016 | |
9 * @brief Everything about creating and evaluating the logbook | |
10 * without the flash part which is included in externLogbookFlash.c | |
11 * and the USB/Bluetooth part in tComm.c | |
12 * CHANGE V0.0.3 hw: ppO2 sensor values | |
13 * CHANGE V0.0.4 hw: fix event bytes according to hwos_interface.odt dated 160610 in bitbucket hwOS | |
14 * @bug | |
15 * @warning | |
16 @verbatim | |
17 ============================================================================== | |
18 ##### Header ##### | |
19 ============================================================================== | |
20 [..] SLogbookHeader | |
21 The order has changed in comparsion to OSTC3 for perfect alignment | |
22 with 16bit and 32bit. The header is 256kB as well. | |
23 DO NOT rearrange anything but add new data to a second page | |
24 beyond diveHeaderEnd. Use extraPagesWithData to indicate that there is | |
25 data available that was not available in the OSTC3 256KB | |
26 This data will be behind the diveHeaderEnd. DO NOT delete diveHeaderEnd. | |
27 | |
28 [..] SLogbookHeaderOSTC3 | |
29 is the format used by the OSTC3. | |
30 logbook_getHeaderOSTC3() does the job using the global headers in logbook.c | |
31 | |
32 [..] SSmallHeader | |
33 - is the format used by the OSTC3 | |
34 | |
35 [..] Summary | |
36 The header format is not perfect and might be optimized prior to | |
37 releasing the diving computer. For now it is good to be compatible | |
38 with PC software available for checking the content of the logbook | |
39 | |
40 | |
41 @endverbatim | |
42 ****************************************************************************** | |
43 * @attention | |
44 * | |
45 * <h2><center>© COPYRIGHT(c) 2014 heinrichs weikamp</center></h2> | |
46 * | |
47 ****************************************************************************** | |
48 */ | |
49 | |
50 /* Includes ------------------------------------------------------------------*/ | |
51 #include <stdint.h> | |
52 #include <string.h> | |
53 #include "logbook.h" | |
54 //#include "test_vpm.h" | |
55 #include "externLogbookFlash.h" | |
56 #include "data_exchange.h" | |
57 #include "decom.h" | |
58 #include "tHome.h" // for tHome_findNextStop() | |
59 | |
60 /* Private types -------------------------------------------------------------*/ | |
61 | |
62 #define NUM_GASES 5 | |
63 | |
64 #define LOGBOOK_VERSION (0x30) | |
65 #define LOGBOOK_VERSION_OSTC3 (0x24) | |
66 | |
67 typedef struct /* don't forget to adjust void clear_divisor(void) */ | |
68 { | |
69 uint8_t temperature; | |
70 uint8_t deco_ndl; | |
71 uint8_t gradientFactor; | |
72 uint8_t ppo2; | |
73 uint8_t decoplan; | |
74 uint8_t cns; | |
75 uint8_t tank; | |
76 } SDivisor; | |
77 | |
78 /* Exported variables --------------------------------------------------------*/ | |
79 | |
80 /* Private variables ---------------------------------------------------------*/ | |
81 uint8_t data_store[10000]; | |
82 SLogbookHeader header; | |
83 SLogbookHeaderOSTC3 headerOSTC3; | |
84 SLogbookHeaderOSTC3compact headerOSTC3compact; | |
85 SSmallHeader smallHeader; | |
86 SDivisor divisor; | |
87 SDivisor divisorBackup; | |
88 | |
89 /* Private function prototypes -----------------------------------------------*/ | |
90 void clear_divisor(void); | |
91 void logbook_SetAverageDepth(float average_depth_meter); | |
92 void logbook_SetMinTemperature(float min_temperature_celsius); | |
93 void logbook_SetMaxCNS(float max_cns_percentage); | |
94 void logbook_SetCompartmentDesaturation(void); | |
95 void logbook_SetLastStop(float last_stop_depth_bar); | |
96 void logbook_writedata(void * data, int length_byte); | |
97 void logbook_UpdateHeader(void); | |
98 | |
99 /* Exported functions --------------------------------------------------------*/ | |
100 | |
101 /** used by test_vpm.c at the moment */ | |
102 void logbook_EndDive(void) | |
103 { | |
104 ext_flash_close_new_dive_log((uint8_t*) &header); | |
105 } | |
106 | |
107 | |
108 // =============================================================================== | |
109 // logbook_last_totalDiveCount | |
110 /// @brief Fix setting issues | |
111 /// @date 04-April-2016 | |
112 /// | |
113 /// @return diveNumber (totalDiveCounter) of latest log entry, 0 if not a valid header | |
114 // =============================================================================== | |
115 uint16_t logbook_lastDive_diveNumber(void) | |
116 { | |
117 SLogbookHeader tempLogbookHeader; | |
118 if(logbook_getHeader(0, &tempLogbookHeader)) | |
119 { | |
120 return tempLogbookHeader.diveNumber; | |
121 } | |
122 else | |
123 { | |
124 return 0; | |
125 } | |
126 } | |
127 | |
128 | |
129 /** | |
130 ****************************************************************************** | |
131 * @brief logbook_getCurrentHeader. / | |
132 * @author Peter Ryser | |
133 * @version V0.0.1 | |
134 * @date 22-April-2014 | |
135 ****************************************************************************** | |
136 * | |
137 * @return SLogbookHeader*: | |
138 */ | |
139 SLogbookHeader* logbook_getCurrentHeader(void) | |
140 { | |
141 return &header; | |
142 } | |
143 | |
144 /** | |
145 ****************************************************************************** | |
146 * @brief logbook_getHeaderOSTC3. / | |
147 * @author heinrichs weikamp gmbh | |
148 * @version V0.0.1 | |
149 * @date 26-Nov-2014 | |
150 ****************************************************************************** | |
151 * | |
152 * @param StepBackwards : 0 Last lokbook entry, 1 second to last entry, etc. | |
153 * @param SSLogbookHeader* pLogbookHeader: Output found LogbookHeader | |
154 * @return uint8_t : 1 = success | |
155 */ | |
156 /* | |
157 SLogbookHeaderOSTC3 * logbook_getHeaderOSTC3(uint8_t StepBackwards) | |
158 { | |
159 if(!logbook_getHeader(StepBackwards, &header)) | |
160 return 0; | |
161 else | |
162 { | |
163 logbook_build_ostc3header(); | |
164 return &headerOSTC3; | |
165 } | |
166 } | |
167 */ | |
168 | |
169 /** | |
170 ****************************************************************************** | |
171 * @brief logbook_getNumberOfHeaders. / | |
172 * @author heinrichs weikamp gmbh | |
173 * @version V0.0.1 | |
174 * @date 18-May-2016 | |
175 ****************************************************************************** | |
176 * | |
177 * @return uint8_t : number of valid headers (0xFAFA) found. | |
178 */ | |
179 uint8_t logbook_getNumberOfHeaders(void) | |
180 { | |
181 return ext_flash_count_dive_headers(); | |
182 } | |
183 | |
184 | |
185 /** | |
186 ****************************************************************************** | |
187 * @brief logbook_getHeader. / | |
188 * @author Peter Ryser | |
189 * @version V0.0.1 | |
190 * @date 22-April-2014 | |
191 ****************************************************************************** | |
192 * | |
193 * @param StepBackwards : 0 Last lokbook entry, 1 second to last entry, etc. | |
194 * @param SSLogbookHeader* pLogbookHeader: Output found LogbookHeader | |
195 * @return uint8_t : 1 = success | |
196 */ | |
197 uint8_t logbook_getHeader(uint8_t StepBackwards,SLogbookHeader* pLogbookHeader) | |
198 { | |
199 ext_flash_read_dive_header((uint8_t *)pLogbookHeader, StepBackwards); | |
200 if(pLogbookHeader->diveHeaderStart != 0xFAFA) | |
201 return 0; | |
202 else | |
203 return 1; | |
204 } | |
205 | |
206 /** | |
207 ****************************************************************************** | |
208 * @brief logbook_initNewdiveProfile. / | |
209 * creates header and smallHeader from diveState and global Settings | |
210 * and writes new lookboock entry on flash device | |
211 * diveState | |
212 * @author Peter Ryser | |
213 * @version V0.0.1 | |
214 * @date 22-April-2014 | |
215 ****************************************************************************** | |
216 * | |
217 * @param SDiveState* pInfo: Input | |
218 * @param SSettings* pSettings: Input | |
219 */ | |
220 | |
221 void logbook_initNewdiveProfile(const SDiveState* pInfo, SSettings* pSettings) | |
222 { | |
223 RTC_DateTypeDef Sdate; | |
224 RTC_TimeTypeDef Stime; | |
225 | |
226 for(int i = 0; i < sizeof(SLogbookHeader); i++) | |
227 { | |
228 ((uint8_t*)(&header))[i] = 0; | |
229 } | |
230 header.diveHeaderStart = 0xFAFA; | |
231 header.diveHeaderEnd = 0xFBFB; | |
232 header.samplingRate = 2; | |
233 if(pInfo->diveSettings.diveMode == DIVEMODE_OC) | |
234 { | |
235 for(int i = 0; i < 5; i++) | |
236 { | |
237 header.gasordil[i].oxygen_percentage = pSettings->gas[i+1].oxygen_percentage; | |
238 header.gasordil[i].helium_percentage = pSettings->gas[i+1].helium_percentage; | |
239 header.gasordil[i].note.uw = pSettings->gas[i+1].note.uw; | |
240 header.gasordil[i].depth_meter = pSettings->gas[i+1].depth_meter; | |
241 } | |
242 } | |
243 else | |
244 { | |
245 for(int i = 0; i < 5; i++) | |
246 { | |
247 header.gasordil[i].oxygen_percentage = pSettings->gas[i+6].oxygen_percentage; | |
248 header.gasordil[i].helium_percentage = pSettings->gas[i+6].helium_percentage; | |
249 header.gasordil[i].note.uw = pSettings->gas[i+6].note.uw; | |
250 header.gasordil[i].depth_meter = pSettings->gas[i+6].depth_meter; | |
251 } | |
252 | |
253 for(int i = 0; i < 5; i++) | |
254 { | |
255 header.setpoint[i].setpoint_cbar = pSettings->setpoint[i+1].setpoint_cbar; | |
256 header.setpoint[i].depth_meter = pSettings->setpoint[i+1].depth_meter; | |
257 } | |
258 } | |
259 // header.gasordil[pInfo->lifeData.actualGas.GasIdInSettings].depth_meter = 0; | |
260 | |
261 translateDate(pInfo->lifeData.dateBinaryFormat, &Sdate); | |
262 translateTime(pInfo->lifeData.timeBinaryFormat, &Stime); | |
263 header.dateYear = Sdate.Year; | |
264 header.dateMonth = Sdate.Month; | |
265 header.dateDay = Sdate.Date; | |
266 header.timeHour = Stime.Hours; | |
267 header.timeMinute = Stime.Minutes; | |
268 header.cnsAtBeginning = (uint16_t)((pInfo->lifeData.cns * 100) + 0.5f); | |
269 header.surfacePressure_mbar = (uint16_t)(pInfo->lifeData.pressure_surface_bar * 1000); | |
270 header.firmwareVersionHigh = firmwareVersion_16bit_high(); | |
271 header.firmwareVersionLow = firmwareVersion_16bit_low(); | |
272 header.logbookProfileVersion = LOGBOOK_VERSION; | |
273 header.salinity = pSettings->salinity; | |
274 header.diveNumber = pSettings->totalDiveCounter; | |
275 header.personalDiveCount = pSettings->personalDiveCount; | |
276 | |
277 header.diveMode = pInfo->diveSettings.diveMode; | |
278 header.CCRmode = pInfo->diveSettings.CCR_Mode; | |
279 header.lastDecostop_m = pSettings->last_stop_depth_meter; | |
280 | |
281 if(pInfo->diveSettings.deco_type.ub.standard == GF_MODE) | |
282 { | |
283 header.decoModel = 1; | |
284 header.gfLow_or_Vpm_conservatism = pInfo->diveSettings.gf_low; | |
285 header.gfHigh = pInfo->diveSettings.gf_high; | |
286 } | |
287 else | |
288 { | |
289 header.decoModel = 2; | |
290 header.gfLow_or_Vpm_conservatism = pInfo->diveSettings.vpm_conservatism; | |
291 header.gfHigh = 0; | |
292 } | |
293 | |
294 memcpy(header.n2Compartments, pInfo->lifeData.tissue_nitrogen_bar, 64); | |
295 memcpy(header.heCompartments, pInfo->lifeData.tissue_helium_bar, 64); | |
296 | |
297 logbook_SetCompartmentDesaturation(); | |
298 | |
299 ext_flash_start_new_dive_log_and_set_actualPointerSample((uint8_t*)&header); | |
300 | |
301 smallHeader.profileLength[0] = 0xFF; | |
302 smallHeader.profileLength[1] = 0xFF; | |
303 smallHeader.profileLength[2] = 0xFF; | |
304 smallHeader.samplingRate_seconds = 2; | |
305 smallHeader.numDivisors = 7; | |
306 | |
307 smallHeader.tempType = 0; | |
308 smallHeader.tempLength = 2; | |
309 smallHeader.tempDivisor = 6; | |
310 | |
311 smallHeader.deco_ndlType = 1; | |
312 smallHeader.deco_ndlLength = 2; | |
313 smallHeader.deco_ndlDivisor = 6; //= 6; | |
314 | |
315 /* GF in % at actual position */ | |
316 smallHeader.gfType = 2; | |
317 smallHeader.gfLength = 1; | |
318 smallHeader.gfDivisor = 0; //12; | |
319 | |
320 /* 3 Sensors: 8bit ppO2 in 0.01bar, 16bit voltage in 0,1mV */ | |
321 smallHeader.ppo2Type = 3; | |
322 smallHeader.ppo2Length = 9; | |
323 smallHeader.ppo2Divisor = 2; //2 | |
324 | |
325 /* last 15 stops in minutes (last, second_to_last, ... */ | |
326 /* last stop depth is defined in header */ | |
327 smallHeader.decoplanType = 4; | |
328 smallHeader.decoplanLength = 15; | |
329 smallHeader.decoplanDivisor = 12;//12; | |
330 | |
331 smallHeader.cnsType = 5; | |
332 smallHeader.cnsLength = 2; | |
333 smallHeader.cnsDivisor = 12; | |
334 | |
335 smallHeader.tankType = 6; | |
336 smallHeader.tankLength = 0; | |
337 smallHeader.tankDivisor = 0; | |
338 | |
339 logbook_writedata((void *) &smallHeader,sizeof(smallHeader)); | |
340 | |
341 clear_divisor(); | |
342 } | |
343 | |
344 /** | |
345 ****************************************************************************** | |
346 * @brief clear_divisor / clears divisor struct | |
347 * @author Peter Ryser | |
348 * @version V0.0.1 | |
349 * @date 22-April-2014 | |
350 ****************************************************************************** | |
351 * | |
352 */ | |
353 void clear_divisor(void) | |
354 { | |
355 divisor.cns = smallHeader.cnsDivisor - 1; | |
356 divisor.decoplan = smallHeader.decoplanDivisor - 1; | |
357 divisor.deco_ndl = smallHeader.deco_ndlDivisor - 1; | |
358 divisor.gradientFactor = smallHeader.gfDivisor -1 ; | |
359 divisor.ppo2 = smallHeader.ppo2Divisor - 1; | |
360 divisor.tank = smallHeader.tankDivisor - 1; | |
361 divisor.temperature = smallHeader.tempDivisor - 1; | |
362 } | |
363 | |
364 | |
365 /** | |
366 ****************************************************************************** | |
367 * @brief add16. / adds 16 bit variable to 8 bit array | |
368 * @author Peter Ryser | |
369 * @version V0.0.1 | |
370 * @date 22-April-2014 | |
371 ****************************************************************************** | |
372 * | |
373 * @param uint8_t *pos: Output 8 bit array | |
374 * @param uint16_t var: 16 bit variable | |
375 */ | |
376 void addU16(uint8_t *pos, uint16_t var) | |
377 { | |
378 *((uint16_t*)pos) = var; | |
379 } | |
380 | |
381 void addS16(uint8_t *pos, int16_t var) | |
382 { | |
383 *((int16_t*)pos) = var; | |
384 } | |
385 | |
386 /** | |
387 ****************************************************************************** | |
388 * @brief logbook_writeSample. / Writes one logbook sampl | |
389 * @author Peter Ryser | |
390 * @date 22-April-2014 | |
391 * @version V0.0.2 | |
392 * @since 20-June-2016 | |
393 * @bug Deco/NDL Status fixed in V0.0.2 | |
394 | |
395 | |
396 ****************************************************************************** | |
397 * | |
398 * @param SDiveState state: | |
399 */ | |
400 | |
401 void logbook_writeSample(SDiveState state) | |
402 { | |
403 uint8_t sample[256]; | |
404 // int position = 0; | |
405 int length = 0; | |
406 // _Bool bEvent = 0; | |
407 uint8_t nextstopDepthMeter = 0; | |
408 uint16_t nextstopLengthSeconds = 0; | |
409 uint8_t nextstopLengthMinutes = 0; | |
410 bit8_Type eventByte1, eventByte2; | |
411 bit8_Type profileByteFlag; | |
412 int i = 0; | |
413 for(i = 0; i <256 ;i++) | |
414 sample[i] = 0; | |
415 addU16(sample, (uint16_t)(state.lifeData.depth_meter * 100)); | |
416 length += 2; | |
417 sample[2] = 0; | |
418 length++; | |
419 eventByte1.uw = 0; | |
420 eventByte2.uw = 0; | |
421 //uint16_t tmpU16 = 0; | |
130
b7689d9e888a
Minor changes to improved code quality and to eliminate warnings
Ideenmodellierer
parents:
38
diff
changeset
|
422 const SDecoinfo * pDecoinfo; // new hw 160620 |
38 | 423 |
424 //BuildEevntyte 1 | |
425 // sub old 0-3 only one at a time | |
426 if(state.events.manualMarker) | |
427 { | |
428 eventByte1.uw = 6; | |
429 } | |
430 else | |
431 if(state.warnings.decoMissed) | |
432 { | |
433 eventByte1.uw = 2; | |
434 } | |
435 else | |
436 if(state.warnings.ppO2Low) | |
437 { | |
438 eventByte1.uw = 4; | |
439 } | |
440 else | |
441 if(state.warnings.ppO2High) | |
442 { | |
443 eventByte1.uw = 5; | |
444 } | |
445 else | |
446 if(state.warnings.lowBattery) | |
447 { | |
448 eventByte1.uw = 7; | |
449 } | |
450 else | |
451 if(state.warnings.slowWarning) | |
452 { | |
453 eventByte1.uw = 1; | |
454 } | |
455 // sub bit 4 to 7 | |
456 if(state.events.manuelGasSet) | |
457 { | |
458 eventByte1.ub.bit4 = 1; | |
459 } | |
460 if(state.events.gasChange) | |
461 { | |
462 eventByte1.ub.bit5 = 1; | |
463 } | |
464 if(state.events.setpointChange) | |
465 { | |
466 eventByte1.ub.bit6 = 1; | |
467 } | |
468 // sub bit 7 + eventbyte2 | |
469 if(state.events.bailout) | |
470 { | |
471 eventByte1.ub.bit7 = 1; | |
472 eventByte2.ub.bit0 = 1; | |
473 } | |
474 //Add EventByte 1 | |
475 if(eventByte1.uw > 0) | |
476 { | |
477 sample[length] = eventByte1.uw; | |
478 length++; | |
479 } | |
480 if(eventByte2.uw > 0) | |
481 { | |
482 sample[length] = eventByte2.uw; | |
483 length++; | |
484 } | |
485 //Add EventInfos | |
486 if(state.events.manuelGasSet) | |
487 { | |
488 //manual gas in %O2 & %He | |
489 sample[length] = state.events.info_manuelGasSetO2; | |
490 length += 1; | |
491 sample[length] = state.events.info_manuelGasSetHe; | |
492 length += 1; | |
493 } | |
494 if(state.events.gasChange) | |
495 { | |
496 //Current gas (gasid) | |
497 sample[length] = state.events.info_GasChange; | |
498 length += 1; | |
499 } | |
500 if(state.events.setpointChange) | |
501 { | |
502 //New setpoint in cbar | |
503 sample[length] = state.events.info_SetpointChange; | |
504 length += 1; | |
505 } | |
506 if(state.events.bailout) | |
507 { | |
508 //bailout gas in % O2 & %He | |
509 sample[length] = state.events.info_bailoutO2; | |
510 length += 1; | |
511 sample[length] = state.events.info_bailoutHe; | |
512 length += 1; | |
513 } | |
514 | |
515 | |
516 if(divisor.temperature == 0) | |
517 { | |
518 divisor.temperature = smallHeader.tempDivisor - 1; | |
519 addS16(&sample[length], (int16_t)((state.lifeData.temperature_celsius * 10.0f) + 0.5f)); | |
520 length += 2; | |
521 } | |
522 else | |
523 { | |
524 divisor.temperature--; | |
525 } | |
526 | |
527 | |
528 if(smallHeader.deco_ndlDivisor > 0) | |
529 { | |
530 if(divisor.deco_ndl == 0) | |
531 { | |
532 divisor.deco_ndl = smallHeader.deco_ndlDivisor - 1; | |
533 | |
534 if(stateUsed->diveSettings.deco_type.ub.standard == GF_MODE) | |
535 pDecoinfo = &stateUsed->decolistBuehlmann; | |
536 else if(stateUsed->diveSettings.deco_type.ub.standard == VPM_MODE) | |
537 pDecoinfo = &stateUsed->decolistVPM; | |
538 else // should not happen as only GF and VPM at the moment | |
539 { | |
540 sample[length] = 0; | |
541 length += 1; | |
542 sample[length] = 0; | |
543 length += 1; | |
544 } | |
545 | |
546 if(pDecoinfo->output_ndl_seconds > 0) | |
547 { | |
548 sample[length] = 0; | |
549 length += 1; | |
550 sample[length] = (uint8_t)pDecoinfo->output_ndl_seconds / 60; | |
551 length += 1; | |
552 } | |
553 else if(pDecoinfo->output_time_to_surface_seconds) | |
554 { | |
555 tHome_findNextStop(pDecoinfo->output_stop_length_seconds, &nextstopDepthMeter, &nextstopLengthSeconds); | |
556 nextstopLengthMinutes = (nextstopLengthSeconds +59 ) / 60; | |
557 | |
558 sample[length] = nextstopDepthMeter; | |
559 length += 1; | |
560 sample[length] = nextstopLengthMinutes; | |
561 length += 1; | |
562 } | |
563 else | |
564 { | |
565 sample[length] = 0; | |
566 length += 1; | |
567 sample[length] = 0; | |
568 length += 1; | |
569 } | |
570 } | |
571 else | |
572 { | |
573 divisor.deco_ndl --; | |
574 } | |
575 } | |
576 | |
577 | |
578 if(smallHeader.ppo2Divisor) | |
579 { | |
580 if(divisor.ppo2 == 0) | |
581 { | |
582 divisor.ppo2 = smallHeader.ppo2Divisor - 1; | |
583 | |
584 for(int i = 0; i <3; i++) | |
585 { | |
586 sample[length] = (uint8_t)(state.lifeData.ppO2Sensor_bar[i] * 100.0f + 0.5f); | |
587 length += 1; | |
588 addU16(&sample[length], (uint16_t)(state.lifeData.sensorVoltage_mV[i] * 10.0f + 0.5f)); | |
589 length += 2; | |
590 } | |
591 } | |
592 else | |
593 { | |
594 divisor.ppo2--; | |
595 } | |
596 } | |
597 | |
598 | |
599 if(smallHeader.decoplanDivisor) | |
600 { | |
601 if(divisor.decoplan == 0) | |
602 { | |
603 divisor.decoplan = smallHeader.decoplanDivisor - 1; | |
604 if(state.diveSettings.deco_type.ub.standard == VPM_MODE) | |
605 { | |
606 for(int i = 0; i <15; i++) | |
607 { | |
608 sample[length] = state.decolistVPM.output_stop_length_seconds[i] / 60; | |
609 length += 1; | |
610 } | |
611 } | |
612 else if(state.diveSettings.deco_type.ub.standard == GF_MODE) | |
613 { | |
614 for(int i = 0; i <15; i++) | |
615 { | |
616 sample[length] = state.decolistBuehlmann.output_stop_length_seconds[i] / 60; | |
617 length += 1; | |
618 } | |
619 } | |
620 else | |
621 { | |
622 for(int i = 0; i <15; i++) | |
623 { | |
624 sample[length] = 0; | |
625 length += 1; | |
626 } | |
627 } | |
628 // add16(&sample[length], state.temperature); | |
629 //length += 2; | |
630 } | |
631 else | |
632 { | |
633 divisor.decoplan --; | |
634 } | |
635 } | |
636 if(divisor.cns == 0) | |
637 { | |
638 divisor.cns = smallHeader.cnsDivisor - 1; | |
639 //addU16(&sample[length], (uint16_t)(state.lifeData.cns * 100.0f + 0.5f)); | |
640 addU16(&sample[length], (uint16_t)(state.lifeData.cns)); // hw 151110 cns is 0 to 100 % and more (not 0 to 1.00 and more) | |
641 length += 2; | |
642 } | |
643 else | |
644 { | |
645 divisor.cns--; | |
646 } | |
647 | |
648 profileByteFlag.uw = length - 3; | |
649 if(eventByte1.uw) | |
650 { | |
651 profileByteFlag.ub.bit7 = 1; | |
652 } | |
653 sample[2] = profileByteFlag.uw; | |
654 logbook_writedata((void *) sample,length); | |
655 | |
656 } | |
657 | |
658 | |
659 | |
660 uint16_t actual_depth1; | |
661 uint16_t actual_depth2; | |
662 uint16_t actual_length1; | |
663 uint16_t actual_length2; | |
664 uint16_t actual_inum; | |
665 | |
666 /** | |
667 ****************************************************************************** | |
668 * @brief readSample. / Reads data of one logbook sample | |
669 * @author Peter Ryser | |
670 * @version V0.0.1 | |
671 * @date 22-April-2014 | |
672 ****************************************************************************** | |
673 * | |
674 * @param int32_t* depth: output Value | |
675 * @param int16_t * gasid: output Value | |
676 * @param int32_t* temperature: output Value | |
677 * @param int32_t* sensor1, sensor2, sensor3: output Value | |
678 * @param int32_t* cns: output Value | |
679 * @return bytes read / 0 = reading Error | |
680 */ | |
681 uint16_t readSample(int32_t* depth, int16_t * gasid, int16_t* setpoint_cbar, int32_t* temperature, int32_t* sensor1, int32_t* sensor2, int32_t* sensor3, int32_t* cns, SManualGas* manualGas, int16_t* bailout, int16_t* decostopDepth) | |
682 { | |
683 int length = 0; | |
684 _Bool bEvent = 0; | |
685 bit8_Type eventByte1, eventByte2; | |
686 bit8_Type profileByteFlag; | |
687 | |
688 eventByte1.uw = 0; | |
689 eventByte2.uw = 0; | |
690 uint8_t tempU8 = 0; | |
691 uint16_t temp = 0; | |
692 uint16_t bytesRead = 0; | |
693 | |
694 if(gasid) | |
695 *gasid = -1; | |
696 if(temperature) | |
697 *temperature = -1000; | |
698 if(sensor1) | |
699 *sensor1 = -1; | |
700 if(sensor2) | |
701 *sensor2 = -1; | |
702 if(sensor3) | |
703 *sensor3 = -1; | |
704 if(cns) | |
705 *cns = -1; | |
706 if(setpoint_cbar) | |
707 *setpoint_cbar = -1; | |
708 if(bailout) | |
709 *bailout = -1; | |
710 if(manualGas) | |
711 { | |
712 manualGas->percentageO2 =-1; | |
713 manualGas->percentageHe =-1; | |
714 } | |
715 if(decostopDepth) | |
716 *decostopDepth = -1; | |
717 | |
718 ext_flash_read_next_sample_part( (uint8_t*)&temp, 2); | |
719 if(depth) | |
720 *depth = (int32_t)temp; | |
721 bytesRead += 2; | |
722 | |
723 ext_flash_read_next_sample_part( &profileByteFlag.uw, 1); | |
724 bytesRead ++; | |
725 | |
726 bEvent = profileByteFlag.ub.bit7; | |
727 profileByteFlag.ub.bit7 = 0; | |
728 length = profileByteFlag.uw; | |
729 | |
730 if(bEvent) | |
731 { | |
732 ext_flash_read_next_sample_part( &eventByte1.uw, 1); | |
733 bytesRead ++; | |
734 | |
735 length--; | |
736 | |
737 //second event byte | |
738 if(eventByte1.ub.bit7) | |
739 { | |
740 ext_flash_read_next_sample_part( &eventByte2.uw, 1); | |
741 bytesRead ++; | |
742 length--; | |
743 } | |
744 else | |
745 { | |
746 eventByte2.uw = 0; | |
747 } | |
748 | |
749 //manual Gas Set | |
750 if( eventByte1.ub.bit4) | |
751 { | |
752 //Evaluate manual Gas | |
753 ext_flash_read_next_sample_part( (uint8_t*)&tempU8, 1); | |
754 bytesRead +=1; | |
755 length -= 1; | |
756 manualGas->percentageO2 = tempU8; | |
757 ext_flash_read_next_sample_part( (uint8_t*)&tempU8, 1); | |
758 bytesRead +=1; | |
759 length -= 1; | |
760 manualGas->percentageHe = tempU8; | |
761 if(gasid) | |
762 *gasid = 0; | |
763 } | |
764 //gas change | |
765 if( eventByte1.ub.bit5) | |
766 { | |
767 ext_flash_read_next_sample_part( &tempU8, 1); | |
768 bytesRead +=1; | |
769 length -= 1; | |
770 if(gasid) | |
771 *gasid = (uint16_t)tempU8; | |
772 } | |
773 //SetpointChange | |
774 if( eventByte1.ub.bit6) | |
775 { | |
776 ext_flash_read_next_sample_part( &tempU8, 1); | |
777 *setpoint_cbar = tempU8; | |
778 bytesRead +=1; | |
779 length -= 1; | |
780 } | |
781 | |
782 // second event Byte | |
783 //bailout | |
784 if(eventByte2.ub.bit1) | |
785 { | |
786 //evaluate bailout gas Gas | |
787 *bailout = 1; | |
788 | |
789 ext_flash_read_next_sample_part( (uint8_t*)&tempU8, 1); | |
790 bytesRead +=1; | |
791 length -= 1; | |
792 manualGas->percentageO2 = tempU8; | |
793 ext_flash_read_next_sample_part( (uint8_t*)&tempU8, 1); | |
794 bytesRead +=1; | |
795 length -= 1; | |
796 manualGas->percentageHe = tempU8; | |
797 | |
798 if(gasid) | |
799 *gasid = 0; | |
800 } | |
801 } | |
802 | |
803 if(divisor.temperature == 0) | |
804 { | |
805 divisor.temperature = smallHeader.tempDivisor - 1; | |
806 ext_flash_read_next_sample_part( (uint8_t*)&temp, 2); | |
807 bytesRead +=2; | |
808 length -= 2; | |
809 if(temperature) | |
810 { | |
811 *temperature = (int32_t)temp; | |
812 } | |
813 } | |
814 else | |
815 { | |
816 divisor.temperature--; | |
817 } | |
818 | |
819 if(smallHeader.deco_ndlDivisor > 0) | |
820 { | |
821 if(divisor.deco_ndl == 0) | |
822 { | |
823 divisor.deco_ndl = smallHeader.deco_ndlDivisor - 1; | |
824 ext_flash_read_next_sample_part( &tempU8, 1); | |
825 if(decostopDepth) | |
826 { | |
827 *decostopDepth = tempU8 * 100; | |
828 } | |
829 ext_flash_read_next_sample_part( &tempU8, 1); | |
830 bytesRead += 2; | |
831 length -= 2; | |
832 } | |
833 else | |
834 { | |
835 divisor.deco_ndl--; | |
836 } | |
837 } | |
838 | |
839 if(divisor.ppo2 == 0) | |
840 { | |
841 int32_t ppO2Tmp = 0; | |
842 divisor.ppo2 = smallHeader.ppo2Divisor -1; | |
843 for(int i = 0; i <3 ; i++) | |
844 { | |
845 ext_flash_read_next_sample_part( &tempU8, 1); | |
846 ppO2Tmp += tempU8; | |
847 bytesRead +=1; | |
848 length -= 1; | |
849 ext_flash_read_next_sample_part( (uint8_t*)&temp, 2); | |
850 bytesRead +=2; | |
851 length -= 2; | |
852 if(sensor1 && (i==0)) | |
853 *sensor1 = (((int32_t)tempU8) * 0xFFFF) + temp; | |
854 if(sensor2 && (i==1)) | |
855 *sensor2 = (((int32_t)tempU8) * 0xFFFF) + temp; | |
856 if(sensor3 && (i==2)) | |
857 *sensor3 = (((int32_t)tempU8) * 0xFFFF) + temp; | |
858 } | |
859 } | |
860 else | |
861 { | |
862 divisor.ppo2--; | |
863 } | |
864 | |
865 if(smallHeader.decoplanDivisor > 0) | |
866 { | |
867 if(divisor.decoplan == 0) | |
868 { | |
869 divisor.decoplan = smallHeader.decoplanDivisor - 1; | |
870 for(int i = 0; i <15; i++) | |
871 ext_flash_read_next_sample_part( &tempU8, 1); | |
872 bytesRead += 15; | |
873 length -= 15; | |
874 } | |
875 else | |
876 { | |
877 divisor.decoplan--; | |
878 } | |
879 } | |
880 | |
881 | |
882 | |
883 if(divisor.cns == 0) | |
884 { | |
885 divisor.cns = smallHeader.cnsDivisor - 1; | |
886 | |
887 ext_flash_read_next_sample_part( (uint8_t*)&temp, 2); | |
888 bytesRead +=2; | |
889 length -= 2; | |
890 if(cns) | |
891 { | |
892 *cns = (int32_t)temp; | |
893 } | |
894 } | |
895 else | |
896 { | |
897 divisor.cns--; | |
898 } | |
899 | |
900 if (length != 0) | |
901 return 0; | |
902 | |
903 return bytesRead; | |
904 } | |
905 /** | |
906 ****************************************************************************** | |
907 * @brief logbook_readSampleData. / Reads sample data of whole logbook entry | |
908 * @author Peter Ryser | |
909 * @version V0.0.1 | |
910 * @date 22-April-2014 | |
911 ****************************************************************************** | |
912 * | |
913 * @param uint8_t StepBackwards: witch lookbook entry? | |
914 * @param uint16_t length : maxlength of output arrays | |
915 * @param int32_t* depth : output array | |
916 * @param int16_t * gasid : output array | |
917 * @param int32_t* temperature : output array | |
918 * @param int32_t* ppo2 : output array | |
919 * @param int32_t* cns : output array | |
920 * @return length of output | |
921 */ | |
922 uint16_t logbook_readSampleData(uint8_t StepBackwards, uint16_t length,uint16_t* depth, uint8_t* gasid, int16_t* temperature, uint16_t* ppo2, uint16_t* setpoint, uint16_t* sensor1, uint16_t* sensor2, uint16_t* sensor3, uint16_t* cns, uint8_t* bailout, uint16_t* decostopDepth) | |
923 { | |
924 //Test read | |
925 //SLogbookHeader header; | |
926 | |
927 //logbook_getHeader(&header); | |
928 SLogbookHeader header; | |
929 int iNum; | |
930 int firstgasid = 0; | |
931 int retVal = 0; | |
932 int compression = 0; | |
933 int i; | |
934 // uint32_t diveTime_seconds; | |
935 int32_t depthVal = 0; | |
936 int16_t gasidVal = 0; | |
937 int16_t setPointVal = 0; | |
938 int16_t bailoutVal = 0; | |
939 int16_t bailoutLast = 0; | |
940 uint16_t setPointLast = 0; | |
941 int32_t temperatureVal = 0; | |
942 int32_t sensor1Val = 0; | |
943 int32_t sensor2Val = 0; | |
944 int32_t sensor3Val = 0; | |
945 int32_t sensor1Last = 0; | |
946 int32_t sensor2Last = 0; | |
947 int32_t sensor3Last = 0; | |
948 int32_t cnsVal = 0; | |
949 int32_t depthLast = 0; | |
950 int16_t gasidLast = 0; | |
951 int32_t temperatureLast = 0; | |
952 int32_t temperatureFirst = 0; | |
953 int32_t cnsLast = 0; | |
954 int16_t decostepDepthVal = 0; | |
955 int16_t decostepDepthLast = 0; | |
956 | |
957 SManualGas manualGasVal; | |
958 SManualGas manualGasLast; | |
959 manualGasLast.percentageO2 = 0; | |
960 manualGasLast.percentageHe = 0; | |
961 | |
962 float ambiant_pressure_bar = 0; | |
963 float ppO2 = 0; | |
964 ext_flash_read_dive_header((uint8_t*)&header, StepBackwards); | |
965 for(i = 0;i< 5;i++) | |
966 { | |
967 if(header.gasordil[i].note.ub.first) | |
968 break; | |
969 } | |
970 firstgasid = i + 1; | |
971 if(header.diveMode == DIVEMODE_CCR) | |
972 setPointLast = header.setpoint[0].setpoint_cbar; | |
973 else | |
974 setPointLast = 0; | |
975 //diveTime_seconds = header.diveTime_seconds ; | |
976 for(compression = 1; compression < 100; compression ++) | |
977 { | |
978 if((header.total_diveTime_seconds / header.samplingRate)/compression <= length) | |
979 break; | |
980 } | |
981 | |
982 | |
983 for(i = 0;i< length;i++) | |
984 { | |
985 if(depth) | |
986 depth[i] = 0; | |
987 if(temperature) | |
988 temperature[i] = 0; | |
989 if(gasid) | |
990 gasid[i] = 0; | |
991 if(ppo2) | |
992 ppo2[i] = 0; | |
993 if(setpoint) | |
994 setpoint[i] = 0; | |
995 if(sensor1) | |
996 sensor1[i] = 0; | |
997 if(sensor2) | |
998 sensor2[i] = 0; | |
999 if(sensor3) | |
1000 sensor3[i] = 0; | |
1001 if(cns) | |
1002 cns[i] = 0; | |
1003 } | |
1004 //We start with fist gasid | |
1005 gasidLast = firstgasid; | |
1006 | |
1007 | |
1008 //uint16_t* ppo2, uint16_t* cns# | |
1009 uint32_t totalNumberOfBytes = 0; | |
1010 uint32_t bytesRead = 0; | |
1011 ext_flash_open_read_sample( StepBackwards,&totalNumberOfBytes); | |
1012 ext_flash_read_next_sample_part((uint8_t*)&smallHeader, sizeof(SSmallHeader)); | |
1013 bytesRead += sizeof(SSmallHeader); | |
1014 | |
1015 clear_divisor(); | |
1016 | |
1017 iNum = 0; | |
1018 int counter = 0; | |
1019 temperatureLast = -1000; | |
1020 while ((bytesRead < totalNumberOfBytes) && (iNum < length)) | |
1021 { | |
1022 ext_flash_set_entry_point(); | |
1023 divisorBackup = divisor; | |
1024 retVal = readSample(&depthVal,&gasidVal, &setPointVal, &temperatureVal, &sensor1Val, &sensor2Val, &sensor3Val, &cnsVal, &manualGasVal, &bailoutVal, &decostepDepthVal); | |
1025 | |
1026 if(retVal == 0) | |
1027 { | |
1028 //Error try to read again!!! | |
1029 ext_flash_reopen_read_sample_at_entry_point(); | |
1030 divisor = divisorBackup; | |
1031 retVal = readSample(&depthVal,&gasidVal,&setPointVal, &temperatureVal, &sensor1Val, &sensor2Val, &sensor3Val, &cnsVal, &manualGasVal, &bailoutVal, &decostepDepthVal); | |
1032 | |
1033 if(retVal == 0) | |
1034 break; | |
1035 } | |
1036 bytesRead +=retVal; | |
1037 | |
1038 //if for some variable no new value is in the sample for (z.B. gasidVal = -1), we take the last value | |
1039 if(depthVal == -1) | |
1040 depthVal = depthLast; | |
1041 else | |
1042 depthLast = depthVal; | |
1043 | |
1044 if(gasidVal == -1) | |
1045 gasidVal = gasidLast; | |
1046 else | |
1047 gasidLast = gasidVal; | |
1048 | |
1049 if(temperatureVal == -1000) | |
1050 temperatureVal = temperatureLast; | |
1051 else | |
1052 { | |
1053 if(temperatureLast == -1000) | |
1054 temperatureFirst = temperatureVal; | |
1055 temperatureLast = temperatureVal; | |
1056 } | |
1057 | |
1058 if(setPointVal == -1) | |
1059 setPointVal = setPointLast; | |
1060 else | |
1061 setPointLast = setPointVal; | |
1062 | |
1063 if(sensor1Val == -1) | |
1064 sensor1Val = sensor1Last; | |
1065 else | |
1066 sensor1Last = sensor1Val; | |
1067 | |
1068 if(sensor2Val == -1) | |
1069 sensor2Val = sensor2Last; | |
1070 else | |
1071 sensor2Last = sensor2Val; | |
1072 | |
1073 if(sensor3Val == -1) | |
1074 sensor3Val = sensor3Last; | |
1075 else | |
1076 sensor3Last = sensor3Val; | |
1077 | |
1078 if(cnsVal == -1) | |
1079 cnsVal = cnsLast; | |
1080 else | |
1081 cnsLast = cnsVal; | |
1082 | |
1083 if(manualGasVal.percentageO2 == -1) | |
1084 manualGasVal = manualGasLast; | |
1085 else | |
1086 manualGasLast = manualGasVal; | |
1087 | |
1088 if(bailoutVal == -1) | |
1089 bailoutVal = bailoutLast; | |
1090 else | |
1091 bailoutLast = bailoutVal; | |
1092 | |
1093 if(decostepDepthVal == -1) | |
1094 decostepDepthVal = decostepDepthLast; | |
1095 else | |
1096 decostepDepthLast = decostepDepthVal; | |
1097 | |
1098 counter++; | |
1099 // Heed compression | |
1100 // Write here to arrays | |
1101 if(counter == compression) | |
1102 { | |
1103 if(depth) | |
1104 depth[iNum] = depthVal; | |
1105 if(gasid) | |
1106 gasid[iNum] = gasidVal; | |
1107 if(temperature) | |
1108 temperature[iNum] = temperatureVal; | |
1109 if(cns) | |
1110 cns[iNum] = cnsVal; | |
1111 if(bailout) | |
1112 bailout[iNum] = bailoutVal; | |
1113 if(decostopDepth) | |
1114 decostopDepth[iNum] = decostepDepthVal; | |
1115 | |
1116 if(ppo2) | |
1117 { | |
1118 //Calc ppo2 - Values | |
1119 SGas gas; | |
1120 gas.setPoint_cbar = setPointVal; | |
1121 if(gasidVal > 0) | |
1122 { | |
1123 gas.helium_percentage = header.gasordil[gasidVal - 1].helium_percentage; | |
1124 gas.nitrogen_percentage = 100 - gas.helium_percentage - header.gasordil[gasidVal - 1].oxygen_percentage; | |
1125 } | |
1126 else | |
1127 { | |
1128 gas.helium_percentage = manualGasVal.percentageHe; | |
1129 gas.nitrogen_percentage = 100 - gas.helium_percentage - manualGasVal.percentageO2; | |
1130 } | |
1131 ambiant_pressure_bar =((float)(depthVal + header.surfacePressure_mbar))/1000; | |
1132 ppO2 = decom_calc_ppO2(ambiant_pressure_bar, &gas ); | |
1133 ppo2[iNum] = (uint16_t) ( ppO2 * 100); | |
1134 } | |
1135 | |
1136 if(setpoint) | |
1137 setpoint[iNum] = setPointVal; | |
1138 | |
1139 if(sensor1) | |
1140 sensor1[iNum] = (sensor1Val / 0xFFFF) & 0xFF; | |
1141 if(sensor2) | |
1142 sensor2[iNum] = (sensor2Val / 0xFFFF) & 0xFF; | |
1143 if(sensor3) | |
1144 sensor3[iNum] = (sensor3Val / 0xFFFF) & 0xFF; | |
1145 iNum++; | |
1146 counter = 0; | |
1147 } | |
1148 } | |
1149 | |
1150 // Fix first Temperature Entries 150930 hw | |
1151 if(temperature) | |
1152 { | |
1153 int i = 0; | |
1154 while((temperature[i] == -1000) && (i < iNum)) | |
1155 temperature[i++] = temperatureFirst; | |
1156 } | |
1157 | |
1158 ext_flash_close_read_sample(); | |
1159 return iNum; | |
1160 } | |
1161 | |
1162 | |
1163 /******************************************************************************** | |
1164 * @brief logbook_InitAndWrite. / Controls writing of logbook | |
1165 * Should be called ten times per second | |
1166 * Automatically Initializes logbook at beginning of dive, | |
1167 * write samples every 2 seconds | |
1168 * and finishes logbook after end of dive | |
1169 *********************************************************************************/ | |
1170 | |
1171 void logbook_InitAndWrite(void) | |
1172 { | |
1173 SSettings *pSettings = settingsGetPointer(); | |
1174 static uint8_t bDiveMode = 0; | |
1175 static uint32_t tickstart = 0; | |
1176 uint32_t ticksdiff = 0; | |
1177 uint32_t lasttick = 0; | |
1178 static float min_temperature_float_celsius = 0; | |
1179 | |
1180 const SDiveState * pStateReal = stateRealGetPointer(); | |
1181 | |
1182 if(!bDiveMode) | |
1183 { | |
1184 if((pStateReal->mode == MODE_DIVE) && (pStateReal->diveSettings.diveMode != DIVEMODE_Apnea) && (pStateReal->lifeData.dive_time_seconds >= 5)) | |
1185 { | |
1186 //InitdiveProfile | |
1187 pSettings->totalDiveCounter++; | |
1188 logbook_initNewdiveProfile(pStateReal,settingsGetPointer()); | |
1189 min_temperature_float_celsius = pStateReal->lifeData.temperature_celsius; | |
1190 //Write logbook sample | |
1191 logbook_writeSample(*pStateReal); | |
1192 resetEvents(); | |
1193 tickstart = HAL_GetTick(); | |
1194 bDiveMode = 1; | |
1195 } | |
1196 } | |
1197 else if((pStateReal->mode == MODE_DIVE) && (pStateReal->diveSettings.diveMode != DIVEMODE_Apnea)) | |
1198 { | |
1199 lasttick = HAL_GetTick(); | |
1200 ticksdiff = time_elapsed_ms(tickstart,lasttick); | |
1201 // | |
1202 if(ticksdiff >= 2000) | |
1203 { | |
1204 //Write logbook sample | |
1205 logbook_writeSample(*pStateReal); | |
1206 resetEvents(); | |
1207 if(min_temperature_float_celsius > pStateReal->lifeData.temperature_celsius) | |
1208 min_temperature_float_celsius = pStateReal->lifeData.temperature_celsius; | |
1209 tickstart = lasttick; | |
1210 if((bDiveMode == 1) && (pStateReal->lifeData.dive_time_seconds >= pSettings->divetimeToCreateLogbook)) | |
1211 { | |
1212 ext_flash_create_new_dive_log((uint8_t*)&header); | |
1213 /** save settings | |
1214 * with new lastDiveLogId and time and day | |
1215 */ | |
1216 pSettings->personalDiveCount++; | |
1217 if(pSettings->logbookOffset) | |
1218 { | |
1219 pSettings->logbookOffset++; | |
1220 } | |
1221 ext_flash_write_settings(); | |
1222 ext_flash_disable_protection_for_logbook(); | |
1223 bDiveMode = 3; | |
1224 } | |
1225 if(bDiveMode == 3) | |
1226 logbook_UpdateHeader(); | |
1227 } | |
1228 } | |
1229 else if(bDiveMode == 3) | |
1230 { | |
1231 //End of Dive | |
1232 logbook_SetAverageDepth(pStateReal->lifeData.average_depth_meter); | |
1233 logbook_SetMinTemperature(min_temperature_float_celsius); | |
1234 logbook_SetMaxCNS(pStateReal->lifeData.cns); | |
1235 logbook_SetCompartmentDesaturation(); | |
1236 logbook_SetLastStop(pStateReal->diveSettings.last_stop_depth_bar); | |
1237 logbook_EndDive(); | |
1238 bDiveMode = 0; | |
1239 } else | |
1240 { | |
1241 ext_flash_enable_protection(); | |
1242 } | |
1243 } | |
1244 | |
1245 | |
1246 /* Private functions ---------------------------------------------------------*/ | |
1247 | |
1248 /******************************************************************************** | |
1249 * @brief logbook_UpdateHeader. / | |
1250 * set date, time, max depth. etc. pp. | |
1251 * the internal pointer to the end of profile and length will be set by | |
1252 ext_flash_close_new_dive_log() in externLogbookFlash.c | |
1253 * @author heinrichs weikamp gmbh | |
1254 * @version V0.0.1 | |
1255 * @date 27-Nov-2014 | |
1256 *********************************************************************************/ | |
1257 void logbook_UpdateHeader(void) | |
1258 { | |
1259 const SDiveState * pStateReal = stateRealGetPointer(); | |
149 | 1260 |
38 | 1261 // uint16_t secondsAtShallow = 0; |
1262 RTC_DateTypeDef Sdate; | |
1263 RTC_TimeTypeDef Stime; | |
1264 uint32_t time1_u32, time2_u32; | |
1265 uint32_t divetimeHelper; | |
1266 | |
1267 /* time and day */ | |
1268 /* don't update CHANGE 160224 hw, maybe save actual time and date at other place | |
1269 translateDate(pStateReal->lifeData.dateBinaryFormat, &Sdate); | |
1270 translateTime(pStateReal->lifeData.timeBinaryFormat, &Stime); | |
1271 | |
1272 header.dateYear = Sdate.Year; | |
1273 header.dateMonth = Sdate.Month; | |
1274 header.dateDay = Sdate.Date; | |
1275 header.timeHour = Stime.Hours; | |
1276 header.timeMinute = Stime.Minutes; | |
1277 */ | |
1278 /// 160315 Quick fix for empty date problem | |
1279 if((!(header.dateYear)) || (!(header.dateMonth)) || (!(header.dateDay))) | |
1280 { | |
1281 translateDate(pStateReal->lifeData.dateBinaryFormat, &Sdate); | |
1282 translateTime(pStateReal->lifeData.timeBinaryFormat, &Stime); | |
1283 | |
1284 header.dateYear = Sdate.Year; | |
1285 header.dateMonth = Sdate.Month; | |
1286 header.dateDay = Sdate.Date; | |
1287 | |
1288 time1_u32 = (uint32_t)header.timeMinute + (uint32_t)(header.timeHour * 60); | |
1289 time2_u32 = (uint32_t)Stime.Minutes + (uint32_t)(Stime.Hours * 60); | |
1290 if(time2_u32 < time1_u32) | |
1291 { | |
1292 if(header.dateDay > 1) | |
1293 { | |
1294 header.dateDay -= 1; | |
1295 } | |
1296 else | |
1297 { | |
1298 header.dateMonth --; | |
1299 if(!header.dateMonth) | |
1300 { | |
1301 header.dateYear--; | |
1302 header.dateMonth = 12; | |
1303 header.dateDay = 31; | |
1304 } | |
1305 else | |
1306 { | |
1307 if(header.dateMonth == 2) | |
1308 header.dateDay = 28; | |
1309 else | |
1310 if((header.dateMonth == 4) || (header.dateMonth == 6) || (header.dateMonth == 9) || (header.dateMonth == 11)) | |
1311 header.dateDay = 30; | |
1312 else | |
1313 header.dateDay = 31; | |
1314 } | |
1315 } | |
1316 } | |
1317 } | |
1318 | |
1319 /* duration */ | |
1320 header.total_diveTime_seconds = pStateReal->lifeData.dive_time_seconds; | |
1321 header.maxDepth = pStateReal->lifeData.max_depth_meter * 100; | |
1322 | |
1323 /* old: | |
1324 | |
1325 secondsAtShallow = pSettings->timeoutDiveReachedZeroDepth; | |
1326 if(pStateReal->lifeData.dive_time_seconds <= secondsAtShallow) | |
1327 secondsAtShallow = 0; | |
1328 header.diveTimeMinutes = (header.total_diveTime_seconds - secondsAtShallow )/ 60; | |
1329 header.diveTimeSeconds = header.total_diveTime_seconds - secondsAtShallow - (header.diveTimeMinutes * 60); | |
1330 */ | |
1331 divetimeHelper = pStateReal->lifeData.dive_time_seconds_without_surface_time; | |
1332 header.diveTimeMinutes = (uint16_t)(divetimeHelper/60); | |
1333 divetimeHelper -= 60 * (uint32_t)header.diveTimeMinutes; | |
1334 header.diveTimeSeconds = (uint16_t)divetimeHelper; | |
1335 | |
1336 /* deco algorithm (final) */ | |
1337 if(pStateReal->diveSettings.deco_type.ub.standard == GF_MODE) | |
1338 { | |
1339 header.decoModel = 1; | |
1340 header.gfLow_or_Vpm_conservatism = pStateReal->diveSettings.gf_low; | |
1341 header.gfHigh = pStateReal->diveSettings.gf_high; | |
1342 } | |
1343 else | |
1344 { | |
1345 header.decoModel = 2; | |
1346 header.gfLow_or_Vpm_conservatism = pStateReal->diveSettings.vpm_conservatism; | |
1347 header.gfHigh = 0; | |
1348 } | |
1349 | |
1350 /* tissue load */ | |
1351 memcpy(header.n2Compartments, pStateReal->lifeData.tissue_nitrogen_bar, 64); | |
1352 memcpy(header.heCompartments, pStateReal->lifeData.tissue_helium_bar, 64); | |
1353 | |
1354 } | |
1355 | |
1356 | |
1357 void logbook_SetAverageDepth(float average_depth_meter) | |
1358 { | |
1359 header.averageDepth_mbar = (uint16_t)(average_depth_meter * 100); | |
1360 } | |
1361 | |
1362 | |
1363 void logbook_SetMinTemperature(float min_temperature_celsius) | |
1364 { | |
1365 header.minTemp = (int16_t)((min_temperature_celsius * 10.0f) + 0.5f); | |
1366 } | |
1367 | |
1368 | |
1369 void logbook_SetMaxCNS(float max_cns_percentage) | |
1370 { | |
1371 if(max_cns_percentage < 9999) | |
1372 header.maxCNS = (uint16_t)(max_cns_percentage); | |
1373 else | |
1374 header.maxCNS = 9999; | |
1375 } | |
1376 | |
1377 | |
1378 void logbook_SetDesaturationTime(void) | |
1379 { | |
1380 header.desaturationTime = 48 * 60; | |
1381 } | |
1382 | |
1383 | |
1384 void logbook_SetCompartmentDesaturation(void) | |
1385 { | |
1386 const SDiveState * pStateReal = stateRealGetPointer(); | |
1387 | |
1388 decom_tissues_desaturation_time(&pStateReal->lifeData, &secondaryInformation); | |
1389 for(int i=0;i<16;i++) | |
1390 { | |
1391 if(secondaryInformation.tissue_nitrogen_desaturation_time_minutes[i] <= (15 * 255)) | |
1392 header.n2CompartDesatTime_min[i] = (uint8_t)((secondaryInformation.tissue_nitrogen_desaturation_time_minutes[i] + 14) / 15); | |
1393 else | |
1394 header.n2CompartDesatTime_min[i] = 255; | |
1395 if(secondaryInformation.tissue_helium_desaturation_time_minutes[i] <= (15 * 255)) | |
1396 header.heCompartDesatTime_min[i] = (uint8_t)((secondaryInformation.tissue_helium_desaturation_time_minutes[i] + 14 )/ 15); | |
1397 else | |
1398 header.heCompartDesatTime_min[i] = 255; | |
1399 } | |
1400 } | |
1401 | |
1402 void logbook_SetLastStop(float last_stop_depth_bar) | |
1403 { | |
1404 header.lastDecostop_m = (uint8_t)(last_stop_depth_bar / 10.0f); | |
1405 } | |
1406 | |
1407 void logbook_writedata(void * data, int length_byte) | |
1408 { | |
1409 ext_flash_write_sample(data, length_byte); | |
1410 } | |
1411 | |
1412 | |
1413 /******************************************************************************** | |
1414 * @brief logbook_build_ostc3header. / | |
1415 * @author heinrichs weikamp gmbh | |
1416 * @version V0.0.2 | |
1417 * @date 27-Nov-2014 | |
1418 *********************************************************************************/ | |
1419 SLogbookHeaderOSTC3 * logbook_build_ostc3header(SLogbookHeader* pHead) | |
1420 { | |
1421 convert_Type data; | |
1422 | |
1423 memcpy(headerOSTC3.diveHeaderStart, &pHead->diveHeaderStart, 2); | |
1424 memcpy(headerOSTC3.pBeginProfileData, &pHead->pBeginProfileData, 3); | |
1425 memcpy(headerOSTC3.pEndProfileData, &pHead->pEndProfileData, 3); | |
1426 | |
1427 data.u8bit.byteHigh = 0; | |
1428 data.u8bit.byteLow = pHead->profileLength[0]; | |
1429 data.u8bit.byteMidLow = pHead->profileLength[1]; | |
1430 data.u8bit.byteMidHigh = pHead->profileLength[2]; | |
1431 | |
1432 if(data.u32bit != 0xFFFFFF) | |
1433 data.u32bit += 3; | |
1434 | |
1435 headerOSTC3.profileLength[0] = data.u8bit.byteLow; | |
1436 headerOSTC3.profileLength[1] = data.u8bit.byteMidLow; | |
1437 headerOSTC3.profileLength[2] = data.u8bit.byteMidHigh; | |
1438 | |
1439 memcpy(headerOSTC3.gasordil, pHead->gasordil, 20); | |
1440 | |
1441 if(pHead->logbookProfileVersion == LOGBOOK_VERSION) | |
1442 { | |
1443 headerOSTC3.logbookProfileVersion = LOGBOOK_VERSION_OSTC3; | |
1444 memcpy(headerOSTC3.personalDiveCount, &pHead->personalDiveCount, 2); | |
1445 headerOSTC3.safetyDistance_10cm = 0; | |
1446 | |
1447 for(int i=0;i<5;i++) | |
1448 { | |
1449 if(!pHead->gasordil[i].note.ub.active) | |
1450 headerOSTC3.gasordil[3 + (i*4)] = 0; | |
1451 else if(pHead->gasordil[i].note.ub.first) | |
1452 { | |
1453 /* depth = 0, note = 1 */ | |
1454 headerOSTC3.gasordil[2 + (i*4)] = 0; | |
1455 headerOSTC3.gasordil[3 + (i*4)] = 1; | |
1456 } | |
1457 else if( pHead->gasordil[i].depth_meter) | |
1458 { | |
1459 /* note = 3 */ | |
1460 headerOSTC3.gasordil[3 + (i*4)] = 3; | |
1461 } | |
1462 } | |
1463 } | |
1464 else | |
1465 { | |
1466 headerOSTC3.logbookProfileVersion = 0xFF; | |
1467 headerOSTC3.personalDiveCount[0] = 0xFF; | |
1468 headerOSTC3.personalDiveCount[1] = 0xFF; | |
1469 headerOSTC3.safetyDistance_10cm = 0xFF; | |
1470 } | |
1471 | |
1472 headerOSTC3.dateYear = pHead->dateYear; | |
1473 headerOSTC3.dateMonth = pHead->dateMonth; | |
1474 headerOSTC3.dateDay = pHead->dateDay; | |
1475 headerOSTC3.timeHour = pHead->timeHour; | |
1476 headerOSTC3.timeMinute = pHead->timeMinute; | |
1477 | |
1478 | |
1479 memcpy(headerOSTC3.maxDepth, &pHead->maxDepth, 2); | |
1480 memcpy(headerOSTC3.diveTimeMinutes, &pHead->diveTimeMinutes, 2); | |
1481 | |
1482 headerOSTC3.diveTimeSeconds = pHead->diveTimeSeconds; | |
1483 | |
1484 memcpy(headerOSTC3.minTemp, &pHead->minTemp, 2); | |
1485 memcpy(headerOSTC3.surfacePressure_mbar,&pHead->surfacePressure_mbar, 2); | |
1486 memcpy(headerOSTC3.desaturationTime, &pHead->desaturationTime, 2); | |
1487 | |
1488 headerOSTC3.firmwareVersionHigh = pHead->firmwareVersionHigh; | |
1489 headerOSTC3.firmwareVersionLow = pHead->firmwareVersionLow; | |
1490 | |
1491 memcpy(headerOSTC3.batteryVoltage, &pHead->batteryVoltage, 2); | |
1492 | |
1493 headerOSTC3.samplingRate = pHead->samplingRate; | |
1494 | |
1495 memcpy(headerOSTC3.cnsAtBeginning, &pHead->cnsAtBeginning, 2); | |
1496 | |
1497 headerOSTC3.gfAtBeginning = pHead->gfAtBeginning; | |
1498 headerOSTC3.gfAtEnd = pHead->gfAtEnd; | |
1499 | |
1500 memcpy(headerOSTC3.setpoint, pHead->setpoint, 10); | |
1501 | |
1502 headerOSTC3.salinity = pHead->salinity; | |
1503 | |
1504 memcpy(headerOSTC3.maxCNS, &pHead->maxCNS, 2); | |
1505 memcpy(headerOSTC3.averageDepth_mbar, &pHead->averageDepth_mbar, 2); | |
1506 memcpy(headerOSTC3.total_diveTime_seconds,&pHead->total_diveTime_seconds, 2); | |
1507 | |
1508 headerOSTC3.gfLow_or_Vpm_conservatism = pHead->gfLow_or_Vpm_conservatism; | |
1509 headerOSTC3.gfHigh = pHead->gfHigh; | |
1510 headerOSTC3.decoModel = pHead->decoModel; | |
1511 | |
1512 memcpy(headerOSTC3.diveNumber, &pHead->diveNumber, 2); | |
1513 | |
1514 headerOSTC3.diveMode = pHead->diveMode; | |
1515 headerOSTC3.CCRmode = pHead->CCRmode; | |
1516 | |
1517 memcpy(headerOSTC3.n2CompartDesatTime_min,pHead->n2CompartDesatTime_min, 16); | |
1518 memcpy(headerOSTC3.n2Compartments, pHead->n2Compartments, 64); | |
1519 memcpy(headerOSTC3.heCompartDesatTime_min,pHead->heCompartDesatTime_min, 16); | |
1520 memcpy(headerOSTC3.heCompartments, pHead->heCompartments, 64); | |
1521 | |
1522 headerOSTC3.lastDecostop_m = pHead->lastDecostop_m; | |
1523 | |
1524 memcpy(headerOSTC3.hwHudBattery_mV, &pHead->hwHudBattery_mV, 2); | |
1525 | |
1526 headerOSTC3.hwHudLastStatus = pHead->hwHudLastStatus; | |
1527 | |
1528 memcpy(headerOSTC3.batteryGaugeRegisters,&pHead->batteryGaugeRegisters, 6); | |
1529 | |
1530 | |
1531 memcpy(headerOSTC3.diveHeaderEnd, &pHead->diveHeaderEnd, 2); | |
1532 | |
1533 return &headerOSTC3; | |
1534 } | |
1535 | |
1536 | |
1537 /******************************************************************************** | |
1538 * @brief logbook_build_ostc3header_compact. / | |
1539 * @author heinrichs weikamp gmbh | |
1540 * @version V0.0.1 | |
1541 * @date 31-Juli-2015 | |
1542 *********************************************************************************/ | |
1543 SLogbookHeaderOSTC3compact * logbook_build_ostc3header_compact(SLogbookHeader* pHead) | |
1544 { | |
1545 convert_Type data; | |
1546 | |
1547 data.u8bit.byteHigh = 0; | |
1548 data.u8bit.byteLow = pHead->profileLength[0]; | |
1549 data.u8bit.byteMidLow = pHead->profileLength[1]; | |
1550 data.u8bit.byteMidHigh = pHead->profileLength[2]; | |
1551 | |
1552 if(data.u32bit != 0xFFFFFF) | |
1553 { | |
1554 data.u32bit += 3; | |
1555 | |
1556 headerOSTC3compact.profileLength[0] = data.u8bit.byteLow; | |
1557 headerOSTC3compact.profileLength[1] = data.u8bit.byteMidLow; | |
1558 headerOSTC3compact.profileLength[2] = data.u8bit.byteMidHigh; | |
1559 | |
1560 headerOSTC3compact.dateYear = pHead->dateYear; | |
1561 headerOSTC3compact.dateMonth = pHead->dateMonth; | |
1562 headerOSTC3compact.dateDay = pHead->dateDay; | |
1563 headerOSTC3compact.timeHour = pHead->timeHour; | |
1564 headerOSTC3compact.timeMinute = pHead->timeMinute; | |
1565 | |
1566 memcpy(headerOSTC3compact.maxDepth, &pHead->maxDepth, 2); | |
1567 memcpy(headerOSTC3compact.diveTimeMinutes, &pHead->diveTimeMinutes, 2); | |
1568 | |
1569 headerOSTC3compact.diveTimeSeconds = pHead->diveTimeSeconds; | |
1570 | |
1571 | |
1572 headerOSTC3compact.totalDiveNumberLow = pHead->diveNumber & 0xFF; | |
1573 headerOSTC3compact.totalDiveNumberHigh = (uint8_t)(pHead->diveNumber/256); | |
1574 headerOSTC3compact.profileVersion = 0x24; // Logbook-Profile version, 0x24 = date and time is start not end | |
1575 } | |
1576 else | |
1577 { | |
1578 memset(&headerOSTC3compact, 0xFF, sizeof(SLogbookHeaderOSTC3compact)); | |
1579 } | |
1580 return &headerOSTC3compact; | |
1581 } | |
1582 | |
1583 | |
1584 /** | |
1585 ****************************************************************************** | |
1586 * @brief logbook_readSampleData. / Reads sample data of whole logbook entry | |
1587 * @author Peter Ryser | |
1588 * @version V0.0.1 | |
1589 * @date 22-April-2014 | |
1590 ****************************************************************************** | |
1591 * | |
1592 * @param uint8_t StepBackwards: witch lookbook entry? | |
1593 * @param uint16_t length : maxlength of output arrays | |
1594 * @param int32_t* depth : output array | |
1595 * @param int16_t * gasid : output array | |
1596 * @param int32_t* temperature : output array | |
1597 * @param int32_t* ppo2 : output array | |
1598 * @param int32_t* cns : output array | |
1599 * @return length of output | |
1600 */ | |
1601 void logbook_recover_brokenlog(uint8_t headerId) | |
1602 { | |
1603 int16_t retVal; | |
1604 int32_t depthVal = 0; | |
1605 int16_t gasidVal = 0; | |
1606 int16_t setPointVal = 0; | |
1607 int16_t bailoutVal = 0; | |
1608 int32_t temperatureVal = 0; | |
1609 int32_t sensor1Val = 0; | |
1610 int32_t sensor2Val = 0; | |
1611 int32_t sensor3Val = 0; | |
1612 int32_t cnsVal = 0; | |
1613 SManualGas manualGasVal; | |
1614 | |
1615 //uint16_t* ppo2, uint16_t* cns# | |
1616 uint32_t bytesRead = 0; | |
1617 | |
1618 ext_flash_read_block_start(); | |
1619 ext_flash_read_next_sample_part((uint8_t*)&smallHeader, sizeof(SSmallHeader)); | |
1620 bytesRead += sizeof(SSmallHeader); | |
1621 | |
1622 clear_divisor(); | |
1623 | |
1624 | |
1625 int sampleCounter = 0; | |
1626 int maxdepth = 0; | |
1627 uint32_t avrdepth = 0; | |
1628 while (true) | |
1629 { | |
1630 | |
1631 ext_flash_set_entry_point(); | |
1632 divisorBackup = divisor; | |
1633 retVal = readSample(&depthVal,&gasidVal, &setPointVal, &temperatureVal, &sensor1Val, &sensor2Val, &sensor3Val, &cnsVal, &manualGasVal, &bailoutVal, NULL); | |
1634 if(retVal == 0) | |
1635 { | |
1636 //Error try to read again!!! | |
1637 ext_flash_reopen_read_sample_at_entry_point(); | |
1638 divisor = divisorBackup; | |
1639 retVal = readSample(&depthVal,&gasidVal, &setPointVal, &temperatureVal, &sensor1Val, &sensor2Val, &sensor3Val, &cnsVal, &manualGasVal, &bailoutVal, NULL); | |
1640 | |
1641 if(retVal == 0) | |
1642 { | |
1643 //Error try to read again!!! | |
1644 ext_flash_reopen_read_sample_at_entry_point(); | |
1645 divisor = divisorBackup; | |
1646 retVal = readSample(&depthVal,&gasidVal, &setPointVal, &temperatureVal, &sensor1Val, &sensor2Val, &sensor3Val, &cnsVal, &manualGasVal, &bailoutVal, NULL); | |
1647 | |
1648 if(retVal == 0) | |
1649 { | |
1650 ext_flash_reopen_read_sample_at_entry_point(); | |
1651 break; | |
1652 } | |
1653 | |
1654 } | |
1655 } | |
1656 if(depthVal > maxdepth) | |
1657 maxdepth = depthVal; | |
1658 avrdepth += depthVal; | |
1659 sampleCounter++; | |
1660 bytesRead +=retVal; | |
1661 } | |
1662 avrdepth/= sampleCounter; | |
1663 ext_flash_close_read_sample(); | |
1664 SLogbookHeader header; | |
1665 | |
1666 ext_flash_read_dive_header2((uint8_t*) &header, headerId, false); | |
1667 header.total_diveTime_seconds = sampleCounter * header.samplingRate; | |
1668 header.diveTimeMinutes = header.total_diveTime_seconds /60; | |
1669 header.diveTimeSeconds = header.total_diveTime_seconds - header.diveTimeMinutes * 60; | |
1670 header.maxDepth = maxdepth; | |
1671 header.averageDepth_mbar = avrdepth; | |
1672 SSettings * settings = settingsGetPointer(); | |
1673 settings->lastDiveLogId = headerId; | |
1674 ext_flash_close_new_dive_log((uint8_t *)&header); | |
1675 } | |
1676 | |
1677 /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/ |