changeset 470:dd0d0952ef35

Merged in Ideenmodellierer/ostc4/Improve_Logtansfer (pull request #42) Improve Logtansfer
author heinrichsweikamp <bitbucket@heinrichsweikamp.com>
date Wed, 15 Apr 2020 07:01:11 +0000
parents dddfe7917131 (current diff) 04d94851cd1b (diff)
children 73da921869d9 8a375f0544d9 edfc1a464b42
files
diffstat 7 files changed, 356 insertions(+), 277 deletions(-) [+]
line wrap: on
line diff
--- a/Discovery/Inc/configuration.h	Wed Apr 08 16:34:54 2020 +0200
+++ b/Discovery/Inc/configuration.h	Wed Apr 15 07:01:11 2020 +0000
@@ -40,7 +40,10 @@
 /* Enable this to skip coplete scan of dive log during startup */
 /* #define TRUST_LOG_CONSISTENCY */
 
-/* Enable this to reset the profile data by pressing enter within log info menu */
-/* #define ENABLE_PROFILE_RESET */
+/* Enable this to transfer additional data list last dive ID and last sample index during raw data requests */
+/* define SEND_DATA_DETAILS */
+
+/* Enable to activate a menu item in reset menu which provide sample ring analysis / repair functionality */
+/* #define ENABLE_ANALYSE_SAMPLES */
 
 #endif
--- a/Discovery/Inc/externLogbookFlash.h	Wed Apr 08 16:34:54 2020 +0200
+++ b/Discovery/Inc/externLogbookFlash.h	Wed Apr 15 07:01:11 2020 +0000
@@ -141,6 +141,9 @@
 void ext_flash_read_header_memory(uint8_t *data);
 void ext_flash_write_header_memory(uint8_t *data);
 
+void ext_flash_read_sample_memory(uint8_t *data,uint16_t blockId);
+void ext_flash_write_sample_memory(uint8_t *data,uint16_t blockId);
+
 void ext_flash_erase_logbook(void);
 void ext_flash_erase_chip(void);
 void ext_flash_erase_firmware(void);
@@ -165,6 +168,9 @@
 
 uint32_t ext_flash_AnalyseSampleBuffer(char *pstrResult);
 void ext_flash_CloseSector(void);
-void ext_flash_invalidate_sample_index(uint32_t sectorStart);
+
+uint32_t ext_flash_read_profilelength_small_header(uint32_t smallHeaderAddr);
+uint8_t ext_flash_SampleOverrunValid(void);
+
 
 #endif /* EXTERN_LOGBOOK_FLASH_H */
--- a/Discovery/Src/externLogbookFlash.c	Wed Apr 08 16:34:54 2020 +0200
+++ b/Discovery/Src/externLogbookFlash.c	Wed Apr 15 07:01:11 2020 +0000
@@ -787,7 +787,6 @@
 				actualAddress = SAMPLESTART;
 			}
 			preparedPageAddress = actualAddress;
-			ext_flash_invalidate_sample_index(preparedPageAddress);
 			ext_flash_erase64kB();
 			actualAddress = actualAdressBackup;
 		}
@@ -972,7 +971,7 @@
 
 
 //  ===============================================================================
-//  ext_flash_read_header_memory
+//  ext_flash_write_header_memory
 /// @brief		This function erases and overwrites the entire logbook header block
 ///	@date			04-April-2016
 ///
@@ -985,6 +984,24 @@
 	ef_write_block(data, 0x40000, EF_HEADER, 0);
 }
 
+void ext_flash_read_sample_memory(uint8_t *data,uint16_t blockId)
+{
+	actualAddress = SAMPLESTART;
+	actualAddress += blockId * 0x8000;	/* add 32k Block offset */
+	actualPointerSample = actualAddress;
+	ext_flash_read_block_start();
+	ext_flash_read_block_multi(data, 0x8000, EF_SAMPLE);
+	ext_flash_read_block_stop();
+}
+
+void ext_flash_write_sample_memory(uint8_t *data,uint16_t blockId)
+{
+	actualAddress = SAMPLESTART;
+	actualAddress += blockId * 0x8000;	/* add 32k Block offset */
+	actualPointerSample = actualAddress;
+	ef_write_block(data, 0x8000, EF_SAMPLE,0);
+}
+
 
 void ext_flash_open_read_sample(uint8_t StepBackwards, uint32_t *totalNumberOfBytes)
 {
@@ -1797,10 +1814,7 @@
 
 	if(do_not_erase == 0)
 	{
-		if((ext_flash_erase_if_on_page_start()) && (type == EF_SAMPLE))		/* invalidate header sample information if needed */
-		{
-			ext_flash_invalidate_sample_index(actualAddress);
-		}
+		ext_flash_erase_if_on_page_start();
 	}
 	
 	while( i<length)
@@ -2183,6 +2197,37 @@
 	}
 }
 
