⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scp_formatter.cpp

📁 BIOSIG is an open source software library for biomedical signal processing. Library works well with
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	memcpy(&Sect1[len1], (int8_t*)(&bUnit), 1);
	len1 += 1;

// Tag 7 (len = 3)
	tg.id = 7;
	tg.len = 3;
	memcpy(&Sect1[len1], (int8_t*) &tg, 3);
	len1 += 3;
	memcpy(&Sect1[len1], (int8_t*)(&S1I->wWeight), 2);
	len1 += 2;
	if (S1I->wWeight == 0)
		bUnit = 0;
	else
		bUnit = 1;
	memcpy(&Sect1[len1], (int8_t*)(&bUnit), 1);
	len1 += 1;

// Tag 8 (len = 1)
	tg.id = 8;
	tg.len = 1;
	memcpy(&Sect1[len1], (int8_t*) &tg, 3);
	len1 += 3;
	memcpy(&Sect1[len1], (int8_t*)(&S1I->bSex), 1);
	len1 += 1;

// Tag 11 (len = 2)
	if (S1I->wSBP != 0) {
		tg.id = 11;
		tg.len = 2;
		memcpy(&Sect1[len1], (int8_t*) &tg, 3);
		len1 += 3;
		memcpy(&Sect1[len1], (int8_t*)(&S1I->wSBP), 2);
		len1 += 2;
	}

// Tag 12 (len = 2)
	if (S1I->wDBP != 0) {
		tg.id = 12;
		tg.len = 2;
		memcpy(&Sect1[len1], (int8_t*) &tg, 3);
		len1 += 3;
		memcpy(&Sect1[len1], (int8_t*)(&S1I->wDBP), 2);
		len1 += 2;
	}

// Tag 14 (max len = 2 + 2 + 2 + 1 + 1 + 6 + 1 + 1 + 1 + 1 + 1 + 16 + 1 + 25 + 25 + 25 + 25 + 25)
// Total = 161 (max value)
	tg.id = 14;
	tg.len = 0;				// Temporary
	memcpy(bBufTmp, (int8_t*) &tg, 3);
	lenTmp = 0;
	memcpy(&bBufTmp[3 + lenTmp], (int8_t*)(&S1I->wInstNum), 2);
	lenTmp += 2;
	memcpy(&bBufTmp[3 + lenTmp], (int8_t*)(&S1I->wDeptNum), 2);
	lenTmp += 2;
	memcpy(&bBufTmp[3 + lenTmp], (int8_t*)(&S1I->wDevID), 2);
	lenTmp += 2;
	memcpy(&bBufTmp[3 + lenTmp], (int8_t*)(&S1I->bDevType), 1);
	lenTmp += 1;
	memcpy(&bBufTmp[3 + lenTmp], (int8_t*)(&S1I->bManCode), 1);
	lenTmp += 1;
	memcpy(&bBufTmp[3 + lenTmp], (int8_t*)(&S1I->szModDesc), 6);
	lenTmp += 6;
	memcpy(&bBufTmp[3 + lenTmp], (int8_t*)(&S1I->bSCPECGProtRevNum), 1);
	lenTmp += 1;
	memcpy(&bBufTmp[3 + lenTmp], (int8_t*)(&S1I->bSCPECGProtCompLev), 1);
	lenTmp += 1;
	memcpy(&bBufTmp[3 + lenTmp], (int8_t*)(&S1I->bLangSuppCode), 1);
	lenTmp += 1;
	memcpy(&bBufTmp[3 + lenTmp], (int8_t*)(&S1I->bCapECGDev), 1);
	lenTmp += 1;
	memcpy(&bBufTmp[3 + lenTmp], (int8_t*)(&S1I->bMainsFreq), 1);
	lenTmp += 1;
	// Reserved area (16 bytes)
	memset(&bBufTmp[3 + lenTmp], '\0', 16);
	lenTmp += 16;
	bUnit = (uint8_t) (strlen(S1I->szAnalProgRevNum) + 1);
	memcpy(&bBufTmp[3 + lenTmp], (int8_t*)(&bUnit), 1);
	lenTmp += 1;
	// (Max len = 25)
	memcpy(&bBufTmp[3 + lenTmp], (int8_t*)(&S1I->szAnalProgRevNum), ((0x00FF) & bUnit));
	lenTmp += ((0x00FF) & bUnit);
	// (Max len = 25)
	memcpy(&bBufTmp[3 + lenTmp], (int8_t*)(&S1I->szSerNumAcqDev), strlen(S1I->szSerNumAcqDev) + 1);
	lenTmp += (strlen(S1I->szSerNumAcqDev) + 1);
	// (Max len = 25)
	memcpy(&bBufTmp[3 + lenTmp], (int8_t*)(&S1I->szAcqDevSystSW), strlen(S1I->szAcqDevSystSW) + 1);
	lenTmp += (strlen(S1I->szAcqDevSystSW) + 1);
	// (Max len = 25)
	memcpy(&bBufTmp[3 + lenTmp], (int8_t*)(&S1I->szSCPImplSW), strlen(S1I->szSCPImplSW) + 1);
	lenTmp += (strlen(S1I->szSCPImplSW) + 1);
	// (Max len = 25)
	memcpy(&bBufTmp[3 + lenTmp], (int8_t*)(&S1I->szAcqDevManuf), strlen(S1I->szAcqDevManuf) + 1);
	lenTmp += (strlen(S1I->szAcqDevManuf) + 1);

	memcpy(&bBufTmp[1], (int8_t*)(&lenTmp), 2);

	memcpy(&Sect1[len1], (int8_t*)(&bBufTmp[0]), lenTmp + 3);
	len1 += (lenTmp + 3);

