上一节,我们实现了一个通用的有限状态机编码器及维特比译码器。这一节,实现两种卷积码(前向、反馈)的状态机初始化类。
前向码需要一组参数,分别是 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
下一节,我们用一个简单的控制台程序测试成果