📄 scp_formatter.cpp
字号:
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 + -