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

📄 decodeqam.cpp

📁 QAM数据调制的编码过程
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	BYTE y = x & 0x08;

	y |= (((y & 0x08) >> 1) ^ (x & 0x04));
	y |= (((y & 0x04) >> 1) ^ (x & 0x02));
	y |= (((y & 0x20) >> 1) ^ (x & 0x01));

	return y;
}

BOOL CDecodeQAM::BitsScramble(LPBYTE lpData, DWORD dwLen)
{
	long int M_SEQ_V29 = 0;
	BYTE data_out = 0;
	BYTE bit = 0;

	for (int n = 0; n < dwLen; n++)
	{
		data_out = 0;

		for (int m = 0; m < 8; m++)
		{
			M_SEQ_V29 <<= 1;
			bit = ((M_SEQ_V29 >> 18) & 0x01) ^ ((M_SEQ_V29 >> 23) & 0x01) ^ ((lpData[n] >> (7-m)) & 0x01);
			data_out |= (bit << (7-m));
			M_SEQ_V29 += bit;
		}
		lpData[n] = data_out;
	}

#if 0
	// 设置扰码器的起始状态:1010 1011 1011 0011 0111 010
	BYTE M_SEQ_V1729[23] = {1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0};
	BYTE data_out = 0;
	BYTE bit = 0;
	BYTE tmp = 0;

	for (int n = 0; n < dwLen; n++)
	{
		data_out = 0;
		tmp = 0;

		for (int m = 0; m < 8; m++)
		{
			// 得到扰码后的数据 data_in ^ M_SEQ_V1729[17] ^ M_SEQ_V1729[22]
			bit = ((lpData[n] >> (7-m)) & 0x01) ^ (M_SEQ_V1729[17] ^ M_SEQ_V1729[22]);
			data_out |= (bit << (7 - m));
			//tmp = M_SEQ_V1729[17] ^ M_SEQ_V1729[22];
			for (int i = 21; i >= 0; i--)
			{
				M_SEQ_V1729[i+1] = M_SEQ_V1729[i];
			}
			M_SEQ_V1729[0] = bit; //tmp;
		}

		lpData[n] = data_out;
	}
#endif

	return TRUE;
}

void CDecodeQAM::GenerateSRRC()
{
	const double a = 0.2;
	const double M_PI = 2*asin(1.0);
	const int M_SAMPLE_RATE = 48000;     //48k采样
	const int M_BAND_RATE = 2400;        // 波特率
	const int M_SAMPLE_PER_BAND = (M_SAMPLE_RATE/M_BAND_RATE);   // 每个波特的采样点
	const int M_FIRST_INDEX = 0;
	const int M_LAST_INDEX = 120;
	const int M_CORE_INDEX = 60;
	unsigned int index = 0;

	// 设h0
	SRRC[M_CORE_INDEX] = 1.0;

	for (int N = M_FIRST_INDEX; N <= M_LAST_INDEX; N++)
	{
		if (N == M_CORE_INDEX)
		{
			continue;
		}

		double t_Div_Tc = (double)(N-M_CORE_INDEX)/(double)M_SAMPLE_PER_BAND;

		/*SRRC[N] = SRRC[M_CORE_INDEX] * (sin(M_PI*(double)(N-M_CORE_INDEX)/(double)M_SAMPLE_PER_BAND) *
			cos(a*M_PI*(double)(N-M_CORE_INDEX)/(double)M_SAMPLE_PER_BAND)) / 
			((M_PI*(double)(N-M_CORE_INDEX)/(double)M_SAMPLE_PER_BAND) *
			(1-4*a*a*((double)(N-M_CORE_INDEX)/(double)M_SAMPLE_PER_BAND)*
			((double)(N-M_CORE_INDEX)/(double)M_SAMPLE_PER_BAND)));*/

		/* 平方根升余弦滚降时域表达式:
		         sin(pi*(t/Tc)*(1-a)) + 4a(t/Tc)*cos(pi*(t/Tc)*(1+a))
		  h(t) = -----------------------------------------------------
		          pi * (t/Tc) * (1-(4a(t/Tc))^2)  
		*/
		if (abs(N-M_CORE_INDEX) != 25)
		{
			SRRC[index++] = (sin(M_PI*(1-a)*t_Div_Tc) + 4*a*t_Div_Tc*cos(M_PI*(1+a)*t_Div_Tc)) / (M_PI*t_Div_Tc*(1-(4*a*t_Div_Tc)*(4*a*t_Div_Tc)));
		}
	}
	
	// 值域微调
	SRRC[0] = SRRC[1] = SRRC[2] = SRRC[3] = 0.0f;
	SRRC[119] = SRRC[118] = SRRC[117] = SRRC[116] = 0.0f;

	SRRC[M_CORE_INDEX-25] = (SRRC[M_CORE_INDEX-24] + SRRC[M_CORE_INDEX-26]) / 2;
	SRRC[M_CORE_INDEX+25] = (SRRC[M_CORE_INDEX+24] + SRRC[M_CORE_INDEX+26]) / 2;

	/*for (int i = 0; i < 120; i++)
	{
		TRACE("SRRC[%d]=%f \n", i, SRRC[i]);
	}*/
}

