?? decode_4_21.c
字號:
#include <stdio.h>
#include "config.h"
extern unsigned short int received[size_rcpc];//引用在main函數(shù)中寫入的接收端接收到的序列。
extern unsigned short int a[3][period];//引用一個選取的刪除圖形
void decode()
{
unsigned short int code[64][3]={{0,0,0},{1,1,1},{1,1,0},{0,0,1},{1,1,1},{0,0,0},{0,0,1},{1,1,0},{1,0,1},{0,1,0},{0,1,1},
{1,0,0},{0,1,0},{1,0,1},{1,0,0},{0,1,1},{0,1,0},{1,0,1},{1,0,0},{0,1,1},{1,0,1},{0,1,0},{0,1,1},{1,0,0},{1,1,1},{0,0,0},
{0,0,1},{1,1,0},{0,0,0},{1,1,1},{1,1,0},{0,0,1},{0,0,1},{1,1,0},{1,1,1},{0,0,0},{1,1,0},{0,0,1},{0,0,0},{1,1,1},{1,0,0},
{0,1,1},{0,1,0},{1,0,1},{0,1,1},{1,0,0},{1,0,1},{0,1,0},{0,1,1},{1,0,0},{1,0,1},{0,1,0},{1,0,0},{0,1,1},{0,1,0},{1,0,1},
{1,1,0},{0,0,1},{0,0,0},{1,1,1},{0,0,1},{1,1,0},{1,1,1},{0,0,0}};
//用于存放從狀態(tài)0->狀態(tài)1->狀態(tài)2->狀態(tài)3->狀態(tài)4------>狀態(tài)63時,所產(chǎn)生的編碼表,具體見本函數(shù)最后的注釋
unsigned short int mettab[2][2]={0,1,1,0};
//這個表是為了計算度量的方便,
//mettab[0][0]=0, mettab[0][1]=1,
//mettab[1][0]=1, mettab[1][1]=0
unsigned short int branch_metric[2]={0};
//計算在當(dāng)前狀態(tài)下,輸入為0或1時,理論輸出的碼字與接收到的碼字之間的漢明距離
unsigned short int path_metric[64]={0};//保存每條路徑的漢明距離總和,最多有效的路徑為64條。
unsigned short int temp[64]={0};//暫時保存路徑度量
unsigned long int path[64]={0};//記錄下進入當(dāng)前狀態(tài)的路徑。路徑長度為32個比特,即可保存32級譯碼,以便回溯,譯碼輸出。
unsigned long int temp_path[64]={0};//暫時保存路徑
unsigned short int min_metric=0;//最終輸出的所有路徑中最小的漢明距離
unsigned short int i,j,k;//循環(huán)變量i,j。k為回溯時暫存數(shù)值j
unsigned short int *p,*q;
unsigned short int decode[length]={0};//譯碼輸出,以每個數(shù)組元素對應(yīng)received中相應(yīng)的數(shù)組元素。
unsigned short int out0,out1,out2;//在譯碼時判斷接收到的碼字,哪幾個是由同一個信息碼編碼而成的。
unsigned short int weight1=0,weight2=0;
p=decode;//將指針初始化,指向輸出的最終譯碼序列
q=received;//初始化指針
printf("this is the RCPC decode:\n");
/************************************************************************************************************
以下這個循環(huán)主要是實現(xiàn)由狀態(tài)0開始的最初的6級譯碼。
這個時候狀態(tài)數(shù)呈2的指數(shù)形式遞增,即狀態(tài)數(shù)為2,4,8,16,32,64
而且此時每個狀態(tài)都只有一個支路進入,而有兩個支路出去
*************************************************************************************************************/
for(i=0;i<6;i++)//記錄前六級的路徑
{
/*=====================================這個部分是將接收到的比特流分組=============================*/
weight1=a[1][i%period];//i%period體現(xiàn)了RCPC刪除圖形的周期性,記錄第二個加法器的權(quán)重
weight2=a[2][i%period];//記錄第三個加法器的權(quán)重
out0=*q;q++;//根據(jù)RCPC的刪除圖形,我們可以知道第一個加法器的輸出是全部保留的。
if(weight1==1)//判斷編碼時對第二加法器的編碼是否進行刪除
{out1=*q;q++;}
if(weight2==1)//判斷編碼時對第三加法器的編碼是否進行刪除
{out2=*q;q++;}
/*================================================================================================*/
for(j=0;(j<(2<<i));j++)
{
branch_metric[j%2]=mettab[code[j][0]][out0]+weight1*mettab[code[j][1]][out1]+weight2*mettab[code[j][2]][out2];
//計算當(dāng)前狀態(tài)下0或1支路的度量。j%2表示了0或1支路;code[j][*]表示了從狀態(tài)j/2--->狀態(tài)j的編碼。
//對mettab查表后的值乘以權(quán)重a[*][i%period]。
//例如:假如當(dāng)a[1][i%period]=0時,對應(yīng)的第2個加法器的度量就不做計算;若a[1][i%period]=1時,對應(yīng)的第2個加法器的度量就需算作計算,
temp[j]=path_metric[j];//暫存需要改變的度量值
path_metric[j]=temp[j/2]+branch_metric[j%2];//使用蝶形算法計算度量。
path[j]=j;//記錄支路的路徑,前6級的路徑和當(dāng)前狀態(tài)密切相關(guān)。
}
}
/********************************************************************************************************************
蝶形算法的介紹
(1) 編碼器共有64 種狀態(tài),分成狀態(tài)i (0 <=i<=31,下面均做此假設(shè)) 和狀態(tài)i+32的上下兩部分。
(2) 編碼器當(dāng)前狀態(tài)為i或i+32時,輸入為0 時,下一狀態(tài)均為2*i 。
(3) 編碼器當(dāng)前狀態(tài)為i 或i+32 時,輸入為1 時,下一狀態(tài)均為2*i+1 。
(4) 編碼器當(dāng)前狀態(tài)為i ,輸入為0 時,若輸出為out0 ,則編碼器當(dāng)前狀態(tài)為i+32 ,輸入為0 時,輸出為7^out0 。
(5) 編碼器當(dāng)前狀態(tài)為i ,輸入為1 時,若輸出為out1 ,則編碼器當(dāng)前狀態(tài)為i + 32 ,輸入為1 時,輸出為7^out1 。
*******************************************************************************************************************/
/*******************************************************************************************************************
以下這個循環(huán)是實現(xiàn)從第7級開始譯碼,這個時候,狀態(tài)保持在64個,每個狀態(tài)都有兩個支路進入,也有兩個支路出去。
每次譯碼時都要進行加-比-選的操作。
同時在這個循環(huán)中還考慮到了,path[]路徑記錄是否已滿的情況:
如果滿了,則譯一個碼,就回溯路徑輸出1個碼字至decode[];
未滿,就繼續(xù)記錄路徑
********************************************************************************************************************/
for(i=6;i<length-6;i++)//減6是因為接收到的序列有6個碼字為填充位,這些填充位是已知的,假定為0
{
if(i>=32)//判斷路徑記錄是否已滿。若已滿,則回溯路徑
{
/*下述兩步是假定path_metric[0]最小時,輸出path[0]最早記錄的1位至decode*/
min_metric=path_metric[0];
*p=(path[0]&0x80000000)>>31;
/*以下這個循環(huán)是查找在path_metric中是否還有更小的度量值,如果有賦值給min_metric*/
for(j=0;j<64;j++)
{if(min_metric>path_metric[j])
{ min_metric=path_metric[j];
k=j;//暫存數(shù)值j
}
*p=(path[k]&0x80000000)>>31;//輸出最后找到的最小度量所對應(yīng)路徑中最早記錄的1位至decode
}
p++;
}
/*=====================================這個部分是將接收到的比特流分組=============================*/
weight1=a[1][i%period];//i%period體現(xiàn)了RCPC刪除圖形的周期性,記錄第二個加法器的權(quán)重
weight2=a[2][i%period];//記錄第三個加法器的權(quán)重
out0=*q;q++;//根據(jù)RCPC的刪除圖形,我們可以知道第一個加法器的輸出是全部保留的。
if(weight1==1)//i%period體現(xiàn)了RCPC刪除圖形的周期性,判斷編碼時對第二個加法器的編碼是否進行刪除
{out1=*q;q++;}
if(weight2==1)//判斷編碼時對第三個加法器的編碼是否進行刪除
{out2=*q;q++;}
/*================================================================================================*/
/*===============以下這個循環(huán)是viterbi譯碼中的核心單元,加—比—選,記錄路徑========================*/
for(j=0;j<64;j++)
{branch_metric[0]=mettab[code[j][0]][out0]+weight1*mettab[code[j][1]][out1]+weight2*mettab[code[j][2]][out2];//記為支路0的度量
branch_metric[1]=mettab[code[j][0]][out0]^1+weight1*(mettab[code[j][1]][out1]^1)+weight2*(mettab[code[j][2]][out2]^1);//記為支路1的度量
temp[j]=path_metric[j];
temp_path[j]=path[j];
if(branch_metric[0]<branch_metric[1])//如果支路0度量小于支路1度量,即從0-31狀態(tài)過來的理論譯碼與接收到序列的漢明距離更小
{path_metric[j]=temp[j/2]+branch_metric[0];//進入狀態(tài)j的路徑度量
path[j]=(temp_path[j/2]<<1)+j%2;//進入狀態(tài)j的路徑,這個路徑是包括前6級輸入的
}
else//如果支路1度量小于支路0度量,即從32-63狀態(tài)過來的理論譯碼與接收到序列的漢明距離更小
{k=j/2+32;
temp[k]=path_metric[k];
temp_path[k]=path[k];
path_metric[j]=temp[k]+branch_metric[1];
path[j]=(temp_path[k]<<1)+j%2;
}
}
}
/***************************************************************************************************************
以下這個部分是當(dāng)接收到的序列已讀取完畢,只剩下最后補上的已知的6個0 bits序列時,通過加-比-選法則來最后將路徑
收斂的過程。
收斂如下:
i=0時: i=1時:
狀態(tài)0,狀態(tài)32--->狀態(tài)0, 狀態(tài)0,狀態(tài)32--->狀態(tài)0,
狀態(tài)1,狀態(tài)33--->狀態(tài)2, 狀態(tài)2,狀態(tài)34--->狀態(tài)4,
狀態(tài)2,狀態(tài)34--->狀態(tài)4, 狀態(tài)4,狀態(tài)36--->狀態(tài)8,
…… ……
狀態(tài)32,狀態(tài)63--->狀態(tài)62, 狀態(tài)30,狀態(tài)62--->狀態(tài)60,
依此類推得到最后收斂至狀態(tài)0。
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -