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

include in ostc4 repository
author heinrichsweikamp
date Sat, 28 Apr 2018 11:52:34 +0200
parents
children 8f8ea3a32e82
comparison
equal deleted inserted replaced
37:ccc45c0e1ea2 38:5f11787b4f42
1 /**
2 ******************************************************************************
3 * @file data_exchange_main.c
4 * @author heinrichs weikamp gmbh
5 * @date 13-Oct-2014
6 * @version V0.0.3
7 * @since 17-Feb-2016
8
9 * @brief Communication with the second CPU == RTE system
10 *
11 @verbatim
12 ==============================================================================
13 ##### Version Changes #####
14 ==============================================================================
15 160217 V0.0.3 pStateUsed->decolistXXXXX.tickstamp = HAL_GetTick(); added
16 150627 V0.0.2
17
18 ==============================================================================
19 ##### How to use #####
20 ==============================================================================
21
22 ==============================================================================
23 ##### Button, Set Time, Clear Deco etc Request #####
24 ==============================================================================
25 was updated (151207) for buttons and clear deco at the moment only
26 using requestNecessary and checking in DataEX_copy_to_LifeData()
27 Hence if there is no confirm from the smallCPU on the data after the request
28 the request will be send again.
29
30 ==============================================================================
31 ##### Device Data #####
32 ==============================================================================
33
34 main CPU always sends the device data info that it has at the moment
35
36 on start it is INT32_MIN, INT32_MAX and 0
37 as initialized in data_central.c variable declaration
38
39 second small CPU gets request to send its device data
40
41 on receiption the data is merged with the data in externLogbookFlash,
42 stored on the externLogbookFlash and from now on send to small CPU
43
44 ==============================================================================
45 ##### Magnet Reset #####
46 ==============================================================================
47
48 @endverbatim
49 ******************************************************************************
50 * @attention
51 *
52 * <h2><center>&copy; COPYRIGHT(c) 2014 heinrichs weikamp</center></h2>
53 *
54 ******************************************************************************
55 */
56
57 /* Includes ------------------------------------------------------------------*/
58 #include <string.h> // for memcopy
59 #include "stm32f4xx_hal.h"
60 #include "stdio.h"
61 #include "ostc.h"
62 #include "settings.h"
63 #include "data_central.h"
64 #include "data_exchange_main.h"
65 #include "base.h"
66 #include "decom.h"
67 #include "calc_crush.h" /* for vpm_init */
68 #include "simulation.h"
69 #include "tCCR.h"
70 #include "timer.h"
71 #include "buehlmann.h"
72 #include "externLogbookFlash.h"
73 #include "bonex_mini.h" // for voltage to battery percentage
74
75
76 /* Expoted variables --------------------------------------------------------*/
77 uint8_t wasPowerOn = 0;
78 confirmbit8_Type requestNecessary = { .uw = 0 };
79 uint8_t wasUpdateNotPowerOn = 0;
80 uint8_t scooterFoundThisPowerOnCylce = 0;
81
82 /* Private variables with external access ------------------------------------*/
83
84
85 /* Private variables ---------------------------------------------------------*/
86 uint8_t told_reset_logik_alles_ok = 0;
87
88 SDataReceiveFromMaster dataOut;
89 SDataExchangeSlaveToMaster dataIn;
90
91 uint32_t systick_last;
92 uint8_t data_old__lost_connection_to_slave_counter_temp = 0;
93 uint8_t data_old__lost_connection_to_slave_counter_retry = 0;
94 uint32_t data_old__lost_connection_to_slave_counter_total = 0;
95
96 /* Private types -------------------------------------------------------------*/
97
98 typedef enum
99 {
100 CPU2_TRANSFER_STOP = 0x00, /*!< */
101 CPU2_TRANSFER_TEST_REQUEST = 0x01, /*!< */
102 CPU2_TRANSFER_TEST_RECEIVE = 0x02, /*!< */
103 CPU2_TRANSFER_SEND_OK = 0x03, /*!< */
104 CPU2_TRANSFER_SEND_FALSE = 0x04, /*!< */
105 CPU2_TRANSFER_DATA = 0x05, /*!< */
106 }CPU2_TRANSFER_StatusTypeDef;
107
108 const uint8_t header_test_request[4] = {0xBB, 0x00, 0x00, 0xBB};
109 const uint8_t header_test_receive[4] = {0xBB, 0x01, 0x01, 0xBB};
110 const uint8_t header_false[4] = {0xBB, 0xFF, 0xFF, 0xBB};
111 const uint8_t header_correct[4] = {0xBB, 0xCC, 0xCC, 0xBB};
112 const uint8_t header_data[4] = {0xAA, 0x01, 0x01, 0xAA};
113
114 /* Private function prototypes -----------------------------------------------*/
115 uint8_t DataEX_check_header_and_footer_ok(void);
116 uint8_t DataEX_check_header_and_footer_devicedata(void);
117 void DataEX_check_DeviceData(void);
118
119 /* Exported functions --------------------------------------------------------*/
120 void DataEX_set_update_RTE_not_power_on(void)
121 {
122 wasUpdateNotPowerOn = 1;
123 }
124
125
126 uint8_t DataEX_was_power_on(void)
127 {
128 return wasPowerOn;
129 }
130
131 uint8_t count_DataEX_Error_Handler = 0;
132 uint8_t last_error_DataEX_Error_Handler = 0;
133
134 void DataEX_Error_Handler(uint8_t answer)
135 {
136 count_DataEX_Error_Handler++;
137 last_error_DataEX_Error_Handler = answer;
138 return;
139 }
140
141
142 uint32_t DataEX_lost_connection_count(void)
143 {
144 return data_old__lost_connection_to_slave_counter_total;
145 }
146
147
148 uint32_t DataEX_time_elapsed_ms(uint32_t ticksstart,uint32_t ticksnow)
149 {
150
151 if(ticksstart <= ticksnow)
152 {
153 return ticksnow - ticksstart;
154 }
155 else
156 {
157 return 0xFFFFFFFF - ticksstart + ticksnow;
158 }
159
160 }
161
162 SDataReceiveFromMaster * dataOutGetPointer(void)
163 {
164 return &dataOut;
165 }
166
167 void DataEX_init(void)
168 {
169 SDiveState * pStateReal = stateRealGetPointerWrite();
170 pStateReal->data_old__lost_connection_to_slave = 1;
171 data_old__lost_connection_to_slave_counter_temp = 0;
172 data_old__lost_connection_to_slave_counter_total = 0;
173
174 memset((void *)&dataOut, 0, sizeof(SDataReceiveFromMaster));
175 // old 160307: for(int i=0;i<EXCHANGE_BUFFERSIZE;i++)
176 // *(uint8_t *)(((uint32_t)&dataOut) + i) = 0;
177
178 dataOut.header.checkCode[0] = 0xBB;
179 dataOut.header.checkCode[1] = 0x01;
180 dataOut.header.checkCode[2] = 0x01;
181 dataOut.header.checkCode[3] = 0xBB;
182
183 dataOut.footer.checkCode[0] = 0xF4;
184 dataOut.footer.checkCode[1] = 0xF3;
185 dataOut.footer.checkCode[2] = 0xF2;
186 dataOut.footer.checkCode[3] = 0xF1;
187
188
189 pStateReal->lifeData.scooterType = 0xFF;
190 pStateReal->lifeData.scooterWattstunden = 0;
191 pStateReal->lifeData.scooterRestkapazitaet = 0;
192 pStateReal->lifeData.scooterDrehzahl = 0;
193 pStateReal->lifeData.scooterSpannung = 0;
194 pStateReal->lifeData.scooterTemperature = 0;
195 pStateReal->lifeData.scooterAmpere = 0;
196 pStateReal->lifeData.scooterRestkapazitaetWhBased = 0;
197 pStateReal->lifeData.scooterRestkapazitaetVoltageBased = 0;
198 pStateReal->lifeData.scooterAgeInMilliSeconds = 0;
199
200 systick_last = HAL_GetTick() - 100;
201 }
202
203
204 void DataEx_call_helper_requests(void)
205 {
206 static uint8_t setDateWasSend = 0;
207 static uint8_t setTimeWasSend = 0;
208 static uint8_t calibrateCompassWasSend = 0;
209 static uint8_t setButtonSensitivityWasSend = 0;
210 static uint8_t clearDecoWasSend = 0;
211 static uint8_t getDeviceDataWasSend = 0;
212 static uint8_t setAccidentFlagWasSend = 0;
213 static uint8_t setEndDiveWasSend = 0;
214
215 if(getDeviceDataWasSend)
216 {
217 dataOut.getDeviceDataNow = 0;
218 requestNecessary.ub.devicedata = 1;
219 }
220 getDeviceDataWasSend = 0;
221 if(dataOut.getDeviceDataNow)
222 {
223 getDeviceDataWasSend = 1;
224 }
225
226 if(setEndDiveWasSend)
227 {
228 dataOut.setEndDive = 0;
229 //requestNecessary.ub.XXX = 1; not implemented and no space here
230 }
231 setEndDiveWasSend = 0;
232 if(dataOut.setEndDive)
233 {
234 setEndDiveWasSend = 1;
235 }
236
237 if(setAccidentFlagWasSend)
238 {
239 dataOut.setAccidentFlag = 0;
240 requestNecessary.ub.accident = 1;
241 }
242 setAccidentFlagWasSend = 0;
243 if(dataOut.setAccidentFlag)
244 {
245 setAccidentFlagWasSend = 1;
246 }
247
248 if(setDateWasSend)
249 {
250 dataOut.setDateNow = 0;
251 requestNecessary.ub.date = 1;
252 }
253 setDateWasSend = 0;
254 if(dataOut.setDateNow)
255 {
256 setDateWasSend = 1;
257 }
258
259 if(setTimeWasSend)
260 {
261 dataOut.setTimeNow = 0;
262 requestNecessary.ub.time = 1;
263 }
264 setTimeWasSend = 0;
265 if(dataOut.setTimeNow)
266 {
267 setTimeWasSend = 1;
268 }
269
270 if(calibrateCompassWasSend)
271 {
272 dataOut.calibrateCompassNow = 0;
273 requestNecessary.ub.compass = 1;
274 }
275 calibrateCompassWasSend = 0;
276 if(dataOut.calibrateCompassNow)
277 {
278 calibrateCompassWasSend = 1;
279 }
280
281 if(clearDecoWasSend)
282 {
283 dataOut.clearDecoNow = 0;
284 requestNecessary.ub.clearDeco = 1;
285 }
286 if(dataOut.clearDecoNow)
287 {
288 clearDecoWasSend = 1;
289 }
290
291 if(setButtonSensitivityWasSend)
292 {
293 dataOut.setButtonSensitivityNow = 0;
294 requestNecessary.ub.button = 1;
295 }
296 setButtonSensitivityWasSend = 0;
297 if(dataOut.setButtonSensitivityNow)
298 {
299 setButtonSensitivityWasSend = 1;
300 }
301 }
302
303
304 uint8_t DataEX_call(void)
305 {
306 uint8_t SPI_DMA_answer = 0;
307
308 HAL_GPIO_WritePin(SMALLCPU_CSB_GPIO_PORT,SMALLCPU_CSB_PIN,GPIO_PIN_SET);
309 delayMicros(10);
310
311 /* one cycle with NotChipSelect true to clear slave spi buffer */
312
313 if(data_old__lost_connection_to_slave_counter_temp >= 3)
314 {
315 data_old__lost_connection_to_slave_counter_temp = 0;
316 data_old__lost_connection_to_slave_counter_retry++;
317 }
318 else
319 {
320 HAL_GPIO_WritePin(SMALLCPU_CSB_GPIO_PORT,SMALLCPU_CSB_PIN,GPIO_PIN_RESET);
321 }
322
323 DataEx_call_helper_requests();
324
325 systick_last = HAL_GetTick();
326
327 //HAL_GPIO_WritePin(OSCILLOSCOPE2_GPIO_PORT,OSCILLOSCOPE2_PIN,GPIO_PIN_RESET); /* only for testing with Oscilloscope */
328
329 SPI_DMA_answer = HAL_SPI_TransmitReceive_DMA(&cpu2DmaSpi, (uint8_t *)&dataOut, (uint8_t *)&dataIn, EXCHANGE_BUFFERSIZE+1);
330 if(SPI_DMA_answer != HAL_OK)
331 DataEX_Error_Handler(SPI_DMA_answer);
332 //HAL_Delay(3);
333 //HAL_GPIO_WritePin(OSCILLOSCOPE2_GPIO_PORT,OSCILLOSCOPE2_PIN,GPIO_PIN_SET); /* only for testing with Oscilloscope */
334
335 return 1;
336 }
337
338 void DateEx_copy_to_dataOut(void)
339 {
340 const SDiveState * pStateReal = stateRealGetPointer();
341 SSettings *settings = settingsGetPointer();
342
343 if(get_globalState() == StStop)
344 dataOut.mode = MODE_SHUTDOWN;
345 else
346 dataOut.mode = 0;
347
348 dataOut.diveModeInfo = pStateReal->diveSettings.diveMode; // hw 170215
349
350 memcpy(&dataOut.data.DeviceData, stateDeviceGetPointer(), sizeof(SDevice));
351
352 dataOut.data.VPMconservatism = pStateReal->diveSettings.vpm_conservatism;
353 dataOut.data.actualGas = pStateReal->lifeData.actualGas;
354 dataOut.data.ambient_pressure_mbar_ceiling = (pStateReal->decolistBuehlmann.output_ceiling_meter * 100) + (pStateReal->lifeData.pressure_surface_bar * 1000);
355 dataOut.data.divetimeToCreateLogbook = settings->divetimeToCreateLogbook;
356 dataOut.data.timeoutDiveReachedZeroDepth = settings->timeoutDiveReachedZeroDepth;
357
358 dataOut.data.offsetPressureSensor_mbar = settings->offsetPressure_mbar;
359 dataOut.data.offsetTemperatureSensor_centiDegree = settings->offsetTemperature_centigrad;
360
361 if((hardwareDataGetPointer()->primarySerial <= 32) || (((hardwareDataGetPointer()->primarySerial == 72) && (hardwareDataGetPointer()->secondarySerial == 15))))
362 {
363 dataOut.revisionHardware = 0x00;
364 dataOut.revisionCRCx0x7A = 0x7A;
365 }
366 else
367 if(hardwareDataGetPointer()->primarySerial < 0xFFFF)
368 {
369 dataOut.revisionHardware = hardwareDataGetPointer()->revision8bit;
370 dataOut.revisionCRCx0x7A = hardwareDataGetPointer()->revision8bit ^ 0x7A;
371 }
372 else
373 {
374 dataOut.revisionHardware = 0xFF;
375 dataOut.revisionCRCx0x7A = 0xFF;
376 }
377
378 /*
379 for(int i = 0; i< 16; i++)
380 {
381 dataOut.data.VPM_adjusted_critical_radius_he[i] = pStateReal->vpm.adjusted_critical_radius_he[i];
382 dataOut.data.VPM_adjusted_critical_radius_n2[i] = pStateReal->vpm.adjusted_critical_radius_n2[i];
383 dataOut.data.VPM_adjusted_crushing_pressure_he[i] = pStateReal->vpm.adjusted_crushing_pressure_he[i];
384 dataOut.data.VPM_adjusted_crushing_pressure_n2[i] = pStateReal->vpm.adjusted_crushing_pressure_n2[i];
385 dataOut.data.VPM_initial_allowable_gradient_he[i] = pStateReal->vpm.initial_allowable_gradient_he[i];
386 dataOut.data.VPM_initial_allowable_gradient_n2[i] = pStateReal->vpm.initial_allowable_gradient_n2[i];
387 dataOut.data.VPM_max_actual_gradient[i] = pStateReal->vpm.max_actual_gradient[i];
388 }
389 */
390
391 if(DataEX_check_header_and_footer_ok() && !told_reset_logik_alles_ok)
392 {
393 MX_tell_reset_logik_alles_ok();
394 told_reset_logik_alles_ok = 1;
395 }
396
397 if(DataEX_check_header_and_footer_ok() && (dataIn.power_on_reset == 1))
398 {
399 if(!wasUpdateNotPowerOn)
400 wasPowerOn = 1;
401
402 RTC_DateTypeDef Sdate;
403 RTC_TimeTypeDef Stime;
404
405 translateDate(settings->backup_localtime_rtc_dr, &Sdate);
406 translateTime(settings->backup_localtime_rtc_tr, &Stime);
407
408 dataOut.data.newTime = Stime;
409 dataOut.setTimeNow = 1;
410 dataOut.data.newDate = Sdate;
411 dataOut.setDateNow = 1;
412
413 settingsHelperButtonSens_keepPercentageValues(settingsGetPointerStandard()->ButtonResponsiveness[3], settings->ButtonResponsiveness);
414 setButtonResponsiveness(settings->ButtonResponsiveness);
415
416 // hw 160720 new lastKnownBatteryPercentage
417 if(!wasUpdateNotPowerOn)
418 {
419 // dataOut.data.newBatteryGaugePercentageFloat = settingsGetPointer()->lastKnownBatteryPercentage;
420 dataOut.data.newBatteryGaugePercentageFloat = 0;
421 dataOut.setBatteryGaugeNow = 1;
422 }
423 }
424 }
425
426
427 void DataEX_copy_to_deco(void)
428 {
429 SDiveState * pStateUsed;
430 if(decoLock == DECO_CALC_running)
431 return;
432 if(stateUsed == stateRealGetPointer())
433 pStateUsed = stateRealGetPointerWrite();
434 else
435 pStateUsed = stateSimGetPointerWrite();
436
437
438 if(decoLock == DECO_CALC_init_as_is_start_of_dive)
439 {
440 vpm_init(&pStateUsed->vpm, pStateUsed->diveSettings.vpm_conservatism, 0, 0);
441 buehlmann_init();
442 timer_init();
443 resetEvents();
444 pStateUsed->diveSettings.internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero = 0;
445 /*
446 * ToDo by Peter
447 * copy VPM stuff etc. pp.
448 * was void initDiveState(SDiveSettings * pDiveSettings, SVpm * pVpm);
449 */
450 }
451
452
453
454 if(decoLock == DECO_CALC_FINSHED_Buehlmann)
455 {
456
457 }
458 switch(decoLock)
459 {
460
461 //Deco_calculation finished
462 case DECO_CALC_FINSHED_vpm:
463 memcpy(&pStateUsed->decolistVPM,&stateDeco.decolistVPM,sizeof(SDecoinfo));
464 pStateUsed->decolistVPM.tickstamp = HAL_GetTick();
465 pStateUsed->vpm.deco_zone_reached = stateDeco.vpm.deco_zone_reached;
466 for(int i = 0; i< 16; i++)
467 {
468 pStateUsed->vpm.adjusted_critical_radius_he[i] = stateDeco.vpm.adjusted_critical_radius_he[i];
469 pStateUsed->vpm.adjusted_critical_radius_n2[i] = stateDeco.vpm.adjusted_critical_radius_n2[i];
470 pStateUsed->vpm.adjusted_crushing_pressure_he[i] = stateDeco.vpm.adjusted_crushing_pressure_he[i];
471 pStateUsed->vpm.adjusted_crushing_pressure_n2[i] = stateDeco.vpm.adjusted_crushing_pressure_n2[i];
472 pStateUsed->vpm.initial_allowable_gradient_he[i] = stateDeco.vpm.initial_allowable_gradient_he[i];
473 pStateUsed->vpm.initial_allowable_gradient_n2[i] = stateDeco.vpm.initial_allowable_gradient_n2[i];
474 pStateUsed->vpm.max_actual_gradient[i] = stateDeco.vpm.max_actual_gradient[i];
475 }
476 break;
477 case DECO_CALC_FINSHED_Buehlmann:
478 memcpy(&pStateUsed->decolistBuehlmann,&stateDeco.decolistBuehlmann,sizeof(SDecoinfo));
479 pStateUsed->decolistBuehlmann.tickstamp = HAL_GetTick();
480 //Copy Data to be stored if regular Buehlmann, not FutureBuehlmann
481 pStateUsed->diveSettings.internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero = stateDeco.diveSettings.internal__pressure_first_stop_ambient_bar_as_upper_limit_for_gf_low_otherwise_zero;
482 break;
483 case DECO_CALC_FINSHED_FutureBuehlmann:
484 memcpy(&pStateUsed->decolistFutureBuehlmann,&stateDeco.decolistFutureBuehlmann,sizeof(SDecoinfo));
485 pStateUsed->decolistFutureBuehlmann.tickstamp = HAL_GetTick();
486 break;
487 case DECO_CALC_FINSHED_Futurevpm:
488 memcpy(&pStateUsed->decolistFutureVPM,&stateDeco.decolistFutureVPM,sizeof(SDecoinfo));
489 pStateUsed->decolistFutureVPM.tickstamp = HAL_GetTick();
490 break;
491 }
492
493 //Copy Inputdata from stateReal to stateDeco
494 memcpy(&stateDeco.lifeData,&pStateUsed->lifeData,sizeof(SLifeData));
495 memcpy(&stateDeco.diveSettings,&pStateUsed->diveSettings,sizeof(SDiveSettings));
496
497 stateDeco.vpm.deco_zone_reached = pStateUsed->vpm.deco_zone_reached;
498 // memcpy(&stateDeco.vpm,&pStateUsed->vpm,sizeof(SVpm));
499 for(int i = 0; i< 16; i++)
500 {
501 stateDeco.vpm.max_crushing_pressure_he[i] = pStateUsed->vpm.max_crushing_pressure_he[i];
502 stateDeco.vpm.max_crushing_pressure_n2[i] = pStateUsed->vpm.max_crushing_pressure_n2[i];
503 stateDeco.vpm.adjusted_critical_radius_he[i] = pStateUsed->vpm.adjusted_critical_radius_he[i];
504 stateDeco.vpm.adjusted_critical_radius_n2[i] = pStateUsed->vpm.adjusted_critical_radius_n2[i];
505 }
506 decoLock = DECO_CALC_ready;
507 }
508
509
510 void DataEX_helper_copy_deviceData(SDeviceLine *lineWrite, const SDeviceLine *lineRead)
511 {
512 lineWrite->date_rtc_dr = lineRead->date_rtc_dr;
513 lineWrite->time_rtc_tr = lineRead->time_rtc_tr;
514 lineWrite->value_int32 = lineRead->value_int32;
515 }
516
517
518
519 void DataEX_helper_SetTime(RTC_TimeTypeDef inStimestructure, uint32_t *outTimetmpreg)
520 {
521 inStimestructure.TimeFormat = RTC_HOURFORMAT_24;
522
523 *outTimetmpreg = (uint32_t)(((uint32_t)RTC_ByteToBcd2(inStimestructure.Hours) << 16U) | \
524 ((uint32_t)RTC_ByteToBcd2(inStimestructure.Minutes) << 8U) | \
525 ((uint32_t)RTC_ByteToBcd2(inStimestructure.Seconds)) | \
526 (((uint32_t)inStimestructure.TimeFormat) << 16U));
527 }
528
529
530 void DataEX_helper_SetDate(RTC_DateTypeDef inSdatestructure, uint32_t *outDatetmpreg)
531 {
532 *outDatetmpreg = (((uint32_t)RTC_ByteToBcd2(inSdatestructure.Year) << 16U) | \
533 ((uint32_t)RTC_ByteToBcd2(inSdatestructure.Month) << 8U) | \
534 ((uint32_t)RTC_ByteToBcd2(inSdatestructure.Date)) | \
535 ((uint32_t)inSdatestructure.WeekDay << 13U));
536 }
537
538
539
540 void DataEX_helper_set_Unknown_Date_deviceData(SDeviceLine *lineWrite)
541 {
542 RTC_DateTypeDef sdatestructure;
543 RTC_TimeTypeDef stimestructure;
544
545 stimestructure.Hours = 1;
546 stimestructure.Minutes = 0;
547 stimestructure.Seconds = 0;
548
549 sdatestructure.Date = 1;
550 sdatestructure.Month = 1;
551 sdatestructure.Year = 16;
552 setWeekday(&sdatestructure);
553
554 DataEX_helper_SetTime(stimestructure, &lineWrite->time_rtc_tr);
555 DataEX_helper_SetDate(sdatestructure, &lineWrite->date_rtc_dr);
556 }
557
558
559 uint8_t DataEX_helper_Check_And_Correct_Date_deviceData(SDeviceLine *lineWrite)
560 {
561 RTC_DateTypeDef sdatestructure;
562 RTC_TimeTypeDef stimestructure;
563
564 // from lineWrite to structure
565 translateDate(lineWrite->date_rtc_dr, &sdatestructure);
566 translateTime(lineWrite->time_rtc_tr, &stimestructure);
567
568 if( (sdatestructure.Year >= 15)
569 && (sdatestructure.Year <= 30)
570 && (sdatestructure.Month <= 12))
571 return 0;
572
573
574 DataEX_helper_set_Unknown_Date_deviceData(lineWrite);
575 return 1;
576 }
577
578
579 uint8_t DataEX_helper_Check_And_Correct_Value_deviceData(SDeviceLine *lineWrite, int32_t from, int32_t to)
580 {
581 if(lineWrite->value_int32 >= from && lineWrite->value_int32 <= to)
582 return 0;
583
584 if(lineWrite->value_int32 < from)
585 lineWrite->value_int32 = from;
586 else
587 lineWrite->value_int32 = to;
588
589 DataEX_helper_set_Unknown_Date_deviceData(lineWrite);
590 return 0;
591 }
592
593
594 void DataEX_check_DeviceData(void)
595 {
596 SDevice *DeviceData = stateDeviceGetPointerWrite();
597
598 DataEX_helper_Check_And_Correct_Date_deviceData(&DeviceData->batteryChargeCompleteCycles);
599 DataEX_helper_Check_And_Correct_Date_deviceData(&DeviceData->batteryChargeCycles);
600 DataEX_helper_Check_And_Correct_Date_deviceData(&DeviceData->depthMaximum);
601 DataEX_helper_Check_And_Correct_Date_deviceData(&DeviceData->diveCycles);
602 DataEX_helper_Check_And_Correct_Date_deviceData(&DeviceData->hoursOfOperation);
603 DataEX_helper_Check_And_Correct_Date_deviceData(&DeviceData->temperatureMaximum);
604 DataEX_helper_Check_And_Correct_Date_deviceData(&DeviceData->temperatureMinimum);
605 DataEX_helper_Check_And_Correct_Date_deviceData(&DeviceData->voltageMinimum);
606
607 DataEX_helper_Check_And_Correct_Value_deviceData(&DeviceData->batteryChargeCompleteCycles, 0, 10000);
608 DataEX_helper_Check_And_Correct_Value_deviceData(&DeviceData->batteryChargeCycles, 0, 20000);
609 DataEX_helper_Check_And_Correct_Value_deviceData(&DeviceData->depthMaximum, 0, (500*100)+1000);
610 DataEX_helper_Check_And_Correct_Value_deviceData(&DeviceData->diveCycles, 0, 20000);
611 DataEX_helper_Check_And_Correct_Value_deviceData(&DeviceData->hoursOfOperation, 0, 1000000);
612 DataEX_helper_Check_And_Correct_Value_deviceData(&DeviceData->temperatureMaximum, -30*100, 150*100);
613 DataEX_helper_Check_And_Correct_Value_deviceData(&DeviceData->temperatureMinimum, -30*100, 150*100);
614 DataEX_helper_Check_And_Correct_Value_deviceData(&DeviceData->voltageMinimum, -1*1000, 6*1000);
615 }
616
617
618 void DataEX_merge_DeviceData_and_store(void)
619 {
620 uint16_t dataLengthRead;
621 SDevice DeviceDataFlash;
622 SDevice *DeviceData = stateDeviceGetPointerWrite();
623
624 dataLengthRead = ext_flash_read_devicedata((uint8_t *)&DeviceDataFlash,sizeof(SDevice));
625
626 if(dataLengthRead == 0)
627 {
628 ext_flash_write_devicedata();
629 return;
630 }
631
632 /*
633 SDeviceLine batteryChargeCycles;
634 SDeviceLine batteryChargeCompleteCycles;
635 SDeviceLine temperatureMinimum;
636 SDeviceLine temperatureMaximum;
637 SDeviceLine depthMaximum;
638 SDeviceLine diveCycles;
639 SDeviceLine voltageMinimum;
640 */
641
642 /* max values */
643 if(DeviceData->batteryChargeCompleteCycles.value_int32 < DeviceDataFlash.batteryChargeCompleteCycles.value_int32)
644 {
645 DataEX_helper_copy_deviceData(&DeviceData->batteryChargeCompleteCycles, &DeviceDataFlash.batteryChargeCompleteCycles);
646 }
647 if(DeviceData->batteryChargeCycles.value_int32 < DeviceDataFlash.batteryChargeCycles.value_int32)
648 {
649 DataEX_helper_copy_deviceData(&DeviceData->batteryChargeCycles, &DeviceDataFlash.batteryChargeCycles);
650 }
651 if(DeviceData->temperatureMaximum.value_int32 < DeviceDataFlash.temperatureMaximum.value_int32)
652 {
653 DataEX_helper_copy_deviceData(&DeviceData->temperatureMaximum, &DeviceDataFlash.temperatureMaximum);
654 }
655 if(DeviceData->depthMaximum.value_int32 < DeviceDataFlash.depthMaximum.value_int32)
656 {
657 DataEX_helper_copy_deviceData(&DeviceData->depthMaximum, &DeviceDataFlash.depthMaximum);
658 }
659 if(DeviceData->diveCycles.value_int32 < DeviceDataFlash.diveCycles.value_int32)
660 {
661 DataEX_helper_copy_deviceData(&DeviceData->diveCycles, &DeviceDataFlash.diveCycles);
662 }
663
664 /* min values */
665 if(DeviceData->temperatureMinimum.value_int32 > DeviceDataFlash.temperatureMinimum.value_int32)
666 {
667 DataEX_helper_copy_deviceData(&DeviceData->temperatureMinimum, &DeviceDataFlash.temperatureMinimum);
668 }
669 // Voltage minimum, keep limit to 2.0 Volt; hw 09.09.2015
670 if(DeviceData->voltageMinimum.value_int32 > DeviceDataFlash.voltageMinimum.value_int32)
671 {
672 if(DeviceDataFlash.voltageMinimum.value_int32 > 2000) // do not copy back 2000 and below
673 DataEX_helper_copy_deviceData(&DeviceData->voltageMinimum, &DeviceDataFlash.voltageMinimum);
674 }
675 if(DeviceData->voltageMinimum.value_int32 < 2000)
676 DeviceData->voltageMinimum.value_int32 = 2000;
677
678 DataEX_check_DeviceData ();
679 ext_flash_write_devicedata();
680 }
681
682
683 void DataEX_copy_to_DeviceData(void)
684 {
685 SDataExchangeSlaveToMasterDeviceData * dataInDevice = (SDataExchangeSlaveToMasterDeviceData *)&dataIn;
686 SDevice * pDeviceState = stateDeviceGetPointerWrite();
687
688 memcpy(pDeviceState, &dataInDevice->DeviceData[dataInDevice->boolDeviceData], sizeof(SDevice));
689 }
690
691
692 void DataEX_copy_to_VpmRepetitiveData(void)
693 {
694 SDataExchangeSlaveToMasterDeviceData * dataInDevice = (SDataExchangeSlaveToMasterDeviceData *)&dataIn;
695 SVpmRepetitiveData * pVpmState = stateVpmRepetitiveDataGetPointerWrite();
696
697 if(dataInDevice->boolVpmRepetitiveDataValid)
698 {
699 memcpy(pVpmState, &dataInDevice->VpmRepetitiveData, sizeof(SVpmRepetitiveData));
700 pVpmState->is_data_from_RTE_CPU = 1;
701 }
702 }
703
704
705 void DataEX_control_connection_while_asking_for_sleep(void)
706 {
707 if(!DataEX_check_header_and_footer_ok())
708 {
709 if(DataEX_check_header_and_footer_devicedata())
710 {
711 data_old__lost_connection_to_slave_counter_retry = 0;
712 data_old__lost_connection_to_slave_counter_temp = 0;
713 stateRealGetPointerWrite()->data_old__lost_connection_to_slave = 0;
714 }
715 else
716 {
717 stateRealGetPointerWrite()->data_old__lost_connection_to_slave = 1;
718 data_old__lost_connection_to_slave_counter_temp += 1;
719 data_old__lost_connection_to_slave_counter_total += 1;
720 }
721 }
722 }
723
724
725 void DataEX_copy_to_LifeData(_Bool *modeChangeFlag)
726 {
727 SDiveState * pStateReal = stateRealGetPointerWrite();
728 static uint16_t getDeviceDataAfterStartOfMainCPU = 20;
729
730 /* internal sensor: HUD data
731 */
732 for(int i=0;i<3;i++)
733 {
734 pStateReal->lifeData.ppO2Sensor_bar[i] = get_ppO2Sensor_bar(i);
735 pStateReal->lifeData.sensorVoltage_mV[i] = get_sensorVoltage_mV(i);
736 }
737 pStateReal->lifeData.HUD_battery_voltage_V = get_HUD_battery_voltage_V();
738
739
740 // wireless - �ltere daten aufr�umen
741 for(int i=0;i<=(2*NUM_GASES+1);i++)
742 {
743 if(pStateReal->lifeData.bottle_bar[i])
744 {
745 if((pStateReal->lifeData.bottle_bar_age_MilliSeconds[i] == 0) || (pStateReal->lifeData.bottle_bar_age_MilliSeconds[i] > 60000))
746 {
747 pStateReal->lifeData.bottle_bar_age_MilliSeconds[i] = 0;
748 pStateReal->lifeData.bottle_bar[i] = 0;
749 }
750 else
751 pStateReal->lifeData.bottle_bar_age_MilliSeconds[i] += 100;
752 }
753 }
754
755 /* Why? hw 8.6.2015
756 if(DataEX_check_header_and_footer_ok() && dataIn.power_on_reset)
757 {
758 return;
759 }
760 */
761 if(!DataEX_check_header_and_footer_ok())
762 {
763 if(DataEX_check_header_and_footer_devicedata())
764 {
765 DataEX_copy_to_DeviceData();
766 DataEX_merge_DeviceData_and_store();
767 DataEX_copy_to_VpmRepetitiveData();
768 data_old__lost_connection_to_slave_counter_temp = 0;
769 data_old__lost_connection_to_slave_counter_retry = 0;
770 pStateReal->data_old__lost_connection_to_slave = 0;
771 }
772 else
773 {
774 pStateReal->data_old__lost_connection_to_slave = 1;
775 data_old__lost_connection_to_slave_counter_temp += 1;
776 data_old__lost_connection_to_slave_counter_total += 1;
777 }
778 return;
779 }
780
781 if(getDeviceDataAfterStartOfMainCPU)
782 {
783 getDeviceDataAfterStartOfMainCPU--;
784 if(getDeviceDataAfterStartOfMainCPU == 0)
785 {
786 dataOut.getDeviceDataNow = 1;
787 getDeviceDataAfterStartOfMainCPU = 10*60*10;// * 100ms
788 }
789 }
790
791 /* new 151207 hw */
792 if(requestNecessary.uw != 0)
793 {
794 if(((dataIn.confirmRequest.uw) & CRBUTTON) != 0)
795 {
796 requestNecessary.ub.button = 0;
797 }
798
799 if(requestNecessary.ub.button == 1)
800 {
801 setButtonResponsiveness(settingsGetPointer()->ButtonResponsiveness);
802 }
803 /*
804 }
805 if((dataIn.confirmRequest.ub.clearDeco != 1) && (requestNecessary.ub.clearDeco == 1))
806 {
807 clearDeco(); // is dataOut.clearDecoNow = 1;
808 }
809 */
810 }
811 requestNecessary.uw = 0; // clear all
812
813 float ambient, surface, density, meter;
814 SSettings *pSettings;
815
816 /* uint8_t IAmStolenPleaseKillMe;
817 */
818 if(settingsGetPointer()->IAmStolenPleaseKillMe > 3)
819 {
820 pSettings->salinity = 0;
821 dataIn.data[dataIn.boolPressureData].surface_mbar = 999;
822 dataIn.data[dataIn.boolPressureData].pressure_mbar = 98971;
823 dataIn.mode = MODE_DIVE;
824 }
825
826 pSettings = settingsGetPointer();
827 ambient = dataIn.data[dataIn.boolPressureData].pressure_mbar / 1000.0f;
828 surface = dataIn.data[dataIn.boolPressureData].surface_mbar / 1000.0f;
829
830 density = ((float)( 100 + pSettings->salinity)) / 100.0f;
831 meter = (ambient - surface);
832 meter /= (0.09807f * density);
833
834
835 pStateReal->pressure_uTick_old = pStateReal->pressure_uTick_new;
836 pStateReal->pressure_uTick_new = dataIn.data[dataIn.boolPressureData].pressure_uTick;
837 pStateReal->pressure_uTick_local_new = HAL_GetTick();
838
839 if(ambient < (surface + 0.04f))
840
841 pStateReal->lifeData.dateBinaryFormat = dataIn.data[dataIn.boolTimeData].localtime_rtc_dr;
842 pStateReal->lifeData.timeBinaryFormat = dataIn.data[dataIn.boolTimeData].localtime_rtc_tr;
843
844 dataOut.setAccidentFlag = 0;
845
846 //Start of diveMode?
847 if(pStateReal->mode != MODE_DIVE && dataIn.mode == MODE_DIVE)
848 {
849 if(modeChangeFlag)
850 *modeChangeFlag = 1;
851 if(stateUsed == stateSimGetPointer())
852 {
853 simulation_exit();
854 }
855 // new 170508
856 settingsGetPointer()->bluetoothActive = 0;
857 MX_Bluetooth_PowerOff();
858 //Init dive Mode
859 decoLock = DECO_CALC_init_as_is_start_of_dive;
860 pStateReal->lifeData.boolResetAverageDepth = 1;
861 pStateReal->lifeData.boolResetStopwatch = 1;
862 }
863
864 //End of diveMode?
865 if(pStateReal->mode == MODE_DIVE && dataIn.mode != MODE_DIVE)
866 {
867 if(modeChangeFlag)
868 *modeChangeFlag = 1;
869 createDiveSettings();
870
871 if(pStateReal->warnings.cnsHigh)
872 {
873 if(pStateReal->lifeData.cns >= 130)
874 dataOut.setAccidentFlag += ACCIDENT_CNSLVL2;
875 else if(pStateReal->lifeData.cns >= 100)
876 dataOut.setAccidentFlag += ACCIDENT_CNS;
877 }
878 if(pStateReal->warnings.decoMissed)
879 dataOut.setAccidentFlag += ACCIDENT_DECOSTOP;
880 }
881 pStateReal->mode = dataIn.mode;
882 pStateReal->chargeStatus = dataIn.chargeStatus;
883
884 pStateReal->lifeData.pressure_ambient_bar = ambient;
885 pStateReal->lifeData.pressure_surface_bar = surface;
886 if(is_ambient_pressure_close_to_surface(&pStateReal->lifeData))
887 {
888 pStateReal->lifeData.depth_meter = 0;
889 }
890 else
891 {
892 pStateReal->lifeData.depth_meter = meter;
893 }
894 pStateReal->lifeData.temperature_celsius = dataIn.data[dataIn.boolPressureData].temperature;
895 pStateReal->lifeData.ascent_rate_meter_per_min = dataIn.data[dataIn.boolPressureData].ascent_rate_meter_per_min;
896 if(pStateReal->mode != MODE_DIVE)
897 pStateReal->lifeData.max_depth_meter = 0;
898 else
899 {
900 if(meter > pStateReal->lifeData.max_depth_meter)
901 pStateReal->lifeData.max_depth_meter = meter;
902 }
903
904 if(dataIn.accidentFlags & ACCIDENT_DECOSTOP)
905 pStateReal->decoMissed_at_the_end_of_dive = 1;
906 if(dataIn.accidentFlags & ACCIDENT_CNS)
907 pStateReal->cnsHigh_at_the_end_of_dive = 1;
908
909 pStateReal->lifeData.dive_time_seconds = (int32_t)dataIn.data[dataIn.boolTimeData].divetime_seconds;
910 pStateReal->lifeData.dive_time_seconds_without_surface_time = (int32_t)dataIn.data[dataIn.boolTimeData].dive_time_seconds_without_surface_time;
911 pStateReal->lifeData.counterSecondsShallowDepth = dataIn.data[dataIn.boolTimeData].counterSecondsShallowDepth;
912 pStateReal->lifeData.surface_time_seconds = (int32_t)dataIn.data[dataIn.boolTimeData].surfacetime_seconds;
913
914 pStateReal->lifeData.compass_heading = dataIn.data[dataIn.boolCompassData].compass_heading;
915 pStateReal->lifeData.compass_roll = dataIn.data[dataIn.boolCompassData].compass_roll;
916 pStateReal->lifeData.compass_pitch = dataIn.data[dataIn.boolCompassData].compass_pitch;
917
918 pStateReal->lifeData.compass_DX_f = dataIn.data[dataIn.boolCompassData].compass_DX_f;
919 pStateReal->lifeData.compass_DY_f = dataIn.data[dataIn.boolCompassData].compass_DY_f;
920 pStateReal->lifeData.compass_DZ_f = dataIn.data[dataIn.boolCompassData].compass_DZ_f;
921
922 pStateReal->compass_uTick_old = pStateReal->compass_uTick_new;
923 pStateReal->compass_uTick_new = dataIn.data[dataIn.boolCompassData].compass_uTick;
924 pStateReal->compass_uTick_local_new = HAL_GetTick();
925
926 pStateReal->lifeData.cns = dataIn.data[dataIn.boolToxicData].cns;
927 pStateReal->lifeData.otu = dataIn.data[dataIn.boolToxicData].otu;
928 pStateReal->lifeData.no_fly_time_minutes = dataIn.data[dataIn.boolToxicData].no_fly_time_minutes;
929 pStateReal->lifeData.desaturation_time_minutes = dataIn.data[dataIn.boolToxicData].desaturation_time_minutes;
930
931 memcpy(pStateReal->lifeData.tissue_nitrogen_bar, dataIn.data[dataIn.boolTisssueData].tissue_nitrogen_bar,sizeof(pStateReal->lifeData.tissue_nitrogen_bar));
932 memcpy(pStateReal->lifeData.tissue_helium_bar, dataIn.data[dataIn.boolTisssueData].tissue_helium_bar,sizeof(pStateReal->lifeData.tissue_helium_bar));
933
934 if(pStateReal->mode == MODE_DIVE)
935 {
936 for(int i= 0; i <16; i++)
937 {
938 pStateReal->vpm.max_crushing_pressure_he[i] = dataIn.data[dataIn.boolCrushingData].max_crushing_pressure_he[i];
939 pStateReal->vpm.max_crushing_pressure_n2[i] = dataIn.data[dataIn.boolCrushingData].max_crushing_pressure_n2[i];
940 pStateReal->vpm.adjusted_critical_radius_he[i] = dataIn.data[dataIn.boolCrushingData].adjusted_critical_radius_he[i];
941 pStateReal->vpm.adjusted_critical_radius_n2[i] = dataIn.data[dataIn.boolCrushingData].adjusted_critical_radius_n2[i];
942 }
943 }
944
945 /* battery and ambient light sensors
946 */
947 pStateReal->lifeData.ambient_light_level = dataIn.data[dataIn.boolAmbientLightData].ambient_light_level;
948 pStateReal->lifeData.battery_charge = dataIn.data[dataIn.boolBatteryData].battery_charge;
949 pStateReal->lifeData.battery_voltage = dataIn.data[dataIn.boolBatteryData].battery_voltage;
950
951 /* now in ext_flash_write_settings() // hw 161027
952 * if((pStateReal->lifeData.battery_charge > 1) && !DataEX_was_power_on() && ((uint8_t)(pStateReal->lifeData.battery_charge) != 0x10)) // get rid of 16% (0x10)
953 * pSettings->lastKnownBatteryPercentage = (uint8_t)(pStateReal->lifeData.battery_charge);
954 */
955
956 /* OC and CCR but no sensors -> moved to updateSetpointStateUsed();
957 float oxygen = 0;
958 if(pStateReal->diveSettings.diveMode == 0)
959 {
960 oxygen = 1.00f;
961 oxygen -= ((float)pStateReal->lifeData.actualGas.nitrogen_percentage)/100.0f;
962 oxygen -= ((float)pStateReal->lifeData.actualGas.helium_percentage)/100.0f;
963 pStateReal->lifeData.ppO2 = pStateReal->lifeData.pressure_ambient_bar * oxygen;
964 }
965 else if(pStateReal->diveSettings.diveMode == 1)
966 {
967 pStateReal->lifeData.ppO2 = ((float)pStateReal->lifeData.actualGas.setPoint_cbar) /100;
968 }
969 */
970
971 /* apnea specials
972 */
973 if(pStateReal->diveSettings.diveMode == DIVEMODE_Apnea)
974 {
975 if(pStateReal->mode != MODE_DIVE)
976 {
977 pStateReal->lifeData.apnea_total_max_depth_meter = 0;
978 pStateReal->lifeData.apnea_last_dive_time_seconds = 0;
979 pStateReal->lifeData.apnea_last_max_depth_meter = 0;
980 }
981 else
982 {
983 if(pStateReal->lifeData.max_depth_meter > pStateReal->lifeData.apnea_total_max_depth_meter)
984 pStateReal->lifeData.apnea_total_max_depth_meter = pStateReal->lifeData.max_depth_meter;
985 }
986
987 if(pStateReal->lifeData.dive_time_seconds > 15)
988 {
989 pStateReal->lifeData.apnea_last_dive_time_seconds = pStateReal->lifeData.dive_time_seconds;
990 }
991
992 if(pStateReal->lifeData.counterSecondsShallowDepth)
993 {
994 if(pStateReal->lifeData.max_depth_meter > 1.5f)
995 {
996 pStateReal->lifeData.apnea_last_max_depth_meter = pStateReal->lifeData.max_depth_meter;
997 }
998 // eset max_depth_meter, average_depth_meter and internal values
999 pStateReal->lifeData.max_depth_meter = 0;
1000 pStateReal->lifeData.boolResetAverageDepth = 1;
1001 pStateReal->lifeData.boolResetStopwatch = 1;
1002 }
1003 }
1004
1005 /* average depth
1006 */
1007 float *AvgDepthValue = &pStateReal->lifeData.average_depth_meter;
1008 float DepthNow = pStateReal->lifeData.depth_meter;
1009 uint32_t *AvgDepthCount = &pStateReal->lifeData.internal.average_depth_meter_Count;
1010 uint32_t *AvgDepthTimer = &pStateReal->lifeData.internal.average_depth_last_update_dive_time_seconds_without_surface_time;
1011 uint32_t AvgSecondsSinceLast;
1012 uint32_t DiveTime = pStateReal->lifeData.dive_time_seconds_without_surface_time;
1013
1014 if(pStateReal->lifeData.boolResetAverageDepth)
1015 {
1016 *AvgDepthValue = DepthNow;
1017 *AvgDepthCount = 1;
1018 *AvgDepthTimer = DiveTime;
1019 pStateReal->lifeData.boolResetAverageDepth = 0;
1020 }
1021 else if (DiveTime > *AvgDepthTimer)
1022 {
1023 AvgSecondsSinceLast = DiveTime - *AvgDepthTimer;
1024 for(int i=0;i<AvgSecondsSinceLast;i++)
1025 {
1026 *AvgDepthValue = (*AvgDepthValue * *AvgDepthCount + DepthNow) / (*AvgDepthCount + 1);
1027 *AvgDepthCount += 1;
1028 }
1029 *AvgDepthTimer = DiveTime;
1030 }
1031 if(*AvgDepthCount == 0)
1032 *AvgDepthValue = 0;
1033
1034
1035 /* stop watch
1036 */
1037 if(pStateReal->lifeData.boolResetStopwatch)
1038 {
1039 pStateReal->lifeData.internal.stopwatch_start_at_this_dive_time_seconds = pStateReal->lifeData.dive_time_seconds;
1040 pStateReal->lifeData.boolResetStopwatch = 0;
1041 }
1042 pStateReal->lifeData.stopwatch_seconds = pStateReal->lifeData.dive_time_seconds - pStateReal->lifeData.internal.stopwatch_start_at_this_dive_time_seconds;
1043
1044 /* wireless data
1045 */
1046 uint16_t wirelessData[4][3];
1047 for(int i=0;i<4;i++)
1048 {
1049 pStateReal->lifeData.wireless_data[i].ageInMilliSeconds = dataIn.data[dataIn.boolWirelessData].wireless_data[i].ageInMilliSeconds;
1050 pStateReal->lifeData.wireless_data[i].status = dataIn.data[dataIn.boolWirelessData].wireless_data[i].status;
1051 pStateReal->lifeData.wireless_data[i].numberOfBytes = dataIn.data[dataIn.boolWirelessData].wireless_data[i].numberOfBytes;
1052 for(int j=0;j<12;j++)
1053 pStateReal->lifeData.wireless_data[i].data[j] = dataIn.data[dataIn.boolWirelessData].wireless_data[i].data[j];
1054 }
1055
1056 /* old stuff
1057 // crc - is done in RTE 160325
1058 // size at the moment 4 bytes + one empty + crc -> minimum 5 bytes (+ crc)
1059 // kopieren: Id, Wert, Alter
1060 for(int i=0;i<4;i++)
1061 {
1062 uint8_t numberOfBytes = pStateReal->lifeData.wireless_data[i].numberOfBytes - 1;
1063
1064 if((numberOfBytes < 5) || (numberOfBytes > 7))
1065 {
1066 wirelessData[i][0] = 0;
1067 wirelessData[i][1] = 0;
1068 wirelessData[i][2] = 0;
1069 }
1070 else
1071 {
1072 if((crc32c_checksum(pStateReal->lifeData.wireless_data[i].data, numberOfBytes, 0, 0) & 0xFF)!= pStateReal->lifeData.wireless_data[i].data[numberOfBytes])
1073 {
1074 // no crc is send at the moment
1075 wirelessData[i][0] = (pStateReal->lifeData.wireless_data[i].data[0] * 256) + pStateReal->lifeData.wireless_data[i].data[1];
1076 wirelessData[i][1] = (pStateReal->lifeData.wireless_data[i].data[3] * 256) + pStateReal->lifeData.wireless_data[i].data[4];
1077 wirelessData[i][2] = pStateReal->lifeData.wireless_data[i].ageInMilliSeconds;
1078
1079 // wirelessData[i][0] = 0;
1080 // wirelessData[i][1] = 0;
1081 // wirelessData[i][2] = 0;
1082
1083 }
1084
1085 else
1086 {
1087 wirelessData[i][0] = (pStateReal->lifeData.wireless_data[i].data[0] * 256) + pStateReal->lifeData.wireless_data[i].data[1];
1088 wirelessData[i][1] = (pStateReal->lifeData.wireless_data[i].data[3] * 256) + pStateReal->lifeData.wireless_data[i].data[4];
1089 wirelessData[i][2] = pStateReal->lifeData.wireless_data[i].ageInMilliSeconds;
1090 }
1091 }
1092 }
1093 */
1094 // neu 160412
1095 for(int i=0;i<4;i++)
1096 {
1097 if(pStateReal->lifeData.wireless_data[i].numberOfBytes == 10)
1098 {
1099 wirelessData[i][0] = (pStateReal->lifeData.wireless_data[i].data[0] >> 4) & 0x7F;
1100 wirelessData[i][1] = 0;
1101 wirelessData[i][2] = pStateReal->lifeData.wireless_data[i].ageInMilliSeconds;
1102 }
1103 else
1104 {
1105 wirelessData[i][0] = 0;
1106 wirelessData[i][1] = 0;
1107 wirelessData[i][2] = 0;
1108 }
1109 }
1110
1111 // aussortieren doppelte ids, j�ngster datensatz ist relevant
1112 for(int i=0;i<3;i++)
1113 {
1114 if(wirelessData[i][0])
1115 {
1116 for(int j=i+1; j<4; j++)
1117 {
1118 if(wirelessData[i][0] == wirelessData[j][0])
1119 {
1120 if(wirelessData[i][2] > wirelessData[j][2])
1121 {
1122 wirelessData[i][0] = wirelessData[j][0];
1123 wirelessData[i][1] = wirelessData[j][1];
1124 wirelessData[i][2] = wirelessData[j][2];
1125 }
1126 wirelessData[j][0] = 0;
1127 wirelessData[j][1] = 0;
1128 wirelessData[j][2] = 0;
1129 }
1130 }
1131 }
1132 }
1133 /*
1134 // neu 160325
1135 for(int i=0;i<4;i++)
1136 {
1137 if(pStateReal->lifeData.wireless_data[i].numberOfBytes == 10)
1138 {
1139 wirelessData[i][0] = (pStateReal->lifeData.wireless_data[i].data[0] * 256) + pStateReal->lifeData.wireless_data[i].data[1];
1140 wirelessData[i][1] = (pStateReal->lifeData.wireless_data[i].data[3] * 256) + pStateReal->lifeData.wireless_data[i].data[4];
1141 wirelessData[i][2] = pStateReal->lifeData.wireless_data[i].ageInMilliSeconds;
1142 }
1143 else
1144 {
1145 wirelessData[i][0] = 0;
1146 wirelessData[i][1] = 0;
1147 wirelessData[i][2] = 0;
1148 }
1149 }
1150
1151 // aussortieren doppelte ids, j�ngster datensatz ist relevant
1152 for(int i=0;i<3;i++)
1153 {
1154 if(wirelessData[i][0])
1155 {
1156 for(int j=i+1; j<4; j++)
1157 {
1158 if(wirelessData[i][0] == wirelessData[j][0])
1159 {
1160 if(wirelessData[i][2] > wirelessData[j][2])
1161 {
1162 wirelessData[i][0] = wirelessData[j][0];
1163 wirelessData[i][1] = wirelessData[j][1];
1164 wirelessData[i][2] = wirelessData[j][2];
1165 }
1166 wirelessData[j][0] = 0;
1167 wirelessData[j][1] = 0;
1168 wirelessData[j][2] = 0;
1169 }
1170 }
1171 }
1172 }
1173 */
1174 /* old
1175 // copy to lifeData
1176 for(int i=0;i<4;i++)
1177 {
1178 if((wirelessData[i][0]) && (wirelessData[i][2]) && (wirelessData[i][2] < 60000))
1179 {
1180 for(int j=1;j<=(2*NUM_GASES+1);j++)
1181 {
1182 if(pStateReal->diveSettings.gas[j].bottle_wireless_id == wirelessData[i][0])
1183 {
1184 pStateReal->lifeData.bottle_bar[j] = wirelessData[i][1];
1185 pStateReal->lifeData.bottle_bar_age_MilliSeconds[j] = wirelessData[i][2];
1186 break;
1187 }
1188 }
1189 }
1190 }
1191 */
1192 // new: Bonex
1193 float scooterSpeedFloat;
1194 int32_t scooterRemainingBattCapacity;
1195
1196 for(int i=0;i<4;i++)
1197 {
1198 if((wirelessData[i][0]))// && (wirelessData[i][2]) && (wirelessData[i][2] < 60000))
1199 {
1200 pStateReal->lifeData.scooterType = (pStateReal->lifeData.wireless_data[i].data[0] >> 4) & 0x07;
1201 pStateReal->lifeData.scooterWattstunden = ((uint16_t)((((uint16_t)(pStateReal->lifeData.wireless_data[i].data[0] & 0x0F) << 8) | (pStateReal->lifeData.wireless_data[i].data[1]))));
1202 // pStateReal->lifeData.scooterWattstunden = pStateReal->lifeData.wireless_data[i].data[0] & 0x0F;
1203 // pStateReal->lifeData.scooterWattstunden *= 256;
1204 // pStateReal->lifeData.scooterWattstunden += pStateReal->lifeData.wireless_data[i].data[1];
1205 pStateReal->lifeData.scooterRestkapazitaet = pStateReal->lifeData.wireless_data[i].data[2];
1206 pStateReal->lifeData.scooterDrehzahl = ((uint16_t)( (int16_t)((pStateReal->lifeData.wireless_data[i].data[4] << 8) | (pStateReal->lifeData.wireless_data[i].data[3]))));
1207 pStateReal->lifeData.scooterSpannung = ((float)(pStateReal->lifeData.wireless_data[i].data[5])) / 5.0f;
1208 pStateReal->lifeData.scooterTemperature = ((uint16_t)( (int16_t)((pStateReal->lifeData.wireless_data[i].data[7] << 8) | (pStateReal->lifeData.wireless_data[i].data[6]))));
1209 pStateReal->lifeData.scooterAmpere = pStateReal->lifeData.wireless_data[i].data[9] >> 1;
1210 pStateReal->lifeData.scooterAgeInMilliSeconds = pStateReal->lifeData.wireless_data[i].ageInMilliSeconds;
1211
1212 if(pStateReal->lifeData.scooterWattstunden > 0)
1213 scooterRemainingBattCapacity = settingsGetPointer()->scooterBattSize / pStateReal->lifeData.scooterWattstunden;
1214 else
1215 scooterRemainingBattCapacity = 100;
1216
1217
1218 if(scooterRemainingBattCapacity < 0)
1219 scooterRemainingBattCapacity = 0;
1220 if(scooterRemainingBattCapacity > 100)
1221 scooterRemainingBattCapacity = 100;
1222 pStateReal->lifeData.scooterRestkapazitaetWhBased = scooterRemainingBattCapacity;
1223
1224 // BONEX_calc_new_ResidualCapacity(&pStateReal->lifeData.scooterRestkapazitaetVoltageBased, (uint32_t)(1000 * pStateReal->lifeData.scooterSpannung),1000,1);
1225 pStateReal->lifeData.scooterRestkapazitaetVoltageBased = BONEX_mini_ResidualCapacityVoltageBased(pStateReal->lifeData.scooterSpannung, pStateReal->lifeData.scooterAgeInMilliSeconds);
1226
1227 scooterSpeedFloat = (float)pStateReal->lifeData.scooterDrehzahl;
1228 scooterSpeedFloat /= (37.0f / 1.1f); // 3700 rpm = 110 m/min
1229 switch(settingsGetPointer()->scooterDrag)
1230 {
1231 case 1:
1232 scooterSpeedFloat *= 0.95f;
1233 break;
1234 case 2:
1235 scooterSpeedFloat *= 0.85f;
1236 break;
1237 case 3:
1238 scooterSpeedFloat *= 0.75f;
1239 break;
1240 default:
1241 break;
1242 }
1243 switch(settingsGetPointer()->scooterLoad)
1244 {
1245 case 1:
1246 scooterSpeedFloat *= 0.90f;
1247 break;
1248 case 2:
1249 scooterSpeedFloat *= 0.80f;
1250 break;
1251 case 3:
1252 scooterSpeedFloat *= 0.70f;
1253 break;
1254 case 4:
1255 scooterSpeedFloat *= 0.60f;
1256 break;
1257 default:
1258 break;
1259 }
1260 if(scooterSpeedFloat < 0)
1261 pStateReal->lifeData.scooterSpeed = 0;
1262 else
1263 if(scooterSpeedFloat > 255)
1264 pStateReal->lifeData.scooterSpeed = 255;
1265 else
1266 pStateReal->lifeData.scooterSpeed = (uint16_t)scooterSpeedFloat;
1267
1268 if(!scooterFoundThisPowerOnCylce && (pStateReal->lifeData.scooterAgeInMilliSeconds > 0))
1269 scooterFoundThisPowerOnCylce = 1;
1270 }
1271 }
1272
1273 /* PIC data
1274 */
1275 for(int i=0;i<4;i++)
1276 {
1277 pStateReal->lifeData.buttonPICdata[i] = dataIn.data[dataIn.boolPICdata].button_setting[i];
1278 }
1279
1280 /* sensorErrors
1281 */
1282 pStateReal->sensorErrorsRTE = dataIn.sensorErrors;
1283
1284 /* end
1285 */
1286 data_old__lost_connection_to_slave_counter_temp = 0;
1287 data_old__lost_connection_to_slave_counter_retry = 0;
1288 pStateReal->data_old__lost_connection_to_slave = 0;
1289 }
1290
1291
1292 uint8_t DataEX_check_RTE_version__needs_update(void)
1293 {
1294 if(data_old__lost_connection_to_slave_counter_retry > 10)
1295 return 1;
1296 else
1297 {
1298 if(stateRealGetPointer()->data_old__lost_connection_to_slave == 0)
1299 {
1300 setActualRTEversion(dataIn.RTE_VERSION_high, dataIn.RTE_VERSION_low);
1301
1302 if(RTEminimum_required_high() < dataIn.RTE_VERSION_high)
1303 return 0;
1304 else
1305 if((RTEminimum_required_high() == dataIn.RTE_VERSION_high) && (RTEminimum_required_low() <= dataIn.RTE_VERSION_low))
1306 return 0;
1307 else
1308 return 1;
1309 }
1310 else
1311 return 0;
1312 }
1313 }
1314
1315
1316 uint8_t DataEX_scooterDataFound(void)
1317 {
1318 return scooterFoundThisPowerOnCylce;
1319 }
1320
1321
1322 uint8_t DataEX_scooterFoundAndValidLicence(void)
1323 {
1324 if(getLicence() != LICENCEBONEX)
1325 return 0;
1326 else
1327 return scooterFoundThisPowerOnCylce;
1328 //return 0xFF;
1329 //return LICENCEBONEX;
1330 }
1331
1332 /* Private functions ---------------------------------------------------------*/
1333
1334 uint8_t DataEX_check_header_and_footer_ok(void)
1335 {
1336 if(dataIn.header.checkCode[0] != 0xA1)
1337 return 0;
1338 if(dataIn.header.checkCode[1] != 0xA2)
1339 return 0;
1340 if(dataIn.header.checkCode[2] != 0xA3)
1341 return 0;
1342 if(dataIn.header.checkCode[3] != 0xA4)
1343 return 0;
1344 if(dataIn.footer.checkCode[0] != 0xE1)
1345 return 0;
1346 if(dataIn.footer.checkCode[1] != 0xE2)
1347 return 0;
1348 if(dataIn.footer.checkCode[2] != 0xE3)
1349 return 0;
1350 if(dataIn.footer.checkCode[3] != 0xE4)
1351 return 0;
1352
1353 return 1;
1354 }
1355
1356 uint8_t DataEX_check_header_and_footer_devicedata(void)
1357 {
1358 if(dataIn.header.checkCode[0] != 0xDF)
1359 return 0;
1360 if(dataIn.header.checkCode[1] != 0xDE)
1361 return 0;
1362 if(dataIn.header.checkCode[2] != 0xDD)
1363 return 0;
1364 if(dataIn.header.checkCode[3] != 0xDC)
1365 return 0;
1366 if(dataIn.footer.checkCode[0] != 0xE1)
1367 return 0;
1368 if(dataIn.footer.checkCode[1] != 0xE2)
1369 return 0;
1370 if(dataIn.footer.checkCode[2] != 0xE3)
1371 return 0;
1372 if(dataIn.footer.checkCode[3] != 0xE4)
1373 return 0;
1374
1375 return 1;
1376 }
1377
1378
1379