连载:有限状态机以及维特比(Viterbi)译码器(二)

上一节,我们实现了一个通用的有限状态机编码器及维特比译码器。这一节,实现两种卷积码(前向、反馈)的状态机初始化类。

前向码需要一组参数,分别是 n,k,m ,还有具体的管脚描述。

管脚描述采用Matlab的八进制格式。

前向卷积码, front_conv_lsmaker.h

/** \brief 本文件实现了前向卷积码的状态机回调函数
 */
#if !defined (FRONT_CONV_LSMAKER_HEADER_VER)
#define  FRONT_CONV_LSMAKER_HEADER_VER 101
namespace LSMVIT
{
    /** \brief 前向卷积码有限状态机生成器
     */
	template <int n, int k, int m>
	class fconv_lsmaker{
	protected:
		int OutPin[n][k][m+1];
	public:
		fconv_lsmaker(const int octPins[/*k*/][n])
		{
			init_Pins(octPins);
		}
		fconv_lsmaker(){}
		~fconv_lsmaker(){}

        /** \brief 根据抽头初始化本类对象
         *
         * \param octPins[k][n] int 抽头,分别是第k组寄存器对第n个输出管脚的影响
         * \return void
         *
         */
		void init_Pins(const int octPins[/*k*/][n])
		{
			for (int i=0;i<k;i++)
			{
				for (int j=0;j<n;j++)
				{
					int noctp = octPins[i][j];
					int cpin = 0, ct = 0;
					while (noctp)
					{
						cpin += (noctp % 10) << (ct * 3);
						noctp /= 10;
						ct ++;
					}//end while
					for (int v = 0; v < m+1; v++)
						OutPin[j][i][v] = (cpin>>(m-v)) & 0x01;
				}// end j
			}// end i
		}
	public:

        /** \brief 回调函数,会递交给状态机
         */
		bool cb_status (int reg, int data, int *pNextReg, int * pOutput)
		{
			if (pNextReg == nullptr || pOutput == nullptr) return false;
			int nOutput[n], nReg[k][m+1];
			for (int i = 0; i< k ; i++)
			{
				nReg[i][0] = (data >> (k-i-1)) & 0x01;
				for (int j = 0;j<m;j++)
					nReg[i][j+1] = (reg>>((k-i-1)*m + (m-1-j))) & 0x01;

			}// end i
			for (int i=0;i<n;i++)
			{
				int cc = 0;
				for (int j = 0;j<k;j++)
				{
					for (int v = 0;v <m+1;v++)
						cc += OutPin[i][j][v] * nReg[j][v];
				}// end j
				nOutput[i] = cc % 2;
			}//end i
			int newreg = 0, out = 0;
			for (int i=0;i<n;i++)
			{
				out <<=1;
				out += nOutput[i];
			}
			for (int j=0;j<k;j++)
			{
				for (int v = 0;v < m ; v++)
				{
					newreg <<= 1;
					newreg += nReg[j][v];
				}
			}
			*pNextReg = newreg;
			*pOutput = out;
			return true;
		} // end function cb_status
	};// end class
};// end name space
#endif


反馈码除了上述参数,还需要反馈管脚描述。

反馈卷积码 feedback_conv_lsmaker.h

/** \brief 本文件实现了反馈卷积码的状态机回调函数
 */
#if !defined (FEEDBACK_CONV_LSMAKER_HEADER_VER)
#define  FEEDBACK_CONV_LSMAKER_HEADER_VER 101
namespace LSMVIT
{
    /** \brief 反馈卷积码有限状态机生成器
     */
	template <int n, int k, int m>
	class feedback_lsmaker{
	protected:
		int OutPin[n][k][m+1];
		int FeedBackPin[k][k][m+1];
	public:
		feedback_lsmaker(const int octPins[/*k*/][n],const int fbPins[/*k*/][k])
		{
			init_Pins(octPins,fbPins);
		}
		feedback_lsmaker(){}
		~feedback_lsmaker(){}

        /** \brief 根据抽头初始化本类对象
         *
         * \param octPins[k][n] int 抽头,分别是第k组寄存器对第n个输出管脚的影响
         * \param fbPins[k][k] int 反馈抽头,分别是第k组寄存器对第k个输入管脚的影响
         * \return void
         *
         */
		void init_Pins(const int octPins[/*k*/][n],const int fbPins[/*k*/][k])
		{
			for (int i=0;i<k;i++)
			{
				for (int j=0;j<n;j++)
				{
					int noctp = octPins[i][j];
					int cpin = 0, ct = 0;
					while (noctp)
					{
						cpin += (noctp % 10) << (ct * 3);
						noctp /= 10;
						ct ++;
					}//end while
					for (int v = 0; v < m+1; v++)
						OutPin[j][i][v] = (cpin>>(m-v)) & 0x01;
				}// end j
			}// end i
            		for (int i=0;i<k;i++)
			{
				for (int j=0;j<k;j++)
				{
					int noctp = fbPins[i][j];
					int cpin = 0, ct = 0;
					while (noctp)
					{
						cpin += (noctp % 10) << (ct * 3);
						noctp /= 10;
						ct ++;
					}//end while
					for (int v = 0; v < m+1; v++)
						FeedBackPin[j][i][v] = (cpin>>(m-v)) & 0x01;
				}// end j
			}// end i
        }
	public:

        /** \brief 回调函数,会递交给状态机
         */
		bool cb_status (int reg, int data, int *pNextReg, int * pOutput)
		{
			if (pNextReg == nullptr || pOutput == nullptr) return false;
			int nOutput[n], nReg[k][m+1];
			for (int i = 0; i< k ; i++)
			{
				nReg[i][0] = (data >> (k-i-1)) & 0x01;
				for (int j = 0;j<m;j++)
					nReg[i][j+1] = (reg>>((k-i-1)*m + (m-1-j))) & 0x01;
			}// end i
			//反馈
			for (int i=0;i<k;i++)
			{

				int cc = 0;
				for (int j = 0;j<k;j++)
				{
					for (int v = 0;v <m+1;v++)
						cc += FeedBackPin[i][j][v] * nReg[j][v];
				}// end j
				nReg[i][0] += cc;
				nReg[i][0] %= 2;
			}//end i

			//输出
			for (int i=0;i<n;i++)
			{
				int cc = 0;
				for (int j = 0;j<k;j++)
				{
					for (int v = 0;v <m+1;v++)
						cc += OutPin[i][j][v] * nReg[j][v];
				}// end j
				nOutput[i] = cc % 2;
			}//end i
			//下一状态
			int newreg = 0, out = 0;
			for (int i=0;i<n;i++)
			{
				out <<=1;
				out += nOutput[i];
			}
			for (int j=0;j<k;j++)
			{
				for (int v = 0;v < m ; v++)
				{
					newreg <<= 1;
					newreg += nReg[j][v];
				}
			}
			*pNextReg = newreg;
			*pOutput = out;
			return true;
		} // end function cb_status
	};// end class
};// end name space
#endif


 

下一节,我们用一个简单的控制台程序测试成果

你可能感兴趣的:(C++,维特比)