MSCBSC 移動通信論壇
搜索
登錄注冊
網(wǎng)絡(luò)優(yōu)化工程師招聘專欄 4G/LTE通信工程師最新職位列表 通信實(shí)習(xí)生/應(yīng)屆生招聘職位

  • 閱讀:2848
  • 回復(fù):0
C/C++ 編程實(shí)現(xiàn) LTE Turbo編碼
weixingguang
初級會員
鎵嬫満鍙風(fēng)爜宸查獙璇? style=


 發(fā)短消息    關(guān)注Ta 

積分 65
帖子 13
威望 8989 個
禮品券 0 個
專家指數(shù) 0
注冊 2016-1-26
專業(yè)方向  無線通信
回答問題數(shù) 0
回答被采納數(shù) 0
回答采納率 0%
 
發(fā)表于 2016-12-16 21:55:02  只看樓主 

C/C++ 編程實(shí)現(xiàn) LTE Turbo編碼



博客源地址http://blog.csdn.net/jxwxg/article/details/53644821。更多SDR,LTE博客請點(diǎn)擊CSDN博客

在LTE協(xié)議TS 136 212中詳細(xì)介紹了LTE里面Turbo編碼的算法。但協(xié)議看起來實(shí)在是太晦澀難懂,本文檔通俗地介紹LTE中Turbo編碼的原理,并用C語言編程實(shí)現(xiàn)了一個LTE Turbo編碼器。


一、 Turbo編碼器

LTE系統(tǒng)采用的1/3碼率的Turbo編碼器,即1個輸入比特會對應(yīng)3個輸出比特,即Xk,Zk,Z’k。其中,Xk叫做系統(tǒng)比特,Xk與輸入的比特相等。Zk和Z’k叫做冗余比特,Zk對應(yīng)編碼器1的輸出,Z’k對應(yīng)編碼器2的輸出,冗余比特用來增強(qiáng)傳輸?shù)目煽啃浴?/span>
圖中每個編碼器的輸入端都有一個單刀雙擲開關(guān),當(dāng)正常編碼時,開關(guān)與輸入連接。當(dāng)沒有輸入,正在添加尾比特時,開關(guān)與輸入斷開。
下面以編碼器1來介紹Turbo編碼的原理。
首先,三個寄存器(D1,D2,D3)初始化為0。輸入比特Ck=1,此時有Xk=1。輸入第一個寄存器的值為D2 +D3 +Ck。第一個編碼器輸出的值為 D1的輸入值+D1的輸出值+D3的輸出值,即Zk=D2 +D3 +Ck + D1+D3。
此次編碼完成后,寄存器的值往后推。即D3的值更新為D2的輸出,D2的值更新為D1的輸出,D1的值更新為D1的輸入值,即D2 +D3 +Ck。
編碼器2的原理與編碼器1類似,輸入比特進(jìn)入編碼器2前需要先進(jìn)行交織,即把位置打亂。交織具體的原理將在下一章介紹。




最后,當(dāng)所有的輸入比特都編碼完成時,需要把開關(guān)與輸入斷開連接以對編碼后的比特添加尾比特。尾比特是為了讓編碼器回到初始狀態(tài),避免了兩個碼字之間的關(guān)聯(lián)性。協(xié)議定義了一共添加12bit的尾比特,12比特具體的值如下圖所示。下圖應(yīng)該按照從上到下,從左往右的順序看,即先看d(k),接著看d(k+1),d(k+2), d(k+3)。Xk,Zk,Z’k與上述定義相同,而X’k對應(yīng)圖中最底下的虛線。



如果系統(tǒng)輸入c0,c1,則編碼后會輸出c0,z(0),z’(0),c1, z(1),z’(1),d(k)(0),d(k)(1), d(k)(2), d(k+1)(0),d(k+1)(1), d(k+1)(2), d(k+2)(0),d(k+2)(1), d(k+2)(2)。


二、 Turbo交織

如果輸入的比特為c0,c1……ci……c(K-1),輸出的比特為c’0,c’1……c’j……c’(K-1),則j=(f1*i + f2*i*i) mod K。
f1,f2和K的定義在LTE協(xié)議里面有一個對應(yīng)的表格,一共188組。編碼的時候根據(jù)表格找到大于編碼輸入長度的最小的K值。




三、 C編程實(shí)現(xiàn)Turbo編碼器

如果看了上述介紹還是不理解LTE Turbo編碼的原理,那么就直接show you the code。對照C語言實(shí)現(xiàn)的Turbo編碼器更容易理解Turbo編碼的原理。


#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#define NOF_REGS 3
#define NOF_TAILINGS 12
#define MAX_CB_SIZE 188
#define MAX_BIT_LENGTH 6144

const uint32_t tc_cb_sizes[MAX_CB_SIZE] = {
40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120,       
128, 136, 144, 152, 160, 168, 176, 184, 192, 200, 208, 216, 224, 232,
240, 248, 256, 264, 272, 280, 288, 296, 304, 312, 320, 328, 336, 344,
352, 360, 368, 376, 384, 392, 400, 408, 416, 424, 432, 440, 448, 456,
464, 472, 480, 488, 496, 504, 512, 528, 544, 560, 576, 592, 608, 624,
640, 656, 672, 688, 704, 720, 736, 752, 768, 784, 800, 816, 832, 848,
864, 880, 896, 912, 928, 944, 960, 976, 992, 1008, 1024, 1056, 1088,
1120, 1152, 1184, 1216, 1248, 1280, 1312, 1344, 1376, 1408, 1440, 1472,
1504, 1536, 1568, 1600, 1632, 1664, 1696, 1728, 1760, 1792, 1824, 1856,
1888, 1920, 1952, 1984, 2016, 2048, 2112, 2176, 2240, 2304, 2368, 2432,
2496, 2560, 2624, 2688, 2752, 2816, 2880, 2944, 3008, 3072, 3136, 3200,
3264, 3328, 3392, 3456, 3520, 3584, 3648, 3712, 3776, 3840, 3904, 3968,
4032, 4096, 4160, 4224, 4288, 4352, 4416, 4480, 4544, 4608, 4672, 4736,
4800, 4864, 4928, 4992, 5056, 5120, 5184, 5248, 5312, 5376, 5440, 5504,
5568, 5632, 5696, 5760, 5824, 5888, 5952, 6016, 6080, 6144 };

const uint32_t f1_list[MAX_CB_SIZE] = { 
3, 7, 19, 7, 7, 11, 5, 11, 7, 41, 103,
15, 9, 17, 9, 21, 101, 21, 57, 23, 13, 27, 11, 27, 85, 29, 33, 15, 17, 33,
103, 19, 19, 37, 19, 21, 21, 115, 193, 21, 133, 81, 45, 23, 243, 151, 155,
25, 51, 47, 91, 29, 29, 247, 29, 89, 91, 157, 55, 31, 17, 35, 227, 65, 19,
37, 41, 39, 185, 43, 21, 155, 79, 139, 23, 217, 25, 17, 127, 25, 239, 17,
137, 215, 29, 15, 147, 29, 59, 65, 55, 31, 17, 171, 67, 35, 19, 39, 19, 199,
21, 211, 21, 43, 149, 45, 49, 71, 13, 17, 25, 183, 55, 127, 27, 29, 29, 57,
45, 31, 59, 185, 113, 31, 17, 171, 209, 253, 367, 265, 181, 39, 27, 127,
143, 43, 29, 45, 157, 47, 13, 111, 443, 51, 51, 451, 257, 57, 313, 271, 179,
331, 363, 375, 127, 31, 33, 43, 33, 477, 35, 233, 357, 337, 37, 71, 71, 37,
39, 127, 39, 39, 31, 113, 41, 251, 43, 21, 43, 45, 45, 161, 89, 323, 47, 23,
47, 263 };