BYTE CDecodeQAM::CalcPhaseOffset(BYTE Q2Q3Q4)
{
	BYTE nPhaseOffset = 0;

	switch (Q2Q3Q4 & 0x07)
	{
	case 0x00:  // 45'
		nPhaseOffset = 1;
		break;
		
	case 0x01:  // 0'
		nPhaseOffset = 0;
		break;
		
	case 0x02:  // 90'
		nPhaseOffset = 2;
		break;
		
	case 0x03:  // 135'
		nPhaseOffset = 3;
		break;
		
	case 0x04:  // 270'
		nPhaseOffset = 6;
		break;
		
	case 0x05:  // 315'
		nPhaseOffset = 7;
		break;
		
	case 0x06:  // 225'
		nPhaseOffset = 5;
		break;
		
	case 0x07:  // 180'
		nPhaseOffset = 4;
		break;
		
	default:
		break;
	}

	return nPhaseOffset;
}

BOOL CDecodeQAM::MapConstellation(BYTE Q1, BYTE nPhase, int* I, int* Q)
{
	*I = 0;
	*Q = 0;

	switch (nPhase)
	{
	case 0x00:
		*I = ((Q1&0x01) == 0) ? 3 : 5;
		*Q = 0;
		break;
		
	case 0x01:
		*I = ((Q1&0x01) == 0) ? 1 : 3;
		*Q = ((Q1&0x01) == 0) ? 1 : 3;
		break;
		
	case 0x02:
		*I = 0;
		*Q = ((Q1&0x01) == 0) ? 3 : 5;
		break;
		
	case 0x03:
		*I = ((Q1&0x01) == 0) ? -1 : -3;
		*Q = ((Q1&0x01) == 0) ? 1 : 3;
		break;
		
	case 0x04:
		*I = ((Q1&0x01) == 0) ? -3 : -5;
		*Q = 0;
		break;
		
	case 0x05:
		*I = ((Q1&0x01) == 0) ? -1 : -3;
		*Q = ((Q1&0x01) == 0) ? -1 : -3;
		break;
		
	case 0x06:
		*I = 0;
		*Q = ((Q1&0x01) == 0) ? -3 : -5;
		break;
		
	case 0x07:
		*I = ((Q1&0x01) == 0) ? 1 : 3;
		*Q = ((Q1&0x01) == 0) ? -1 : -3;
		break;

	default:
		return FALSE;
		break;
	}

	return TRUE;
}

void CDecodeQAM::WriteToWaveFile(LPBYTE lpBuffer, DWORD dwLen)
{
	CFile File;

	if( !File.Open( "K:\\Fax\\a.wav", CFile::modeReadWrite || CFile::modeCreate ))
	{
		return;
	}

	//WAV 的头数据
	BYTE m_WaveHead[44] = {0x52, 0x49, 0x46, 0x46,	//ChunkID           "RIFF"
						0x00, 0x00, 0x00, 0x00,		//ChunkSize		需要计算
						0x57, 0x41, 0x56, 0x45,		//Format    "WAVE"
						0x66, 0x6D, 0x74, 0x20,		//SubChunk1ID  "fmt "
						0x10, 0x00, 0x00, 0x00,		//SubChunk1Size
						0x01, 0x00,					//AudioFormat
						0x01, 0x00,					//NumChannels
						0x80, 0xBB, 0x00, 0x00,		//SampleRate
						0x80, 0xBB, 0x00, 0x00,		//ByteRate
						0x01, 0x00,					//BlockAlign
						0x08, 0x00,					//BitsPerSample
						0x64, 0x61, 0x74, 0x61,		//SubChunk2ID       "DATA"
						0x00, 0x00, 0x00, 0x00		//SubChunk2Size		需要计算
						};

	/* 计算WAVE 文件的实际长度 */  
	m_WaveHead[4] = (BYTE)((dwLen + 36) & 0x000000FF);
	m_WaveHead[5] = (BYTE)(((dwLen + 36) & 0x0000FF00) >> 8);
	m_WaveHead[6] = (BYTE)(((dwLen + 36) & 0x00FF0000) >> 16);
	m_WaveHead[7] = (BYTE)(((dwLen + 36) & 0xFF000000) >> 24);

	m_WaveHead[40] = (BYTE)(dwLen & 0x000000FF);
	m_WaveHead[41] = (BYTE)((dwLen & 0x0000FF00) >> 8);
	m_WaveHead[42] = (BYTE)((dwLen & 0x00FF0000) >> 16);
	m_WaveHead[43] = (BYTE)((dwLen & 0xFF000000) >> 24);

	File.Write(m_WaveHead, 44);

	File.Write(lpBuffer, dwLen);
	File.Flush();
	File.Close();
}

