File: ofdm_ldpc_tx.m

package info (click to toggle)
codec2 1.2.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 76,376 kB
  • sloc: ansic: 436,819; cpp: 2,091; objc: 1,736; sh: 1,510; python: 1,405; asm: 683; makefile: 605
file content (144 lines) | stat: -rw-r--r-- 4,857 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
140
141
142
143
144
% ofdm_ldpc_tx.m
% David Rowe April 2017
%
% File based ofdm tx with LDPC encoding and interleaver.  Generates a
% file of ofdm samples, including optional channel simulation.

#{ 
  1. 10 seconds, AWGN channel at SNR3k=3dB

    octave:4> ofdm_ldpc_tx("test_700d.raw", "700D", 10, 3)

  2. 10 seconds, multipath poor channel at SNR=6dB

    octave:5> ofdm_ldpc_tx("test_700d.raw", "700D", 10, 6, "mpp")
    
  3. Data mode example, three bursts of one packet each, SNR=100dB:
  
    octave:6> ofdm_ldpc_tx("test_datac0.raw","datac0",1,100,"awgn","bursts",3)
    
  4. Data mode example, three bursts of one packet each, SNR=100dB, with CRC
     to enable demodulation by freedv_data_raw_rx:
  
    octave:6> ofdm_ldpc_tx("test_datac0.raw","datac0",1,100,"awgn","bursts",3, "crc")
    
#}

function ofdm_ldpc_tx(filename, mode="700D", N, SNR3kdB=100, channel='awgn', varargin)
  ofdm_lib;
  ldpc;
  gp_interleaver;
  channel_lib;
  pkg load signal;
  randn('seed',1);
  more off;

  tx_clip_en = 0; freq_offset_Hz = 0.0; burst_mode = 0; Nbursts = 1;
  crc_mode = 0;
  i = 1;
  while i<=length(varargin)
    if strcmp(varargin{i},"txclip") 
      tx_clip_en = 1;
    elseif strcmp(varargin{i},"bursts") 
      burst_mode = 1;
      Nbursts = varargin{i+1}; i++;
    elseif strcmp(varargin{i},"crc") 
      crc_mode = 1;
     else
      printf("\nERROR unknown argument: %s\n", varargin{i});
      return;
    end
    i++;      
  end
 
  % init modem

  config = ofdm_init_mode(mode);
  states = ofdm_init(config);
  print_config(states);
  ofdm_load_const;

  if burst_mode
    % burst mode: treat N as Npackets
    Npackets = N; 
  else
    % streaming mode: treat N as Nseconds
    Npackets = round(N/states.Tpacket);
  end

  % some constants used for assembling modem frames
  [code_param Nbitspercodecframe Ncodecframespermodemframe] = codec_to_frame_packing(states, mode);

  % OK generate a modem frame using random payload bits

  if strcmp(mode, "2020")
    payload_bits = round(ofdm_rand(Ncodecframespermodemframe*Nbitspercodecframe)/32767);
  else
    payload_bits = round(ofdm_rand(code_param.data_bits_per_frame)/32767);
    if crc_mode
      unpacked_crc16 = crc16_unpacked(payload_bits(1:end-16));
      payload_bits(end-15:end) = unpacked_crc16;
    end
  end
  [packet_bits bits_per_packet] = fec_encode(states, code_param, mode, payload_bits);

  % modulate to create symbols and interleave
  tx_symbols = [];
  for b=1:bps:bits_per_packet
    if bps == 2 tx_symbols = [tx_symbols qpsk_mod(packet_bits(b:b+bps-1))]; end
    if bps == 4 tx_symbols = [tx_symbols qam16_mod(states.qam16, packet_bits(b:b+bps-1))]; end
  end
  assert(gp_deinterleave(gp_interleave(tx_symbols)) == tx_symbols);
  tx_symbols = gp_interleave(tx_symbols);

  % generate txt (non FEC protected) symbols
  txt_bits = zeros(1,Ntxtbits);
  txt_symbols = [];
  for b=1:bps:length(txt_bits)
    if bps == 2 txt_symbols = [txt_symbols qpsk_mod(txt_bits(b:b+bps-1))]; end
    if bps == 4 txt_symbols = [txt_symbols qam16_mod(states.qam16,txt_bits(b:b+bps-1))]; end
  end

  % assemble interleaved modem packet that include UW and txt symbols
  modem_packet = assemble_modem_packet_symbols(states, tx_symbols, txt_symbols);

  % sanity check
  [rx_uw rx_codeword_syms payload_amps txt_bits] = disassemble_modem_packet(states, modem_packet, ones(1,length(modem_packet)));
  assert(rx_uw == states.tx_uw);

  % create a burst of concatenated packets
  atx = ofdm_txframe(states, modem_packet); tx = [];
  for f=1:Npackets
    tx = [tx atx];
  end
  if length(states.data_mode)
    % note for burst mode postamble provides a "column" of pilots at the end of the burst
    tx = [states.tx_preamble tx states.tx_postamble];
  end
  
  % if burst mode concatenate multiple bursts with spaces
  if burst_mode
    atx = tx; tx = zeros(1,states.Fs); on_time = 0; off_time = states.Fs;
    for b=1:Nbursts
      tx = [tx atx zeros(1,states.Fs)];
      on_time += length(atx);
      off_time += states.Fs;
    end
    % adjust channel simulator SNR setpoint given (burst on length)/(total length including silence) ratio
    mark_space_SNR_offset = 10*log10(on_time/(on_time+off_time));
    SNRdB_setpoint = SNR3kdB + mark_space_SNR_offset;
    printf("SNR3kdB: %4.2f Burst offset: %4.2f SNRdB_setpoint: %4.2f\n", SNR3kdB, mark_space_SNR_offset, SNRdB_setpoint)
  else
    SNRdB_setpoint = SNR3kdB; % no adjustment to SNR in streaming mode
  end

  printf("Npackets: %d  Nbursts: %d  ", Npackets, Nbursts);
  states.verbose=1;
  tx = ofdm_hilbert_clipper(states, tx, tx_clip_en);
  [rx_real rx] = ofdm_channel(states, tx, SNRdB_setpoint, channel, freq_offset_Hz);
  frx = fopen(filename,"wb"); fwrite(frx, rx_real, "short"); fclose(frx);
  if length(rx) >= states.Fs
    figure(1); clf; plot(20*log10(abs(fft(rx(1:states.Fs)/16384))));
    axis([1 states.Fs -20 60])
  end
endfunction