comparison Small_CPU/Src/scheduler.c @ 38:5f11787b4f42

include in ostc4 repository
author heinrichsweikamp
date Sat, 28 Apr 2018 11:52:34 +0200
parents
children a6f0881074a4
comparison
equal deleted inserted replaced
37:ccc45c0e1ea2 38:5f11787b4f42
1 /**
2 ******************************************************************************
3 * @file scheduler.c
4 * @author heinrichs weikamp gmbh
5 * @date 27-March-2014
6 * @version V0.0.6
7 * @since 18-June-2015
8 * @brief the main part except for base.c
9 *
10 @verbatim
11 ==============================================================================
12 ##### How to use #####
13 ==============================================================================
14 @endverbatim
15 ******************************************************************************
16 * @attention
17 *
18 * <h2><center>&copy; COPYRIGHT(c) 2015 heinrichs weikamp</center></h2>
19 *
20 ******************************************************************************
21 */
22
23
24 //#define DEBUGMODE
25
26 /* Includes ------------------------------------------------------------------*/
27 #include <string.h>
28 #include "baseCPU2.h"
29 #include "stm32f4xx_hal.h"
30 #include "i2c.h"
31 #include "scheduler.h"
32 #include "pressure.h"
33 #include "compass.h"
34 #include "batteryGasGauge.h"
35 #include "batteryCharger.h"
36 #include "spi.h"
37 #include "rtc.h"
38 #include "dma.h"
39 #include "adc.h"
40 #include "calc_crush.h"
41 #include "stm32f4xx_hal_rtc_ex.h"
42 #include "decom.h"
43 #include "wireless.h"
44 #include "tm_stm32f4_otp.h"
45
46
47 /* Private types -------------------------------------------------------------*/
48 const SGas Air = {79,0,0,0,0};
49
50 uint8_t testarrayindex = 0;
51 uint32_t testarray[256];
52 uint32_t testarrayMain[256];
53
54 /* Exported variables --------------------------------------------------------*/
55 SGlobal global;
56 SDevice DeviceDataFlash;
57 uint8_t deviceDataFlashValid = 0;
58 uint8_t deviceDataSubSeconds = 0;
59
60 /* Private variables ---------------------------------------------------------*/
61 /* can be lost while in sleep */
62 uint8_t clearDecoNow = 0;
63 uint8_t setButtonsNow = 0;
64
65 /* has to be in SRAM2 */
66 uint8_t secondsCount = 0;
67
68 /* Private function prototypes -----------------------------------------------*/
69
70 _Bool vpm_crush2(void);
71 void scheduleUpdateDeviceData(void);
72 void initStructWithZeero(uint8_t* data, uint16_t length);
73 long get_nofly_time_minutes(void);
74 void copyActualGas(SGas gas);
75 void copyPressureData(void);
76 void copyCnsAndOtuData(void);
77 void copyTimeData(void);
78 void copyCompassData(void);
79 void copyCompassDataDuringCalibration(int16_t dx, int16_t dy, int16_t dz);
80 //void copyBatteryData(void); now in header
81 void copyAmbientLightData(void);
82 void copyTissueData(void);
83 void copyVpmCrushingData(void);
84 void copyDeviceData(void);
85 void changeAgeWirelessData(void);
86 void copyWirelessData(void);
87 void copyPICdata(void);
88 uint16_t schedule_update_timer_helper(int8_t thisSeconds);
89
90
91 uint32_t time_elapsed_ms(uint32_t ticksstart,uint32_t ticksnow);
92
93 _Bool scheduleCheck_pressure_reached_dive_mode_level(void);
94 void scheduleSetDate(SDeviceLine *line);
95
96 /* Exported functions --------------------------------------------------------*/
97
98 void initGlobals(void)
99 {
100 initStructWithZeero((uint8_t*) &global, sizeof(SGlobal));
101
102 global.dataSendToSlavePending = 0;
103 global.dataSendToSlaveIsValid = 1;
104 global.dataSendToSlaveIsNotValidCount = 0;
105
106 global.mode = MODE_POWERUP;
107 global.repetitive_dive = 0;
108 global.conservatism = 0;
109 global.whichGas = 0;
110 global.aktualGas[0] = Air;
111 global.lifeData.actualGas = global.aktualGas[0];
112
113 const uint8_t button_standard_sensitivity = ((2400-( 90 *24))/10)+15;
114 global.ButtonResponsiveness[0] = button_standard_sensitivity;
115 global.ButtonResponsiveness[1] = button_standard_sensitivity;
116 global.ButtonResponsiveness[2] = button_standard_sensitivity;
117 global.ButtonResponsiveness[3] = button_standard_sensitivity;
118
119 global.ButtonPICdata[0] = 0xFF;
120 global.ButtonPICdata[1] = 0xFF;
121 global.ButtonPICdata[2] = 0xFF;
122 global.ButtonPICdata[3] = 0xFF;
123
124 global.I2C_SystemStatus = 0xFF; // 0x00 would be everything working
125
126 global.lifeData.pressure_ambient_bar = 1.0f;
127 global.lifeData.pressure_surface_bar = 1.0f;
128 decom_reset_with_1000mbar(&global.lifeData);
129
130 global.demo_mode = 0;
131
132 for(int i = 0; i < MAX_SENSORS; i++)
133 {
134 global.sensorError[i] = HAL_OK; // HAL_OK = 0;
135 }
136
137 global.dataSendToMaster.RTE_VERSION_high = firmwareVersionHigh();//RTE_VERSION_HIGH;;
138 global.dataSendToMaster.RTE_VERSION_low = firmwareVersionLow();//RTE_VERSION_LOW;;
139 global.dataSendToMaster.chargeStatus = 0;
140
141 global.dataSendToMaster.power_on_reset = 1;
142 global.dataSendToMaster.header.checkCode[0] = 0xA1;
143 global.dataSendToMaster.header.checkCode[1] = 0xA2;
144 global.dataSendToMaster.header.checkCode[2] = 0xA3;
145 global.dataSendToMaster.header.checkCode[3] = 0xA4;
146 global.dataSendToMaster.footer.checkCode[3] = 0xE4;
147 global.dataSendToMaster.footer.checkCode[2] = 0xE3;
148 global.dataSendToMaster.footer.checkCode[1] = 0xE2;
149 global.dataSendToMaster.footer.checkCode[0] = 0xE1;
150 global.dataSendToMaster.sensorErrors = 0;
151
152 global.sync_error_count = 0;
153 global.check_sync_not_running = 0;
154
155 global.deviceDataSendToMaster.RTE_VERSION_high = firmwareVersionHigh();//RTE_VERSION_HIGH;
156 global.deviceDataSendToMaster.RTE_VERSION_low = firmwareVersionLow();//RTE_VERSION_LOW;
157 global.deviceDataSendToMaster.chargeStatus = 0;
158
159 global.deviceDataSendToMaster.power_on_reset = 1;
160 global.deviceDataSendToMaster.header.checkCode[0] = 0xDF;
161 global.deviceDataSendToMaster.header.checkCode[1] = 0xDE;
162 global.deviceDataSendToMaster.header.checkCode[2] = 0xDD;
163 global.deviceDataSendToMaster.header.checkCode[3] = 0xDC;
164 global.deviceDataSendToMaster.footer.checkCode[3] = 0xE4;
165 global.deviceDataSendToMaster.footer.checkCode[2] = 0xE3;
166 global.deviceDataSendToMaster.footer.checkCode[1] = 0xE2;
167 global.deviceDataSendToMaster.footer.checkCode[0] = 0xE1;
168
169 global.dataSendToSlave.getDeviceDataNow = 0;
170
171 global.deviceData.batteryChargeCompleteCycles.value_int32 = 0;
172 global.deviceData.batteryChargeCycles.value_int32 = 0;
173 global.deviceData.depthMaximum.value_int32 = 0;
174 global.deviceData.diveCycles.value_int32 = 0;
175 global.deviceData.hoursOfOperation.value_int32 = 0;
176 global.deviceData.temperatureMaximum.value_int32 = INT32_MIN;
177 global.deviceData.temperatureMinimum.value_int32 = INT32_MAX;
178 global.deviceData.voltageMinimum.value_int32 = INT32_MAX;
179 }
180
181
182 void scheduleSpecial_Evaluate_DataSendToSlave(void)
183 {
184 global.dataSendToSlavePending = 0;
185 if(!global.dataSendToSlaveIsValid)
186 return;
187
188 global.dataSendToMaster.confirmRequest.uw = 0;
189
190 if(TM_OTP_Read(0,0) == 0xFF)
191 {
192 if(global.dataSendToSlave.revisionHardware == (global.dataSendToSlave.revisionCRCx0x7A ^ 0x7A))
193 TM_OTP_Write(0,0,global.dataSendToSlave.revisionHardware);
194 }
195
196 if(global.dataSendToSlave.setAccidentFlag)
197 {
198 global.dataSendToMaster.confirmRequest.ub.accident = 1;
199 global.deviceData.diveAccident.value_int32 = global.dataSendToSlave.setAccidentFlag;
200 scheduleSetDate(&global.deviceData.diveAccident);
201 global.accidentFlag |= global.dataSendToSlave.setAccidentFlag;
202 if(global.accidentFlag == ACCIDENT_CNS) // LVL1
203 global.accidentRemainingSeconds = 2*60*60;
204 else
205 global.accidentRemainingSeconds = 24*60*60;
206 }
207
208 if(global.dataSendToSlave.setTimeNow)
209 {
210 global.dataSendToMaster.confirmRequest.ub.time = 1;
211 RTC_SetTime(global.dataSendToSlave.data.newTime);
212 schedule_update_timer_helper(0);
213 }
214
215 if(global.dataSendToSlave.setDateNow)
216 {
217 global.dataSendToMaster.confirmRequest.ub.date = 1;
218 RTC_SetDate(global.dataSendToSlave.data.newDate);
219 schedule_update_timer_helper(0);
220 }
221
222 if(global.dataSendToSlave.calibrateCompassNow)
223 {
224 global.dataSendToMaster.confirmRequest.ub.compass = 1;
225 global.mode = MODE_CALIB;
226 }
227
228 if(global.dataSendToSlave.clearDecoNow)
229 {
230 global.dataSendToMaster.confirmRequest.ub.clearDeco = 1;
231 clearDecoNow = 1;
232 }
233
234 if(global.dataSendToSlave.setButtonSensitivityNow)
235 {
236 global.dataSendToMaster.confirmRequest.ub.button = 1;
237 global.ButtonResponsiveness[0] = global.dataSendToSlave.data.buttonResponsiveness[0];
238 global.ButtonResponsiveness[1] = global.dataSendToSlave.data.buttonResponsiveness[1];
239 global.ButtonResponsiveness[2] = global.dataSendToSlave.data.buttonResponsiveness[2];
240 global.ButtonResponsiveness[3] = global.dataSendToSlave.data.buttonResponsiveness[3];
241 setButtonsNow = 1;
242 }
243
244 if(global.dataSendToSlave.setBatteryGaugeNow)
245 {
246 global.dataSendToMaster.confirmRequest.ub.batterygauge = 1;
247 battery_gas_gauge_set(global.dataSendToSlave.data.newBatteryGaugePercentageFloat);
248 }
249
250 if((global.mode == MODE_SURFACE) && (global.dataSendToSlave.mode == MODE_SHUTDOWN))
251 {
252 global.mode = MODE_SHUTDOWN;
253 }
254
255 if(global.mode == MODE_DIVE)
256 {
257 copyActualGas(global.dataSendToSlave.data.actualGas);
258 }
259 else
260 {
261 copyActualGas(Air);
262 global.settings.divetimeToCreateLogbook = global.dataSendToSlave.data.divetimeToCreateLogbook;
263 global.settings.timeoutDiveReachedZeroDepth = global.dataSendToSlave.data.timeoutDiveReachedZeroDepth;
264 }
265
266 /* for simulation / testing */
267 global.ceiling_from_main_CPU_mbar = global.dataSendToSlave.data.ambient_pressure_mbar_ceiling;
268
269 /* for device data updates */
270 deviceDataFlashValid = 0;
271 memcpy(&DeviceDataFlash, &global.dataSendToSlave.data.DeviceData, sizeof(SDevice));
272 deviceDataFlashValid = 1;
273 }
274
275
276 /**
277 ******************************************************************************
278 * @brief schedule_time_compare_helper.
279 * @author heinrichs weikamp gmbh
280 * @version V0.0.1
281 * @date 20-Oct-2016
282 ******************************************************************************
283 */
284
285 uint8_t RtcBugFixChsw(uint8_t inStupidTime)
286 {
287 uint8_t multiplesOf16 = 0;
288
289 multiplesOf16 = inStupidTime / 16;
290
291 inStupidTime -= multiplesOf16 * 16;
292
293 return (10 * multiplesOf16) + inStupidTime;
294 }
295
296
297 uint32_t minCounterDebug = 0;
298
299 uint32_t schedule_time_compare_helper(RTC_TimeTypeDef timeNow, RTC_DateTypeDef dateNow, RTC_TimeTypeDef timeLast, RTC_DateTypeDef dateLast)
300 {
301 uint32_t nowInSeconds;
302 uint32_t lastInSeconds;
303 uint32_t resultDiff;
304
305 if(timeNow.Minutes != timeLast.Minutes)
306 minCounterDebug++;
307
308 nowInSeconds = (uint32_t)RtcBugFixChsw(timeNow.Hours) * 3600;
309 nowInSeconds += (uint32_t)RtcBugFixChsw(timeNow.Minutes) * 60;
310 nowInSeconds += (uint32_t)RtcBugFixChsw(timeNow.Seconds);
311
312 lastInSeconds = (uint32_t)RtcBugFixChsw(timeLast.Hours) * 3600;
313 lastInSeconds += (uint32_t)RtcBugFixChsw(timeLast.Minutes) * 60;
314 lastInSeconds += (uint32_t)RtcBugFixChsw(timeLast.Seconds);
315
316 /*
317 nowInSeconds = (uint32_t)timeNow.Hours * 3600;
318 nowInSeconds += (uint32_t)timeNow.Minutes * 60;
319 nowInSeconds += (uint32_t)timeNow.Seconds;
320
321 lastInSeconds = (uint32_t)timeLast.Hours * 3600;
322 lastInSeconds += (uint32_t)timeLast.Minutes * 60;
323 lastInSeconds += (uint32_t)timeLast.Seconds;
324 */
325
326 if(dateNow.Date != dateLast.Date)
327 {
328 resultDiff = 86400 + nowInSeconds - lastInSeconds;
329 }
330 else
331 {
332 resultDiff = nowInSeconds - lastInSeconds;
333 }
334 return resultDiff;
335 }
336
337
338
339 /**
340 ******************************************************************************
341 * @brief schedule_update_timer_helper.
342 * @author heinrichs weikamp gmbh
343 * @version V0.0.1
344 * @date 20-Oct-2016
345 * @brief use 0 for init
346 use -1 for RTC controlled
347 use >= 1 for manual control
348 ******************************************************************************
349 */
350 extern RTC_HandleTypeDef RTCHandle;
351
352 uint16_t schedule_update_timer_helper(int8_t thisSeconds)
353 {
354 static RTC_TimeTypeDef sTimeLast;
355 static RTC_DateTypeDef sDateLast;
356 RTC_TimeTypeDef sTimeNow;
357 RTC_DateTypeDef sDateNow;
358 uint32_t secondsPast;
359 uint32_t tempNewValue = 0;
360
361 HAL_RTC_GetTime(&RTCHandle, &sTimeNow, RTC_FORMAT_BCD);
362 HAL_RTC_GetDate(&RTCHandle, &sDateNow, RTC_FORMAT_BCD);
363
364 if(thisSeconds != 0) // otherwise just store sTimeLast, sDateLast and return 0
365 {
366 secondsPast = schedule_time_compare_helper(sTimeNow, sDateNow, sTimeLast, sDateLast);
367
368 if(thisSeconds > 0) // use this value instead, good for pre-loading sTimeLast and sDateLast
369 {
370 secondsPast = thisSeconds;
371 }
372
373 if(global.seconds_since_last_dive)
374 {
375 if(secondsPast >= 777900)
376 {
377 global.seconds_since_last_dive = 0;
378 }
379 else
380 {
381 tempNewValue = ((uint32_t)global.seconds_since_last_dive) + secondsPast;
382 if(tempNewValue > 777900) // a bit more than nine days [seconds]
383 global.seconds_since_last_dive = 0;
384 else
385 global.seconds_since_last_dive = (long)tempNewValue;
386 }
387 }
388 }
389
390 sTimeLast = sTimeNow;
391 sDateLast = sDateNow;
392
393 return tempNewValue;
394 }
395
396
397
398
399 /**
400 ******************************************************************************
401 * @brief schedule_check_resync.
402 * @author heinrichs weikamp gmbh
403 * @version V0.0.2
404 * @date 18-June-2015
405 ******************************************************************************
406 */
407 void schedule_check_resync(void)
408 {
409 if((global.check_sync_not_running >= 10) || (global.dataSendToSlaveIsNotValidCount >= 2))
410 {
411 global.dataSendToSlaveIsNotValidCount = 0;
412 global.check_sync_not_running = 0;
413 global.sync_error_count++;
414 MX_SPI_DeInit();
415 HAL_Delay(30); /* could be closer to length of data transmission 23.Feb.2015 hw */
416 MX_DMA_Init();
417 MX_SPI1_Init();
418 SPI_Start_single_TxRx_with_Master();
419 }
420 }
421
422
423 /**
424 ******************************************************************************
425 * @brief scheduleDiveMode. / Dive Mode: Main Loop
426 * @author Peter Ryser
427 * @version V0.0.1
428 * @date 22-April-2014
429 ******************************************************************************
430 */
431 void scheduleDiveMode(void)
432 {
433 uint32_t tickstart = 0;
434 uint32_t ticksdiff = 0;
435 uint32_t lasttick = 0;
436 tickstart = HAL_GetTick();
437 uint8_t counterPressure100msec = 0;
438 uint8_t counterCompass100msec = 0;
439 uint8_t counterAmbientLight100msec = 0;
440 uint16_t counterWireless1msec = 0;
441 // uint8_t counterDemo250msec = 0;
442 uint32_t turbo_seconds = 0;
443 uint8_t counterAscentRate = 0;
444 float lastPressure_bar = 0.0f;
445 global.dataSendToMaster.mode = MODE_DIVE;
446 global.deviceDataSendToMaster.mode = MODE_DIVE;
447 //uint16_t counterSecondsShallowDepth = 0;
448 uint8_t counter_exit = 0;
449
450 tickstart = HAL_GetTick() - 1000;
451
452 global.deviceData.diveCycles.value_int32++;
453 scheduleSetDate(&global.deviceData.diveCycles);
454 global.lifeData.counterSecondsShallowDepth = 0;
455
456 while(global.mode == MODE_DIVE)
457 {
458 schedule_check_resync();
459 lasttick = HAL_GetTick();
460 ticksdiff = time_elapsed_ms(tickstart,lasttick);
461
462
463 //Evaluate wireless data every ms, if present
464 if(ticksdiff > counterWireless1msec)
465 {
466 counterWireless1msec++;
467 changeAgeWirelessData();
468 global.wirelessReceived = wireless_evaluate(global.wirelessdata,MAX_WIRELESS_BYTES, &global.wirelessConfidenceStatus);
469 if((global.wirelessReceived > 0) && !wireless_evaluate_crc_error(global.wirelessdata,global.wirelessReceived))
470 {
471 copyWirelessData();
472 }
473 }
474
475 //Evaluate pressure at 20 ms, 120 ms, 220 ms,....
476 if(ticksdiff >= counterPressure100msec * 100 + 20)
477 {
478 global.check_sync_not_running++;
479 pressure_update();
480 scheduleUpdateDeviceData();
481 if(global.demo_mode)
482 {
483 turbo_seconds = demo_modify_temperature_and_pressure(global.lifeData.dive_time_seconds, counterPressure100msec, global.ceiling_from_main_CPU_mbar);
484 if(turbo_seconds)
485 {
486 global.lifeData.dive_time_seconds += turbo_seconds;
487 decom_tissues_exposure((int)(turbo_seconds), &global.lifeData);
488 copyTissueData();
489 }
490 if((global.lifeData.counterSecondsShallowDepth > 1) && (global.lifeData.counterSecondsShallowDepth < (global.settings.timeoutDiveReachedZeroDepth - 10)))
491 global.lifeData.counterSecondsShallowDepth = (global.settings.timeoutDiveReachedZeroDepth - 10);
492 }
493
494
495 //Calc ascentrate every two second (20 * 100 ms)
496 counterAscentRate++;
497 if(counterAscentRate == 20)
498 {
499 global.lifeData.pressure_ambient_bar = get_pressure_mbar() / 1000.0f;
500 if(lastPressure_bar >= 0)
501 {
502 //2 seconds * 30 == 1 minute, bar * 10 = meter
503 global.lifeData.ascent_rate_meter_per_min = (lastPressure_bar - global.lifeData.pressure_ambient_bar) * 30 * 10;
504 }
505 lastPressure_bar = global.lifeData.pressure_ambient_bar;
506 counterAscentRate = 0;
507
508 // if(global.demo_mode)
509 // global.lifeData.ascent_rate_meter_per_min /= 4;
510 }
511 copyPressureData();
512 counterPressure100msec++;
513 }
514 //evaluate compass data at 50 ms, 150 ms, 250 ms,....
515 if(ticksdiff >= counterCompass100msec * 100 + 50)
516 {
517 compass_read();
518 acceleration_read();
519 compass_calc();
520 copyCompassData();
521 counterCompass100msec++;
522 }
523
524 if(ticksdiff >= counterAmbientLight100msec * 100 + 70)
525 {
526 adc_ambient_light_sensor_get_data();
527 copyAmbientLightData();
528 counterAmbientLight100msec++;
529 }
530
531 /* if(global.demo_mode && (ticksdiff >= counterDemo250msec * 250 + 10))
532 {
533 global.lifeData.dive_time_seconds++;
534 copyTimeData();
535 counterDemo250msec++;
536 }
537 */
538 //Evaluate tissues, toxic data, vpm, etc. once a second
539 if(ticksdiff >= 1000)
540 {
541 if(global.dataSendToSlave.diveModeInfo != DIVEMODE_Apnea)
542 {
543 scheduleUpdateLifeData(0); // includes tissues
544 global.lifeData.dive_time_seconds++; // there is dive_time_seconds_without_surface_time too
545 global.lifeData.ppO2 = decom_calc_ppO2(global.lifeData.pressure_ambient_bar, &global.lifeData.actualGas);
546 decom_oxygen_calculate_cns(&global.lifeData.cns,global.lifeData.ppO2);
547 decom_oxygen_calculate_otu(&global.lifeData.otu,global.lifeData.ppO2);
548 battery_gas_gauge_get_data();
549
550
551 /** counter_exit allows safe exit via button for testing
552 * and demo_mode is exited too if aplicable.
553 */
554 if(global.dataSendToMaster.mode == MODE_ENDDIVE)
555 {
556 counter_exit++;
557 if(counter_exit >= 2)
558 {
559 global.mode = MODE_SURFACE;
560 global.demo_mode = 0;
561 }
562 }
563
564 if(is_ambient_pressure_close_to_surface(&global.lifeData))
565 {
566 global.lifeData.counterSecondsShallowDepth++;
567 if((global.lifeData.counterSecondsShallowDepth >= global.settings.timeoutDiveReachedZeroDepth) || ((global.lifeData.dive_time_seconds < 60) && (global.demo_mode == 0)) || (global.dataSendToSlave.setEndDive))
568 {
569 global.seconds_since_last_dive = 1; // start counter
570 schedule_update_timer_helper(0); // zum starten :-)
571 global.dataSendToMaster.mode = MODE_ENDDIVE;
572 global.deviceDataSendToMaster.mode = MODE_ENDDIVE;
573 }
574 }
575 else
576 {
577 global.lifeData.counterSecondsShallowDepth = 0;
578 global.lifeData.dive_time_seconds_without_surface_time++;
579 }
580 vpm_crush2();
581 }
582 else // DIVEMODE_Apnea
583 {
584 global.lifeData.dive_time_seconds++;
585
586 // exit dive mode
587 if(global.dataSendToMaster.mode == MODE_ENDDIVE)
588 {
589 counter_exit++;
590 if(counter_exit >= 2)
591 {
592 scheduleUpdateLifeData(-1); // 'restart' tissue calculations without calculating time during apnea mode
593 global.lifeData.dive_time_seconds = 0; // use backup noflytime and desaturation time
594 global.mode = MODE_SURFACE;
595 global.demo_mode = 0;
596 }
597 }
598
599 // surface break
600 if(is_ambient_pressure_close_to_surface(&global.lifeData))
601 {
602 global.lifeData.counterSecondsShallowDepth++;
603 if(global.lifeData.counterSecondsShallowDepth > 3) // time for main cpu to copy to apnea_last_dive_time_seconds
604 {
605 global.lifeData.dive_time_seconds = 0; // this apnea dive ends here
606 }
607 if((global.lifeData.counterSecondsShallowDepth >= global.settings.timeoutDiveReachedZeroDepth) || (global.dataSendToSlave.setEndDive))
608 {
609 global.dataSendToMaster.mode = MODE_ENDDIVE;
610 global.deviceDataSendToMaster.mode = MODE_ENDDIVE;
611 }
612 }
613 else
614 {
615 global.lifeData.counterSecondsShallowDepth = 0;
616 global.lifeData.dive_time_seconds_without_surface_time++;
617 }
618 } // standard dive or DIVEMODE_Apnea
619
620 copyVpmCrushingData();
621 copyTimeData();
622 copyCnsAndOtuData();
623 copyBatteryData();
624
625 // new hw 170523
626 if(global.I2C_SystemStatus != HAL_OK)
627 {
628 MX_I2C1_TestAndClear();
629 MX_I2C1_Init();
630 if(!is_init_pressure_done())
631 {
632 init_pressure();
633 }
634 }
635
636 counterCompass100msec = 0;
637 counterPressure100msec = 0;
638 counterAmbientLight100msec = 0;
639 counterWireless1msec = 0;
640 // counterDemo250msec = 0;
641
642 /** keep it in rhythm, do not drop the execution time
643 * therefore do not use tickstart = HAL_GetTick();
644 * here
645 */
646 tickstart += 1000;
647 }
648 }
649 }
650
651
652 /**
653 ******************************************************************************
654 * @brief scheduleSurfaceMode / surface mode: Main Loop
655 * @author Peter Ryser
656 * @version V0.0.1
657 * @date 22-April-2014
658 ******************************************************************************
659 */
660
661
662 // ===============================================================================
663 // scheduleTestMode
664 /// @brief included for sealed hardware with permanent RTE update message
665 // ===============================================================================
666 void scheduleTestMode(void)
667 {
668 uint32_t tickstart = 0;
669 uint32_t ticksdiff = 0;
670 uint32_t lasttick = 0;
671 tickstart = HAL_GetTick();
672
673 uint8_t counterPressure100msec = 0;
674
675 float temperature_carousel = 0.0f;
676 float temperature_changer = 0.1f;
677
678 while(global.mode == MODE_TEST)
679 {
680 schedule_check_resync();
681 lasttick = HAL_GetTick();
682 ticksdiff = time_elapsed_ms(tickstart,lasttick);
683
684 //Evaluate pressure at 20 ms, 120 ms, 220 ms,...
685 if(ticksdiff >= counterPressure100msec * 100 + 20)
686 {
687 global.check_sync_not_running++;
688
689 pressure_update();
690 scheduleUpdateDeviceData();
691 global.lifeData.ascent_rate_meter_per_min = 0;
692 copyPressureData();
693
694 if(temperature_carousel > 20.0f)
695 {
696 temperature_carousel = 20.0f;
697 temperature_changer = -0.1f;
698 }
699 else
700 if(temperature_carousel < 0)
701 {
702 temperature_carousel = 0;
703 temperature_changer = +0.1f;
704 }
705
706 temperature_carousel += temperature_changer;
707
708 uint8_t boolPressureData = !global.dataSendToMaster.boolPressureData;
709
710 global.dataSendToMaster.data[boolPressureData].pressure_mbar = get_pressure_mbar();
711
712 global.dataSendToMaster.data[boolPressureData].temperature = temperature_carousel;
713 global.dataSendToMaster.data[boolPressureData].pressure_uTick = HAL_GetTick();
714 global.dataSendToMaster.boolPressureData = boolPressureData;
715
716
717 counterPressure100msec++;
718 }
719
720 if(ticksdiff >= 1000)
721 {
722 //Set back tick counter
723 tickstart = HAL_GetTick();
724 counterPressure100msec = 0;
725 }
726 };
727 }
728
729
730 void scheduleSurfaceMode(void)
731 {
732 uint32_t tickstart = 0;
733 uint32_t ticksdiff = 0;
734 uint32_t lasttick = 0;
735 tickstart = HAL_GetTick();
736 uint8_t counterPressure100msec = 0;
737 uint8_t counterCompass100msec = 0;
738 uint8_t counterAmbientLight100msec = 0;
739 uint16_t counterWireless1msec = 0;
740 global.dataSendToMaster.mode = MODE_SURFACE;
741 global.deviceDataSendToMaster.mode = MODE_SURFACE;
742
743 while(global.mode == MODE_SURFACE)
744 {
745 printf("surface...\n");
746
747 schedule_check_resync();
748 lasttick = HAL_GetTick();
749 ticksdiff = time_elapsed_ms(tickstart,lasttick);
750
751 if(ticksdiff > counterWireless1msec)
752 {
753 counterWireless1msec++;
754 changeAgeWirelessData();
755 global.wirelessReceived = wireless_evaluate(global.wirelessdata,MAX_WIRELESS_BYTES, &global.wirelessConfidenceStatus);
756 if((global.wirelessReceived > 0) && !wireless_evaluate_crc_error(global.wirelessdata,global.wirelessReceived))
757 {
758 copyWirelessData();
759 }
760 }
761 if(setButtonsNow == 1)
762 {
763 if(scheduleSetButtonResponsiveness())
764 setButtonsNow = 0;
765 }
766
767 //Evaluate pressure at 20 ms, 120 ms, 220 ms,...
768 if(ticksdiff >= counterPressure100msec * 100 + 20)
769 {
770 global.check_sync_not_running++;
771 pressure_update();
772 scheduleUpdateDeviceData();
773 global.lifeData.ascent_rate_meter_per_min = 0;
774 copyPressureData();
775 counterPressure100msec++;
776
777 if(scheduleCheck_pressure_reached_dive_mode_level())
778 global.mode = MODE_DIVE;
779 }
780
781 //evaluate compass data at 50 ms, 150 ms, 250 ms,...
782
783 if(ticksdiff >= counterCompass100msec * 100 + 50)
784 {
785 compass_read();
786 acceleration_read();
787 compass_calc();
788 copyCompassData();
789 counterCompass100msec++;
790 }
791
792 //evaluate compass data at 70 ms, 170 ms, 270 ms,...
793 if(ticksdiff >= counterAmbientLight100msec * 100 + 70)
794 {
795 adc_ambient_light_sensor_get_data();
796 copyAmbientLightData();
797 counterAmbientLight100msec++;
798 }
799 //Evaluate tissues, toxic data, etc. once a second
800 if(ticksdiff >= 1000)
801 {
802 if(clearDecoNow)
803 {
804 decom_reset_with_1000mbar(&global.lifeData); ///< this should almost reset desaturation time
805 // new 160215 hw
806 global.repetitive_dive = 0;
807 global.seconds_since_last_dive = 0; ///< this will reset OTU and CNS as well
808 global.no_fly_time_minutes = 0;
809 global.accidentFlag = 0;
810 global.accidentRemainingSeconds = 0;
811 vpm_init(&global.vpm, global.conservatism, global.repetitive_dive, global.seconds_since_last_dive);
812 clearDecoNow = 0;
813 }
814
815 //Set back tick counter
816 tickstart = HAL_GetTick();
817
818
819 if(global.seconds_since_last_dive)
820 {
821 schedule_update_timer_helper(-1);
822 // global.seconds_since_last_dive++;
823 // if(global.seconds_since_last_dive > 777900) // a bit more than nine days [seconds]
824 // global.seconds_since_last_dive = 0;
825 }
826
827 if(global.accidentRemainingSeconds)
828 {
829 global.accidentRemainingSeconds--;
830 if(!global.accidentRemainingSeconds)
831 global.accidentFlag = 0;
832 }
833 global.dataSendToMaster.accidentFlags = global.accidentFlag;
834
835 update_surface_pressure(1);
836 scheduleUpdateLifeData(0);
837 decom_oxygen_calculate_otu_degrade(&global.lifeData.otu, global.seconds_since_last_dive);
838 decom_oxygen_calculate_cns_degrade(&global.lifeData.cns, global.seconds_since_last_dive);
839 global.lifeData.desaturation_time_minutes = decom_calc_desaturation_time(global.lifeData.tissue_nitrogen_bar,global.lifeData.tissue_helium_bar,global.lifeData.pressure_surface_bar);
840 battery_charger_get_status_and_contral_battery_gas_gauge(0);
841 battery_gas_gauge_get_data();
842
843 copyCnsAndOtuData();
844 copyTimeData();
845 copyBatteryData();
846 copyDeviceData();
847
848 // new hw 170523
849 if(global.I2C_SystemStatus != HAL_OK)
850 {
851 MX_I2C1_TestAndClear();
852 MX_I2C1_Init();
853 if(!is_init_pressure_done())
854 {
855 init_pressure();
856 }
857 }
858
859 counterCompass100msec = 0;
860 counterPressure100msec = 0;
861 counterAmbientLight100msec = 0;
862 counterWireless1msec = 0;
863 }
864 }
865 }
866
867
868 /**
869 ******************************************************************************
870 * @brief scheduleCompassCalibrationMode
871 * @author heinrichs weikamp gmbh
872 * @version V0.0.1
873 * @since 31-March-2015
874 * @date 31-March-2015
875 ******************************************************************************
876 */
877 void scheduleCompassCalibrationMode(void)
878 {
879 compass_init(1,7); // fast mode, max gain
880 compass_calib(); // duration : 1 minute!
881 compass_init(0,7); // back to normal mode
882
883 if(global.seconds_since_last_dive)
884 {
885 schedule_update_timer_helper(-1);
886 // global.seconds_since_last_dive += 60;
887 // if(global.seconds_since_last_dive > 777900) // a bit more than nine days [seconds]
888 // global.seconds_since_last_dive = 0;
889 }
890
891 scheduleUpdateLifeData(0);
892 global.mode = MODE_SURFACE;
893 }
894
895
896 /**
897 ******************************************************************************
898 * @brief scheduleSleepMode / sleep mode: Main Loop
899 * @author heinrichs weikamp gmbh
900 * @version V0.0.2
901 * @since 31-March-2015
902 * @date 22-April-2014
903 ******************************************************************************
904 */
905
906 void scheduleSleepMode(void)
907 {
908 global.dataSendToMaster.mode = 0;
909 global.deviceDataSendToMaster.mode = 0;
910
911 /* prevent button wake up problem while in sleep_prepare
912 * sleep prepare does I2C_DeInit()
913 */
914 if(global.mode != MODE_SLEEP)
915 MX_I2C1_Init();
916 else
917 do
918 {
919 I2C_DeInit();
920
921 #ifdef DEBUGMODE
922 HAL_Delay(2000);
923 #else
924 RTC_StopMode_2seconds();
925 #endif
926
927
928
929 if(global.mode == MODE_SLEEP)
930 secondsCount += 2;
931
932 MX_I2C1_Init();
933 pressure_sensor_get_pressure_raw();
934
935 if(secondsCount >= 30)
936 {
937 pressure_sensor_get_temperature_raw();
938 battery_gas_gauge_get_data();
939 // ReInit_battery_charger_status_pins();
940 battery_charger_get_status_and_contral_battery_gas_gauge(1);
941 // DeInit_battery_charger_status_pins();
942 secondsCount = 0;
943 }
944
945 pressure_calculation();
946
947 scheduleUpdateDeviceData();
948 update_surface_pressure(2);
949
950 if(global.seconds_since_last_dive)
951 {
952 schedule_update_timer_helper(-1);
953 // global.seconds_since_last_dive += 2;
954 // if(global.seconds_since_last_dive > 777900) // a bit more than nine days [seconds]
955 // global.seconds_since_last_dive = 0;
956 }
957
958 if(global.accidentRemainingSeconds)
959 {
960 if(global.accidentRemainingSeconds > 2)
961 global.accidentRemainingSeconds -= 2;
962 else
963 {
964 global.accidentRemainingSeconds = 0;
965 global.accidentFlag = 0;
966 }
967 }
968
969 if(scheduleCheck_pressure_reached_dive_mode_level())
970 global.mode = MODE_BOOT;
971
972 scheduleUpdateLifeData(2000);
973 }
974 while(global.mode == MODE_SLEEP);
975 /* new section for system after Standby */
976 scheduleUpdateLifeData(-1);
977 clearDecoNow = 0;
978 setButtonsNow = 0;
979 }
980
981
982
983 /* Private functions ---------------------------------------------------------*/
984
985
986 /**
987 ******************************************************************************
988 * @brief scheduleCheck_pressure_reached_dive_mode_level
989 * @author heinrichs weikamp gmbh
990 * @version V0.0.1 from inline code
991 * @date 09-Sept-2015
992 ******************************************************************************
993 */
994 _Bool scheduleCheck_pressure_reached_dive_mode_level(void)
995 {
996 if(get_pressure_mbar() > 1160)
997 return 1;
998 else
999 if((global.mode == MODE_SURFACE) && (get_pressure_mbar() > (get_surface_mbar() + 100)) && (get_surface_mbar() > 880))
1000 return 1;
1001 else
1002 return 0;
1003 }
1004
1005
1006 /**
1007 ******************************************************************************
1008 * @brief scheduleUpdateLifeData / calculates tissues
1009 * @author Peter Ryser
1010 * @version V0.0.1
1011 * @date 22-April-2014
1012 ******************************************************************************
1013 */
1014
1015
1016 void scheduleUpdateLifeData(int32_t asynchron_milliseconds_since_last)
1017 {
1018 static _Bool first = 1;
1019 static uint32_t tickstart = 0;
1020 static uint32_t ticksrest = 0;
1021
1022 uint32_t ticksdiff = 0;
1023 uint32_t ticksnow = 0;
1024 uint32_t time_seconds = 0;
1025 uint8_t whichGasTmp = 0;
1026
1027 if(asynchron_milliseconds_since_last < 0)
1028 {
1029 first = 1;
1030 tickstart = 0;
1031 ticksrest = 0;
1032 return;
1033 }
1034
1035 if(!asynchron_milliseconds_since_last && first)
1036 {
1037 tickstart = HAL_GetTick();
1038 first = 0;
1039 return;
1040 }
1041
1042 whichGasTmp = global.whichGas;
1043 global.lifeData.actualGas = global.aktualGas[whichGasTmp];
1044 global.lifeData.pressure_ambient_bar = get_pressure_mbar() / 1000.0f;
1045 global.lifeData.pressure_surface_bar = get_surface_mbar() / 1000.0f;
1046
1047 if(!asynchron_milliseconds_since_last)
1048 {
1049 ticksnow = HAL_GetTick();
1050 ticksdiff = time_elapsed_ms(tickstart,ticksnow);
1051 }
1052 else
1053 {
1054 first = 1;
1055 ticksdiff = asynchron_milliseconds_since_last;
1056 }
1057
1058 if(ticksrest > 1000) // whatever happens after standby with STM32L476
1059 ticksrest = 0; // maybe move static to SRAM2
1060
1061 ticksdiff += ticksrest;
1062 time_seconds = ticksdiff/ 1000;
1063 ticksrest = ticksdiff - time_seconds * 1000;
1064 tickstart = ticksnow;
1065
1066 decom_tissues_exposure((int)time_seconds, &global.lifeData);
1067 if(global.demo_mode)
1068 decom_tissues_exposure((int)(3*time_seconds), &global.lifeData);
1069 copyTissueData();
1070 }
1071
1072
1073 /**
1074 ******************************************************************************
1075 * @brief scheduleUpdateDeviceData
1076 * @author heinrichs weikamp gmbh
1077 * @version V0.0.1
1078 * @date 16-March-2015
1079 *
1080 * two step process
1081 * first compare with data from main CPU == externalLogbookFlash
1082 * second update with new sensor data
1083 ******************************************************************************
1084 */
1085 void scheduleSetDate(SDeviceLine *line)
1086 {
1087 extern RTC_HandleTypeDef RTCHandle;
1088
1089 line->date_rtc_dr = (uint32_t)(RTCHandle.Instance->DR & RTC_DR_RESERVED_MASK);
1090 line->time_rtc_tr = (uint32_t)(RTCHandle.Instance->TR & RTC_TR_RESERVED_MASK);
1091 }
1092
1093
1094 void scheduleCopyDeviceData(SDeviceLine *lineWrite, const SDeviceLine *lineRead)
1095 {
1096 lineWrite->date_rtc_dr = lineRead->date_rtc_dr;
1097 lineWrite->time_rtc_tr = lineRead->time_rtc_tr;
1098 lineWrite->value_int32 = lineRead->value_int32;
1099 }
1100
1101
1102 void scheduleUpdateDeviceData(void)
1103 {
1104 /* first step, main CPU */
1105
1106 if(deviceDataFlashValid)
1107 {
1108 /* max values */
1109 if(global.deviceData.batteryChargeCompleteCycles.value_int32 < DeviceDataFlash.batteryChargeCompleteCycles.value_int32)
1110 {
1111 scheduleCopyDeviceData(&global.deviceData.batteryChargeCompleteCycles, &DeviceDataFlash.batteryChargeCompleteCycles);
1112 }
1113 if(global.deviceData.batteryChargeCycles.value_int32 < DeviceDataFlash.batteryChargeCycles.value_int32)
1114 {
1115 scheduleCopyDeviceData(&global.deviceData.batteryChargeCycles, &DeviceDataFlash.batteryChargeCycles);
1116 }
1117 if(global.deviceData.temperatureMaximum.value_int32 < DeviceDataFlash.temperatureMaximum.value_int32)
1118 {
1119 scheduleCopyDeviceData(&global.deviceData.temperatureMaximum, &DeviceDataFlash.temperatureMaximum);
1120 }
1121 if(global.deviceData.depthMaximum.value_int32 < DeviceDataFlash.depthMaximum.value_int32)
1122 {
1123 scheduleCopyDeviceData(&global.deviceData.depthMaximum, &DeviceDataFlash.depthMaximum);
1124 }
1125 if(global.deviceData.diveCycles.value_int32 < DeviceDataFlash.diveCycles.value_int32)
1126 {
1127 scheduleCopyDeviceData(&global.deviceData.diveCycles, &DeviceDataFlash.diveCycles);
1128 }
1129 if(global.deviceData.hoursOfOperation.value_int32 < DeviceDataFlash.hoursOfOperation.value_int32)
1130 {
1131 scheduleCopyDeviceData(&global.deviceData.hoursOfOperation, &DeviceDataFlash.hoursOfOperation);
1132 }
1133
1134 /* min values */
1135 if(global.deviceData.temperatureMinimum.value_int32 > DeviceDataFlash.temperatureMinimum.value_int32)
1136 {
1137 scheduleCopyDeviceData(&global.deviceData.temperatureMinimum, &DeviceDataFlash.temperatureMinimum);
1138 }
1139 if(global.deviceData.voltageMinimum.value_int32 > DeviceDataFlash.voltageMinimum.value_int32)
1140 {
1141 scheduleCopyDeviceData(&global.deviceData.voltageMinimum, &DeviceDataFlash.voltageMinimum);
1142 }
1143 }
1144
1145 /* second step, sensor data */
1146 int32_t temperature_centigrad_int32;
1147 int32_t pressure_mbar_int32;
1148 int32_t voltage_mvolt_int32;
1149
1150 temperature_centigrad_int32 = (int32_t)(get_temperature() * 100);
1151 if(temperature_centigrad_int32 < global.deviceData.temperatureMinimum.value_int32)
1152 {
1153 global.deviceData.temperatureMinimum.value_int32 = temperature_centigrad_int32;
1154 scheduleSetDate(&global.deviceData.temperatureMinimum);
1155 }
1156
1157 if(temperature_centigrad_int32 > global.deviceData.temperatureMaximum.value_int32)
1158 {
1159 global.deviceData.temperatureMaximum.value_int32 = temperature_centigrad_int32;
1160 scheduleSetDate(&global.deviceData.temperatureMaximum);
1161 }
1162
1163 pressure_mbar_int32 = (int32_t)get_pressure_mbar();
1164 if(pressure_mbar_int32 > global.deviceData.depthMaximum.value_int32)
1165 {
1166 global.deviceData.depthMaximum.value_int32 = pressure_mbar_int32;
1167 scheduleSetDate(&global.deviceData.depthMaximum);
1168 }
1169
1170 voltage_mvolt_int32 = (int32_t)(get_voltage() * 1000);
1171 if(voltage_mvolt_int32 < global.deviceData.voltageMinimum.value_int32)
1172 {
1173 global.deviceData.voltageMinimum.value_int32 = voltage_mvolt_int32;
1174 scheduleSetDate(&global.deviceData.voltageMinimum);
1175 }
1176
1177 /* third step, counter */
1178 switch (global.mode)
1179 {
1180 case MODE_SURFACE:
1181 case MODE_DIVE:
1182 default:
1183 deviceDataSubSeconds++;
1184 if(deviceDataSubSeconds > 10)
1185 {
1186 deviceDataSubSeconds = 0;
1187 global.deviceData.hoursOfOperation.value_int32++;
1188 }
1189 break;
1190
1191 case MODE_SLEEP:
1192 case MODE_SHUTDOWN:
1193 break;
1194 }
1195 }
1196
1197
1198 void scheduleUpdateDeviceDataChargerFull(void)
1199 {
1200 global.deviceData.batteryChargeCompleteCycles.value_int32++;
1201 scheduleSetDate(&global.deviceData.batteryChargeCompleteCycles);
1202 }
1203
1204
1205 void scheduleUpdateDeviceDataChargerCharging(void)
1206 {
1207 global.deviceData.batteryChargeCycles.value_int32++;
1208 scheduleSetDate(&global.deviceData.batteryChargeCycles);
1209 }
1210
1211
1212 /**
1213 ******************************************************************************
1214 * @brief vpm_crush / calls vpm calc_crushing_pressure every four seconds during descend
1215 * @author Peter Ryser
1216 * @version V0.0.1
1217 * @date 22-April-2014
1218 ******************************************************************************
1219 */
1220 _Bool vpm_crush2(void)
1221 {
1222 int i = 0;
1223 static float starting_ambient_pressure = 0;
1224 static float ending_ambient_pressure = 0;
1225 static float time_calc_begin = -1;
1226 static float initial_helium_pressure[16];
1227 static float initial_nitrogen_pressure[16];
1228 ending_ambient_pressure = global.lifeData.pressure_ambient_bar * 10;
1229
1230 if((global.lifeData.dive_time_seconds <= 4) || (starting_ambient_pressure >= ending_ambient_pressure))
1231 {
1232 time_calc_begin = global.lifeData.dive_time_seconds;
1233 starting_ambient_pressure = global.lifeData.pressure_ambient_bar * 10;
1234 for( i = 0; i < 16; i++)
1235 {
1236 initial_helium_pressure[i] = global.lifeData.tissue_helium_bar[i] * 10;
1237 initial_nitrogen_pressure[i] = global.lifeData.tissue_nitrogen_bar[i] * 10;
1238 }
1239 return 0;
1240 }
1241 if(global.lifeData.dive_time_seconds - time_calc_begin >= 4)
1242 {
1243 if(ending_ambient_pressure > starting_ambient_pressure + 0.5f)
1244 {
1245 float rate = (ending_ambient_pressure - starting_ambient_pressure) * 60 / 4;
1246 calc_crushing_pressure(&global.lifeData, &global.vpm, initial_helium_pressure, initial_nitrogen_pressure, starting_ambient_pressure, rate);
1247
1248 time_calc_begin = global.lifeData.dive_time_seconds;
1249 starting_ambient_pressure = global.lifeData.pressure_ambient_bar * 10;
1250 for( i = 0; i < 16; i++)
1251 {
1252 initial_helium_pressure[i] = global.lifeData.tissue_helium_bar[i] * 10;
1253 initial_nitrogen_pressure[i] = global.lifeData.tissue_nitrogen_bar[i] * 10;
1254 }
1255
1256 return 1;
1257 }
1258
1259 }
1260 return 0;
1261 };
1262
1263
1264 void initStructWithZeero(uint8_t* data, uint16_t length)
1265 {
1266 for(uint16_t i = 0; i < length; i++)
1267 data[i] = 0;
1268 }
1269
1270
1271 long get_nofly_time_minutes(void)
1272 {
1273
1274 if(global.no_fly_time_minutes <= 0)
1275 return 0;
1276
1277 long minutes_since_last_dive = global.seconds_since_last_dive/60;
1278
1279 if((global.seconds_since_last_dive > 0) && (global.no_fly_time_minutes > minutes_since_last_dive))
1280 {
1281 return (global.no_fly_time_minutes - minutes_since_last_dive);
1282 }
1283 else
1284 {
1285 global.no_fly_time_minutes = 0;
1286 return 0;
1287 }
1288 }
1289
1290
1291 //Supports threadsave copying!!!
1292 void copyActualGas(SGas gas)
1293 {
1294 uint8_t whichGas = !global.whichGas;
1295 global.aktualGas[whichGas] = gas;
1296 global.whichGas = whichGas;
1297 }
1298
1299
1300 //Supports threadsave copying!!!
1301 void copyPressureData(void)
1302 {
1303 global.dataSendToMaster.sensorErrors = I2C1_Status();
1304 //uint8_t dataSendToMaster.
1305 uint8_t boolPressureData = !global.dataSendToMaster.boolPressureData;
1306 global.dataSendToMaster.data[boolPressureData].temperature = get_temperature();
1307 global.dataSendToMaster.data[boolPressureData].pressure_mbar = get_pressure_mbar();
1308 global.dataSendToMaster.data[boolPressureData].surface_mbar = get_surface_mbar();
1309 global.dataSendToMaster.data[boolPressureData].ascent_rate_meter_per_min = global.lifeData.ascent_rate_meter_per_min;
1310 global.dataSendToMaster.data[boolPressureData].pressure_uTick = HAL_GetTick();
1311 global.dataSendToMaster.boolPressureData = boolPressureData;
1312 }
1313
1314
1315 //Supports threadsave copying!!!
1316 void copyCnsAndOtuData(void)
1317 {
1318 //uint8_t dataSendToMaster.
1319 uint8_t boolToxicData = !global.dataSendToMaster.boolToxicData;
1320 global.dataSendToMaster.data[boolToxicData].cns = global.lifeData.cns;
1321 global.dataSendToMaster.data[boolToxicData].otu = global.lifeData.otu;
1322 global.dataSendToMaster.data[boolToxicData].desaturation_time_minutes = global.lifeData.desaturation_time_minutes;
1323 global.dataSendToMaster.data[boolToxicData].no_fly_time_minutes = get_nofly_time_minutes();
1324 global.dataSendToMaster.boolToxicData = boolToxicData;
1325 }
1326
1327
1328 //Supports threadsave copying!!!
1329 void copyTimeData(void)
1330 {
1331 extern RTC_HandleTypeDef RTCHandle;
1332
1333 uint8_t boolTimeData = !global.dataSendToMaster.boolTimeData;
1334 global.dataSendToMaster.data[boolTimeData].localtime_rtc_tr = (uint32_t)(RTCHandle.Instance->TR & RTC_TR_RESERVED_MASK);
1335 global.dataSendToMaster.data[boolTimeData].localtime_rtc_dr = (uint32_t)(RTCHandle.Instance->DR & RTC_DR_RESERVED_MASK);
1336 global.dataSendToMaster.data[boolTimeData].divetime_seconds = (uint32_t)global.lifeData.dive_time_seconds;
1337 global.dataSendToMaster.data[boolTimeData].dive_time_seconds_without_surface_time = (uint32_t)global.lifeData.dive_time_seconds_without_surface_time;
1338 global.dataSendToMaster.data[boolTimeData].surfacetime_seconds = (uint32_t)global.seconds_since_last_dive;
1339 global.dataSendToMaster.data[boolTimeData].counterSecondsShallowDepth = (uint32_t)global.lifeData.counterSecondsShallowDepth;
1340 global.dataSendToMaster.boolTimeData = boolTimeData;
1341 }
1342
1343
1344 //Supports threadsave copying!!!
1345 void copyCompassData(void)
1346 {
1347 extern float compass_heading;
1348 extern float compass_roll;
1349 extern float compass_pitch;
1350 //uint8_t dataSendToMaster.
1351 uint8_t boolCompassData = !global.dataSendToMaster.boolCompassData;
1352 global.dataSendToMaster.data[boolCompassData].compass_heading = compass_heading;
1353 global.dataSendToMaster.data[boolCompassData].compass_roll = compass_roll;
1354 global.dataSendToMaster.data[boolCompassData].compass_pitch = compass_pitch;
1355 global.dataSendToMaster.data[boolCompassData].compass_DX_f = 0;
1356 global.dataSendToMaster.data[boolCompassData].compass_DY_f = 0;
1357 global.dataSendToMaster.data[boolCompassData].compass_DZ_f = 0;
1358 global.dataSendToMaster.data[boolCompassData].compass_uTick = HAL_GetTick();
1359 global.dataSendToMaster.boolCompassData = boolCompassData;
1360 }
1361
1362
1363 void copyCompassDataDuringCalibration(int16_t dx, int16_t dy, int16_t dz)
1364 {
1365 extern float compass_heading;
1366 extern float compass_roll;
1367 extern float compass_pitch;
1368 //uint8_t dataSendToMaster.
1369 uint8_t boolCompassData = !global.dataSendToMaster.boolCompassData;
1370 global.dataSendToMaster.data[boolCompassData].compass_heading = compass_heading;
1371 global.dataSendToMaster.data[boolCompassData].compass_roll = compass_roll;
1372 global.dataSendToMaster.data[boolCompassData].compass_pitch = compass_pitch;
1373 global.dataSendToMaster.data[boolCompassData].compass_DX_f = dx;
1374 global.dataSendToMaster.data[boolCompassData].compass_DY_f = dy;
1375 global.dataSendToMaster.data[boolCompassData].compass_DZ_f = dz;
1376 global.dataSendToMaster.boolCompassData = boolCompassData;
1377 }
1378
1379
1380 //Supports threadsave copying!!!
1381 void copyBatteryData(void)
1382 {
1383 uint8_t boolBatteryData = !global.dataSendToMaster.boolBatteryData;
1384 global.dataSendToMaster.data[boolBatteryData].battery_voltage = get_voltage();
1385 global.dataSendToMaster.data[boolBatteryData].battery_charge= get_charge();
1386 global.dataSendToMaster.boolBatteryData = boolBatteryData;
1387 }
1388
1389
1390 //Supports threadsave copying!!!
1391 void copyAmbientLightData(void)
1392 {
1393 uint8_t boolAmbientLightData = !global.dataSendToMaster.boolAmbientLightData;
1394 global.dataSendToMaster.data[boolAmbientLightData].ambient_light_level = get_ambient_light_level();
1395 global.dataSendToMaster.boolAmbientLightData = boolAmbientLightData;
1396 }
1397
1398
1399 //Supports threadsave copying!!!
1400 void copyTissueData(void)
1401 {
1402 //uint8_t dataSendToMaster.
1403 uint8_t boolTisssueData = !global.dataSendToMaster.boolTisssueData;
1404 for(int i = 0; i < 16; i++)
1405 {
1406 global.dataSendToMaster.data[boolTisssueData].tissue_nitrogen_bar[i] = global.lifeData.tissue_nitrogen_bar[i];
1407 global.dataSendToMaster.data[boolTisssueData].tissue_helium_bar[i] = global.lifeData.tissue_helium_bar[i];
1408 }
1409 global.dataSendToMaster.boolTisssueData = boolTisssueData;
1410 }
1411
1412
1413 //Supports threadsave copying!!!
1414 void copyVpmCrushingData(void)
1415 {
1416 //uint8_t dataSendToMaster.
1417 uint8_t boolCrushingData = !global.dataSendToMaster.boolCrushingData;
1418 for(int i = 0; i < 16; i++)
1419 {
1420 global.dataSendToMaster.data[boolCrushingData].max_crushing_pressure_n2[i] = global.vpm.max_crushing_pressure_n2[i];
1421 global.dataSendToMaster.data[boolCrushingData].max_crushing_pressure_he[i] = global.vpm.max_crushing_pressure_he[i];
1422 global.dataSendToMaster.data[boolCrushingData].adjusted_critical_radius_he[i] = global.vpm.adjusted_critical_radius_he[i];
1423 global.dataSendToMaster.data[boolCrushingData].adjusted_critical_radius_n2[i] = global.vpm.adjusted_critical_radius_n2[i];
1424 }
1425 global.dataSendToMaster.boolCrushingData = boolCrushingData;
1426 }
1427
1428
1429 void copyDeviceData(void)
1430 {
1431 uint8_t boolDeviceData = !global.deviceDataSendToMaster.boolDeviceData;
1432 memcpy(&global.deviceDataSendToMaster.DeviceData[boolDeviceData], &global.deviceData,sizeof(SDevice));
1433 global.deviceDataSendToMaster.boolDeviceData = boolDeviceData;
1434
1435 global.deviceDataSendToMaster.boolVpmRepetitiveDataValid = 0;
1436 memcpy(&global.deviceDataSendToMaster.VpmRepetitiveData.adjusted_critical_radius_he, &global.vpm.adjusted_critical_radius_he, sizeof(16*4));
1437 memcpy(&global.deviceDataSendToMaster.VpmRepetitiveData.adjusted_critical_radius_n2, &global.vpm.adjusted_critical_radius_n2, sizeof(16*4));
1438 memcpy(&global.deviceDataSendToMaster.VpmRepetitiveData.adjusted_crushing_pressure_he, &global.vpm.adjusted_crushing_pressure_he, sizeof(16*4));
1439 memcpy(&global.deviceDataSendToMaster.VpmRepetitiveData.adjusted_crushing_pressure_n2, &global.vpm.adjusted_crushing_pressure_n2, sizeof(16*4));
1440 memcpy(&global.deviceDataSendToMaster.VpmRepetitiveData.initial_allowable_gradient_he, &global.vpm.initial_allowable_gradient_he, sizeof(16*4));
1441 memcpy(&global.deviceDataSendToMaster.VpmRepetitiveData.initial_allowable_gradient_n2, &global.vpm.initial_allowable_gradient_n2, sizeof(16*4));
1442 memcpy(&global.deviceDataSendToMaster.VpmRepetitiveData.max_actual_gradient, &global.vpm.max_actual_gradient, sizeof(16*4));
1443 global.deviceDataSendToMaster.VpmRepetitiveData.repetitive_variables_not_valid = global.vpm.repetitive_variables_not_valid;
1444 global.deviceDataSendToMaster.boolVpmRepetitiveDataValid = 1;
1445 }
1446
1447 void changeAgeWirelessData(void)
1448 {
1449 for(int i=0;i<4;i++)
1450 {
1451 if(global.dataSendToMaster.data[global.dataSendToMaster.boolWirelessData].wireless_data[i].ageInMilliSeconds)
1452 global.dataSendToMaster.data[global.dataSendToMaster.boolWirelessData].wireless_data[i].ageInMilliSeconds++;
1453 }
1454 }
1455
1456 void copyWirelessData(void)
1457 {
1458 uint8_t boolWirelessData = !global.dataSendToMaster.boolWirelessData;
1459 SDataWireless *dataOld, *dataNew;
1460 for(int i=0;i<3;i++)
1461 {
1462 dataNew = &global.dataSendToMaster.data[boolWirelessData].wireless_data[i+1];
1463 dataOld = &global.dataSendToMaster.data[!boolWirelessData].wireless_data[i];
1464 dataNew->ageInMilliSeconds = dataOld->ageInMilliSeconds;
1465 dataNew->numberOfBytes = dataOld->numberOfBytes;
1466 dataNew->status = dataOld->status;
1467 memcpy(dataNew->data, dataOld->data,8);
1468 }
1469
1470 global.dataSendToMaster.data[boolWirelessData].wireless_data[0].ageInMilliSeconds = 1;
1471 global.dataSendToMaster.data[boolWirelessData].wireless_data[0].numberOfBytes = global.wirelessReceived;
1472 global.dataSendToMaster.data[boolWirelessData].wireless_data[0].status = global.wirelessConfidenceStatus;
1473 for(int i=0;i<MAX_WIRELESS_BYTES;i++)
1474 global.dataSendToMaster.data[boolWirelessData].wireless_data[0].data[i] = global.wirelessdata[i];
1475 for(int i=MAX_WIRELESS_BYTES;i<12;i++)
1476 global.dataSendToMaster.data[boolWirelessData].wireless_data[0].data[i] = 0xFF;
1477
1478 global.dataSendToMaster.boolWirelessData = boolWirelessData;
1479 }
1480
1481 /* copyPICdata(); is used in spi.c */
1482 void copyPICdata(void)
1483 {
1484 uint8_t boolPICdata = !global.dataSendToMaster.boolPICdata;
1485 for(int i = 0; i < 3; i++)
1486 {
1487 global.dataSendToMaster.data[boolPICdata].button_setting[i] = global.ButtonPICdata[i];
1488 }
1489 global.dataSendToMaster.boolPICdata = boolPICdata;
1490 }
1491
1492
1493
1494
1495 typedef enum
1496 {
1497 SPI3_OK = 0x00,
1498 SPI3_DEINIT = 0x01,
1499 } SPI3_StatusTypeDef;
1500 /* if spi3 is running and the SPI3_ButtonAdjust call returns OK, all is fine
1501 if the SPI3_ButtonAdjust call returns error, the spi3 is DeInit
1502 and will be init the next call of scheduleSetButtonResponsiveness()
1503 and data will be send again on the third call
1504 therefore on return 0 of scheduleSetButtonResponsiveness() the caller flag should kept active
1505 */
1506 uint8_t scheduleSetButtonResponsiveness(void)
1507 {
1508 static uint8_t SPI3status = SPI3_OK;
1509
1510 if((SPI3status == SPI3_OK) && (SPI3_ButtonAdjust(global.ButtonResponsiveness, global.ButtonPICdata)))
1511 {
1512 copyPICdata();
1513 return 1;
1514 }
1515 else
1516 {
1517 for(int i=0;i<3;i++)
1518 {
1519 global.ButtonPICdata[i] = 0xFF;
1520 }
1521 copyPICdata();
1522
1523 if(SPI3status == SPI3_OK)
1524 {
1525 MX_SPI3_DeInit();
1526 SPI3status = SPI3_DEINIT;
1527 }
1528 else
1529 {
1530 MX_SPI3_Init();
1531 SPI3status = SPI3_OK;
1532 }
1533 return 0;
1534 }
1535 }
1536
1537
1538 //save time diffenrence
1539 uint32_t time_elapsed_ms(uint32_t ticksstart,uint32_t ticksnow)
1540 {
1541 if(ticksstart <= ticksnow)
1542 {
1543 return ticksnow - ticksstart;
1544 }
1545 else
1546 {
1547 return 0xFFFFFFFF - ticksstart + ticksnow;
1548 }
1549 }
1550
1551 /* same as in data_central.c */
1552 _Bool is_ambient_pressure_close_to_surface(SLifeData *lifeDataCall)
1553 {
1554 if(lifeDataCall->pressure_ambient_bar < (lifeDataCall->pressure_surface_bar + 0.1f)) // hw 161121 now 1 mter, before 0.04f
1555 return true;
1556 else
1557 return false;
1558 }
1559
1560
1561 /************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/
1562