+/* This function validates a potential jump of sample address by checking the last sector for empty memory cells */
+uint8_t ext_flash_SampleOverrunValid(void)
+{
+	uint8_t jumpvalid = 1;
+	uint32_t curAddress, actualaddrbackup;
+	uint8_t tmpBuffer;
+	uint8_t emptyCellCnt = 0;
+
+	actualaddrbackup = actualAddress;
+	curAddress = SAMPLESTOP - 20;	/* check the last 10 bytes of the last sample sector */
+	actualAddress = curAddress;
+	ext_flash_read_block_start();
+	while(actualAddress < SAMPLESTOP)
+	{
+		tmpBuffer = read_spi(HOLDCS);/* read data */
+		if(tmpBuffer == 0xFF)
+		{
+			emptyCellCnt++;
+		}
+		actualAddress++;
+	}
+	ext_flash_read_block_stop();
+
+	if(emptyCellCnt == 20)
+	{
+		jumpvalid = 0;
+	}
+	actualAddress = actualaddrbackup;
+	return jumpvalid;
+}
+
 uint32_t ext_flash_AnalyseSampleBuffer(char *pstrResult)
 {
 	uint8_t sectorState[16];	/* samples are stored in 16 sector / 64k each */
@@ -2281,55 +2326,18 @@
 	return startedSectors;
 }
 
-/* In case of a sample ring overrun the headers of the dive which will no longer have sample data needs to be updated */
-void ext_flash_invalidate_sample_index(uint32_t sectorStart)
+uint32_t ext_flash_read_profilelength_small_header(uint32_t smallHeaderAddr)
 {
-	uint8_t emptySamples[] = {0,0,0, 0,0,0, 0,0,0};	/* entry of start, stop and length */
-	uint8_t diveidx;
-
-	uint8_t  header1, header2;
-
-  	SSettings *settings = settingsGetPointer();
-  	diveidx = settings->lastDiveLogId + 1;
-  	convert_Type dataStart, dataEnd;
-
-  	uint32_t HeaderAddrBackup = actualPointerHeader;
-
-	while(diveidx != settings->lastDiveLogId)
-	{
-		actualAddress = HEADERSTART + (0x800 * diveidx) + HEADER2OFFSET;
-		ext_flash_read_block_start();
-		ext_flash_read_block(&header1, EF_HEADER);
-		ext_flash_read_block(&header2, EF_HEADER);
-		dataStart.u8bit.byteHigh = 0;
-		ext_flash_read_block(&dataStart.u8bit.byteLow, EF_HEADER);
-		ext_flash_read_block(&dataStart.u8bit.byteMidLow, EF_HEADER);
-		ext_flash_read_block(&dataStart.u8bit.byteMidHigh, EF_HEADER);
-		dataEnd.u8bit.byteHigh = 0;
-		ext_flash_read_block(&dataEnd.u8bit.byteLow, EF_HEADER);
-		ext_flash_read_block(&dataEnd.u8bit.byteMidLow, EF_HEADER);
-		ext_flash_read_block(&dataEnd.u8bit.byteMidHigh, EF_HEADER);
-		ext_flash_read_block_stop();
-
-		if((header1 == 0xFA) && (header2 == 0xFA))					/* Dive ID is in use */
-		{
-			if(((dataStart.u32bit >= sectorStart) && (dataStart.u32bit <= sectorStart+0xFFFF))	/* Sample start is within erased sector */
-			  || ((dataEnd.u32bit >= sectorStart) && (dataEnd.u32bit <= sectorStart+0xFFFF))) /* End of sample data is within erased sector */
-			{
-				  actualAddress = HEADERSTART + (0x800 * diveidx) + HEADER2OFFSET;
-				  ext_flash_incf_address(EF_HEADER);					/* skip header bytes */
-				  ext_flash_incf_address(EF_HEADER);
-				  actualPointerHeader = actualAddress;
-				  ef_write_block(emptySamples,9,EF_HEADER,1);			/* clear start, stop and length data */
-				  actualPointerHeader = HeaderAddrBackup;
-			}
-	   }
-	   diveidx++;
-	}
+	uint32_t profileLength = 0;
+	actualPointerSample = smallHeaderAddr;
+	actualAddress = actualPointerSample;
+	ext_flash_read_block_start();
+	ext_flash_read_next_sample_part((uint8_t*)&profileLength,  3);
+	ext_flash_close_read_sample();
+	return profileLength;
 }
 
 
-
 /*
 uint8_t ext_flash_erase_firmware_if_not_empty(void)
 {
--- a/Discovery/Src/logbook.c	Wed Apr 08 16:34:54 2020 +0200
+++ b/Discovery/Src/logbook.c	Wed Apr 15 07:01:11 2020 +0000
@@ -91,7 +91,7 @@
 static SSmallHeader smallDummyHeader;
 static uint16_t	dummyWriteIdx;
 static uint16_t	dummyReadIdx;
-static uint8_t dummyMemoryBuffer[1000*4];
+static uint8_t dummyMemoryBuffer[5000];
 
 
 /* Private function prototypes -----------------------------------------------*/
@@ -981,6 +981,7 @@
 	int16_t decostepDepthVal = 0;
 	int16_t decostepDepthLast = 0;
 	uint16_t tankVal = 0;
+	uint32_t small_profileLength = 0;
 
      SManualGas manualGasVal;
      SManualGas manualGasLast;
@@ -1040,8 +1041,8 @@
 
 
 		//uint16_t* ppo2, uint16_t* cns#
-     uint32_t totalNumberOfBytes = 0;
-     uint32_t bytesRead = 0;
+    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);
@@ -1051,7 +1052,10 @@
     iNum = 0;
     int counter = 0;
 		temperatureLast = -1000;
-	if(totalNumberOfBytes > 2)	/* read real data */
+
+	small_profileLength = (smallHeader.profileLength[2] << 16) + (smallHeader.profileLength[1] << 8) + smallHeader.profileLength[0];
+
+	if(totalNumberOfBytes == small_profileLength)	/* sizes provided by header and small header are the same => real data */
 	{
 		while ((bytesRead < totalNumberOfBytes) && (iNum < length))
 		{
@@ -1460,152 +1464,174 @@
 {
 	convert_Type data,data2;
 	uint16_t dummyLength = 0;
+	uint8_t returnEmptyHeader = 0;
 
-	memcpy(headerOSTC3.diveHeaderStart,			&pHead->diveHeaderStart,					2);
-	memcpy(headerOSTC3.pBeginProfileData,		&pHead->pBeginProfileData,				3);
-	memcpy(headerOSTC3.pEndProfileData,			&pHead->pEndProfileData,					3);
+	uint32_t headerProfileLength, sampleProfileLength, sampleProfileStart;
 
 
-	data.u8bit.byteHigh = 0;
-	data.u8bit.byteLow 			= pHead->pBeginProfileData[0];
-	data.u8bit.byteMidLow 	= pHead->pBeginProfileData[1];
-	data.u8bit.byteMidHigh 	= pHead->pBeginProfileData[2];
-
-	data2.u8bit.byteHigh = 0;
-	data2.u8bit.byteLow 			= pHead->pEndProfileData[0];
-	data2.u8bit.byteMidLow 	= pHead->pEndProfileData[1];
-	data2.u8bit.byteMidHigh 	= pHead->pEndProfileData[2];
-
-	if( (pHead->pBeginProfileData[0] == 0)			/* no sample data available => use dummy */
-		&&(pHead->pBeginProfileData[1] == 0)
-		&&(pHead->pBeginProfileData[2] == 0))
+	if(pHead->diveHeaderStart != 0xFAFA)
 	{
-		dummyLength = logbook_fillDummySampleBuffer(pHead);
-
-		data2.u32bit = data.u32bit + dummyLength;	/* calc new end address (which is equal to dummyLength) */
-		data.u32bit = data2.u32bit;				    /* data is used below to represent the length */
+		returnEmptyHeader = 1;
 	}
 	else
 	{
-		/* check if sample address information are corrupted by address range. */
-		/* TODO: Workaround. Better solution would be to check end of ring for 0xFF pattern */
-		if((data.u32bit > data2.u32bit) && (data.u32bit < (SAMPLESTOP - 0x9000)))
+		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->pBeginProfileData[0];
+		data.u8bit.byteMidLow 	= pHead->pBeginProfileData[1];
+		data.u8bit.byteMidHigh 	= pHead->pBeginProfileData[2];
+
+		sampleProfileStart = data.u32bit;
+
+		data2.u8bit.byteHigh = 0;
+		data2.u8bit.byteLow 			= pHead->pEndProfileData[0];
+		data2.u8bit.byteMidLow 	= pHead->pEndProfileData[1];
+		data2.u8bit.byteMidHigh 	= pHead->pEndProfileData[2];
+
+		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)		/* if the profile in use ? */
 		{
-			data2.u32bit = data.u32bit + DEFAULT_SAMPLES;
-			pHead->pEndProfileData[0] = data2.u8bit.byteLow;
-			pHead->pEndProfileData[1] = data2.u8bit.byteMidLow;
-			pHead->pEndProfileData[2] = data2.u8bit.byteMidHigh;
-			data.u32bit = DEFAULT_SAMPLES;
+			if(data2.u32bit < sampleProfileStart)		/* Wrap around of sample ring detected */
+			{
+				if(ext_flash_SampleOverrunValid() == 0)	/* Wrap around does not seem to be valid => fallback */
+				{
+					sampleProfileStart = 0;
+				}
+			}
+			if( sampleProfileStart == 0)				/* should never happen unless OSTC with older debug version is in use (or invalid overrun) */
+			{
+				sampleProfileLength = 1;
+				headerProfileLength = 2;
+			}
+			else
+			{
+				headerProfileLength = (pHead->profileLength[2] << 16) + (pHead->profileLength[1] << 8) + pHead->profileLength[0];
+				sampleProfileLength = ext_flash_read_profilelength_small_header(sampleProfileStart);
+			}
+
+			if(sampleProfileLength != headerProfileLength)
+			{
+				dummyLength = logbook_fillDummySampleBuffer(pHead);
+
+				data2.u32bit = sampleProfileStart + dummyLength;	/* calc new end address (which is equal to dummyLength) */
+				data.u32bit = dummyLength;				    /* data is used below to represent the length */
+			}
+
+			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);
 		}
 		else
 		{
-			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;
-			}
+			returnEmptyHeader = 1;
 		}
 	}
-	else
+	if(returnEmptyHeader)			/* profile not in use => return array full of 0xFF */
 	{
-		headerOSTC3.logbookProfileVersion = 0xFF;
-		headerOSTC3.personalDiveCount[0] = 0xFF;
-		headerOSTC3.personalDiveCount[1] = 0xFF;
-		headerOSTC3.safetyDistance_10cm = 0xFF;
+		memset(&headerOSTC3, 0xFF, sizeof(headerOSTC3));
 	}
 
-	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;
 }
 
@@ -1618,74 +1644,86 @@
 *********************************************************************************/
 SLogbookHeaderOSTC3compact * logbook_build_ostc3header_compact(SLogbookHeader* pHead)
 {
+	uint8_t returnEmptyHeader = 0;
 	convert_Type data, data2;
 	uint32_t dummyLength = 0;
-
-
-	data.u8bit.byteHigh = 0;
-	data.u8bit.byteLow 			= pHead->pBeginProfileData[0];
-	data.u8bit.byteMidLow 	= pHead->pBeginProfileData[1];
-	data.u8bit.byteMidHigh 	= pHead->pBeginProfileData[2];
+	uint32_t headerProfileLength, sampleProfileLength, sampleProfileStart;
 
-	data2.u8bit.byteHigh = 0;
-	data2.u8bit.byteLow 			= pHead->pEndProfileData[0];
-	data2.u8bit.byteMidLow 	= pHead->pEndProfileData[1];
-	data2.u8bit.byteMidHigh 	= pHead->pEndProfileData[2];
-
-	if( (pHead->pBeginProfileData[0] == 0)			/* no sample data available => use dummy */
-		&&(pHead->pBeginProfileData[1] == 0)
-		&&(pHead->pBeginProfileData[2] == 0))
+	if(pHead->diveHeaderStart != 0xFAFA)
 	{
-		dummyLength = logbook_fillDummySampleBuffer(pHead);
-
-		data2.u32bit = data.u32bit + dummyLength;	/* calc new end address (which is equal to dummyLength) */
-		data.u32bit = data2.u32bit;				    /* data is used below to represent the length */
+		returnEmptyHeader = 1;
 	}
 	else
 	{
-		/* check if sample address information are corrupted by address range. */
-		/* TODO: Workaround. Better solution would be to check end of ring for 0xFF pattern */
-		if((data.u32bit > data2.u32bit) && (data.u32bit < (SAMPLESTOP - 0x9000)))
+		data.u8bit.byteHigh = 0;
+		data.u8bit.byteLow 		= pHead->pBeginProfileData[0];
+		data.u8bit.byteMidLow 	= pHead->pBeginProfileData[1];
+		data.u8bit.byteMidHigh 	= pHead->pBeginProfileData[2];
+
+		sampleProfileStart = data.u32bit;
+
+		data2.u8bit.byteHigh = 0;
+		data2.u8bit.byteLow 	= pHead->pEndProfileData[0];
+		data2.u8bit.byteMidLow 	= pHead->pEndProfileData[1];
+		data2.u8bit.byteMidHigh = pHead->pEndProfileData[2];
+
+		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)
 		{
-			data2.u32bit = data.u32bit + DEFAULT_SAMPLES;
-			pHead->pEndProfileData[0] = data2.u8bit.byteLow;
-			pHead->pEndProfileData[1] = data2.u8bit.byteMidLow;
-			pHead->pEndProfileData[2] = data2.u8bit.byteMidHigh;
-			data.u32bit = DEFAULT_SAMPLES;
+			if(data2.u32bit < sampleProfileStart)		/* Wrap around of sample ring detected */
+			{
+				if(ext_flash_SampleOverrunValid() == 0)	/* Wrap around does not seem to be valid => fallback */
+				{
+					sampleProfileStart = 0;
+				}
+			}
+
+			if( sampleProfileStart == 0)			/* no sample data available => use dummy */
+			{
+				sampleProfileLength = 1;
+				headerProfileLength = 2;
+			}
+			else
+			{
+				headerProfileLength = (pHead->profileLength[2] << 16) + (pHead->profileLength[1] << 8) + pHead->profileLength[0];
+				sampleProfileLength = ext_flash_read_profilelength_small_header(sampleProfileStart);
+			}
+			if(sampleProfileLength != headerProfileLength)
+			{
+				dummyLength = logbook_fillDummySampleBuffer(pHead);
+
+				data2.u32bit = sampleProfileStart + dummyLength;	/* calc new end address (which is equal to dummyLength) */
+				data.u32bit = dummyLength;				   			/* data is used below to represent the length */
+			}
+			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
 		{
-			data.u8bit.byteHigh = 0;
-			data.u8bit.byteLow 		= pHead->profileLength[0];
-			data.u8bit.byteMidLow 	= pHead->profileLength[1];
-			data.u8bit.byteMidHigh 	= pHead->profileLength[2];
+			returnEmptyHeader = 1;
 		}
 	}
-	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		
+	if(returnEmptyHeader)
 	{
 		memset(&headerOSTC3compact, 0xFF, sizeof(SLogbookHeaderOSTC3compact));
 	}
@@ -1910,7 +1948,7 @@
         divisor.temperature--;
     }
 
-    logbook_writeDummy((void *) &smallDummyHeader,sizeof(smallDummyHeader));
+    logbook_writeDummy((void *) sample,length);
 }
 
 
--- a/Discovery/Src/tComm.c	Wed Apr 08 16:34:54 2020 +0200
+++ b/Discovery/Src/tComm.c	Wed Apr 15 07:01:11 2020 +0000
@@ -589,6 +589,8 @@
     uint8_t aTxBuffer[128];
     uint8_t aRxBuffer[68];
     uint8_t answer;
+    uint16_t index;
+    uint32_t header_profileLength, OSTC3_profileLength;
     aTxBuffer[0] = type;
     aTxBuffer[1] = prompt4D4C(receiveStartByteUart);
     uint8_t tempHigh, tempLow;
@@ -665,6 +667,8 @@
         case 0x85: // hw read entire logbook memory
         case 0x86: // hw overwrite entire logbook memory
         case 0x87: // hw ext_flash_repair_SPECIAL_dive_numbers_starting_count_with memory(x)
+        case 0x88: /* read entire sample memory  */
+        case 0x89: /* write entire sample memory */
 
 #endif
         case 0xC1: // 	Start low-level bootloader
@@ -885,14 +889,25 @@
             for(int i=0;i<8;i++)
                 HAL_UART_Transmit(&UartHandle, (uint8_t *)(logCopyDataPtr + (0x8000 * i)), (uint16_t)0x8000,60000);
             releaseFrame(98,logCopyDataPtr);
+#ifdef SEND_DATA_DETAILS
+            HAL_UART_Transmit(&UartHandle, (uint8_t*)&pSettings->lastDiveLogId, 1,60000);
+#endif
             break;
 
         case 0x86:
             aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
             logCopyDataPtr = getFrame(98);
             for(int i=0;i<8;i++)
+            {
                 HAL_UART_Receive(&UartHandle, (uint8_t *)(logCopyDataPtr + (0x8000 * i)), (uint16_t)0x8000,60000);
+            }
             ext_flash_write_header_memory((uint8_t *)logCopyDataPtr);
+#ifdef SEND_DATA_DETAILS
+            if(HAL_UART_Receive(&UartHandle, (uint8_t *)(logCopyDataPtr + (0x8000 * 8)), (uint16_t)0x01,60000) == HAL_OK)	/* receive lastlogID */
+            {
+            	pSettings->lastDiveLogId = *(uint8_t*)(logCopyDataPtr + (0x40000));
+            }
+#endif
             releaseFrame(98,logCopyDataPtr);
             break;
 
@@ -906,6 +921,39 @@
             ext_flash_repair_SPECIAL_dive_numbers_starting_count_with(totalDiveCount.u16bit);
             aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
             break;
+        case 0x88:
+             aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+             logCopyDataPtr = getFrame(98);
+
+             for(index = 0; index <384; index++)		/* transmit in 32k blocks */
+             {
+            	 ext_flash_read_sample_memory((uint8_t *)logCopyDataPtr, index);
+                 if(HAL_UART_Transmit(&UartHandle, (uint8_t *)(logCopyDataPtr), (uint16_t)0x8000,60000) != HAL_OK)
+                 {
+                	 break;
+                 }
+             }
+             releaseFrame(98,logCopyDataPtr);
+             HAL_UART_Transmit(&UartHandle, (uint8_t*)&pSettings->logFlashNextSampleStartAddress, 4,60000);	/* send next sample pos */
+        	break;
+        case 0x89:
+             aTxBuffer[count++] = prompt4D4C(receiveStartByteUart);
+             logCopyDataPtr = getFrame(98);
+
+             for(index = 0; index <384; index++)		/* transmit in 32k blocks  384*/
+             {
+
+                 if(HAL_UART_Receive(&UartHandle, (uint8_t *)(logCopyDataPtr), (uint16_t)0x8000,60000) != HAL_OK)
+                 {
+                	 break;
+                 }
+                 ext_flash_write_sample_memory((uint8_t *)logCopyDataPtr, index);
+             }
+
+             releaseFrame(98,logCopyDataPtr);
+             HAL_UART_Receive(&UartHandle, (uint8_t*)&pSettings->logFlashNextSampleStartAddress, 4,60000);	/* send next sample pos */
+        	break;
+
 #endif
         }
 
@@ -1184,9 +1232,11 @@
         if(HAL_UART_Transmit(&UartHandle, (uint8_t*)plogbookHeaderOSTC3, 256,5000)!= HAL_OK)
             return 0;
 
-        if((logbookHeader.pBeginProfileData[0]==0)	/* no sample information */
-        	&& (logbookHeader.pBeginProfileData[1]==0)
-			&& (logbookHeader.pBeginProfileData[2]==0))
+        OSTC3_profileLength = (plogbookHeaderOSTC3->profileLength[2] << 16) + (plogbookHeaderOSTC3->profileLength[1] << 8)
+                								    + plogbookHeaderOSTC3->profileLength[0] -3;
+        header_profileLength = (logbookHeader.profileLength[2] << 16) + (logbookHeader.profileLength[1] << 8) + logbookHeader.profileLength[0];
+       
+        if(OSTC3_profileLength != header_profileLength)			/* has headerdata been changed to dummy data? */
         {
         	sampleTotalLength = logbook_fillDummySampleBuffer(&logbookHeader);
 			while(sampleTotalLength >= 128)
@@ -1202,7 +1252,6 @@
 				if(HAL_UART_Transmit(&UartHandle, (uint8_t*)aTxBuffer, sampleTotalLength,5000)!= HAL_OK)
 					return 0;
 			}
-
         }
         else
         {
--- a/Discovery/Src/tInfoLog.c	Wed Apr 08 16:34:54 2020 +0200
+++ b/Discovery/Src/tInfoLog.c	Wed Apr 15 07:01:11 2020 +0000
@@ -66,9 +66,6 @@
 void stepBackInfo(void);
 void stepForwardInfo(void);
 void showLogExit(void);
-#ifdef ENABLE_PROFILE_RESET
-void resetDiveProfile(void);
-#endif
 
 /* Exported functions --------------------------------------------------------*/
 void tInfoLog_init(void)
@@ -181,9 +178,6 @@
     switch(sendAction)
     {
     case ACTION_BUTTON_ENTER:
-#ifdef ENABLE_PROFILE_RESET
-    	resetDiveProfile();
-#endif
         break;
     case ACTION_BUTTON_NEXT:
         showNextLogPage();
@@ -437,21 +431,3 @@
     show_logbook_test(0, stepBack);
 }
 
-#ifdef ENABLE_PROFILE_RESET
-void resetDiveProfile()
-{
-	uint8_t stepBack;
-	SLogbookHeader logbookHeader;
-	convert_Type dataStart;
-	stepBack = (6 * (infolog.page - 1)) + infolog.line - 1; /* calculate current dive ID */
-	logbook_getHeader(stepBack ,&logbookHeader);
-
-    dataStart.u8bit.byteHigh = 0;
-    dataStart.u8bit.byteLow = logbookHeader.pBeginProfileData[0];
-    dataStart.u8bit.byteMidLow = logbookHeader.pBeginProfileData[1];
-    dataStart.u8bit.byteMidHigh = logbookHeader.pBeginProfileData[2];
-
-    dataStart.u32bit &= 0xFFFF0000;		/* set to sector start */
-	ext_flash_invalidate_sample_index(dataStart.u32bit);
-}
-#endif
--- a/Discovery/Src/tMenuEditSystem.c	Wed Apr 08 16:34:54 2020 +0200
+++ b/Discovery/Src/tMenuEditSystem.c	Wed Apr 15 07:01:11 2020 +0000
@@ -41,9 +41,6 @@
 #include "motion.h"
 #include "t7.h"
 
-/* Uncomment to activate a menu item in reset menu which provide sample ring analysis / repair functionality */
-#define ENABLE_ANALYSE_SAMPLES
-
 #define CV_SUBPAGE_MAX		(2u)	/* max number of customer view selection pages */
 /*#define HAVE_DEBUG_VIEW */
 static uint8_t infoPage = 0;
@@ -97,7 +94,9 @@
 uint8_t OnAction_LogbookOffset(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
 uint8_t OnAction_SetFactoryDefaults(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
 uint8_t OnAction_SetBatteryCharge(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
+#ifdef ENABLE_ANALYSE_SAMPLES
 uint8_t OnAction_RecoverSampleIdx(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
+#endif
 #ifdef SCREENTEST
 uint8_t OnAction_ScreenTest		(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action);
 #endif
@@ -1635,18 +1634,18 @@
     return EXIT_TO_MENU;
 }
 
-
+#ifdef ENABLE_ANALYSE_SAMPLES
 uint8_t OnAction_RecoverSampleIdx(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
 {
 	char text[32];
 	char strResult[20];
 
-
 	ext_flash_AnalyseSampleBuffer(strResult);
     snprintf(&text[0],30,"Ring: %s",strResult); //"Code: %X",settingsGetPointer()->logFlashNextSampleStartAddress); //getLicence());
     write_label_var(  30, 800, ME_Y_LINE6, &FontT42, text);
     return UNSPECIFIC_RETURN;
 }
+#endif
 
 uint8_t OnAction_SetBatteryCharge(uint32_t editId, uint8_t blockNumber, uint8_t digitNumber, uint8_t digitContent, uint8_t action)
 {