BOOL CDecodeQAM::SRRCFilter(int *piInData, unsigned int uiInLen, double *pOutData, unsigned int *puiOutLen)
{
	const int M_SAMPLE_PER_BAND = 20;

	int iLoop = 0;
	int iSubLoop = 0;

	GenerateSRRC();

	for (iLoop = 0; iLoop < uiInLen; iLoop++)
	{
		int nStartIndex = 0;
		int nEndIndex = 120;
		int nPos = iLoop * M_SAMPLE_PER_BAND - 50;

		// 计算起始位置
		if (nPos < 0)
		{
			nStartIndex += abs(nPos);
			nPos = 0;
		}
		if (iLoop >= (uiInLen-3))
		{
			nEndIndex -= ((iLoop-(uiInLen-3))*20 + 10);
		}

		// 开始累加升余弦波
		for (iSubLoop = nStartIndex; iSubLoop < nEndIndex; iSubLoop++)
		{
			pOutData[nPos] += piInData[iLoop] * SRRC[iSubLoop];
			nPos++;
		}
	}

	*puiOutLen = M_SAMPLE_PER_BAND * uiInLen;

	return TRUE;
}

/****************************************************************************/
/* clear: zeroize a FIR delay line                                          */
/****************************************************************************/
void CDecodeQAM::srrc_clear(int ntaps, double z[])
{
	int ii;
	for (ii = 0; ii < ntaps; ii++) 
	{
		z[ii] = 0;
	}
}

/****************************************************************************
* filter: Does the basic FIR algorithm: store input sample, calculate       
* output sample, shift delay line                                           
*****************************************************************************/
void CDecodeQAM::srrc_intrp(int din[], int din_len, double t1[], double sum1[])
{
	int ii,jj,kk;
	double accum;

	for(ii=0;ii<din_len;ii++)
	{
		/* store input at the beginning of the delay line */
		t1[0]=(double)din[ii];
	     
		/* calc FIR */
		for(jj=0;jj<5;jj++)
		{
			accum=0;
			for (kk = 0; kk < h1_len; kk++) 
			{
				accum += h1[kk] * t1[kk];
			}

			/* shift delay line */
			for (kk= h1_len-2; kk >= 0; kk--) 
			{
				t1[kk + 1] = t1[kk];
			}

			t1[0]=0;  //pad 0
			sum1[ii*5+jj]=accum;
		} 
	}
}

void CDecodeQAM::srrc_fir_ha1(double din[], int din_len, double t2[], double sum1[])
{
	int ii,jj,kk;
	double accum;

	for(ii=0;ii<din_len;ii++)
	{
		/* store input at the beginning of the delay line */
		t2[0]=din[ii];
	     
		/* calc FIR */
		for(jj=0;jj<2;jj++)
		{
			accum=0;
			for (kk = 0; kk < h2_len; kk++) 
			{
				accum += h2[kk] * t2[kk];	
			}

			/* shift delay line */
			for (kk= h2_len-2; kk >= 0; kk--) 
			{
				t2[kk + 1] = t2[kk];
			}

			t2[0]=0;   //pad 0
			sum1[ii*2+jj]=accum;
		} 
	}
}

void CDecodeQAM::srrc_fir_ha2(double din[], int din_len, double t3[], double sum1[])
{
	int ii,jj,kk;
	double accum;

	for(ii=0;ii<din_len;ii++)
	{
		/* store input at the beginning of the delay line */
		t3[0]=din[ii];
	     
		/* calc FIR */
		for(jj=0;jj<2;jj++)
		{
			accum=0;

			for (kk = 0; kk < h3_len; kk++) 
			{
				accum += h3[kk] * t3[kk];
			}

			/* shift delay line */
			for (kk= h3_len-2; kk >= 0; kk--) 
			{
				t3[kk + 1] = t3[kk];
			}

			t3[0]=0;   //pad 0
			sum1[ii*2+jj]=accum;
		} 
	}
}

/****************************************************************************
* filter: Does the basic FIR algorithm: store input sample, calculate       
* output sample, shift delay line                                           
*****************************************************************************/
void CDecodeQAM::srrc_tx_filter(int din[], int din_len, double dout[], unsigned int *dout_len)
{
	static double *sum1;
	static double *sum2;
    
	static double *t1;
	static double *t2;
	static double *t3;
	
	t1 = (double *)malloc(h1_len*sizeof(double));
	t2 = (double *)malloc(h2_len*sizeof(double));
	t3 = (double *)malloc(h3_len*sizeof(double));
	sum1 = (double *)malloc(din_len*5*sizeof(double));
	sum2 = (double *)malloc(din_len*10*sizeof(double));
	
	srrc_intrp(din, din_len, t1, sum1);
    
	srrc_fir_ha1(sum1, din_len*5, t2, sum2);
   
	srrc_fir_ha2(sum2, din_len*10, t3,dout);
     
	*dout_len =din_len*20;
	
	free(t1);
	free(t2);
	free(t3);
	free(sum1);
	free(sum2);
}

⌨️ 快捷键说明

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