You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

190 lines
6.5 KiB

% ldpc_gen_c_h_file.m
% David Rowe Sep 2015, B. Van Slyke 2019
%
% Create .c and h files for use in LDPC decoders
%
% NOTE: You'll need to install the CML library as a number of functions involved
% in LDPC use it. See ldpc.m for instructions in installing the CML
% library.
%
% Inputs:
% First parameter - name of file with LDPC codes
% Second parameter - , defaults to 100
% Third parameter - decoder_type, defaults to 0
%
% Output: Two files with the same filename as the LDPC input, but with .c and .h
% extensions.
function ldpc_gen_c_h_file(varargin)
ldpc % load ldpc functions
ldpc_fsk_lib % for ldpc_encode
% Assuming cml has been installed in the users' home folder, which is the
% default install location
init_cml('~/cml/');
if nargin == 0
printf("Error - you must specify a file containing the LDPC codes (e.g. HRA_112_112.txt).\n");
return;
end
loadStr = varargin{1};
% The ldpc variable name may not be what we want for a file/variable names, but
% the load filename will be, so use it.
[~,ldpcArrayName,ext] = fileparts(loadStr);
includeFileName = strcat(ldpcArrayName, '.h');
sourceFileName = strcat(ldpcArrayName, '.c');
% Get the ext of the file first. If it's a txt, then do what we
% are doing. If .mat, then just load, knowing the variable is HRA
if strcmp(ext, '.mat') == 1
load(loadStr);
else
% When calling 'load' this way, it returns a struct. The code assumes the
% struct has one element, and the one/first element is the array
% to process
tempStruct = load(loadStr);
b = fieldnames(tempStruct);
ldpcArrayName = b{1,1};
% extract the array from the struct
HRA = tempStruct.(ldpcArrayName);
endif
max_iterations = 100;
decoder_type = 0;
% user overloads
if nargin == 2
max_iterations = varargin{2};
end
if nargin == 3
decoder_type = varargin{3};
end
% the tests are performed using BPSK modulation, but in practice codes can be used
% with other modulation, e.g. QPSK
mod_order = 2; modulation = 'BPSK'; mapping = 'gray';
[code_param framesize rate] = ldpc_init_user(HRA, modulation, mod_order, mapping);
code_length = code_param.symbols_per_frame;
code_length % reported as 112.
% ********************* test for enc/dec
[input_decoder_c, detected_data] = genInputOutputData(code_param, max_iterations, decoder_type);
% First, create the H file
f = fopen(includeFileName, "wt");
printHeader(f, includeFileName, ldpcArrayName, mfilename());
fprintf(f,"#define %s_NUMBERPARITYBITS %d\n", ldpcArrayName, rows(code_param.H_rows));
fprintf(f,"#define %s_MAX_ROW_WEIGHT %d\n", ldpcArrayName, columns(code_param.H_rows));
fprintf(f,"#define %s_CODELENGTH %d\n", ldpcArrayName, code_param.symbols_per_frame);
fprintf(f,"#define %s_NUMBERROWSHCOLS %d\n", ldpcArrayName, rows(code_param.H_cols));
fprintf(f,"#define %s_MAX_COL_WEIGHT %d\n", ldpcArrayName, columns(code_param.H_cols));
fprintf(f,"#define %s_DEC_TYPE %d\n", ldpcArrayName, decoder_type);
fprintf(f,"#define %s_MAX_ITER %d\n", ldpcArrayName, max_iterations);
fprintf(f,"\n");
fprintf(f,"extern const uint16_t %s_H_rows[];\n", ldpcArrayName);
fprintf(f,"extern const uint16_t %s_H_cols[];\n", ldpcArrayName);
fprintf(f,"extern const float %s_input[];\n", ldpcArrayName);
fprintf(f,"extern const char %s_detected_data[];\n\n", ldpcArrayName);
fclose(f);
% Then, the C file
f = fopen(sourceFileName, "wt");
printHeader(f, sourceFileName, ldpcArrayName, mfilename());
fprintf(f, "#include <stdint.h>\n");
fprintf(f, "#include \"%s\"\n", includeFileName);
% clock out 2D array to linear C array in row order ....
fprintf(f,"\nconst uint16_t %s_H_rows[] = {\n", ldpcArrayName);
[r c] = size(code_param.H_rows);
for j=1:c
for i=1:r
fprintf(f, "%d", code_param.H_rows(i,j));
if (i == r) && (j ==c) % weird, this does nothing
fprintf(f,"\n};\n");
else
fprintf(f,", ");
end
end
end
fprintf(f,"\nconst uint16_t %s_H_cols[] = {\n", ldpcArrayName);
[r c] = size(code_param.H_cols);
for j=1:c
for i=1:r
fprintf(f, "%d", code_param.H_cols(i,j));
if (i == r) && (j == c)
fprintf(f,"\n};\n");
else
fprintf(f,", ");
end
end
end
% input and detected_data arrays
fprintf(f,"const float %s_input[] = {\n", ldpcArrayName);
for i=1:length(input_decoder_c)
fprintf(f, "%.17g", input_decoder_c(i));
if i == length(input_decoder_c)
fprintf(f,"\n};\n");
else
fprintf(f,", ");
end
end
fprintf(f,"const char %s_detected_data[] = {\n", ldpcArrayName);
for i=1:length(detected_data)
fprintf(f, "%d", detected_data(i));
if i == length(detected_data)
fprintf(f,"\n};\n");
else
fprintf(f,", ");
end
end
fclose(f);
endfunction
function printHeader(f, includeFileName, ldpcArrayName, mFilename)
fprintf(f, "/*\n FILE....: %s\n\n", includeFileName);
fprintf(f, " Static arrays for LDPC codec %s, generated by %s.m.\n*/\n\n", ldpcArrayName, mFilename);
endfunction
function [input_decoder_c, detected_data] = genInputOutputData(code_param, max_iterations, decoder_type)
% borrowed from test_ldpc_fsk_lib.m, simple_ut
EsNodB = 3;
data = round( rand( 1, code_param.data_bits_per_frame ) );
codeword = ldpc_encode(code_param, data); %defined in ldps_fsk_lib.
s = 1 - 2 * codeword;
%aa = code_param.symbols_per_frame % test - this WAS 112, then it gets set to 224???
%code_param.symbols_per_frame = length( s )
EsNo = 10^(EsNodB/10);
variance = 1/(2*EsNo);
noise = sqrt(variance)* randn(1,code_param.symbols_per_frame);
r = s + noise;
% borrowed from ldpc_fsk_lib.m, ldpc_decode
llr = sd_to_llr(r);
[x_hat, PCcnt] = MpDecode(llr, code_param.H_rows, code_param.H_cols, ...
max_iterations, decoder_type, 1, 1);
Niters = sum(PCcnt!=0);
detected_data = x_hat(Niters,:);
input_decoder_c = llr;
endfunction