// Tag 20 (max len = 64)
	tg.id = 20;
	tg.len = strlen(S1I->szRefPhys) + 1;
	memcpy(&Sect1[len1], (int8_t*) &tg, 3);
	len1 += 3;
	memcpy(&Sect1[len1], S1I->szRefPhys, tg.len);
	len1 += tg.len;

// Tag 21 (max len = 64)
	tg.id = 21;
	tg.len = strlen(S1I->szLCPhys) + 1;
	memcpy(&Sect1[len1], (int8_t*) &tg, 3);
	len1 += 3;
	memcpy(&Sect1[len1], S1I->szLCPhys, tg.len);
	len1 += tg.len;

// Tag 24 (len = 1)
	tg.id = 24;
	tg.len = 1;
	memcpy(&Sect1[len1], (int8_t*) &tg, 3);
	len1 += 3;
	memcpy(&Sect1[len1], (int8_t*)(&S1I->bStatCode), 1);
	len1 += 1;

// Tag 25 (len = 4)
	tg.id = 25;
	tg.len = 4;
	memcpy(&Sect1[len1], (int8_t*) &tg, 3);
	len1 += 3;
	memcpy(&Sect1[len1], (int8_t*)(&S1I->DOA.yyyy), 2);
	len1 += 2;
	memcpy(&Sect1[len1], (int8_t*)(&S1I->DOA.mm), 1);
	len1 += 1;
	memcpy(&Sect1[len1], (int8_t*)(&S1I->DOA.dd), 1);
	len1 += 1;

// Tag 26 (len = 3)
	tg.id = 26;
	tg.len = 3;
	memcpy(&Sect1[len1], (int8_t*) &tg, 3);
	len1 += 3;
	memcpy(&Sect1[len1], (int8_t*)(&S1I->TOA.hh), 1);
	len1 += 1;
	memcpy(&Sect1[len1], (int8_t*)(&S1I->TOA.mm), 1);
	len1 += 1;
	memcpy(&Sect1[len1], (int8_t*)(&S1I->TOA.ss), 1);
	len1 += 1;

// Tag 31 (max len = 12)
	tg.id = 31;
	tg.len = strlen(S1I->szSeqNum) + 1;
	memcpy(&Sect1[len1], (int8_t*) &tg, 3);
	len1 += 3;
	memcpy(&Sect1[len1], S1I->szSeqNum, tg.len);
	len1 += tg.len;

// Tag 34 (max len = 29)
	tg.id = 34;
	tg.len = 4 + strlen(S1I->szDateTimeZoneDesc) + 1;
	memcpy(&Sect1[len1], (int8_t*) &tg, 3);
	len1 += 3;
	memcpy(&Sect1[len1], (int8_t*)(&S1I->wDateTimeZoneOffset), 2);
	len1 += 2;
	memcpy(&Sect1[len1], (int8_t*)(&S1I->wDateTimeZoneIndex), 2);
	len1 += 2;
	memcpy(&Sect1[len1], S1I->szDateTimeZoneDesc, strlen(S1I->szDateTimeZoneDesc) + 1);
	len1 += (strlen(S1I->szDateTimeZoneDesc) + 1);

// Tag 255 (len = 0)
	tg.id = 255;
	tg.len = 0;
	memcpy(&Sect1[len1], (int8_t*) &tg, 3);
	len1 += 3;

// Evaluate the size and correct it if odd
	if ((len1 % 2) != 0) {
		memset(&Sect1[len1], '\0', 1);
		len1 += 1;
	}

// Correct the len in the section header
	Sect1Head.len = len1;
	memcpy(Sect1, (int8_t*) &Sect1Head, 16);

// Evaluate the CRC
	crc = CRCEvaluate(&Sect1[2], len1 - 2);

// Correct the CRC in the section header
	memcpy(Sect1, (int8_t*) &crc, 2);

// Store the length of Section1
	lenSect1 = len1;

	return (true);
}

bool cSCP_Formatter::CreateSCPSection3()
{
	SCPSECT_HEAD	Sect3Head;
	uint32_t		len1;
	uint16_t		crc;
	uint16_t		i;
	uint8_t			bNum, bNum1;
	if (ESI == NULL)
		return (false);

// Create the header
	Sect3Head.crc = 0;				// Temporary
	Sect3Head.sectid = 3;
	Sect3Head.len = 0;				// Temporary
	Sect3Head.sectver = S1I->bSCPECGProtRevNum;
	Sect3Head.protver = S1I->bSCPECGProtRevNum;
	Sect3Head.SCPres[0] = '\0';
	Sect3Head.SCPres[1] = '\0';
	Sect3Head.SCPres[2] = '\0';
	Sect3Head.SCPres[3] = '\0';
	Sect3Head.SCPres[4] = '\0';
	Sect3Head.SCPres[5] = '\0';

	memcpy(Sect3, (int8_t*) &Sect3Head, 16);
	len1 = 16;
// Create all the fields
// Situations with a number of leads > 15 are not supported
	if (ESI->bNumLead > 15)
		return (false);

// Number of leads enclosed
	memcpy(&Sect3[len1], (int8_t*) &ESI->bNumLead, 1);
	len1 += 1;
// Flags
// Situations with reference beat subtraction are not supported
	if (ESI->fRefBeatUsedForCompr)
		return (false);
// Situations with not all the leads simultaneously recorded are not supported
	if (!ESI->fLeadsAllSimultRecord)
		return (false);
// Situations number of leads simultaneouly recorded != total number of leads are not supported
	if (ESI->bNumLeadSimultRecord != ESI->bNumLead)
		return (false);
	bNum = 0;
	if (ESI->fRefBeatUsedForCompr)
		bNum |= 0x01;
	if (ESI->fLeadsAllSimultRecord)
		bNum |= 0x04;
// We assume hat all the leads are recorded simultaneously
	bNum1 = (0x1F) & ESI->bNumLeadSimultRecord;
	bNum |= (bNum1 << 3);
	memcpy(&Sect3[len1], (int8_t*) &bNum, 1);
	len1 += 1;
// We assume to have max 15 leads
	for (i = 0; i < ESI->bNumLead; i++) {
		bNum = ESI->LeadR_codes[i];
		memcpy(&Sect3[len1], (int8_t*) &ESI->dwStartSampleR, 4);
		len1 += 4;
		memcpy(&Sect3[len1], (int8_t*) &ESI->dwEndSampleR, 4);
		len1 += 4;
		memcpy(&Sect3[len1], (int8_t*) &bNum, 1);
		len1 += 1;
	}

// Evaluate the size and correct it if odd
	if ((len1 % 2) != 0) {
		memset(&Sect3[len1], '\0', 1);
		len1 += 1;
	}

// Correct the len in the section header
	Sect3Head.len = len1;
	memcpy(Sect3, (int8_t*) &Sect3Head, 16);

// Evaluate the CRC
	crc = CRCEvaluate(&Sect3[2], len1 - 2);

// Correct the CRC in the section header
	memcpy(Sect3, (int8_t*) &crc, 2);

// Store the length of Section3
	lenSect3 = len1;

	return (true);
}