const uint32_t f2_list[MAX_CB_SIZE] = { 
10, 12, 42, 16, 18, 20, 22, 24, 26, 84,
90, 32, 34, 108, 38, 120, 84, 44, 46, 48, 50, 52, 36, 56, 58, 60, 62, 32,           
198, 68, 210, 36, 74, 76, 78, 120, 82, 84, 86, 44, 90, 46, 94, 48, 98, 40,
102, 52, 106, 72, 110, 168, 114, 58, 118, 180, 122, 62, 84, 64, 66, 68, 420,
96, 74, 76, 234, 80, 82, 252, 86, 44, 120, 92, 94, 48, 98, 80, 102, 52, 106,
48, 110, 112, 114, 58, 118, 60, 122, 124, 84, 64, 66, 204, 140, 72, 74, 76,
78, 240, 82, 252, 86, 88, 60, 92, 846, 48, 28, 80, 102, 104, 954, 96, 110,
112, 114, 116, 354, 120, 610, 124, 420, 64, 66, 136, 420, 216, 444, 456,
468, 80, 164, 504, 172, 88, 300, 92, 188, 96, 28, 240, 204, 104, 212, 192,
220, 336, 228, 232, 236, 120, 244, 248, 168, 64, 130, 264, 134, 408, 138,
280, 142, 480, 146, 444, 120, 152, 462, 234, 158, 80, 96, 902, 166, 336,
170, 86, 174, 176, 178, 120, 182, 184, 186, 94, 190, 480 };

int search_segment_index(int input_length)
{
        int j= 0;
        while( j < MAX_CB_SIZE && tc_cb_sizes[j] < input_length)
                j++;

        if(j == MAX_CB_SIZE)
                return -1;
        else
                return j;
}

int turbo_interleaver(uint8_t *interleaver, int input_length)
{
        if(input_length > MAX_BIT_LENGTH)
                return -1;

        // Find code block index
        int segment_index = search_segment_index(input_length);
        if(segment_index == -1)
                return -1;

        uint32_t f1 = f1_list[segment_index];
        uint32_t f2 = f2_list[segment_index];

        uint32_t i = 0, j;
        for(i = 0; i < input_length; i++)
        {
                j = (f1 * i + f2 * i * 1) % input_length;
                interleaver[i] = j;
        }

        for(i = input_length; i < MAX_BIT_LENGTH; i++)
                interleaver[i] = 0;

        return 0;
}

void lte_turbo(uint8_t *input, uint8_t* output, uint32_t input_length)
{

        // Initialization of turbo registers
        uint8_t reg1_1, reg1_2, reg1_3, reg2_1, reg2_2, reg2_3;

        reg1_1 = 0;
        reg1_2 = 0;
        reg1_3 = 0;

        reg2_1 = 0;
        reg2_2 = 0;
        reg2_3 = 0;

        // Initialization of turbo interleaver
        uint8_t* input_interleaver = malloc(MAX_BIT_LENGTH * sizeof(uint8_t));
        if (turbo_interleaver(input_interleaver, input_length) < 0 )
        {
                printf("Initialization of turbo interleaver ERROR!\n");
                exit(-1);
        }

        uint32_t k = 0, i, j;
        uint8_t bit, in, out;
        for(i = 0; i < input_length; i++)
        {
                bit = input[i];
                
                // X[k]
                output[k] = input[i];
                k++;

                in = bit ^ (reg1_3 ^ reg1_2);
                out = reg1_3 ^ (reg1_1 ^ in);

                reg1_3 = reg1_2;
                reg1_2 = reg1_1;
                reg1_1 = in;

                // Z[k]
                output[k] = out;
                k++;

                bit = input[input_interleaver[i]];

                in = bit ^ (reg2_3 ^ reg2_2);
                out = reg2_3 ^ (reg2_1 ^ in);

                reg2_3 = reg2_2;
                reg2_2 = reg2_1;
                reg2_1 = in;

                // Z*[k]
                output[k] = out;
                k++;
        }

        k = 3 * input_length;

        // Tailing coder 1
        for(j = 0; j< NOF_REGS; j++)
        {
                bit = reg1_3 ^ reg1_2;

                output[k] = bit;
                k++;

                in = bit ^ (reg1_3 ^ reg1_2);
                out = reg1_3 ^ (reg1_1 ^ in);

                reg1_3 = reg1_2;
                reg1_2 = reg1_1;
                reg1_1 = in;

                output[k] = out;
                k++;
        }

        // Tailing coder 2
        for(j = 0; j < NOF_REGS; j++)
        {
                bit = reg2_3 ^ reg2_2;

                output[k] = bit;
                k++;

                in = bit ^ (reg2_3 ^ reg2_2);
                out = reg2_3 ^ (reg2_1 ^ in);

                reg2_3 = reg2_2;
                reg2_2 = reg2_1;
                reg2_1 = in;

                output[k] = out;
                k++;
        }

        free(input_interleaver);

}

