Mercurial > public > ostc4
diff Discovery/Src/logbook.c @ 38:5f11787b4f42
include in ostc4 repository
author | heinrichsweikamp |
---|---|
date | Sat, 28 Apr 2018 11:52:34 +0200 |
parents | |
children | b7689d9e888a |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Discovery/Src/logbook.c Sat Apr 28 11:52:34 2018 +0200 @@ -0,0 +1,1677 @@ +/** + ****************************************************************************** + * @copyright heinrichs weikamp + * @file logbook.c + * @author heinrichs weikamp gmbh and heinrichs weikamp gmbh + * @date 22-Apr-2014 + * @version V0.0.3 + * @since 03-Feb-2016 + * @brief Everything about creating and evaluating the logbook + * without the flash part which is included in externLogbookFlash.c + * and the USB/Bluetooth part in tComm.c + * CHANGE V0.0.3 hw: ppO2 sensor values + * CHANGE V0.0.4 hw: fix event bytes according to hwos_interface.odt dated 160610 in bitbucket hwOS + * @bug + * @warning + @verbatim + ============================================================================== + ##### Header ##### + ============================================================================== + [..] SLogbookHeader + The order has changed in comparsion to OSTC3 for perfect alignment + with 16bit and 32bit. The header is 256kB as well. + DO NOT rearrange anything but add new data to a second page + beyond diveHeaderEnd. Use extraPagesWithData to indicate that there is + data available that was not available in the OSTC3 256KB + This data will be behind the diveHeaderEnd. DO NOT delete diveHeaderEnd. + + [..] SLogbookHeaderOSTC3 + is the format used by the OSTC3. + logbook_getHeaderOSTC3() does the job using the global headers in logbook.c + + [..] SSmallHeader + - is the format used by the OSTC3 + + [..] Summary + The header format is not perfect and might be optimized prior to + releasing the diving computer. For now it is good to be compatible + with PC software available for checking the content of the logbook + + + @endverbatim + ****************************************************************************** + * @attention + * + * <h2><center>© COPYRIGHT(c) 2014 heinrichs weikamp</center></h2> + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include <stdint.h> +#include <string.h> +#include "logbook.h" +//#include "test_vpm.h" +#include "externLogbookFlash.h" +#include "data_exchange.h" +#include "decom.h" +#include "tHome.h" // for tHome_findNextStop() + +/* Private types -------------------------------------------------------------*/ + +#define NUM_GASES 5 + +#define LOGBOOK_VERSION (0x30) +#define LOGBOOK_VERSION_OSTC3 (0x24) + +typedef struct /* don't forget to adjust void clear_divisor(void) */ +{ + uint8_t temperature; + uint8_t deco_ndl; + uint8_t gradientFactor; + uint8_t ppo2; + uint8_t decoplan; + uint8_t cns; + uint8_t tank; +} SDivisor; + +/* Exported variables --------------------------------------------------------*/ + +/* Private variables ---------------------------------------------------------*/ +uint8_t data_store[10000]; +SLogbookHeader header; +SLogbookHeaderOSTC3 headerOSTC3; +SLogbookHeaderOSTC3compact headerOSTC3compact; +SSmallHeader smallHeader; +SDivisor divisor; +SDivisor divisorBackup; + +/* Private function prototypes -----------------------------------------------*/ +void clear_divisor(void); +void logbook_SetAverageDepth(float average_depth_meter); +void logbook_SetMinTemperature(float min_temperature_celsius); +void logbook_SetMaxCNS(float max_cns_percentage); +void logbook_SetCompartmentDesaturation(void); +void logbook_SetLastStop(float last_stop_depth_bar); +void logbook_writedata(void * data, int length_byte); +void logbook_UpdateHeader(void); + +/* Exported functions --------------------------------------------------------*/ + +/** used by test_vpm.c at the moment */ +void logbook_EndDive(void) +{ + ext_flash_close_new_dive_log((uint8_t*) &header); +} + + +// =============================================================================== +// logbook_last_totalDiveCount +/// @brief Fix setting issues +/// @date 04-April-2016 +/// +/// @return diveNumber (totalDiveCounter) of latest log entry, 0 if not a valid header +// =============================================================================== +uint16_t logbook_lastDive_diveNumber(void) +{ + SLogbookHeader tempLogbookHeader; + if(logbook_getHeader(0, &tempLogbookHeader)) + { + return tempLogbookHeader.diveNumber; + } + else + { + return 0; + } +} + + +/** + ****************************************************************************** + * @brief logbook_getCurrentHeader. / + * @author Peter Ryser + * @version V0.0.1 + * @date 22-April-2014 + ****************************************************************************** + * + * @return SLogbookHeader*: +*/ +SLogbookHeader* logbook_getCurrentHeader(void) +{ + return &header; +} + +/** + ****************************************************************************** + * @brief logbook_getHeaderOSTC3. / + * @author heinrichs weikamp gmbh + * @version V0.0.1 + * @date 26-Nov-2014 + ****************************************************************************** + * + * @param StepBackwards : 0 Last lokbook entry, 1 second to last entry, etc. + * @param SSLogbookHeader* pLogbookHeader: Output found LogbookHeader + * @return uint8_t : 1 = success +*/ +/* +SLogbookHeaderOSTC3 * logbook_getHeaderOSTC3(uint8_t StepBackwards) +{ + if(!logbook_getHeader(StepBackwards, &header)) + return 0; + else + { + logbook_build_ostc3header(); + return &headerOSTC3; + } +} +*/ + +/** + ****************************************************************************** + * @brief logbook_getNumberOfHeaders. / + * @author heinrichs weikamp gmbh + * @version V0.0.1 + * @date 18-May-2016 + ****************************************************************************** + * + * @return uint8_t : number of valid headers (0xFAFA) found. +*/ +uint8_t logbook_getNumberOfHeaders(void) +{ + return ext_flash_count_dive_headers(); +} + + +/** + ****************************************************************************** + * @brief logbook_getHeader. / + * @author Peter Ryser + * @version V0.0.1 + * @date 22-April-2014 + ****************************************************************************** + * + * @param StepBackwards : 0 Last lokbook entry, 1 second to last entry, etc. + * @param SSLogbookHeader* pLogbookHeader: Output found LogbookHeader + * @return uint8_t : 1 = success +*/ +uint8_t logbook_getHeader(uint8_t StepBackwards,SLogbookHeader* pLogbookHeader) +{ + ext_flash_read_dive_header((uint8_t *)pLogbookHeader, StepBackwards); + if(pLogbookHeader->diveHeaderStart != 0xFAFA) + return 0; + else + return 1; +} + +/** + ****************************************************************************** + * @brief logbook_initNewdiveProfile. / + * creates header and smallHeader from diveState and global Settings + * and writes new lookboock entry on flash device + * diveState + * @author Peter Ryser + * @version V0.0.1 + * @date 22-April-2014 + ****************************************************************************** + * + * @param SDiveState* pInfo: Input + * @param SSettings* pSettings: Input +*/ + +void logbook_initNewdiveProfile(const SDiveState* pInfo, SSettings* pSettings) +{ + RTC_DateTypeDef Sdate; + RTC_TimeTypeDef Stime; + + for(int i = 0; i < sizeof(SLogbookHeader); i++) + { + ((uint8_t*)(&header))[i] = 0; + } + header.diveHeaderStart = 0xFAFA; + header.diveHeaderEnd = 0xFBFB; + header.samplingRate = 2; + if(pInfo->diveSettings.diveMode == DIVEMODE_OC) + { + for(int i = 0; i < 5; i++) + { + header.gasordil[i].oxygen_percentage = pSettings->gas[i+1].oxygen_percentage; + header.gasordil[i].helium_percentage = pSettings->gas[i+1].helium_percentage; + header.gasordil[i].note.uw = pSettings->gas[i+1].note.uw; + header.gasordil[i].depth_meter = pSettings->gas[i+1].depth_meter; + } + } + else + { + for(int i = 0; i < 5; i++) + { + header.gasordil[i].oxygen_percentage = pSettings->gas[i+6].oxygen_percentage; + header.gasordil[i].helium_percentage = pSettings->gas[i+6].helium_percentage; + header.gasordil[i].note.uw = pSettings->gas[i+6].note.uw; + header.gasordil[i].depth_meter = pSettings->gas[i+6].depth_meter; + } + + for(int i = 0; i < 5; i++) + { + header.setpoint[i].setpoint_cbar = pSettings->setpoint[i+1].setpoint_cbar; + header.setpoint[i].depth_meter = pSettings->setpoint[i+1].depth_meter; + } + } +// header.gasordil[pInfo->lifeData.actualGas.GasIdInSettings].depth_meter = 0; + + translateDate(pInfo->lifeData.dateBinaryFormat, &Sdate); + translateTime(pInfo->lifeData.timeBinaryFormat, &Stime); + header.dateYear = Sdate.Year; + header.dateMonth = Sdate.Month; + header.dateDay = Sdate.Date; + header.timeHour = Stime.Hours; + header.timeMinute = Stime.Minutes; + header.cnsAtBeginning = (uint16_t)((pInfo->lifeData.cns * 100) + 0.5f); + header.surfacePressure_mbar = (uint16_t)(pInfo->lifeData.pressure_surface_bar * 1000); + header.firmwareVersionHigh = firmwareVersion_16bit_high(); + header.firmwareVersionLow = firmwareVersion_16bit_low(); + header.logbookProfileVersion = LOGBOOK_VERSION; + header.salinity = pSettings->salinity; + header.diveNumber = pSettings->totalDiveCounter; + header.personalDiveCount = pSettings->personalDiveCount; + + header.diveMode = pInfo->diveSettings.diveMode; + header.CCRmode = pInfo->diveSettings.CCR_Mode; + header.lastDecostop_m = pSettings->last_stop_depth_meter; + + if(pInfo->diveSettings.deco_type.ub.standard == GF_MODE) + { + header.decoModel = 1; + header.gfLow_or_Vpm_conservatism = pInfo->diveSettings.gf_low; + header.gfHigh = pInfo->diveSettings.gf_high; + } + else + { + header.decoModel = 2; + header.gfLow_or_Vpm_conservatism = pInfo->diveSettings.vpm_conservatism; + header.gfHigh = 0; + } + + memcpy(header.n2Compartments, pInfo->lifeData.tissue_nitrogen_bar, 64); + memcpy(header.heCompartments, pInfo->lifeData.tissue_helium_bar, 64); + + logbook_SetCompartmentDesaturation(); + + ext_flash_start_new_dive_log_and_set_actualPointerSample((uint8_t*)&header); + + smallHeader.profileLength[0] = 0xFF; + smallHeader.profileLength[1] = 0xFF; + smallHeader.profileLength[2] = 0xFF; + smallHeader.samplingRate_seconds = 2; + smallHeader.numDivisors = 7; + + smallHeader.tempType = 0; + smallHeader.tempLength = 2; + smallHeader.tempDivisor = 6; + + smallHeader.deco_ndlType = 1; + smallHeader.deco_ndlLength = 2; + smallHeader.deco_ndlDivisor = 6; //= 6; + + /* GF in % at actual position */ + smallHeader.gfType = 2; + smallHeader.gfLength = 1; + smallHeader.gfDivisor = 0; //12; + + /* 3 Sensors: 8bit ppO2 in 0.01bar, 16bit voltage in 0,1mV */ + smallHeader.ppo2Type = 3; + smallHeader.ppo2Length = 9; + smallHeader.ppo2Divisor = 2; //2 + + /* last 15 stops in minutes (last, second_to_last, ... */ + /* last stop depth is defined in header */ + smallHeader.decoplanType = 4; + smallHeader.decoplanLength = 15; + smallHeader.decoplanDivisor = 12;//12; + + smallHeader.cnsType = 5; + smallHeader.cnsLength = 2; + smallHeader.cnsDivisor = 12; + + smallHeader.tankType = 6; + smallHeader.tankLength = 0; + smallHeader.tankDivisor = 0; + + logbook_writedata((void *) &smallHeader,sizeof(smallHeader)); + + clear_divisor(); +} + +/** + ****************************************************************************** + * @brief clear_divisor / clears divisor struct + * @author Peter Ryser + * @version V0.0.1 + * @date 22-April-2014 + ****************************************************************************** + * +*/ +void clear_divisor(void) +{ + divisor.cns = smallHeader.cnsDivisor - 1; + divisor.decoplan = smallHeader.decoplanDivisor - 1; + divisor.deco_ndl = smallHeader.deco_ndlDivisor - 1; + divisor.gradientFactor = smallHeader.gfDivisor -1 ; + divisor.ppo2 = smallHeader.ppo2Divisor - 1; + divisor.tank = smallHeader.tankDivisor - 1; + divisor.temperature = smallHeader.tempDivisor - 1; +} + + +/** + ****************************************************************************** + * @brief add16. / adds 16 bit variable to 8 bit array + * @author Peter Ryser + * @version V0.0.1 + * @date 22-April-2014 + ****************************************************************************** + * + * @param uint8_t *pos: Output 8 bit array + * @param uint16_t var: 16 bit variable +*/ +void addU16(uint8_t *pos, uint16_t var) +{ + *((uint16_t*)pos) = var; +} + +void addS16(uint8_t *pos, int16_t var) +{ + *((int16_t*)pos) = var; +} + +/** + ****************************************************************************** + * @brief logbook_writeSample. / Writes one logbook sampl + * @author Peter Ryser + * @date 22-April-2014 + * @version V0.0.2 + * @since 20-June-2016 + * @bug Deco/NDL Status fixed in V0.0.2 + + +****************************************************************************** + * + * @param SDiveState state: + */ + +void logbook_writeSample(SDiveState state) +{ + uint8_t sample[256]; + // int position = 0; + int length = 0; +// _Bool bEvent = 0; + uint8_t nextstopDepthMeter = 0; + uint16_t nextstopLengthSeconds = 0; + uint8_t nextstopLengthMinutes = 0; + bit8_Type eventByte1, eventByte2; + bit8_Type profileByteFlag; + int i = 0; + for(i = 0; i <256 ;i++) + sample[i] = 0; + addU16(sample, (uint16_t)(state.lifeData.depth_meter * 100)); + length += 2; + sample[2] = 0; + length++; + eventByte1.uw = 0; + eventByte2.uw = 0; + //uint16_t tmpU16 = 0; + const SDecoinfo * pDecoinfo; // new hw 160620 + + //BuildEevntyte 1 + // sub old 0-3 only one at a time + if(state.events.manualMarker) + { + eventByte1.uw = 6; + } + else + if(state.warnings.decoMissed) + { + eventByte1.uw = 2; + } + else + if(state.warnings.ppO2Low) + { + eventByte1.uw = 4; + } + else + if(state.warnings.ppO2High) + { + eventByte1.uw = 5; + } + else + if(state.warnings.lowBattery) + { + eventByte1.uw = 7; + } + else + if(state.warnings.slowWarning) + { + eventByte1.uw = 1; + } + // sub bit 4 to 7 + if(state.events.manuelGasSet) + { + eventByte1.ub.bit4 = 1; + } + if(state.events.gasChange) + { + eventByte1.ub.bit5 = 1; + } + if(state.events.setpointChange) + { + eventByte1.ub.bit6 = 1; + } + // sub bit 7 + eventbyte2 + if(state.events.bailout) + { + eventByte1.ub.bit7 = 1; + eventByte2.ub.bit0 = 1; + } + //Add EventByte 1 + if(eventByte1.uw > 0) + { + sample[length] = eventByte1.uw; + length++; + } + if(eventByte2.uw > 0) + { + sample[length] = eventByte2.uw; + length++; + } + //Add EventInfos + if(state.events.manuelGasSet) + { + //manual gas in %O2 & %He + sample[length] = state.events.info_manuelGasSetO2; + length += 1; + sample[length] = state.events.info_manuelGasSetHe; + length += 1; + } + if(state.events.gasChange) + { + //Current gas (gasid) + sample[length] = state.events.info_GasChange; + length += 1; + } + if(state.events.setpointChange) + { + //New setpoint in cbar + sample[length] = state.events.info_SetpointChange; + length += 1; + } + if(state.events.bailout) + { + //bailout gas in % O2 & %He + sample[length] = state.events.info_bailoutO2; + length += 1; + sample[length] = state.events.info_bailoutHe; + length += 1; + } + + + if(divisor.temperature == 0) + { + divisor.temperature = smallHeader.tempDivisor - 1; + addS16(&sample[length], (int16_t)((state.lifeData.temperature_celsius * 10.0f) + 0.5f)); + length += 2; + } + else + { + divisor.temperature--; + } + + + if(smallHeader.deco_ndlDivisor > 0) + { + if(divisor.deco_ndl == 0) + { + divisor.deco_ndl = smallHeader.deco_ndlDivisor - 1; + + if(stateUsed->diveSettings.deco_type.ub.standard == GF_MODE) + pDecoinfo = &stateUsed->decolistBuehlmann; + else if(stateUsed->diveSettings.deco_type.ub.standard == VPM_MODE) + pDecoinfo = &stateUsed->decolistVPM; + else // should not happen as only GF and VPM at the moment + { + sample[length] = 0; + length += 1; + sample[length] = 0; + length += 1; + } + + if(pDecoinfo->output_ndl_seconds > 0) + { + sample[length] = 0; + length += 1; + sample[length] = (uint8_t)pDecoinfo->output_ndl_seconds / 60; + length += 1; + } + else if(pDecoinfo->output_time_to_surface_seconds) + { + tHome_findNextStop(pDecoinfo->output_stop_length_seconds, &nextstopDepthMeter, &nextstopLengthSeconds); + nextstopLengthMinutes = (nextstopLengthSeconds +59 ) / 60; + + sample[length] = nextstopDepthMeter; + length += 1; + sample[length] = nextstopLengthMinutes; + length += 1; + } + else + { + sample[length] = 0; + length += 1; + sample[length] = 0; + length += 1; + } + } + else + { + divisor.deco_ndl --; + } + } + + + if(smallHeader.ppo2Divisor) + { + if(divisor.ppo2 == 0) + { + divisor.ppo2 = smallHeader.ppo2Divisor - 1; + + for(int i = 0; i <3; i++) + { + sample[length] = (uint8_t)(state.lifeData.ppO2Sensor_bar[i] * 100.0f + 0.5f); + length += 1; + addU16(&sample[length], (uint16_t)(state.lifeData.sensorVoltage_mV[i] * 10.0f + 0.5f)); + length += 2; + } + } + else + { + divisor.ppo2--; + } + } + + + if(smallHeader.decoplanDivisor) + { + if(divisor.decoplan == 0) + { + divisor.decoplan = smallHeader.decoplanDivisor - 1; + if(state.diveSettings.deco_type.ub.standard == VPM_MODE) + { + for(int i = 0; i <15; i++) + { + sample[length] = state.decolistVPM.output_stop_length_seconds[i] / 60; + length += 1; + } + } + else if(state.diveSettings.deco_type.ub.standard == GF_MODE) + { + for(int i = 0; i <15; i++) + { + sample[length] = state.decolistBuehlmann.output_stop_length_seconds[i] / 60; + length += 1; + } + } + else + { + for(int i = 0; i <15; i++) + { + sample[length] = 0; + length += 1; + } + } + // add16(&sample[length], state.temperature); + //length += 2; + } + else + { + divisor.decoplan --; + } + } + if(divisor.cns == 0) + { + divisor.cns = smallHeader.cnsDivisor - 1; + //addU16(&sample[length], (uint16_t)(state.lifeData.cns * 100.0f + 0.5f)); + addU16(&sample[length], (uint16_t)(state.lifeData.cns)); // hw 151110 cns is 0 to 100 % and more (not 0 to 1.00 and more) + length += 2; + } + else + { + divisor.cns--; + } + + profileByteFlag.uw = length - 3; + if(eventByte1.uw) + { + profileByteFlag.ub.bit7 = 1; + } + sample[2] = profileByteFlag.uw; + logbook_writedata((void *) sample,length); + +} + + + +uint16_t actual_depth1; +uint16_t actual_depth2; +uint16_t actual_length1; +uint16_t actual_length2; +uint16_t actual_inum; + +/** + ****************************************************************************** + * @brief readSample. / Reads data of one logbook sample + * @author Peter Ryser + * @version V0.0.1 + * @date 22-April-2014 + ****************************************************************************** + * + * @param int32_t* depth: output Value + * @param int16_t * gasid: output Value + * @param int32_t* temperature: output Value + * @param int32_t* sensor1, sensor2, sensor3: output Value + * @param int32_t* cns: output Value + * @return bytes read / 0 = reading Error + */ +uint16_t readSample(int32_t* depth, int16_t * gasid, int16_t* setpoint_cbar, int32_t* temperature, int32_t* sensor1, int32_t* sensor2, int32_t* sensor3, int32_t* cns, SManualGas* manualGas, int16_t* bailout, int16_t* decostopDepth) +{ + int length = 0; + _Bool bEvent = 0; + bit8_Type eventByte1, eventByte2; + bit8_Type profileByteFlag; + + eventByte1.uw = 0; + eventByte2.uw = 0; + uint8_t tempU8 = 0; + uint16_t temp = 0; + uint16_t bytesRead = 0; + + if(gasid) + *gasid = -1; + if(temperature) + *temperature = -1000; + if(sensor1) + *sensor1 = -1; + if(sensor2) + *sensor2 = -1; + if(sensor3) + *sensor3 = -1; + if(cns) + *cns = -1; + if(setpoint_cbar) + *setpoint_cbar = -1; + if(bailout) + *bailout = -1; + if(manualGas) + { + manualGas->percentageO2 =-1; + manualGas->percentageHe =-1; + } + if(decostopDepth) + *decostopDepth = -1; + + ext_flash_read_next_sample_part( (uint8_t*)&temp, 2); + if(depth) + *depth = (int32_t)temp; + bytesRead += 2; + + ext_flash_read_next_sample_part( &profileByteFlag.uw, 1); + bytesRead ++; + + bEvent = profileByteFlag.ub.bit7; + profileByteFlag.ub.bit7 = 0; + length = profileByteFlag.uw; + + if(bEvent) + { + ext_flash_read_next_sample_part( &eventByte1.uw, 1); + bytesRead ++; + + length--; + + //second event byte + if(eventByte1.ub.bit7) + { + ext_flash_read_next_sample_part( &eventByte2.uw, 1); + bytesRead ++; + length--; + } + else + { + eventByte2.uw = 0; + } + + //manual Gas Set + if( eventByte1.ub.bit4) + { + //Evaluate manual Gas + ext_flash_read_next_sample_part( (uint8_t*)&tempU8, 1); + bytesRead +=1; + length -= 1; + manualGas->percentageO2 = tempU8; + ext_flash_read_next_sample_part( (uint8_t*)&tempU8, 1); + bytesRead +=1; + length -= 1; + manualGas->percentageHe = tempU8; + if(gasid) + *gasid = 0; + } + //gas change + if( eventByte1.ub.bit5) + { + ext_flash_read_next_sample_part( &tempU8, 1); + bytesRead +=1; + length -= 1; + if(gasid) + *gasid = (uint16_t)tempU8; + } + //SetpointChange + if( eventByte1.ub.bit6) + { + ext_flash_read_next_sample_part( &tempU8, 1); + *setpoint_cbar = tempU8; + bytesRead +=1; + length -= 1; + } + + // second event Byte + //bailout + if(eventByte2.ub.bit1) + { + //evaluate bailout gas Gas + *bailout = 1; + + ext_flash_read_next_sample_part( (uint8_t*)&tempU8, 1); + bytesRead +=1; + length -= 1; + manualGas->percentageO2 = tempU8; + ext_flash_read_next_sample_part( (uint8_t*)&tempU8, 1); + bytesRead +=1; + length -= 1; + manualGas->percentageHe = tempU8; + + if(gasid) + *gasid = 0; + } + } + + if(divisor.temperature == 0) + { + divisor.temperature = smallHeader.tempDivisor - 1; + ext_flash_read_next_sample_part( (uint8_t*)&temp, 2); + bytesRead +=2; + length -= 2; + if(temperature) + { + *temperature = (int32_t)temp; + } + } + else + { + divisor.temperature--; + } + + if(smallHeader.deco_ndlDivisor > 0) + { + if(divisor.deco_ndl == 0) + { + divisor.deco_ndl = smallHeader.deco_ndlDivisor - 1; + ext_flash_read_next_sample_part( &tempU8, 1); + if(decostopDepth) + { + *decostopDepth = tempU8 * 100; + } + ext_flash_read_next_sample_part( &tempU8, 1); + bytesRead += 2; + length -= 2; + } + else + { + divisor.deco_ndl--; + } + } + + if(divisor.ppo2 == 0) + { + int32_t ppO2Tmp = 0; + divisor.ppo2 = smallHeader.ppo2Divisor -1; + for(int i = 0; i <3 ; i++) + { + ext_flash_read_next_sample_part( &tempU8, 1); + ppO2Tmp += tempU8; + bytesRead +=1; + length -= 1; + ext_flash_read_next_sample_part( (uint8_t*)&temp, 2); + bytesRead +=2; + length -= 2; + if(sensor1 && (i==0)) + *sensor1 = (((int32_t)tempU8) * 0xFFFF) + temp; + if(sensor2 && (i==1)) + *sensor2 = (((int32_t)tempU8) * 0xFFFF) + temp; + if(sensor3 && (i==2)) + *sensor3 = (((int32_t)tempU8) * 0xFFFF) + temp; + } + } + else + { + divisor.ppo2--; + } + + if(smallHeader.decoplanDivisor > 0) + { + if(divisor.decoplan == 0) + { + divisor.decoplan = smallHeader.decoplanDivisor - 1; + for(int i = 0; i <15; i++) + ext_flash_read_next_sample_part( &tempU8, 1); + bytesRead += 15; + length -= 15; + } + else + { + divisor.decoplan--; + } + } + + + + if(divisor.cns == 0) + { + divisor.cns = smallHeader.cnsDivisor - 1; + + ext_flash_read_next_sample_part( (uint8_t*)&temp, 2); + bytesRead +=2; + length -= 2; + if(cns) + { + *cns = (int32_t)temp; + } + } + else + { + divisor.cns--; + } + + if (length != 0) + return 0; + + return bytesRead; +} +/** + ****************************************************************************** + * @brief logbook_readSampleData. / Reads sample data of whole logbook entry + * @author Peter Ryser + * @version V0.0.1 + * @date 22-April-2014 + ****************************************************************************** + * + * @param uint8_t StepBackwards: witch lookbook entry? + * @param uint16_t length : maxlength of output arrays + * @param int32_t* depth : output array + * @param int16_t * gasid : output array + * @param int32_t* temperature : output array + * @param int32_t* ppo2 : output array + * @param int32_t* cns : output array + * @return length of output + */ +uint16_t logbook_readSampleData(uint8_t StepBackwards, uint16_t length,uint16_t* depth, uint8_t* gasid, int16_t* temperature, uint16_t* ppo2, uint16_t* setpoint, uint16_t* sensor1, uint16_t* sensor2, uint16_t* sensor3, uint16_t* cns, uint8_t* bailout, uint16_t* decostopDepth) +{ + //Test read + //SLogbookHeader header; + + //logbook_getHeader(&header); + SLogbookHeader header; + int iNum; + int firstgasid = 0; + int retVal = 0; + int compression = 0; + int i; + // uint32_t diveTime_seconds; + int32_t depthVal = 0; + int16_t gasidVal = 0; + int16_t setPointVal = 0; + int16_t bailoutVal = 0; + int16_t bailoutLast = 0; + uint16_t setPointLast = 0; + int32_t temperatureVal = 0; + int32_t sensor1Val = 0; + int32_t sensor2Val = 0; + int32_t sensor3Val = 0; + int32_t sensor1Last = 0; + int32_t sensor2Last = 0; + int32_t sensor3Last = 0; + int32_t cnsVal = 0; + int32_t depthLast = 0; + int16_t gasidLast = 0; + int32_t temperatureLast = 0; + int32_t temperatureFirst = 0; + int32_t cnsLast = 0; + int16_t decostepDepthVal = 0; + int16_t decostepDepthLast = 0; + + SManualGas manualGasVal; + SManualGas manualGasLast; + manualGasLast.percentageO2 = 0; + manualGasLast.percentageHe = 0; + + float ambiant_pressure_bar = 0; + float ppO2 = 0; + ext_flash_read_dive_header((uint8_t*)&header, StepBackwards); + for(i = 0;i< 5;i++) + { + if(header.gasordil[i].note.ub.first) + break; + } + firstgasid = i + 1; + if(header.diveMode == DIVEMODE_CCR) + setPointLast = header.setpoint[0].setpoint_cbar; + else + setPointLast = 0; + //diveTime_seconds = header.diveTime_seconds ; + for(compression = 1; compression < 100; compression ++) + { + if((header.total_diveTime_seconds / header.samplingRate)/compression <= length) + break; + } + + + for(i = 0;i< length;i++) + { + if(depth) + depth[i] = 0; + if(temperature) + temperature[i] = 0; + if(gasid) + gasid[i] = 0; + if(ppo2) + ppo2[i] = 0; + if(setpoint) + setpoint[i] = 0; + if(sensor1) + sensor1[i] = 0; + if(sensor2) + sensor2[i] = 0; + if(sensor3) + sensor3[i] = 0; + if(cns) + cns[i] = 0; + } + //We start with fist gasid + gasidLast = firstgasid; + + + //uint16_t* ppo2, uint16_t* cns# + uint32_t totalNumberOfBytes = 0; + uint32_t bytesRead = 0; + ext_flash_open_read_sample( StepBackwards,&totalNumberOfBytes); + ext_flash_read_next_sample_part((uint8_t*)&smallHeader, sizeof(SSmallHeader)); + bytesRead += sizeof(SSmallHeader); + + clear_divisor(); + + iNum = 0; + int counter = 0; + temperatureLast = -1000; + while ((bytesRead < totalNumberOfBytes) && (iNum < length)) + { + ext_flash_set_entry_point(); + divisorBackup = divisor; + retVal = readSample(&depthVal,&gasidVal, &setPointVal, &temperatureVal, &sensor1Val, &sensor2Val, &sensor3Val, &cnsVal, &manualGasVal, &bailoutVal, &decostepDepthVal); + + if(retVal == 0) + { + //Error try to read again!!! + ext_flash_reopen_read_sample_at_entry_point(); + divisor = divisorBackup; + retVal = readSample(&depthVal,&gasidVal,&setPointVal, &temperatureVal, &sensor1Val, &sensor2Val, &sensor3Val, &cnsVal, &manualGasVal, &bailoutVal, &decostepDepthVal); + + if(retVal == 0) + break; + } + bytesRead +=retVal; + + //if for some variable no new value is in the sample for (z.B. gasidVal = -1), we take the last value + if(depthVal == -1) + depthVal = depthLast; + else + depthLast = depthVal; + + if(gasidVal == -1) + gasidVal = gasidLast; + else + gasidLast = gasidVal; + + if(temperatureVal == -1000) + temperatureVal = temperatureLast; + else + { + if(temperatureLast == -1000) + temperatureFirst = temperatureVal; + temperatureLast = temperatureVal; + } + + if(setPointVal == -1) + setPointVal = setPointLast; + else + setPointLast = setPointVal; + + if(sensor1Val == -1) + sensor1Val = sensor1Last; + else + sensor1Last = sensor1Val; + + if(sensor2Val == -1) + sensor2Val = sensor2Last; + else + sensor2Last = sensor2Val; + + if(sensor3Val == -1) + sensor3Val = sensor3Last; + else + sensor3Last = sensor3Val; + + if(cnsVal == -1) + cnsVal = cnsLast; + else + cnsLast = cnsVal; + + if(manualGasVal.percentageO2 == -1) + manualGasVal = manualGasLast; + else + manualGasLast = manualGasVal; + + if(bailoutVal == -1) + bailoutVal = bailoutLast; + else + bailoutLast = bailoutVal; + + if(decostepDepthVal == -1) + decostepDepthVal = decostepDepthLast; + else + decostepDepthLast = decostepDepthVal; + + counter++; + // Heed compression + // Write here to arrays + if(counter == compression) + { + if(depth) + depth[iNum] = depthVal; + if(gasid) + gasid[iNum] = gasidVal; + if(temperature) + temperature[iNum] = temperatureVal; + if(cns) + cns[iNum] = cnsVal; + if(bailout) + bailout[iNum] = bailoutVal; + if(decostopDepth) + decostopDepth[iNum] = decostepDepthVal; + + if(ppo2) + { + //Calc ppo2 - Values + SGas gas; + gas.setPoint_cbar = setPointVal; + if(gasidVal > 0) + { + gas.helium_percentage = header.gasordil[gasidVal - 1].helium_percentage; + gas.nitrogen_percentage = 100 - gas.helium_percentage - header.gasordil[gasidVal - 1].oxygen_percentage; + } + else + { + gas.helium_percentage = manualGasVal.percentageHe; + gas.nitrogen_percentage = 100 - gas.helium_percentage - manualGasVal.percentageO2; + } + ambiant_pressure_bar =((float)(depthVal + header.surfacePressure_mbar))/1000; + ppO2 = decom_calc_ppO2(ambiant_pressure_bar, &gas ); + ppo2[iNum] = (uint16_t) ( ppO2 * 100); + } + + if(setpoint) + setpoint[iNum] = setPointVal; + + if(sensor1) + sensor1[iNum] = (sensor1Val / 0xFFFF) & 0xFF; + if(sensor2) + sensor2[iNum] = (sensor2Val / 0xFFFF) & 0xFF; + if(sensor3) + sensor3[iNum] = (sensor3Val / 0xFFFF) & 0xFF; + iNum++; + counter = 0; + } + } + + // Fix first Temperature Entries 150930 hw + if(temperature) + { + int i = 0; + while((temperature[i] == -1000) && (i < iNum)) + temperature[i++] = temperatureFirst; + } + + ext_flash_close_read_sample(); + return iNum; +} + + +/******************************************************************************** + * @brief logbook_InitAndWrite. / Controls writing of logbook + * Should be called ten times per second + * Automatically Initializes logbook at beginning of dive, + * write samples every 2 seconds + * and finishes logbook after end of dive +*********************************************************************************/ + +void logbook_InitAndWrite(void) +{ + SSettings *pSettings = settingsGetPointer(); + static uint8_t bDiveMode = 0; + static uint32_t tickstart = 0; + uint32_t ticksdiff = 0; + uint32_t lasttick = 0; + static float min_temperature_float_celsius = 0; + + const SDiveState * pStateReal = stateRealGetPointer(); + + if(!bDiveMode) + { + if((pStateReal->mode == MODE_DIVE) && (pStateReal->diveSettings.diveMode != DIVEMODE_Apnea) && (pStateReal->lifeData.dive_time_seconds >= 5)) + { + //InitdiveProfile + pSettings->totalDiveCounter++; + logbook_initNewdiveProfile(pStateReal,settingsGetPointer()); + min_temperature_float_celsius = pStateReal->lifeData.temperature_celsius; + //Write logbook sample + logbook_writeSample(*pStateReal); + resetEvents(); + tickstart = HAL_GetTick(); + bDiveMode = 1; + } + } + else if((pStateReal->mode == MODE_DIVE) && (pStateReal->diveSettings.diveMode != DIVEMODE_Apnea)) + { + lasttick = HAL_GetTick(); + ticksdiff = time_elapsed_ms(tickstart,lasttick); + // + if(ticksdiff >= 2000) + { + //Write logbook sample + logbook_writeSample(*pStateReal); + resetEvents(); + if(min_temperature_float_celsius > pStateReal->lifeData.temperature_celsius) + min_temperature_float_celsius = pStateReal->lifeData.temperature_celsius; + tickstart = lasttick; + if((bDiveMode == 1) && (pStateReal->lifeData.dive_time_seconds >= pSettings->divetimeToCreateLogbook)) + { + ext_flash_create_new_dive_log((uint8_t*)&header); + /** save settings + * with new lastDiveLogId and time and day + */ + pSettings->personalDiveCount++; + if(pSettings->logbookOffset) + { + pSettings->logbookOffset++; + } + ext_flash_write_settings(); + ext_flash_disable_protection_for_logbook(); + bDiveMode = 3; + } + if(bDiveMode == 3) + logbook_UpdateHeader(); + } + } + else if(bDiveMode == 3) + { + //End of Dive + logbook_SetAverageDepth(pStateReal->lifeData.average_depth_meter); + logbook_SetMinTemperature(min_temperature_float_celsius); + logbook_SetMaxCNS(pStateReal->lifeData.cns); + logbook_SetCompartmentDesaturation(); + logbook_SetLastStop(pStateReal->diveSettings.last_stop_depth_bar); + logbook_EndDive(); + bDiveMode = 0; + } else + { + ext_flash_enable_protection(); + } +} + + +/* Private functions ---------------------------------------------------------*/ + +/******************************************************************************** + * @brief logbook_UpdateHeader. / + * set date, time, max depth. etc. pp. + * the internal pointer to the end of profile and length will be set by + ext_flash_close_new_dive_log() in externLogbookFlash.c + * @author heinrichs weikamp gmbh + * @version V0.0.1 + * @date 27-Nov-2014 +*********************************************************************************/ +void logbook_UpdateHeader(void) +{ + const SDiveState * pStateReal = stateRealGetPointer(); + SSettings *pSettings = settingsGetPointer(); +// uint16_t secondsAtShallow = 0; + RTC_DateTypeDef Sdate; + RTC_TimeTypeDef Stime; + uint32_t time1_u32, time2_u32; + uint32_t divetimeHelper; + + /* time and day */ + /* don't update CHANGE 160224 hw, maybe save actual time and date at other place + translateDate(pStateReal->lifeData.dateBinaryFormat, &Sdate); + translateTime(pStateReal->lifeData.timeBinaryFormat, &Stime); + + header.dateYear = Sdate.Year; + header.dateMonth = Sdate.Month; + header.dateDay = Sdate.Date; + header.timeHour = Stime.Hours; + header.timeMinute = Stime.Minutes; + */ + /// 160315 Quick fix for empty date problem + if((!(header.dateYear)) || (!(header.dateMonth)) || (!(header.dateDay))) + { + translateDate(pStateReal->lifeData.dateBinaryFormat, &Sdate); + translateTime(pStateReal->lifeData.timeBinaryFormat, &Stime); + + header.dateYear = Sdate.Year; + header.dateMonth = Sdate.Month; + header.dateDay = Sdate.Date; + + time1_u32 = (uint32_t)header.timeMinute + (uint32_t)(header.timeHour * 60); + time2_u32 = (uint32_t)Stime.Minutes + (uint32_t)(Stime.Hours * 60); + if(time2_u32 < time1_u32) + { + if(header.dateDay > 1) + { + header.dateDay -= 1; + } + else + { + header.dateMonth --; + if(!header.dateMonth) + { + header.dateYear--; + header.dateMonth = 12; + header.dateDay = 31; + } + else + { + if(header.dateMonth == 2) + header.dateDay = 28; + else + if((header.dateMonth == 4) || (header.dateMonth == 6) || (header.dateMonth == 9) || (header.dateMonth == 11)) + header.dateDay = 30; + else + header.dateDay = 31; + } + } + } + } + + /* duration */ + header.total_diveTime_seconds = pStateReal->lifeData.dive_time_seconds; + header.maxDepth = pStateReal->lifeData.max_depth_meter * 100; + + /* old: + + secondsAtShallow = pSettings->timeoutDiveReachedZeroDepth; + if(pStateReal->lifeData.dive_time_seconds <= secondsAtShallow) + secondsAtShallow = 0; + header.diveTimeMinutes = (header.total_diveTime_seconds - secondsAtShallow )/ 60; + header.diveTimeSeconds = header.total_diveTime_seconds - secondsAtShallow - (header.diveTimeMinutes * 60); + */ + divetimeHelper = pStateReal->lifeData.dive_time_seconds_without_surface_time; + header.diveTimeMinutes = (uint16_t)(divetimeHelper/60); + divetimeHelper -= 60 * (uint32_t)header.diveTimeMinutes; + header.diveTimeSeconds = (uint16_t)divetimeHelper; + + /* deco algorithm (final) */ + if(pStateReal->diveSettings.deco_type.ub.standard == GF_MODE) + { + header.decoModel = 1; + header.gfLow_or_Vpm_conservatism = pStateReal->diveSettings.gf_low; + header.gfHigh = pStateReal->diveSettings.gf_high; + } + else + { + header.decoModel = 2; + header.gfLow_or_Vpm_conservatism = pStateReal->diveSettings.vpm_conservatism; + header.gfHigh = 0; + } + + /* tissue load */ + memcpy(header.n2Compartments, pStateReal->lifeData.tissue_nitrogen_bar, 64); + memcpy(header.heCompartments, pStateReal->lifeData.tissue_helium_bar, 64); + +} + + +void logbook_SetAverageDepth(float average_depth_meter) +{ + header.averageDepth_mbar = (uint16_t)(average_depth_meter * 100); +} + + +void logbook_SetMinTemperature(float min_temperature_celsius) +{ + header.minTemp = (int16_t)((min_temperature_celsius * 10.0f) + 0.5f); +} + + +void logbook_SetMaxCNS(float max_cns_percentage) +{ + if(max_cns_percentage < 9999) + header.maxCNS = (uint16_t)(max_cns_percentage); + else + header.maxCNS = 9999; +} + + +void logbook_SetDesaturationTime(void) +{ + header.desaturationTime = 48 * 60; +} + + +void logbook_SetCompartmentDesaturation(void) +{ + const SDiveState * pStateReal = stateRealGetPointer(); + + decom_tissues_desaturation_time(&pStateReal->lifeData, &secondaryInformation); + for(int i=0;i<16;i++) + { + if(secondaryInformation.tissue_nitrogen_desaturation_time_minutes[i] <= (15 * 255)) + header.n2CompartDesatTime_min[i] = (uint8_t)((secondaryInformation.tissue_nitrogen_desaturation_time_minutes[i] + 14) / 15); + else + header.n2CompartDesatTime_min[i] = 255; + if(secondaryInformation.tissue_helium_desaturation_time_minutes[i] <= (15 * 255)) + header.heCompartDesatTime_min[i] = (uint8_t)((secondaryInformation.tissue_helium_desaturation_time_minutes[i] + 14 )/ 15); + else + header.heCompartDesatTime_min[i] = 255; + } +} + +void logbook_SetLastStop(float last_stop_depth_bar) +{ + header.lastDecostop_m = (uint8_t)(last_stop_depth_bar / 10.0f); +} + +void logbook_writedata(void * data, int length_byte) +{ + ext_flash_write_sample(data, length_byte); +} + + +/******************************************************************************** + * @brief logbook_build_ostc3header. / + * @author heinrichs weikamp gmbh + * @version V0.0.2 + * @date 27-Nov-2014 +*********************************************************************************/ +SLogbookHeaderOSTC3 * logbook_build_ostc3header(SLogbookHeader* pHead) +{ + convert_Type data; + + memcpy(headerOSTC3.diveHeaderStart, &pHead->diveHeaderStart, 2); + memcpy(headerOSTC3.pBeginProfileData, &pHead->pBeginProfileData, 3); + memcpy(headerOSTC3.pEndProfileData, &pHead->pEndProfileData, 3); + + data.u8bit.byteHigh = 0; + data.u8bit.byteLow = pHead->profileLength[0]; + data.u8bit.byteMidLow = pHead->profileLength[1]; + data.u8bit.byteMidHigh = pHead->profileLength[2]; + + if(data.u32bit != 0xFFFFFF) + data.u32bit += 3; + + headerOSTC3.profileLength[0] = data.u8bit.byteLow; + headerOSTC3.profileLength[1] = data.u8bit.byteMidLow; + headerOSTC3.profileLength[2] = data.u8bit.byteMidHigh; + + memcpy(headerOSTC3.gasordil, pHead->gasordil, 20); + + if(pHead->logbookProfileVersion == LOGBOOK_VERSION) + { + headerOSTC3.logbookProfileVersion = LOGBOOK_VERSION_OSTC3; + memcpy(headerOSTC3.personalDiveCount, &pHead->personalDiveCount, 2); + headerOSTC3.safetyDistance_10cm = 0; + + for(int i=0;i<5;i++) + { + if(!pHead->gasordil[i].note.ub.active) + headerOSTC3.gasordil[3 + (i*4)] = 0; + else if(pHead->gasordil[i].note.ub.first) + { + /* depth = 0, note = 1 */ + headerOSTC3.gasordil[2 + (i*4)] = 0; + headerOSTC3.gasordil[3 + (i*4)] = 1; + } + else if( pHead->gasordil[i].depth_meter) + { + /* note = 3 */ + headerOSTC3.gasordil[3 + (i*4)] = 3; + } + } + } + else + { + headerOSTC3.logbookProfileVersion = 0xFF; + headerOSTC3.personalDiveCount[0] = 0xFF; + headerOSTC3.personalDiveCount[1] = 0xFF; + headerOSTC3.safetyDistance_10cm = 0xFF; + } + + headerOSTC3.dateYear = pHead->dateYear; + headerOSTC3.dateMonth = pHead->dateMonth; + headerOSTC3.dateDay = pHead->dateDay; + headerOSTC3.timeHour = pHead->timeHour; + headerOSTC3.timeMinute = pHead->timeMinute; + + + memcpy(headerOSTC3.maxDepth, &pHead->maxDepth, 2); + memcpy(headerOSTC3.diveTimeMinutes, &pHead->diveTimeMinutes, 2); + + headerOSTC3.diveTimeSeconds = pHead->diveTimeSeconds; + + memcpy(headerOSTC3.minTemp, &pHead->minTemp, 2); + memcpy(headerOSTC3.surfacePressure_mbar,&pHead->surfacePressure_mbar, 2); + memcpy(headerOSTC3.desaturationTime, &pHead->desaturationTime, 2); + + headerOSTC3.firmwareVersionHigh = pHead->firmwareVersionHigh; + headerOSTC3.firmwareVersionLow = pHead->firmwareVersionLow; + + memcpy(headerOSTC3.batteryVoltage, &pHead->batteryVoltage, 2); + + headerOSTC3.samplingRate = pHead->samplingRate; + + memcpy(headerOSTC3.cnsAtBeginning, &pHead->cnsAtBeginning, 2); + + headerOSTC3.gfAtBeginning = pHead->gfAtBeginning; + headerOSTC3.gfAtEnd = pHead->gfAtEnd; + + memcpy(headerOSTC3.setpoint, pHead->setpoint, 10); + + headerOSTC3.salinity = pHead->salinity; + + memcpy(headerOSTC3.maxCNS, &pHead->maxCNS, 2); + memcpy(headerOSTC3.averageDepth_mbar, &pHead->averageDepth_mbar, 2); + memcpy(headerOSTC3.total_diveTime_seconds,&pHead->total_diveTime_seconds, 2); + + headerOSTC3.gfLow_or_Vpm_conservatism = pHead->gfLow_or_Vpm_conservatism; + headerOSTC3.gfHigh = pHead->gfHigh; + headerOSTC3.decoModel = pHead->decoModel; + + memcpy(headerOSTC3.diveNumber, &pHead->diveNumber, 2); + + headerOSTC3.diveMode = pHead->diveMode; + headerOSTC3.CCRmode = pHead->CCRmode; + + memcpy(headerOSTC3.n2CompartDesatTime_min,pHead->n2CompartDesatTime_min, 16); + memcpy(headerOSTC3.n2Compartments, pHead->n2Compartments, 64); + memcpy(headerOSTC3.heCompartDesatTime_min,pHead->heCompartDesatTime_min, 16); + memcpy(headerOSTC3.heCompartments, pHead->heCompartments, 64); + + headerOSTC3.lastDecostop_m = pHead->lastDecostop_m; + + memcpy(headerOSTC3.hwHudBattery_mV, &pHead->hwHudBattery_mV, 2); + + headerOSTC3.hwHudLastStatus = pHead->hwHudLastStatus; + + memcpy(headerOSTC3.batteryGaugeRegisters,&pHead->batteryGaugeRegisters, 6); + + + memcpy(headerOSTC3.diveHeaderEnd, &pHead->diveHeaderEnd, 2); + + return &headerOSTC3; +} + + +/******************************************************************************** + * @brief logbook_build_ostc3header_compact. / + * @author heinrichs weikamp gmbh + * @version V0.0.1 + * @date 31-Juli-2015 +*********************************************************************************/ +SLogbookHeaderOSTC3compact * logbook_build_ostc3header_compact(SLogbookHeader* pHead) +{ + convert_Type data; + + data.u8bit.byteHigh = 0; + data.u8bit.byteLow = pHead->profileLength[0]; + data.u8bit.byteMidLow = pHead->profileLength[1]; + data.u8bit.byteMidHigh = pHead->profileLength[2]; + + if(data.u32bit != 0xFFFFFF) + { + data.u32bit += 3; + + headerOSTC3compact.profileLength[0] = data.u8bit.byteLow; + headerOSTC3compact.profileLength[1] = data.u8bit.byteMidLow; + headerOSTC3compact.profileLength[2] = data.u8bit.byteMidHigh; + + headerOSTC3compact.dateYear = pHead->dateYear; + headerOSTC3compact.dateMonth = pHead->dateMonth; + headerOSTC3compact.dateDay = pHead->dateDay; + headerOSTC3compact.timeHour = pHead->timeHour; + headerOSTC3compact.timeMinute = pHead->timeMinute; + + memcpy(headerOSTC3compact.maxDepth, &pHead->maxDepth, 2); + memcpy(headerOSTC3compact.diveTimeMinutes, &pHead->diveTimeMinutes, 2); + + headerOSTC3compact.diveTimeSeconds = pHead->diveTimeSeconds; + + + headerOSTC3compact.totalDiveNumberLow = pHead->diveNumber & 0xFF; + headerOSTC3compact.totalDiveNumberHigh = (uint8_t)(pHead->diveNumber/256); + headerOSTC3compact.profileVersion = 0x24; // Logbook-Profile version, 0x24 = date and time is start not end + } + else + { + memset(&headerOSTC3compact, 0xFF, sizeof(SLogbookHeaderOSTC3compact)); + } + return &headerOSTC3compact; +} + + +/** + ****************************************************************************** + * @brief logbook_readSampleData. / Reads sample data of whole logbook entry + * @author Peter Ryser + * @version V0.0.1 + * @date 22-April-2014 + ****************************************************************************** + * + * @param uint8_t StepBackwards: witch lookbook entry? + * @param uint16_t length : maxlength of output arrays + * @param int32_t* depth : output array + * @param int16_t * gasid : output array + * @param int32_t* temperature : output array + * @param int32_t* ppo2 : output array + * @param int32_t* cns : output array + * @return length of output + */ +void logbook_recover_brokenlog(uint8_t headerId) +{ + int16_t retVal; + int32_t depthVal = 0; + int16_t gasidVal = 0; + int16_t setPointVal = 0; + int16_t bailoutVal = 0; + int32_t temperatureVal = 0; + int32_t sensor1Val = 0; + int32_t sensor2Val = 0; + int32_t sensor3Val = 0; + int32_t cnsVal = 0; + SManualGas manualGasVal; + + //uint16_t* ppo2, uint16_t* cns# + uint32_t bytesRead = 0; + + ext_flash_read_block_start(); + ext_flash_read_next_sample_part((uint8_t*)&smallHeader, sizeof(SSmallHeader)); + bytesRead += sizeof(SSmallHeader); + + clear_divisor(); + + + int sampleCounter = 0; + int maxdepth = 0; + uint32_t avrdepth = 0; + while (true) + { + + ext_flash_set_entry_point(); + divisorBackup = divisor; + retVal = readSample(&depthVal,&gasidVal, &setPointVal, &temperatureVal, &sensor1Val, &sensor2Val, &sensor3Val, &cnsVal, &manualGasVal, &bailoutVal, NULL); + if(retVal == 0) + { + //Error try to read again!!! + ext_flash_reopen_read_sample_at_entry_point(); + divisor = divisorBackup; + retVal = readSample(&depthVal,&gasidVal, &setPointVal, &temperatureVal, &sensor1Val, &sensor2Val, &sensor3Val, &cnsVal, &manualGasVal, &bailoutVal, NULL); + + if(retVal == 0) + { + //Error try to read again!!! + ext_flash_reopen_read_sample_at_entry_point(); + divisor = divisorBackup; + retVal = readSample(&depthVal,&gasidVal, &setPointVal, &temperatureVal, &sensor1Val, &sensor2Val, &sensor3Val, &cnsVal, &manualGasVal, &bailoutVal, NULL); + + if(retVal == 0) + { + ext_flash_reopen_read_sample_at_entry_point(); + break; + } + + } + } + if(depthVal > maxdepth) + maxdepth = depthVal; + avrdepth += depthVal; + sampleCounter++; + bytesRead +=retVal; + } + avrdepth/= sampleCounter; + ext_flash_close_read_sample(); + SLogbookHeader header; + + ext_flash_read_dive_header2((uint8_t*) &header, headerId, false); + header.total_diveTime_seconds = sampleCounter * header.samplingRate; + header.diveTimeMinutes = header.total_diveTime_seconds /60; + header.diveTimeSeconds = header.total_diveTime_seconds - header.diveTimeMinutes * 60; + header.maxDepth = maxdepth; + header.averageDepth_mbar = avrdepth; + SSettings * settings = settingsGetPointer(); + settings->lastDiveLogId = headerId; + ext_flash_close_new_dive_log((uint8_t *)&header); +} + +/************************ (C) COPYRIGHT heinrichs weikamp *****END OF FILE****/