comparison Discovery/Src/data_central.c @ 38:5f11787b4f42

include in ostc4 repository
author heinrichsweikamp
date Sat, 28 Apr 2018 11:52:34 +0200
parents
children cc9c18075e00
comparison
equal deleted inserted replaced
37:ccc45c0e1ea2 38:5f11787b4f42
1 /**
2 ******************************************************************************
3 * @copyright heinrichs weikamp
4 * @file data_central.c
5 * @author heinrichs weikamp gmbh
6 * @date 10-November-2014
7 * @version V1.0.2
8 * @since 10-Nov-2014
9 * @brief All the data EXCEPT
10 * - settings (settings.c)
11 * feste Werte, die nur an der Oberfl�che ge�ndert werden
12 * - dataIn and dataOut (data_exchange.h and data_exchange_main.c)
13 * Austausch mit Small CPU
14 * @bug
15 * @warning
16 @verbatim
17 ==============================================================================
18 ##### SDiveState Real and Sim #####
19 ==============================================================================
20 [..] SDiveSettings
21 copy of parts of Settings that are necessary during the dive
22 and could be modified during the dive without post dive changes.
23
24 [..] SLifeData
25 written in DataEX_copy_to_LifeData();
26 block 1 "lifedata" set by SmallCPU in stateReal
27 block 2 "actualGas" set by main CPU from user input and send to Small CPU
28 block 3 "calculated data" set by main CPU based on "lifedata"
29
30 [..] SVpm
31
32 [..] SEvents
33
34 [..] SDecoinfo
35
36 [..] mode
37 set by SmallCPU in stateReal, can be surface, dive, ...
38
39 [..] data_old__lost_connection_to_slave
40 set by DataEX_copy_to_LifeData();
41
42 ==============================================================================
43 ##### SDiveState Deco #####
44 ==============================================================================
45 [..] kjbkldafj�lasdfjasdf
46
47 ==============================================================================
48 ##### decoLock #####
49 ==============================================================================
50 [..] The handler that synchronizes the data between IRQ copy and main deco loop
51
52
53 @endverbatim
54 ******************************************************************************
55 * @attention
56 *
57 * <h2><center>&copy; COPYRIGHT(c) 2015 heinrichs weikamp</center></h2>
58 *
59 ******************************************************************************
60 */
61
62 /* Includes ------------------------------------------------------------------*/
63 #include <string.h>
64 #include "data_central.h"
65 #include "calc_crush.h"
66 #include "decom.h"
67 #include "stm32f4xx_hal.h"
68 #include "settings.h"
69 #include "data_exchange_main.h"
70 #include "ostc.h" // for button adjust on hw testboard 1
71 #include "tCCR.h"
72 #include "crcmodel.h"
73
74 SDiveState stateReal = { 0 };
75 SDiveState stateSim = { 0 };
76 SDiveState stateDeco = { 0 };
77
78 SLifeData2 secondaryInformation = { 0 };
79
80 SDevice stateDevice =
81 {
82 /* max is 0x7FFFFFFF, min is 0x80000000 but also defined in stdint.h :-) */
83
84 /* count, use 0 */
85 .batteryChargeCompleteCycles.value_int32 = 0,
86 .batteryChargeCycles.value_int32 = 0,
87 .diveCycles.value_int32 = 0,
88 .hoursOfOperation.value_int32 = 0,
89
90 /* max values, use min. */
91 .temperatureMaximum.value_int32 = INT32_MIN,
92 .depthMaximum.value_int32 = INT32_MIN,
93
94 /* min values, use max. */
95 .temperatureMinimum.value_int32 = INT32_MAX,
96 .voltageMinimum.value_int32 = INT32_MAX,
97 };
98
99 SVpmRepetitiveData stateVPM =
100 {
101 .repetitive_variables_not_valid = 1,
102 .is_data_from_RTE_CPU = 0,
103 };
104
105 const SDiveState * stateUsed = &stateReal;
106
107
108 void set_stateUsedToReal(void)
109 {
110 stateUsed = &stateReal;
111 }
112
113 void set_stateUsedToSim(void)
114 {
115 stateUsed = &stateSim;
116 }
117
118 _Bool is_stateUsedSetToSim(void)
119 {
120 if(stateUsed == &stateSim)
121 return 1;
122 else
123 return 0;
124
125 }
126
127 const SDiveState * stateRealGetPointer(void)
128 {
129 return &stateReal;
130 }
131
132 SDiveState * stateRealGetPointerWrite(void)
133 {
134 return &stateReal;
135 }
136
137
138 const SDiveState * stateSimGetPointer(void)
139 {
140 return &stateSim;
141 }
142
143
144 SDiveState * stateSimGetPointerWrite(void)
145 {
146 return &stateSim;
147 }
148
149
150 const SDevice * stateDeviceGetPointer(void)
151 {
152 return &stateDevice;
153 }
154
155
156 SDevice * stateDeviceGetPointerWrite(void)
157 {
158 return &stateDevice;
159 }
160
161
162 const SVpmRepetitiveData * stateVpmRepetitiveDataGetPointer(void)
163 {
164 return &stateVPM;
165 }
166
167
168 SVpmRepetitiveData * stateVpmRepetitiveDataGetPointerWrite(void)
169 {
170 return &stateVPM;
171 }
172
173
174 uint32_t time_elapsed_ms(uint32_t ticksstart,uint32_t ticksnow)
175 {
176 if(ticksstart <= ticksnow)
177 return ticksnow - ticksstart;
178 else
179 return 0xFFFFFFFF - ticksstart + ticksnow;
180 }
181
182
183 uint8_t decoLock = DECO_CALC_undefined;
184 int ascent_rate_meter_per_min = 12;
185 int descent_rate_meter_per_min = 20;
186 int max_depth = 70;
187 int bottom_time = 10;
188
189 _Bool vpm_crush(SDiveState* pDiveState);
190 void setSimulationValues(int _ascent_rate_meter_per_min, int _descent_rate_meter_per_min, int _max_depth, int _bottom_time )
191 {
192 ascent_rate_meter_per_min = _ascent_rate_meter_per_min;
193 descent_rate_meter_per_min = _descent_rate_meter_per_min;
194 max_depth = _max_depth;
195 bottom_time = _bottom_time;
196 }
197
198
199
200 int current_second(void) {
201
202 return HAL_GetTick() / 1000;
203 // printf("milliseconds: %lld\n", milliseconds);
204 //return milliseconds;
205 }
206
207
208
209 #define OXY_ONE_SIXTIETH_PART 0.0166667f
210
211 /*void oxygen_calculate_cns(float* oxygen_cns, float pressure_oxygen_real)
212 {
213 int cns_no_range = 0;
214 _Bool not_found = 1;
215 //for the cns calculation
216 const float cns_ppo2_ranges[60][2] = { {0.50, 0.00}, {0.60, 0.14}, {0.64, 0.15}, {0.66, 0.16}, {0.68, 0.17}, {0.70, 0.18},
217 {0.74, 0.19}, {0.76, 0.20}, {0.78, 0.21}, {0.80, 0.22}, {0.82, 0.23}, {0.84, 0.24},
218 {0.86, 0.25}, {0.88, 0.26}, {0.90, 0.28}, {0.92, 0.29}, {0.94, 0.30}, {0.96, 0.31},
219 {0.98, 0.32}, {1.00, 0.33}, {1.02, 0.35}, {1.04, 0.36}, {1.06, 0.38}, {1.08, 0.40},
220 {1.10, 0.42}, {1.12, 0.43}, {1.14, 0.43}, {1.16, 0.44}, {1.18, 0.46}, {1.20, 0.47},
221 {1.22, 0.48}, {1.24, 0.51}, {1.26, 0.52}, {1.28, 0.54}, {1.30, 0.56}, {1.32, 0.57},
222 {1.34, 0.60}, {1.36, 0.62}, {1.38, 0.63}, {1.40, 0.65}, {1.42, 0.68}, {1.44, 0.71},
223 {1.46, 0.74}, {1.48, 0.78}, {1.50, 0.83}, {1.52, 0.93}, {1.54, 1.04}, {1.56, 1.19},
224 {1.58, 1.47}, {1.60, 2.22}, {1.62, 5.00}, {1.65, 6.25}, {1.67, 7.69}, {1.70, 10.0},
225 {1.72,12.50}, {1.74,20.00}, {1.77,25.00}, {1.79,31.25}, {1.80,50.00}, {1.82,100.0}};
226 //find the correct cns range for the corresponding ppo2
227 cns_no_range = 58;
228 while (cns_no_range && not_found)
229 {
230 if (pressure_oxygen_real > cns_ppo2_ranges[cns_no_range][0])
231 {
232 cns_no_range++;
233 not_found = 0;
234 }
235 else
236 cns_no_range--;
237 }
238
239 //calculate cns for the actual ppo2 for 1 second
240 *oxygen_cns += OXY_ONE_SIXTIETH_PART * cns_ppo2_ranges[cns_no_range][1];
241 }*/
242
243 uint8_t calc_MOD(uint8_t gasId)
244 {
245 int16_t oxygen, maxppO2, result;
246 SSettings *pSettings;
247
248 pSettings = settingsGetPointer();
249
250 oxygen = (int16_t)(pSettings->gas[gasId].oxygen_percentage);
251
252 if(pSettings->gas[gasId].note.ub.deco > 0)
253 maxppO2 =(int16_t)(pSettings->ppO2_max_deco);
254 else
255 maxppO2 =(int16_t)(pSettings->ppO2_max_std);
256
257 result = 10 * maxppO2;
258 result /= oxygen;
259 result -= 10;
260
261 if(result < 0)
262 return 0;
263
264 if(result > 255)
265 return 255;
266
267 return result;
268 }
269
270 uint8_t calc_MinOD(uint8_t gasId)
271 {
272 int16_t oxygen, minppO2, result;
273 SSettings *pSettings;
274
275 pSettings = settingsGetPointer();
276
277 oxygen = (int16_t)(pSettings->gas[gasId].oxygen_percentage);
278 minppO2 =(int16_t)(pSettings->ppO2_min);
279 result = 10 * minppO2;
280 result += 9;
281 result /= oxygen;
282 result -= 10;
283
284 if(result < 0)
285 return 0;
286
287 if(result > 255)
288 return 255;
289
290 return result;
291 }
292 /*
293 float calc_ppO2(float input_ambient_pressure_bar, SGas* pGas)
294 {
295 float percent_N2 = 0;
296 float percent_He = 0;
297 float percent_O2 = 0;
298 decom_get_inert_gases(input_ambient_pressure_bar, pGas, &percent_N2, &percent_He);
299 percent_O2 = 1 - percent_N2 - percent_He;
300
301 return (input_ambient_pressure_bar - WATER_VAPOUR_PRESSURE) * percent_O2;
302 }*/
303
304 float get_ambiant_pressure_simulation(long dive_time_seconds, float surface_pressure_bar )
305 {
306 static
307 long descent_time;
308 float depth_meter;
309
310 descent_time = 60 * max_depth / descent_rate_meter_per_min;
311
312 if(dive_time_seconds <= descent_time)
313 {
314 depth_meter = ((float)(dive_time_seconds * descent_rate_meter_per_min)) / 60;
315 return surface_pressure_bar + depth_meter / 10;
316 }
317 //else if(dive_time_seconds <= (descent_time + bottom_time * 60))
318 return surface_pressure_bar + max_depth / 10;
319
320
321
322 }
323
324 void UpdateLifeDataTest(SDiveState * pDiveState)
325 {
326 static int last_second = -1;
327 int now = current_second();
328 if(last_second == now)
329 return;
330 last_second = now;
331
332 pDiveState->lifeData.dive_time_seconds += 1;
333 pDiveState->lifeData.pressure_ambient_bar = get_ambiant_pressure_simulation(pDiveState->lifeData.dive_time_seconds,pDiveState->lifeData.pressure_surface_bar);
334
335 pDiveState->lifeData.depth_meter = (pDiveState->lifeData.pressure_ambient_bar - pDiveState->lifeData.pressure_surface_bar) * 10.0f;
336 if(pDiveState->lifeData.max_depth_meter < pDiveState->lifeData.depth_meter)
337 pDiveState->lifeData.max_depth_meter = pDiveState->lifeData.depth_meter;
338 decom_tissues_exposure(1, &pDiveState->lifeData);
339 pDiveState->lifeData.ppO2 = decom_calc_ppO2( pDiveState->lifeData.pressure_ambient_bar, &pDiveState->lifeData.actualGas);
340 decom_oxygen_calculate_cns(& pDiveState->lifeData.cns, pDiveState->lifeData.ppO2);
341
342 vpm_crush(pDiveState);
343 }
344
345
346 _Bool vpm_crush(SDiveState* pDiveState)
347 {
348 int i = 0;
349 static float starting_ambient_pressure = 0;
350 static float ending_ambient_pressure = 0;
351 static float time_calc_begin = -1;
352 static float initial_helium_pressure[16];
353 static float initial_nitrogen_pressure[16];
354 ending_ambient_pressure = pDiveState->lifeData.pressure_ambient_bar * 10;
355
356 if((pDiveState->lifeData.dive_time_seconds <= 4) || (starting_ambient_pressure >= ending_ambient_pressure))
357 {
358 time_calc_begin = pDiveState->lifeData.dive_time_seconds;
359 starting_ambient_pressure = pDiveState->lifeData.pressure_ambient_bar * 10;
360 for( i = 0; i < 16; i++)
361 {
362 initial_helium_pressure[i] = pDiveState->lifeData.tissue_helium_bar[i] * 10;
363 initial_nitrogen_pressure[i] = pDiveState->lifeData.tissue_nitrogen_bar[i] * 10;
364 }
365 return false;
366 }
367 if(pDiveState->lifeData.dive_time_seconds - time_calc_begin >= 4)
368 {
369 if(ending_ambient_pressure > starting_ambient_pressure + 0.5f)
370 {
371 float rate = (ending_ambient_pressure - starting_ambient_pressure) * 60 / 4;
372 calc_crushing_pressure(&pDiveState->lifeData, &pDiveState->vpm, initial_helium_pressure, initial_nitrogen_pressure, starting_ambient_pressure, rate);
373
374 time_calc_begin = pDiveState->lifeData.dive_time_seconds;
375 starting_ambient_pressure = pDiveState->lifeData.pressure_ambient_bar * 10;
376 for( i = 0; i < 16; i++)
377 {
378 initial_helium_pressure[i] = pDiveState->lifeData.tissue_helium_bar[i] * 10;
379 initial_nitrogen_pressure[i] = pDiveState->lifeData.tissue_nitrogen_bar[i] * 10;
380 }
381
382 return true;
383 }
384
385 }
386 return false;
387 };
388
389
390 void createDiveSettings(void)
391 {
392 SSettings* pSettings = settingsGetPointer();
393
394 setActualGasFirst(&stateReal.lifeData);
395
396 stateReal.diveSettings.compassHeading = pSettings->compassBearing;
397 stateReal.diveSettings.ascentRate_meterperminute = 10;
398
399 stateReal.diveSettings.diveMode = pSettings->dive_mode;
400 stateReal.diveSettings.CCR_Mode = pSettings->CCR_Mode;
401 if(stateReal.diveSettings.diveMode == DIVEMODE_CCR)
402 stateReal.diveSettings.ccrOption = 1;
403 else
404 stateReal.diveSettings.ccrOption = 0;
405 memcpy(stateReal.diveSettings.gas, pSettings->gas,sizeof(pSettings->gas));
406 memcpy(stateReal.diveSettings.setpoint, pSettings->setpoint,sizeof(pSettings->setpoint));
407 stateReal.diveSettings.gf_high = pSettings->GF_high;
408 stateReal.diveSettings.gf_low = pSettings->GF_low;
409 stateReal.diveSettings.input_next_stop_increment_depth_bar = ((float)pSettings->stop_increment_depth_meter) / 10.0f;
410 stateReal.diveSettings.last_stop_depth_bar = ((float)pSettings->last_stop_depth_meter) / 10.0f;
411 stateReal.diveSettings.vpm_conservatism = pSettings->VPM_conservatism.ub.standard;
412 stateReal.diveSettings.deco_type.uw = pSettings->deco_type.uw;
413 stateReal.diveSettings.fallbackOption = pSettings->fallbackToFixedSetpoint;
414 stateReal.diveSettings.ppo2sensors_deactivated = pSettings->ppo2sensors_deactivated;
415 stateReal.diveSettings.future_TTS_minutes = pSettings->future_TTS;
416
417 decom_CreateGasChangeList(&stateReal.diveSettings, &stateReal.lifeData); // decogaslist
418 stateReal.diveSettings.internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero = 0;
419
420 /* for safety */
421 stateReal.diveSettings.input_second_to_last_stop_depth_bar = stateReal.diveSettings.last_stop_depth_bar + stateReal.diveSettings.input_next_stop_increment_depth_bar;
422 /* and the proper calc */
423 for(int i = 1; i <10; i++)
424 {
425 if(stateReal.diveSettings.input_next_stop_increment_depth_bar * i > stateReal.diveSettings.last_stop_depth_bar)
426 {
427 stateReal.diveSettings.input_second_to_last_stop_depth_bar = stateReal.diveSettings.input_next_stop_increment_depth_bar * i;
428 break;
429 }
430 }
431 }
432
433
434 void copyDiveSettingsToSim(void)
435 {
436 memcpy(&stateSim, &stateReal, sizeof(stateReal));
437 }
438
439
440 void copyVpmRepetetiveDataToSim(void)
441 {
442 SDiveState * pSimData = stateSimGetPointerWrite();
443 const SVpmRepetitiveData * pVpmData = stateVpmRepetitiveDataGetPointer();
444
445 if(pVpmData->is_data_from_RTE_CPU)
446 {
447 for(int i=0; i<16;i++)
448 {
449 pSimData->vpm.adjusted_critical_radius_he[i] = pVpmData->adjusted_critical_radius_he[i];
450 pSimData->vpm.adjusted_critical_radius_n2[i] = pVpmData->adjusted_critical_radius_n2[i];
451
452 pSimData->vpm.adjusted_crushing_pressure_he[i] = pVpmData->adjusted_crushing_pressure_he[i];
453 pSimData->vpm.adjusted_crushing_pressure_n2[i] = pVpmData->adjusted_crushing_pressure_n2[i];
454
455 pSimData->vpm.initial_allowable_gradient_he[i] = pVpmData->initial_allowable_gradient_he[i];
456 pSimData->vpm.initial_allowable_gradient_n2[i] = pVpmData->initial_allowable_gradient_n2[i];
457
458 pSimData->vpm.max_actual_gradient[i] = pVpmData->max_actual_gradient[i];
459 }
460 pSimData->vpm.repetitive_variables_not_valid = pVpmData->repetitive_variables_not_valid;
461 }
462 }
463
464
465 void updateSetpointStateUsed(void)
466 {
467 SLifeData *pLifeDataWrite;
468
469 if(is_stateUsedSetToSim())
470 pLifeDataWrite = &stateSimGetPointerWrite()->lifeData;
471 else
472 pLifeDataWrite = &stateRealGetPointerWrite()->lifeData;
473
474 if(stateUsed->diveSettings.diveMode != DIVEMODE_CCR)
475 {
476 pLifeDataWrite->actualGas.setPoint_cbar = 0;
477 pLifeDataWrite->ppO2 = decom_calc_ppO2(stateUsed->lifeData.pressure_ambient_bar, &stateUsed->lifeData.actualGas);
478 }
479 else
480 {
481 if(stateUsed->diveSettings.CCR_Mode == CCRMODE_Sensors)
482 {
483 pLifeDataWrite->actualGas.setPoint_cbar = get_ppO2SensorWeightedResult_cbar();
484 }
485
486 if((stateUsed->lifeData.pressure_ambient_bar * 100) < stateUsed->lifeData.actualGas.setPoint_cbar)
487 pLifeDataWrite->ppO2 = stateUsed->lifeData.pressure_ambient_bar;
488 else
489 pLifeDataWrite->ppO2 = ((float)stateUsed->lifeData.actualGas.setPoint_cbar) / 100;
490 }
491 }
492
493 /*
494 void fallbackToFixedSetpoints(SLifeData *lifeData)
495 {
496
497 }
498 */
499
500 void setActualGasFirst(SLifeData *lifeData)
501 {
502 SSettings* pSettings = settingsGetPointer();
503 uint8_t start = 0;
504 uint8_t gasId = 0;
505 uint8_t setpoint_cbar = 0;
506
507 if(pSettings->dive_mode == DIVEMODE_CCR)
508 {
509 setpoint_cbar = pSettings->setpoint[1].setpoint_cbar;
510 start = NUM_OFFSET_DILUENT+1;
511 }
512 else
513 {
514 setpoint_cbar = 0;
515 start = 1;
516 }
517
518 gasId = start;
519 for(int i=start;i<=NUM_GASES+start;i++)
520 {
521 if(pSettings->gas[i].note.ub.first)
522 {
523 gasId = i;
524 break;
525 }
526 }
527 setActualGas(lifeData, gasId, setpoint_cbar);
528 }
529
530 void setActualGasAir(SLifeData *lifeData)
531 {
532 SSettings* pSettings = settingsGetPointer();
533 uint8_t nitrogen;
534 nitrogen = 79;
535 lifeData->actualGas.GasIdInSettings = 0;
536 lifeData->actualGas.nitrogen_percentage = nitrogen;
537 lifeData->actualGas.helium_percentage =0;
538 lifeData->actualGas.setPoint_cbar = 0;
539 lifeData->actualGas.change_during_ascent_depth_meter_otherwise_zero = 0;
540 }
541
542
543 void setActualGas(SLifeData *lifeData, uint8_t gasId, uint8_t setpoint_cbar)
544 {
545 SSettings* pSettings = settingsGetPointer();
546 uint8_t nitrogen;
547
548 nitrogen = 100;
549 nitrogen -= pSettings->gas[gasId].oxygen_percentage;
550 nitrogen -= pSettings->gas[gasId].helium_percentage;
551
552 lifeData->actualGas.GasIdInSettings = gasId;
553 lifeData->actualGas.nitrogen_percentage = nitrogen;
554 lifeData->actualGas.helium_percentage = pSettings->gas[gasId].helium_percentage;
555 lifeData->actualGas.setPoint_cbar = setpoint_cbar;
556 lifeData->actualGas.change_during_ascent_depth_meter_otherwise_zero = 0;
557
558 if((pSettings->dive_mode == DIVEMODE_CCR) && (gasId > NUM_OFFSET_DILUENT))
559 lifeData->lastDiluent_GasIdInSettings = gasId;
560 }
561
562
563 void setActualGas_DM(SLifeData *lifeData, uint8_t gasId, uint8_t setpoint_cbar)
564 {
565 //Real dive => Set events for logbook
566 if(stateUsed == stateRealGetPointer())
567 {
568 SDiveState * pStateUsed;
569 pStateUsed = stateRealGetPointerWrite();
570
571 if(stateUsed->diveSettings.ccrOption && gasId < 6)
572 {
573 if(lifeData->actualGas.GasIdInSettings != gasId)
574 {
575 SSettings* pSettings = settingsGetPointer();
576 pStateUsed->events.bailout = 1;
577 pStateUsed->events.info_bailoutO2 = pSettings->gas[gasId].oxygen_percentage;
578 pStateUsed->events.info_bailoutHe = pSettings->gas[gasId].helium_percentage;
579 }
580 }
581 else
582 {
583 if(lifeData->actualGas.GasIdInSettings != gasId)
584 {
585 pStateUsed->events.gasChange = 1;
586 pStateUsed->events.info_GasChange = gasId;
587 }
588 if( lifeData->actualGas.setPoint_cbar != setpoint_cbar)
589 {
590 // setPoint_cbar = 255 -> change to sensor mode
591 pStateUsed->events.setpointChange = 1;
592 pStateUsed->events.info_SetpointChange = setpoint_cbar;
593 }
594 }
595 }
596 setActualGas(lifeData, gasId, setpoint_cbar);
597 }
598
599 void setActualGas_ExtraGas(SLifeData *lifeData, uint8_t oxygen, uint8_t helium, uint8_t setpoint_cbar)
600 {
601 uint8_t nitrogen;
602
603 nitrogen = 100;
604 nitrogen -= oxygen;
605 nitrogen -= helium;
606
607 //Real dive => Set events for logbook
608 if(stateUsed == stateRealGetPointer())
609 {
610 SDiveState * pStateUsed;
611 pStateUsed = stateRealGetPointerWrite();
612 if((lifeData->actualGas.nitrogen_percentage != nitrogen) || (lifeData->actualGas.helium_percentage != helium))
613 {
614 pStateUsed->events.manuelGasSet = 1;
615 pStateUsed->events.info_manuelGasSetHe = helium;
616 pStateUsed->events.info_manuelGasSetO2 = oxygen;
617 }
618 if( lifeData->actualGas.setPoint_cbar != setpoint_cbar)
619 {
620 pStateUsed->events.setpointChange = 1;
621 pStateUsed->events.info_SetpointChange = setpoint_cbar;
622 }
623 }
624 lifeData->actualGas.GasIdInSettings = 0;
625 lifeData->actualGas.nitrogen_percentage = nitrogen;
626 lifeData->actualGas.helium_percentage = helium;
627 lifeData->actualGas.setPoint_cbar = setpoint_cbar;
628 lifeData->actualGas.change_during_ascent_depth_meter_otherwise_zero = 0;
629
630 }
631
632 void setButtonResponsiveness(uint8_t *ButtonSensitivyList)
633 {
634 SDataReceiveFromMaster *pDataOut = dataOutGetPointer();
635
636 for(int i=0; i<4; i++)
637 {
638 pDataOut->data.buttonResponsiveness[i] = settingsHelperButtonSens_translate_percentage_to_hwOS_values(ButtonSensitivyList[i]);
639 }
640 pDataOut->setButtonSensitivityNow = 1;
641 }
642
643
644 void setDate(RTC_DateTypeDef Sdate)
645 {
646 SDataReceiveFromMaster *pDataOut = dataOutGetPointer();
647
648 pDataOut->data.newDate = Sdate;
649 pDataOut->setDateNow = 1;
650 }
651
652
653 void setTime(RTC_TimeTypeDef Stime)
654 {
655 SDataReceiveFromMaster *pDataOut = dataOutGetPointer();
656
657 pDataOut->data.newTime = Stime;
658 pDataOut->setTimeNow = 1;
659 }
660
661
662 void setBatteryPercentage(uint8_t newChargePercentage)
663 {
664 SDataReceiveFromMaster *pDataOut = dataOutGetPointer();
665
666 pDataOut->data.newBatteryGaugePercentageFloat = settingsGetPointer()->lastKnownBatteryPercentage;
667 pDataOut->setBatteryGaugeNow = 1;
668 }
669
670
671 void calibrateCompass(void)
672 {
673 SDataReceiveFromMaster *pDataOut = dataOutGetPointer();
674 pDataOut->calibrateCompassNow = 1;
675 }
676
677
678 void clearDeco(void)
679 {
680 SDataReceiveFromMaster *pDataOut = dataOutGetPointer();
681 pDataOut->clearDecoNow = 1;
682
683 stateRealGetPointerWrite()->cnsHigh_at_the_end_of_dive = 0;
684 stateRealGetPointerWrite()->decoMissed_at_the_end_of_dive = 0;
685 }
686
687
688 int32_t helper_days_from_civil(int32_t y, uint32_t m, uint32_t d)
689 {
690 y += 2000;
691 y -= m <= 2;
692 int32_t era = (y >= 0 ? y : y-399) / 400;
693 uint32_t yoe = (uint32_t)(y - era * 400); // [0, 399]
694 uint32_t doy = (153*(m + (m > 2 ? -3 : 9)) + 2)/5 + d-1; // [0, 365]
695 uint32_t doe = yoe * 365 + yoe/4 - yoe/100 + doy; // [0, 146096]
696 return era * 146097 + (int32_t)(doe) - 719468;
697 }
698
699
700 uint8_t helper_weekday_from_days(int32_t z)
701 {
702 return (uint8_t)(z >= -4 ? (z+4) % 7 : (z+5) % 7 + 6);
703 }
704
705
706 void setWeekday(RTC_DateTypeDef *sDate)
707 {
708 uint8_t day;
709 // [0, 6] -> [Sun, Sat]
710 day = helper_weekday_from_days(helper_days_from_civil(sDate->Year, sDate->Month, sDate->Date));
711 // [1, 7] -> [Mon, Sun]
712 if(day == 0)
713 day = 7;
714 sDate->WeekDay = day;
715 }
716
717
718 void translateDate(uint32_t datetmpreg, RTC_DateTypeDef *sDate)
719 {
720 datetmpreg = (uint32_t)(datetmpreg & RTC_DR_RESERVED_MASK);
721
722 /* Fill the structure fields with the read parameters */
723 sDate->Year = (uint8_t)((datetmpreg & (RTC_DR_YT | RTC_DR_YU)) >> 16);
724 sDate->Month = (uint8_t)((datetmpreg & (RTC_DR_MT | RTC_DR_MU)) >> 8);
725 sDate->Date = (uint8_t)(datetmpreg & (RTC_DR_DT | RTC_DR_DU));
726 sDate->WeekDay = (uint8_t)((datetmpreg & (RTC_DR_WDU)) >> 13);
727
728 /* Convert the date structure parameters to Binary format */
729 sDate->Year = (uint8_t)RTC_Bcd2ToByte(sDate->Year);
730 sDate->Month = (uint8_t)RTC_Bcd2ToByte(sDate->Month);
731 sDate->Date = (uint8_t)RTC_Bcd2ToByte(sDate->Date);
732 }
733
734 void translateTime(uint32_t tmpreg, RTC_TimeTypeDef *sTime)
735 {
736 tmpreg = (uint32_t)(tmpreg & RTC_TR_RESERVED_MASK);
737
738 /* Fill the structure fields with the read parameters */
739 sTime->Hours = (uint8_t)((tmpreg & (RTC_TR_HT | RTC_TR_HU)) >> 16);
740 sTime->Minutes = (uint8_t)((tmpreg & (RTC_TR_MNT | RTC_TR_MNU)) >>8);
741 sTime->Seconds = (uint8_t)(tmpreg & (RTC_TR_ST | RTC_TR_SU));
742 sTime->TimeFormat = (uint8_t)((tmpreg & (RTC_TR_PM)) >> 16);
743
744 /* Convert the time structure parameters to Binary format */
745 sTime->Hours = (uint8_t)RTC_Bcd2ToByte(sTime->Hours);
746 sTime->Minutes = (uint8_t)RTC_Bcd2ToByte(sTime->Minutes);
747 sTime->Seconds = (uint8_t)RTC_Bcd2ToByte(sTime->Seconds);
748 sTime->SubSeconds = 0;
749 }
750
751
752 /*
753 void initDiveState(SDiveSettings * pDiveSettings, SVpm * pVpm)
754 {
755 SSettings* pSettings = settingsGetPointer();
756 for(int i = 0; i< NUM_GASES; i++)
757 {
758 pDiveSettings->gas[i] = pSettings->gas[i];
759 pDiveSettings->gas[NUM_OFFSET_DILUENT + i] = pSettings->gas[NUM_OFFSET_DILUENT + i];
760 pDiveSettings->setpoint[i] = pSettings->setpoint[i];
761 }
762 pDiveSettings->diveMode = pSettings->dive_mode;
763
764 pDiveSettings->gf_high = pSettings->GF_high;
765 pDiveSettings->gf_low = pSettings->GF_low;
766 pDiveSettings->last_stop_depth_bar = ((float)pSettings->last_stop_depth_meter) / 10.0;
767 pDiveSettings->ascentRate_meterperminute = 10;
768 pDiveSettings->vpm_conservatism = 1;
769
770 pDiveSettings->input_next_stop_increment_depth_bar = ((float)pSettings->stop_increment_depth_meter) / 10.0f;
771
772 vpm_init(pVpm, pDiveSettings->vpm_conservatism, 0, 0);
773 }
774 */
775 _Bool deco_zone_reached(void)
776 {
777 if(stateUsed->diveSettings.deco_type.ub.standard == GF_MODE)
778 return stateUsed->lifeData.pressure_ambient_bar <= stateUsed->diveSettings.internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero;
779 else
780 return stateUsed->vpm.deco_zone_reached;
781
782 }
783
784
785 void resetEvents(void)
786 {
787 SDiveState * pStateUsed;
788 if(stateUsed == stateRealGetPointer())
789 pStateUsed = stateRealGetPointerWrite();
790 else
791 pStateUsed = stateSimGetPointerWrite();
792
793 memset(&pStateUsed->events,0, sizeof(SEvents));
794 }
795
796
797 /* This is derived from crc32b but does table lookup. First the table
798 itself is calculated, if it has not yet been set up.
799 Not counting the table setup (which would probably be a separate
800 function), when compiled to Cyclops with GCC, this function executes in
801 7 + 13n instructions, where n is the number of bytes in the input
802 message. It should be doable in 4 + 9n instructions. In any case, two
803 of the 13 or 9 instrucions are load byte.
804 This is Figure 14-7 in the text. */
805
806 /* http://www.hackersdelight.org/ i guess ;-) *hw */
807
808 uint32_t crc32c_checksum(uint8_t* message, uint16_t length, uint8_t* message2, uint16_t length2) {
809 int i, j;
810 uint32_t byte, crc, mask;
811 static unsigned int table[256] = {0};
812
813 /* Set up the table, if necessary. */
814 if (table[1] == 0) {
815 for (byte = 0; byte <= 255; byte++) {
816 crc = byte;
817 for (j = 7; j >= 0; j--) { // Do eight times.
818 mask = -(crc & 1);
819 crc = (crc >> 1) ^ (0xEDB88320 & mask);
820 }
821 table[byte] = crc;
822 }
823 }
824
825 /* Through with table setup, now calculate the CRC. */
826 i = 0;
827 crc = 0xFFFFFFFF;
828 while (length--) {
829 byte = message[i];
830 crc = (crc >> 8) ^ table[(crc ^ byte) & 0xFF];
831 i = i + 1;
832 }
833 if(length2)
834 {
835 i = 0;
836 while (length2--) {
837 byte = message2[i];
838 crc = (crc >> 8) ^ table[(crc ^ byte) & 0xFF];
839 i = i + 1;
840 }
841 }
842 return ~crc;
843 }
844
845
846 uint32_t CRC_CalcBlockCRC_moreThan768000(uint32_t *buffer1, uint32_t *buffer2, uint32_t words)
847 {
848 cm_t crc_model;
849 uint32_t word_to_do;
850 uint8_t byte_to_do;
851 int i;
852
853 // Values for the STM32F generator.
854
855 crc_model.cm_width = 32; // 32-bit CRC
856 crc_model.cm_poly = 0x04C11DB7; // CRC-32 polynomial
857 crc_model.cm_init = 0xFFFFFFFF; // CRC initialized to 1's
858 crc_model.cm_refin = FALSE; // CRC calculated MSB first
859 crc_model.cm_refot = FALSE; // Final result is not bit-reversed
860 crc_model.cm_xorot = 0x00000000; // Final result XOR'ed with this
861
862 cm_ini(&crc_model);
863
864 while (words--)
865 {
866 // The STM32F10x hardware does 32-bit words at a time!!!
867 if(words > (768000/4))
868 word_to_do = *buffer2++;
869 else
870 word_to_do = *buffer1++;
871
872 // Do all bytes in the 32-bit word.
873
874 for (i = 0; i < sizeof(word_to_do); i++)
875 {
876 // We calculate a *byte* at a time. If the CRC is MSB first we
877 // do the next MS byte and vica-versa.
878
879 if (crc_model.cm_refin == FALSE)
880 {
881 // MSB first. Do the next MS byte.
882
883 byte_to_do = (uint8_t) ((word_to_do & 0xFF000000) >> 24);
884 word_to_do <<= 8;
885 }
886 else
887 {
888 // LSB first. Do the next LS byte.
889
890 byte_to_do = (uint8_t) (word_to_do & 0x000000FF);
891 word_to_do >>= 8;
892 }
893
894 cm_nxt(&crc_model, byte_to_do);
895 }
896 }
897
898 // Return the final result.
899
900 return (cm_crc(&crc_model));
901 }
902
903
904 uint32_t CRC_CalcBlockCRC(uint32_t *buffer, uint32_t words)
905 {
906 cm_t crc_model;
907 uint32_t word_to_do;
908 uint8_t byte_to_do;
909 int i;
910
911 // Values for the STM32F generator.
912
913 crc_model.cm_width = 32; // 32-bit CRC
914 crc_model.cm_poly = 0x04C11DB7; // CRC-32 polynomial
915 crc_model.cm_init = 0xFFFFFFFF; // CRC initialized to 1's
916 crc_model.cm_refin = FALSE; // CRC calculated MSB first
917 crc_model.cm_refot = FALSE; // Final result is not bit-reversed
918 crc_model.cm_xorot = 0x00000000; // Final result XOR'ed with this
919
920 cm_ini(&crc_model);
921
922 while (words--)
923 {
924 // The STM32F10x hardware does 32-bit words at a time!!!
925
926 word_to_do = *buffer++;
927
928 // Do all bytes in the 32-bit word.
929
930 for (i = 0; i < sizeof(word_to_do); i++)
931 {
932 // We calculate a *byte* at a time. If the CRC is MSB first we
933 // do the next MS byte and vica-versa.
934
935 if (crc_model.cm_refin == FALSE)
936 {
937 // MSB first. Do the next MS byte.
938
939 byte_to_do = (uint8_t) ((word_to_do & 0xFF000000) >> 24);
940 word_to_do <<= 8;
941 }
942 else
943 {
944 // LSB first. Do the next LS byte.
945
946 byte_to_do = (uint8_t) (word_to_do & 0x000000FF);
947 word_to_do >>= 8;
948 }
949
950 cm_nxt(&crc_model, byte_to_do);
951 }
952 }
953
954 // Return the final result.
955
956 return (cm_crc(&crc_model));
957 }
958
959
960 _Bool is_ambient_pressure_close_to_surface(SLifeData *lifeData)
961 {
962 if(lifeData->pressure_ambient_bar < (lifeData->pressure_surface_bar + 0.04f))
963 return true;
964 else
965 return false;
966 }
967
968 uint8_t stateUsed_scooterRemainingBattCapacity(void)
969 {
970 const uint8_t useCapacityValue = 1; // 2 is the new one, 1 = scooterRestkapazitaetWhBased is the official used
971
972 switch(useCapacityValue)
973 {
974 case 0:
975 default:
976 return stateUsed->lifeData.scooterRestkapazitaet;
977
978 case 1:
979 return stateUsed->lifeData.scooterRestkapazitaetWhBased;
980
981 case 2:
982 return stateUsed->lifeData.scooterRestkapazitaetVoltageBased;
983 }
984 }