int main(int argc, char* argv[])
{
        uint32_t input_length = 100;
        if(argc == 2)
                input_length = atoi(argv[1]);
        printf("Input bits length %d.\n", input_length);

        uint32_t output_length = input_length * 3 + NOF_TAILINGS;
        uint8_t* input = malloc(input_length * sizeof(uint8_t));
        uint8_t* output = malloc(output_length * sizeof(uint8_t));

        srand(time(NULL));
        int i;
        for(i = 0; i < input_length; i++)
                input[i] = rand() % 2;

        puts("Input Bits :");
        for(i = 0; i < input_length; i++)
        {
                printf("%d ", input[i]);
                if( (i+1) % 20 == 0)
                        printf("\n");
        }
        printf("\n");

        lte_turbo(input, output, input_length);

        puts("Output Bits :");
        for(i = 0; i < output_length; i++)
        {
                printf("%d ", output[i]);
                if( (i+1) % 20 == 0)
                        printf("\n");
        }

        printf("\n");

        free(input);
        free(output);
        return 0;
}

編譯
gcc turbo.c -o turbo

運(yùn)行 參數(shù)為輸入Bit長度。LTE規(guī)定當(dāng)輸入bit長度大于6144時,需要對bit進(jìn)行分割,本代碼沒有實(shí)現(xiàn)這部分功能。
./turbo 200 

四 、備注


上述代碼效率較低,如果要編寫更高效的Turbo編碼器,可以使用查表的算法或者使用SSE、AVX等指令集。


掃碼關(guān)注5G通信官方公眾號,免費(fèi)領(lǐng)取以下5G精品資料
  • 1、回復(fù)“YD5GAI”免費(fèi)領(lǐng)取《中國移動:5G網(wǎng)絡(luò)AI應(yīng)用典型場景技術(shù)解決方案白皮書
  • 2、回復(fù)“5G6G”免費(fèi)領(lǐng)取《5G_6G毫米波測試技術(shù)白皮書-2022_03-21
  • 3、回復(fù)“YD6G”免費(fèi)領(lǐng)取《中國移動:6G至簡無線接入網(wǎng)白皮書
  • 4、回復(fù)“LTBPS”免費(fèi)領(lǐng)取《《中國聯(lián)通5G終端白皮書》
  • 5、回復(fù)“ZGDX”免費(fèi)領(lǐng)取《中國電信5G NTN技術(shù)白皮書
  • 6、回復(fù)“TXSB”免費(fèi)領(lǐng)取《通信設(shè)備安裝工程施工工藝圖解
  • 7、回復(fù)“YDSL”免費(fèi)領(lǐng)取《中國移動算力并網(wǎng)白皮書
  • 8、回復(fù)“5GX3”免費(fèi)領(lǐng)取《 R16 23501-g60 5G的系統(tǒng)架構(gòu)1
  • 對本帖內(nèi)容的看法? 我要點(diǎn)評

     
    [充值威望,立即自動到帳] [VIP貴賓權(quán)限+威望套餐] 另有大量優(yōu)惠贈送活動,請光臨充值中心
    充值擁有大量的威望和最高的下載權(quán)限,下載站內(nèi)資料無憂

    快速回復(fù)主題    
    標(biāo)題
    內(nèi)容
     上傳資料請點(diǎn)左側(cè)【添加附件】

    當(dāng)前時區(qū) GMT+8, 現(xiàn)在時間是 2025-02-02 14:26:06
    渝ICP備11001752號  Copyright @ 2006-2016 mscbsc.com  本站統(tǒng)一服務(wù)郵箱:mscbsc@163.com

    Processed in 0.244827 second(s), 13 queries , Gzip enabled
    TOP
    清除 Cookies - 聯(lián)系我們 - 移動通信網(wǎng) - 移動通信論壇 - 通信招聘網(wǎng) - Archiver