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