File: ccsds_ldpc.cpp

package info (click to toggle)
satdump 1.2.2%2Bgb79af48-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 81,648 kB
  • sloc: cpp: 276,768; ansic: 164,598; lisp: 1,219; sh: 283; xml: 106; makefile: 7
file content (139 lines) | stat: -rw-r--r-- 4,943 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include "ccsds_ldpc.h"
#include <cstdlib>
#include <cmath>
#include <cstring>
#include "common/dsp/buffer.h"
#include "make_ccsds.h"
#include "logger.h"

#define MAX_SIMD_SIZE 32

namespace codings
{
    namespace ldpc
    {
        CCSDSLDPC::CCSDSLDPC(ldpc_rate_t rate, int block_size)
            : d_rate(rate), d_block_size(block_size)
        {
            if (d_rate == RATE_7_8)
            {
                init_dec(ccsds_78::make_r78_code());

                d_frame_size = 8160;
                d_codeword_size = 8176;
                d_data_size = 7136;

                depunc_buffer_in = dsp::create_volk_buffer<int8_t>(d_codeword_size * MAX_SIMD_SIZE);
                depunc_buffer_ou = dsp::create_volk_buffer<uint8_t>(d_codeword_size * MAX_SIMD_SIZE);
            }
            else
            {
                ccsds_ar4ja::ar4ja_rate_t rate4 = ccsds_ar4ja::AR4JA_RATE_1_2;
                if (d_rate == RATE_1_2)
                    rate4 = ccsds_ar4ja::AR4JA_RATE_1_2;
                else if (d_rate == RATE_2_3)
                    rate4 = ccsds_ar4ja::AR4JA_RATE_2_3;
                else if (d_rate == RATE_4_5)
                    rate4 = ccsds_ar4ja::AR4JA_RATE_4_5;

                ccsds_ar4ja::ar4ja_blocksize_t block4 = ccsds_ar4ja::AR4JA_BLOCK_1024;
                if (d_block_size == 1024)
                    block4 = ccsds_ar4ja::AR4JA_BLOCK_1024;
                else if (d_block_size == 4096)
                    block4 = ccsds_ar4ja::AR4JA_BLOCK_4096;
                else if (d_block_size == 16384)
                    block4 = ccsds_ar4ja::AR4JA_BLOCK_16384;
                else
                    throw std::runtime_error("This blocksize is not supported!");

                auto pcm = ccsds_ar4ja::make_ar4ja_code(rate4, block4, &d_M);
                init_dec(pcm);

                d_frame_size = pcm.get_n_cols() - d_M; // Punctured codeword size
                d_codeword_size = pcm.get_n_cols();    // Full codeword size
                d_data_size = pcm.get_n_rows() - d_M;  // Data words size

                depunc_buffer_in = dsp::create_volk_buffer<int8_t>(d_codeword_size * MAX_SIMD_SIZE);
                depunc_buffer_ou = dsp::create_volk_buffer<uint8_t>(d_codeword_size * MAX_SIMD_SIZE);
            }
        }

        void CCSDSLDPC::init_dec(Sparse_matrix pcm)
        {
            ldpc_decoder = get_best_ldpc_decoder(pcm);

            d_simd = ldpc_decoder->simd();
            d_is_geneneric = d_simd == 1;
        }

        CCSDSLDPC::~CCSDSLDPC()
        {
            delete ldpc_decoder;
            volk_free(depunc_buffer_in);
            volk_free(depunc_buffer_ou);
        }

        int CCSDSLDPC::decode(int8_t *codeword, uint8_t *frame, int iterations)
        {
            if (d_rate == RATE_7_8)
            {
                for (int i = 0; i < d_simd; i++)
                {
                    memcpy(&depunc_buffer_in[i * d_codeword_size + 18], &codeword[i * d_frame_size], 8158);
                    for (int i = 0; i < d_simd; i++) // First 18s are 0s
                        memset(&depunc_buffer_in[i * d_codeword_size], 0, 18);
                }
            }
            else
            {
                for (int i = 0; i < d_simd; i++)
                {
                    memcpy(&depunc_buffer_in[i * d_codeword_size], &codeword[i * d_frame_size], d_frame_size);
                    // Last d_M bits are 0s
                    memset(&depunc_buffer_in[i * d_codeword_size + d_frame_size], 0, d_M);
                }
            }

            d_corr_errors = 0;

            if (d_is_geneneric)
                for (int i = 0; i < d_simd; i++)
                    d_corr_errors += ldpc_decoder->decode(&depunc_buffer_ou[i * d_codeword_size], &depunc_buffer_in[i * d_codeword_size], iterations);
            else
                d_corr_errors = ldpc_decoder->decode(depunc_buffer_ou, depunc_buffer_in, iterations);

            d_corr_errors /= d_simd;

            if (d_rate == RATE_7_8)
            {
                for (int i = 0; i < d_simd; i++)
                {
                    memcpy(&frame[i * d_frame_size], &depunc_buffer_ou[i * d_codeword_size + 18], 8158);
                }
            }
            else
            {
                for (int i = 0; i < d_simd; i++)
                {
                    memcpy(&frame[i * d_frame_size], &depunc_buffer_ou[i * d_codeword_size], d_frame_size);
                }
            }

            return d_corr_errors;
        }

        ldpc_rate_t ldpc_rate_from_string(std::string str)
        {
            if (str == "1/2")
                return RATE_1_2;
            else if (str == "2/3")
                return RATE_2_3;
            else if (str == "4/5")
                return RATE_4_5;
            else if (str == "7/8")
                return RATE_7_8;
            else
                throw std::runtime_error("Invalid LDPC code rate " + str);
        }
    }
}