bool cSCP_Formatter::CreateSCPSection6()
{
	SCPSECT_HEAD	Sect6Head;
	uint32_t		len1;
	uint32_t		numByteCompRhythm;
	uint16_t		crc;
	uint16_t		i, num;
	uint8_t			bNum;
	if (ESI == NULL)
		return (false);

// Create the header
	Sect6Head.crc = 0;				// Temporary
	Sect6Head.sectid = 6;
	Sect6Head.len = 0;				// Temporary
	Sect6Head.sectver = S1I->bSCPECGProtRevNum;
	Sect6Head.protver = S1I->bSCPECGProtRevNum;
	Sect6Head.SCPres[0] = '\0';
	Sect6Head.SCPres[1] = '\0';
	Sect6Head.SCPres[2] = '\0';
	Sect6Head.SCPres[3] = '\0';
	Sect6Head.SCPres[4] = '\0';
	Sect6Head.SCPres[5] = '\0';

	memcpy(Sect6, (int8_t*) &Sect6Head, 16);
	len1 = 16;

// Create all the fields

// AVM
	memcpy(&Sect6[len1], (int8_t*) &ESI->wAmplR, 2);
	len1 += 2;

// Sample interval
	memcpy(&Sect6[len1], (int8_t*) &ESI->wIntvR, 2);
	len1 += 2;

// Situations with first or second differences are not supported
	if (ESI->wEncodingType != 0)
		return (false);

// Diff used
	bNum = (uint8_t) ESI->wEncodingType;
	memcpy(&Sect6[len1], (int8_t*) &bNum, 1);
	len1 += 1;

// Situations with bimodal compression are not supported
	if (ESI->fBimodal)
		return (false);

// Bimodal/Non-bimodal
	bNum = 0;
	memcpy(&Sect6[len1], (int8_t*) &bNum, 1);
	len1 += 1;

// Fill the length block
	numByteCompRhythm = ESI->dwEndSampleR * 2;
// Each sample is stored on 2 bytes for each of the 15 leads (we assume to have max 15 leads)
	for (i = 0; i < ESI->bNumLead; i++) {
		memcpy(&Sect6[len1], (int8_t*) &numByteCompRhythm, 2);
		len1 += 2;
	}

// Fill tha data block with the ECG samples
// Write the ECG samples (we assume to have max 15 leads)
	for (i = 0; i < ESI->bNumLead; i++) {		for (num = 0; num < ESI->dwEndSampleR; num++) {		/* ##FIXME## this is a hack 			it would be best if this could be done within functions SWRITE (not defined yet)		*/ 
			int16_t val = (int16_t) ESI->LeadR[i][num];			memcpy(&Sect6[len1], (int8_t*) &val, 2);
			len1 += 2;
		}
	}
// Evaluate the size and correct it if odd
	if ((len1 % 2) != 0) {
		memset(&Sect6[len1], '\0', 1);
		len1 += 1;
	}

// Correct the len in the section header
	Sect6Head.len = len1;
	memcpy(Sect6, (int8_t*) &Sect6Head, 16);

// Evaluate the CRC
	crc = CRCEvaluate(&Sect6[2], len1 - 2);

// Correct the CRC in the section header
	memcpy(Sect6, (int8_t*) &crc, 2);

// Store the length of Section6
	lenSect6 = len1;

	return (true);
}

bool cSCP_Formatter::CorrectSCPSection0()
{
	uint16_t	crc;

// Write the proper length of each section
	Sect0.sect_1.sectlen = lenSect1;
	Sect0.sect_3.sectlen = lenSect3;
	Sect0.sect_6.sectlen = lenSect6;

// Correct the indexes
	Sect0.sect_3.index = Sect0.sect_1.index + Sect0.sect_1.sectlen;
	Sect0.sect_6.index = Sect0.sect_3.index + Sect0.sect_3.sectlen;

// Evaluate the CRC
	crc = CRCEvaluate(&((uint8_t*)(&Sect0))[2], lenSect0 - 2);

// Correct the CRC in the section header
	memcpy((int8_t*)(&Sect0), (int8_t*) &crc, 2);

	return (true);
}

