1% ldpc_gen_c_h_file.m
2% David Rowe Sep 2015, B. Van Slyke 2019
3%
4% Create .c and h files for use in LDPC decoders
5%
6% NOTE:  You'll need to install the CML library as a number of functions involved
7%        in LDPC use it.  See ldpc.m for instructions in installing the CML
8%        library.
9%
10% usage examples:
11%
12%   1/ Using codes defined in external files:
13%
14%     octave:1> ldpc_gen_c_h_file("HRA_112_112.txt")
15%     octave:1> ldpc_gen_c_h_file(""H_4096_8192_3d.mat")
16%
17%   2/ Using built in CML codes:
18%
19%     octave:1> ldpc_gen_c_h_file("dvbs2", 0.6, 16200)
20%
21% Output: Two files with the same filename as the LDPC input, but with .c and .h
22% extensions.
23
24function ldpc_gen_c_h_file(varargin)
25
26    ldpc  % load ldpc functions
27    ldpc_fsk_lib  % for ldpc_encode
28
29    % Assuming cml has been installed in the users' home folder, which is the
30    % default install location
31    init_cml();
32
33    if nargin == 0
34        printf("Error - you must specify a file containing the LDPC codes (e.g. HRA_112_112.txt).\n");
35        return;
36    end
37    loadStr = varargin{1};
38
39    max_iterations = 100;
40    decoder_type = 0;
41    % the tests are performed using BPSK modulation, but in practice codes can be used
42    % with other modulation, e.g. QPSK
43    mod_order = 2; modulation = 'BPSK'; mapping = 'gray';
44
45    if strcmp(loadStr, "dvbs2")
46        rate = varargin{2};
47        framesize = varargin{3};
48        code_param = ldpc_init_builtin(loadStr, rate, framesize, modulation, mod_order, mapping);
49        n = code_param.ldpc_coded_bits_per_frame;
50        k = code_param.ldpc_data_bits_per_frame;
51        ldpcArrayName = sprintf("H_%d_%d",n,k);
52        includeFileName = strcat(ldpcArrayName, '.h');
53        sourceFileName = strcat(ldpcArrayName,  '.c');
54    else
55        % The ldpc variable name may not be what we want for a file/variable names, but
56        % the load filename will be, so use it.
57        [~,ldpcArrayName,ext] = fileparts(loadStr);
58        includeFileName = strcat(ldpcArrayName, '.h');
59        sourceFileName = strcat(ldpcArrayName,  '.c');
60
61        % Get the ext of the file first.  If it's a txt, then do what we
62        % are doing.  If .mat, then just load, knowing the variable is HRA
63        if strcmp(ext, '.mat') == 1
64            load(loadStr);
65            if exist("H") & !exist("HRA")
66                printf("renaming H to HRA...\n");
67                HRA=H;
68            end
69        else
70            % When calling 'load' this way, it returns a struct.  The code assumes the
71            % struct has one element, and the one/first element is the array
72            % to process
73            tempStruct = load(loadStr);
74            b = fieldnames(tempStruct);
75            ldpcArrayName = b{1,1};
76            % extract the array from the struct
77            HRA = tempStruct.(ldpcArrayName);
78        endif
79
80        code_param = ldpc_init_user(HRA, modulation, mod_order, mapping);
81    end
82
83    code_length = code_param.coded_syms_per_frame;
84
85    % First, create the H file
86    f = fopen(includeFileName, "wt");
87    printHeader(f, includeFileName, ldpcArrayName, mfilename());
88
89    fprintf(f,"#define %s_NUMBERPARITYBITS %d\n", ldpcArrayName, rows(code_param.H_rows));
90    fprintf(f,"#define %s_MAX_ROW_WEIGHT %d\n", ldpcArrayName, columns(code_param.H_rows));
91    fprintf(f,"#define %s_CODELENGTH %d\n", ldpcArrayName, code_param.coded_syms_per_frame);
92    fprintf(f,"#define %s_NUMBERROWSHCOLS %d\n", ldpcArrayName, rows(code_param.H_cols));
93    fprintf(f,"#define %s_MAX_COL_WEIGHT %d\n", ldpcArrayName, columns(code_param.H_cols));
94    fprintf(f,"#define %s_DEC_TYPE %d\n", ldpcArrayName, decoder_type);
95    fprintf(f,"#define %s_MAX_ITER %d\n", ldpcArrayName, max_iterations);
96    fprintf(f,"\n");
97    fprintf(f,"extern const uint16_t %s_H_rows[];\n", ldpcArrayName);
98    fprintf(f,"extern const uint16_t %s_H_cols[];\n", ldpcArrayName);
99
100    fclose(f);
101
102
103    % Then, the C file
104    f = fopen(sourceFileName, "wt");
105    printHeader(f, sourceFileName, ldpcArrayName, mfilename());
106    fprintf(f, "#include <stdint.h>\n");
107    fprintf(f, "#include \"%s\"\n", includeFileName);
108
109    % clock out 2D array to linear C array in row order ....
110    fprintf(f,"\nconst uint16_t %s_H_rows[] = {\n", ldpcArrayName);
111    [r c] = size(code_param.H_rows);
112    for j=1:c
113        for i=1:r
114            fprintf(f, "%d", code_param.H_rows(i,j));
115            if (i == r) && (j ==c)  % weird, this does nothing
116                fprintf(f,"\n};\n");
117            else
118                fprintf(f,", ");
119            end
120        end
121    end
122
123    fprintf(f,"\nconst uint16_t %s_H_cols[] = {\n", ldpcArrayName);
124    [r c] = size(code_param.H_cols);
125    for j=1:c
126        for i=1:r
127            fprintf(f, "%d", code_param.H_cols(i,j));
128            if (i == r) && (j == c)
129                fprintf(f,"\n};\n");
130            else
131                fprintf(f,", ");
132            end
133        end
134    end
135
136    fclose(f);
137endfunction
138
139function printHeader(f, includeFileName, ldpcArrayName, mFilename)
140    fprintf(f, "/*\n  FILE....: %s\n\n", includeFileName);
141    fprintf(f, "  Static arrays for LDPC codec %s, generated by %s.m.\n*/\n\n", ldpcArrayName, mFilename);
142endfunction
143