bool cSCP_Formatter::CorrectSCPHeader()
{
	uint32_t	len1;
	uint16_t	crc;

	TotalFile = (uint8_t*)malloc(6 + lenSect0 + lenSect1 + lenSect3 + lenSect6);
	if (TotalFile == NULL)
		return (false);

// Copy the sections in the final buffer
	memcpy(TotalFile, (int8_t*)&FileHead, 6);
	len1 = 6;
	memcpy(&TotalFile[len1], (int8_t*)&Sect0, lenSect0);
	len1 += lenSect0;
	memcpy(&TotalFile[len1], (int8_t*)&Sect1, lenSect1);
	len1 += lenSect1;
	memcpy(&TotalFile[len1], (int8_t*)&Sect3, lenSect3);
	len1 += lenSect3;
	memcpy(&TotalFile[len1], (int8_t*)&Sect6, lenSect6);
	len1 += lenSect6;

// Write the proper length of the file
	memcpy(&((int8_t*)&FileHead)[2], (int8_t*)&len1, 4);
	memcpy(TotalFile, (int8_t*)&FileHead, 6);

// Evaluate the CRC
	crc = CRCEvaluate(&TotalFile[2], len1 - 2);

// Correct the CRC in the section header
	memcpy((int8_t*)&FileHead, (int8_t*)&crc, 2);
	memcpy(TotalFile, (int8_t*)&FileHead, 6);

	return (true);
}

bool cSCP_Formatter::WriteSCPFile(char* szFilePathName)
{
	FILE*		fp;
	uint32_t	len1;

	fp = fopen(szFilePathName, "wb");
	if (fp == NULL) {
		free(TotalFile);
		return (false);
	}

	len1 = 6 + lenSect0 + lenSect1 + lenSect3 + lenSect6;

	if (fwrite(TotalFile, len1, 1, fp) != 1) {
		free(TotalFile);
		fclose(fp);
		unlink(szFilePathName);
		return (false);
	}

	free(TotalFile);
	fclose(fp);

	return (true);
}

/********************************************************************
*	CRCEvaluate														*
*																	*
* Parameters: datablock is the buffer on which to evaluate the CRC.	*
*			  datalength is the length of the whole buffer			*
*																	*
* Description:	Evaluate the SCP-ECG CRC on a data block			*
*				(all file or a section)								*
*																	*
 ********************************************************************/

uint16_t cSCP_Formatter::CRCEvaluate(uint8_t* datablock, uint32_t datalength) {
	uint32_t	i;
	uint16_t	crc_tot;
	uint8_t		crchi, crclo;
	uint8_t		a, b;
	uint8_t		tmp1, tmp2;

	crchi = 0xFF;
	crclo = 0xFF;

	for (i = 0; i < datalength; i++) {
		a = datablock[i];
		a ^= crchi;
		crchi = a;
		a >>= 4;
		a &= 0x0F;
		a ^= crchi;
		crchi = crclo;
		crclo = a;
		tmp1 = ((a & 0x0F) << 4) & 0xF0;
		tmp2 = ((a & 0xF0) >> 4) & 0x0F;
		a = tmp1 | tmp2;
		b = a;
		tmp1 = ((a & 0x7F) << 1) & 0xFE;
		tmp2 = ((a & 0x80) >> 7) & 0x01;
		a = tmp1 | tmp2;
		a &= 0x1F;
		crchi ^= a;
		a = b & 0xF0;
		crchi ^= a;
		tmp1 = ((b & 0x7F) << 1) & 0xFE;
		tmp2 = ((b & 0x80) >> 7) & 0x01;
		b = tmp1 | tmp2;
		b &= 0xE0;
		crclo ^= b;
	}

	crc_tot = ((0x00FF & (uint16_t) crchi) << 8) & 0xFF00;
	crc_tot |= (0x00FF & (uint16_t) crclo);

	return (crc_tot);
}

/********************************************************************
*	CRCCheck														*
*																	*
* Parameters: datablock is the buffer on which to verify the CRC.	*
*			  It starts with the two CRC-CCITT bytes.				*
*			  datalength is the length of the whole buffer			*
*			  (including the two CRC bytes)							*
*																	*
* Description:	Check the SCP-ECG CRC on a data block				*
*				(all file or a section)								*
*																	*
 ********************************************************************/

int16_t cSCP_Formatter::CRCCheck(uint8_t* datablock, uint32_t datalength)
{
	uint16_t crc;

	crc = 0;

	if (datalength <= 2)
		return (-1);

	// Evaluate CRC
	crc = CRCEvaluate((uint8_t*) (datablock + 2), (uint32_t) (datalength - 2));
	if (((uint8_t) ((crc & 0xFF00) >> 8) != (uint8_t) datablock[1]) ||
		((uint8_t) (crc & 0x00FF) != (uint8_t) datablock[0]))
		return (0);
	else
		return (1);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -