Making a modem: transmit digital data over the air using OFDM and GNU Radio

Hello, Habr.

This text can be considered a continuation of the article "We analyze the sound of the Dial-up modem ", which dealt with the method of establishing communication between modems. Today we will go further and see in practice how the data is transmitted, for which we will create a simple modem implementation using OFDM and GNU Radio.

We will transmit the data by air, in the literal sense of the word - a speaker and a microphone will be enough for reception and transmission.

For those who are interested in how this works, continued under the cut.

So, our task is to make the simplest modem capable of transmitting data from point A to point B. There are many ways to modulate a digital signal, we will use OFDM - a method widely used in modern communication systems. In OFDM, a Fourier transform digital signal is converted into several parallel subcarriers, which ensures high speed and efficiency of the transmission channel. OFDM is used a lot where, from digital television and radio, to LTE. Our audio channel is much narrower and more modest in terms of parameters, so that the speeds will be lower, but basically the essence, in general, does not change. Strictly speaking, OFDM is not intended for data transmission over the air, although for small distances a conventional microphone and speaker will be quite enough.

OFDM at GNU Radio


The minimum graph for testing reception and transmission is shown below:



Source code for GNU Radio 3.8:

ofdm1.grc
options:
  parameters:
    author: ''
    category: '[GRC Hier Blocks]'
    cmake_opt: ''
    comment: ''
    copyright: ''
    description: ''
    gen_cmake: 'On'
    gen_linking: dynamic
    generate_options: qt_gui
    hier_block_src_path: '.:'
    id: ofdm_test_1
    max_nouts: '0'
    output_language: python
    placement: (0,0)
    qt_qss_theme: ''
    realtime_scheduling: ''
    run: 'True'
    run_command: '{python} -u {filename}'
    run_options: prompt
    sizing_mode: fixed
    thread_safe_setters: ''
    title: OFDM Test 1
    window_size: ''
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [8, 8]
    rotation: 0
    state: enabled

blocks:
- name: fft_len
  id: variable
  parameters:
    comment: ''
    value: '64'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [448, 12.0]
    rotation: 0
    state: enabled
- name: packet_len
  id: variable
  parameters:
    comment: ''
    value: '12'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [336, 12.0]
    rotation: 0
    state: enabled
- name: samp_rate
  id: variable
  parameters:
    comment: ''
    value: '2400'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [216, 12.0]
    rotation: 0
    state: enabled
- name: blocks_file_source_0
  id: blocks_file_source
  parameters:
    affinity: ''
    alias: ''
    begin_tag: pmt.PMT_NIL
    comment: ''
    file: D:\Temp\1\data2.txt
    length: '0'
    maxoutbuf: '0'
    minoutbuf: '0'
    offset: '0'
    repeat: 'True'
    type: byte
    vlen: '1'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [32, 128.0]
    rotation: 0
    state: enabled
- name: blocks_stream_to_tagged_stream_0
  id: blocks_stream_to_tagged_stream
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    len_tag_key: '"key"'
    maxoutbuf: '0'
    minoutbuf: '0'
    packet_len: packet_len
    type: byte
    vlen: '1'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [488, 156.0]
    rotation: 0
    state: enabled
- name: blocks_throttle_0
  id: blocks_throttle
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    ignoretag: 'True'
    maxoutbuf: '0'
    minoutbuf: '0'
    samples_per_second: samp_rate
    type: byte
    vlen: '1'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [272, 168.0]
    rotation: 0
    state: enabled
- name: blocks_udp_sink_0
  id: blocks_udp_sink
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    eof: 'True'
    ipaddr: 127.0.0.1
    port: '40868'
    psize: '128'
    type: byte
    vlen: '1'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [424, 476.0]
    rotation: 180
    state: enabled
- name: channels_channel_model_0
  id: channels_channel_model
  parameters:
    affinity: ''
    alias: ''
    block_tags: 'True'
    comment: ''
    epsilon: '1.0'
    freq_offset: 0 * 1.0/fft_len
    maxoutbuf: '0'
    minoutbuf: '0'
    noise_voltage: '0.1'
    seed: '0'
    taps: 1.0 + 1.0j
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [1112.0, 280]
    rotation: 270
    state: enabled
- name: digital_ofdm_rx_0
  id: digital_ofdm_rx
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    cp_len: fft_len//4
    fft_len: fft_len
    header_mod: '"BPSK"'
    log: 'False'
    maxoutbuf: '0'
    minoutbuf: '0'
    occupied_carriers: ((-4,-3,-2,-1,1,2,3,4),)
    packet_len_key: '"key"'
    payload_mod: '"QPSK"'
    pilot_carriers: ((-6,-5,5,6),)
    pilot_symbols: ((-1,1,-1,1),)
    scramble_bits: 'False'
    sync_word1: None
    sync_word2: None
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [776, 428.0]
    rotation: 180
    state: enabled
- name: digital_ofdm_tx_0
  id: digital_ofdm_tx
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    cp_len: fft_len//4
    fft_len: fft_len
    header_mod: '"BPSK"'
    log: 'False'
    maxoutbuf: '0'
    minoutbuf: '0'
    occupied_carriers: ((-4,-3,-2,-1,1,2,3,4),)
    packet_len_key: '"key"'
    payload_mod: '"QPSK"'
    pilot_carriers: ((-6,-5,5,6),)
    pilot_symbols: ((-1,1,-1,1),)
    rolloff: '0'
    scramble_bits: 'False'
    sync_word1: None
    sync_word2: None
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [776, 80.0]
    rotation: 0
    state: enabled
- name: qtgui_freq_sink_x_0
  id: qtgui_freq_sink_x
  parameters:
    affinity: ''
    alias: ''
    alpha1: '1.0'
    alpha10: '1.0'
    alpha2: '1.0'
    alpha3: '1.0'
    alpha4: '1.0'
    alpha5: '1.0'
    alpha6: '1.0'
    alpha7: '1.0'
    alpha8: '1.0'
    alpha9: '1.0'
    autoscale: 'False'
    average: '1.0'
    axislabels: 'True'
    bw: samp_rate
    color1: '"blue"'
    color10: '"dark blue"'
    color2: '"red"'
    color3: '"green"'
    color4: '"black"'
    color5: '"cyan"'
    color6: '"magenta"'
    color7: '"yellow"'
    color8: '"dark red"'
    color9: '"dark green"'
    comment: ''
    ctrlpanel: 'False'
    fc: '0'
    fftsize: '1024'
    freqhalf: 'True'
    grid: 'False'
    gui_hint: ''
    label: Relative Gain
    label1: Rx Spectrum
    label10: ''
    label2: ''
    label3: ''
    label4: ''
    label5: ''
    label6: ''
    label7: ''
    label8: ''
    label9: ''
    legend: 'True'
    maxoutbuf: '0'
    minoutbuf: '0'
    name: Rx Spectrum
    nconnections: '1'
    showports: 'True'
    tr_chan: '0'
    tr_level: '0.0'
    tr_mode: qtgui.TRIG_MODE_FREE
    tr_tag: '""'
    type: complex
    units: dB
    update_time: '0.10'
    width1: '1'
    width10: '1'
    width2: '1'
    width3: '1'
    width4: '1'
    width5: '1'
    width6: '1'
    width7: '1'
    width8: '1'
    width9: '1'
    wintype: firdes.WIN_BLACKMAN_hARRIS
    ymax: '10'
    ymin: '-140'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [1232, 92.0]
    rotation: 0
    state: enabled

connections:
- [blocks_file_source_0, '0', blocks_throttle_0, '0']
- [blocks_stream_to_tagged_stream_0, '0', digital_ofdm_tx_0, '0']
- [blocks_throttle_0, '0', blocks_stream_to_tagged_stream_0, '0']
- [channels_channel_model_0, '0', digital_ofdm_rx_0, '0']
- [digital_ofdm_rx_0, '0', blocks_udp_sink_0, '0']
- [digital_ofdm_tx_0, '0', channels_channel_model_0, '0']
- [digital_ofdm_tx_0, '0', qtgui_freq_sink_x_0, '0']

metadata:
  file_format: 1


A plain text file is used as the data source (in my case, it contains the string “Hello Habr !!”), then the data is divided into blocks that are fed to the OFDM Transmitter . OFDM is a rather complicated type of modulation, in the settings of the OFDM encoder you need to specify a lot of not quite obvious parameters.



A more detailed analysis of the values ​​can be found here . Of course, the parameters of the OFDM Receiver block must match the transmission parameters.

The Channel Model block is used to simulate the communication channel, the QT GUI Frequency Sink blockused to visualize the spectrum. It is also worth paying attention to the low sampling frequency (sample rate = 2400), this is specially done so that the signal occupies a small band of the spectrum suitable for transmission over the audio channel.

Unfortunately, I did not find a built-in unit for displaying received data in GNU Radio, so I have to use UDP. The UDP Sink block is used to output data; a Python program is used to receive data:

import socket

UDP_IP = "127.0.0.1"
UDP_PORT = 40868

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((UDP_IP, UDP_PORT))
sock.settimeout(0.5)

while True:
    try:
        data, addr = sock.recvfrom(128) 
        print("Msg:", data, 'Hex:', ' '.join('{:02x}'.format(x) for x in data))
    except socket.timeout:
        pass

This allows you to display the received data in the console, which is quite convenient. Perhaps there is an easier way to output to GNU Radio, if anyone knows, write in the comments.

If everything was done correctly, we can run GNU Radio and our script for reception, the result should look something like this:



It would seem that you can close the topic? No, everything interesting is just beginning.

Go on air


In the above example, everything is pretty simple. But there is one “but” - GNU Radio works with the so-called “complex signal”, which is actually a pair of numbers 90 degrees out of phase. This is convenient for computer processing, but we cannot just take and broadcast a complex number.

And there are two options. Owners of SDR transmitters (HackRF, LimeSDR, USRP, etc.) may not read further, but simply take a ready-made unit for GNU Radio, in which everything is done “automatically”. But since we are going to transmit a signal using a sound card, we must do the conversion ourselves, for which we use the flowchart that is in any article on DSP:



Here OFDM is our transmitter, Fc carrier frequency, we will set it to 4KHz so that the signal reaches the maximum sensitivity of the speakers and microphone. The flowchart of the graph for transfer is also correspondingly complicated:



For testing convenience, I use WAV File Sink so that the saved file can be recorded and played separately. We can also open the file and see its spectrum, we can make sure that the center frequency is really 4KHz:



Reception


And finally, the last step: create a block diagram for receiving a signal. Here, in fact, everything is the same, only in the reverse order.



We multiply the original signal by the phase-shifted reference signals, then with the help of LPF we cut off the high-frequency components. The output is a complex signal that can be used for further processing.

The graph for reception in GNU Radio is as follows:



It is worth noting the Audio Source block for receiving data from a sound card, the QT GUI Frequency Sink block is used to visualize the received signal.

For testing, I recorded a WAV file on a smartphone; when I bring it to the microphone of a computer, decoded text appears on the screen:



Conclusion


As you can see, receiving and transmitting signals using GNU Radio is quite interesting and clear. OFDM has a fairly large number of parameters; those who wish can experiment on their own with the FFT block size, the number of carriers, the transmission frequency, etc.

Thank you all for your attention and successful experiments.

For those who wish, the source is under the spoiler.

ofdm2.grc
options:
  parameters:
    author: ''
    category: Custom
    cmake_opt: ''
    comment: ''
    copyright: ''
    description: Transmit a pre-defined signal (a complex sine) as OFDM packets.
    gen_cmake: 'On'
    gen_linking: dynamic
    generate_options: qt_gui
    hier_block_src_path: '.:'
    id: ofdm_test_2
    max_nouts: '0'
    output_language: python
    placement: (0,0)
    qt_qss_theme: ''
    realtime_scheduling: ''
    run: 'True'
    run_command: '{python} -u {filename}'
    run_options: prompt
    sizing_mode: fixed
    thread_safe_setters: ''
    title: OFDM Test 2
    window_size: 1280, 1024
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [8, 12.0]
    rotation: 0
    state: enabled

blocks:
- name: audio_samp_rate
  id: variable
  parameters:
    comment: ''
    value: '24000'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [648, 20.0]
    rotation: 0
    state: true
- name: carrier_freq
  id: variable
  parameters:
    comment: ''
    value: '4000'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [792, 20.0]
    rotation: 0
    state: true
- name: fft_len
  id: variable
  parameters:
    comment: ''
    value: '64'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [448, 20.0]
    rotation: 0
    state: enabled
- name: len_tag_key
  id: variable
  parameters:
    comment: ''
    value: '"packet_len"'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [320, 20.0]
    rotation: 0
    state: enabled
- name: packet_len
  id: variable
  parameters:
    comment: ''
    value: '12'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [216, 20.0]
    rotation: 0
    state: enabled
- name: samp_rate
  id: variable
  parameters:
    comment: ''
    value: '2400'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [536, 20.0]
    rotation: 0
    state: enabled
- name: analog_sig_source_x_0
  id: analog_sig_source_x
  parameters:
    affinity: ''
    alias: ''
    amp: '1'
    comment: ''
    freq: carrier_freq
    maxoutbuf: '0'
    minoutbuf: '0'
    offset: '0'
    phase: '0'
    samp_rate: audio_samp_rate
    type: float
    waveform: analog.GR_COS_WAVE
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [1080, 88.0]
    rotation: 0
    state: true
- name: analog_sig_source_x_0_0
  id: analog_sig_source_x
  parameters:
    affinity: ''
    alias: ''
    amp: '1'
    comment: ''
    freq: carrier_freq
    maxoutbuf: '0'
    minoutbuf: '0'
    offset: '0'
    phase: '0'
    samp_rate: audio_samp_rate
    type: float
    waveform: analog.GR_SIN_WAVE
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [1080, 344.0]
    rotation: 0
    state: true
- name: analog_sig_source_x_0_0_0
  id: analog_sig_source_x
  parameters:
    affinity: ''
    alias: ''
    amp: '1'
    comment: ''
    freq: carrier_freq
    maxoutbuf: '0'
    minoutbuf: '0'
    offset: '0'
    phase: '0'
    samp_rate: audio_samp_rate
    type: float
    waveform: analog.GR_SIN_WAVE
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [1376, 824.0]
    rotation: 180
    state: true
- name: analog_sig_source_x_0_1
  id: analog_sig_source_x
  parameters:
    affinity: ''
    alias: ''
    amp: '1'
    comment: ''
    freq: carrier_freq
    maxoutbuf: '0'
    minoutbuf: '0'
    offset: '0'
    phase: '0'
    samp_rate: audio_samp_rate
    type: float
    waveform: analog.GR_COS_WAVE
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [1376, 672.0]
    rotation: 180
    state: true
- name: audio_sink_0
  id: audio_sink
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    device_name: ''
    num_inputs: '1'
    ok_to_block: 'True'
    samp_rate: audio_samp_rate
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [1608, 224.0]
    rotation: 0
    state: disabled
- name: audio_source_0
  id: audio_source
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    device_name: ''
    maxoutbuf: '0'
    minoutbuf: '0'
    num_outputs: '1'
    ok_to_block: 'True'
    samp_rate: audio_samp_rate
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [1376, 584.0]
    rotation: 180
    state: enabled
- name: blocks_add_xx_0
  id: blocks_add_xx
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    maxoutbuf: '0'
    minoutbuf: '0'
    num_inputs: '2'
    type: float
    vlen: '1'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [1480, 264.0]
    rotation: 0
    state: true
- name: blocks_complex_to_float_0
  id: blocks_complex_to_float
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    maxoutbuf: '0'
    minoutbuf: '0'
    vlen: '1'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [1128, 256.0]
    rotation: 0
    state: true
- name: blocks_file_source_0
  id: blocks_file_source
  parameters:
    affinity: ''
    alias: ''
    begin_tag: pmt.PMT_NIL
    comment: ''
    file: D:\Temp\1\data2.txt
    length: '0'
    maxoutbuf: '0'
    minoutbuf: '0'
    offset: '0'
    repeat: 'True'
    type: byte
    vlen: '1'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [32, 224.0]
    rotation: 0
    state: enabled
- name: blocks_float_to_complex_0
  id: blocks_float_to_complex
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    maxoutbuf: '0'
    minoutbuf: '0'
    vlen: '1'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [744, 768.0]
    rotation: 180
    state: true
- name: blocks_multiply_xx_0
  id: blocks_multiply_xx
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    maxoutbuf: '0'
    minoutbuf: '0'
    num_inputs: '2'
    type: float
    vlen: '1'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [1336, 176.0]
    rotation: 0
    state: true
- name: blocks_multiply_xx_0_0
  id: blocks_multiply_xx
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    maxoutbuf: '0'
    minoutbuf: '0'
    num_inputs: '2'
    type: float
    vlen: '1'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [1336, 344.0]
    rotation: 0
    state: enabled
- name: blocks_multiply_xx_0_1
  id: blocks_multiply_xx
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    maxoutbuf: '0'
    minoutbuf: '0'
    num_inputs: '2'
    type: float
    vlen: '1'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [1168, 696.0]
    rotation: 180
    state: true
- name: blocks_multiply_xx_0_1_0
  id: blocks_multiply_xx
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    maxoutbuf: '0'
    minoutbuf: '0'
    num_inputs: '2'
    type: float
    vlen: '1'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [1176, 864.0]
    rotation: 180
    state: true
- name: blocks_null_sink_0
  id: blocks_null_sink
  parameters:
    affinity: ''
    alias: ''
    bus_structure_sink: '[[0,],]'
    comment: ''
    num_inputs: '1'
    type: float
    vlen: '1'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [1608, 168.0]
    rotation: 0
    state: true
- name: blocks_stream_to_tagged_stream_0
  id: blocks_stream_to_tagged_stream
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    len_tag_key: '"key"'
    maxoutbuf: '0'
    minoutbuf: '0'
    packet_len: packet_len
    type: byte
    vlen: '1'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [424, 252.0]
    rotation: 0
    state: enabled
- name: blocks_throttle_0
  id: blocks_throttle
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    ignoretag: 'True'
    maxoutbuf: '0'
    minoutbuf: '0'
    samples_per_second: samp_rate
    type: byte
    vlen: '1'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [248, 264.0]
    rotation: 0
    state: enabled
- name: blocks_udp_sink_0
  id: blocks_udp_sink
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    eof: 'True'
    ipaddr: 127.0.0.1
    port: '40868'
    psize: '128'
    type: byte
    vlen: '1'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [104, 748.0]
    rotation: 180
    state: enabled
- name: blocks_wavfile_sink_0
  id: blocks_wavfile_sink
  parameters:
    affinity: ''
    alias: ''
    bits_per_sample: '16'
    comment: ''
    file: D:\Temp\1\ofdm.wav
    nchan: '1'
    samp_rate: audio_samp_rate
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [1608, 308.0]
    rotation: 0
    state: disabled
- name: digital_ofdm_rx_0
  id: digital_ofdm_rx
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    cp_len: fft_len//4
    fft_len: fft_len
    header_mod: '"BPSK"'
    log: 'False'
    maxoutbuf: '0'
    minoutbuf: '0'
    occupied_carriers: ((-4,-3,-2,-1,1,2,3,4),)
    packet_len_key: '"key"'
    payload_mod: '"QPSK"'
    pilot_carriers: ((-6,-5,5,6),)
    pilot_symbols: ((-1,1,-1,1),)
    scramble_bits: 'False'
    sync_word1: None
    sync_word2: None
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [440, 700.0]
    rotation: 180
    state: enabled
- name: digital_ofdm_tx_0
  id: digital_ofdm_tx
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    cp_len: fft_len//4
    fft_len: fft_len
    header_mod: '"BPSK"'
    log: 'False'
    maxoutbuf: '0'
    minoutbuf: '0'
    occupied_carriers: ((-4,-3,-2,-1,1,2,3,4),)
    packet_len_key: '"key"'
    payload_mod: '"QPSK"'
    pilot_carriers: ((-6,-5,5,6),)
    pilot_symbols: ((-1,1,-1,1),)
    rolloff: '0'
    scramble_bits: 'False'
    sync_word1: None
    sync_word2: None
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [664, 176.0]
    rotation: 0
    state: enabled
- name: low_pass_filter_0
  id: low_pass_filter
  parameters:
    affinity: ''
    alias: ''
    beta: '6.76'
    comment: ''
    cutoff_freq: carrier_freq
    decim: audio_samp_rate//samp_rate
    gain: '1'
    interp: '1'
    maxoutbuf: '0'
    minoutbuf: '0'
    samp_rate: audio_samp_rate
    type: fir_filter_fff
    width: '1000'
    win: firdes.WIN_HAMMING
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [960, 648.0]
    rotation: 180
    state: true
- name: low_pass_filter_0_0
  id: low_pass_filter
  parameters:
    affinity: ''
    alias: ''
    beta: '6.76'
    comment: ''
    cutoff_freq: carrier_freq
    decim: audio_samp_rate//samp_rate
    gain: '1'
    interp: '1'
    maxoutbuf: '0'
    minoutbuf: '0'
    samp_rate: audio_samp_rate
    type: fir_filter_fff
    width: '1000'
    win: firdes.WIN_HAMMING
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [960, 816.0]
    rotation: 180
    state: true
- name: qtgui_freq_sink_x_0
  id: qtgui_freq_sink_x
  parameters:
    affinity: ''
    alias: ''
    alpha1: '1.0'
    alpha10: '1.0'
    alpha2: '1.0'
    alpha3: '1.0'
    alpha4: '1.0'
    alpha5: '1.0'
    alpha6: '1.0'
    alpha7: '1.0'
    alpha8: '1.0'
    alpha9: '1.0'
    autoscale: 'False'
    average: '1.0'
    axislabels: 'True'
    bw: samp_rate
    color1: '"blue"'
    color10: '"dark blue"'
    color2: '"red"'
    color3: '"green"'
    color4: '"black"'
    color5: '"cyan"'
    color6: '"magenta"'
    color7: '"yellow"'
    color8: '"dark red"'
    color9: '"dark green"'
    comment: ''
    ctrlpanel: 'False'
    fc: '0'
    fftsize: '1024'
    freqhalf: 'True'
    grid: 'False'
    gui_hint: ''
    label: Relative Gain
    label1: Rx Spectrum
    label10: ''
    label2: ''
    label3: ''
    label4: ''
    label5: ''
    label6: ''
    label7: ''
    label8: ''
    label9: ''
    legend: 'True'
    maxoutbuf: '0'
    minoutbuf: '0'
    name: Rx Spectrum
    nconnections: '1'
    showports: 'True'
    tr_chan: '0'
    tr_level: '0.0'
    tr_mode: qtgui.TRIG_MODE_FREE
    tr_tag: '""'
    type: complex
    units: dB
    update_time: '0.10'
    width1: '1'
    width10: '1'
    width2: '1'
    width3: '1'
    width4: '1'
    width5: '1'
    width6: '1'
    width7: '1'
    width8: '1'
    width9: '1'
    wintype: firdes.WIN_BLACKMAN_hARRIS
    ymax: '10'
    ymin: '-140'
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [728, 612.0]
    rotation: 0
    state: enabled
- name: rational_resampler_xxx_0
  id: rational_resampler_xxx
  parameters:
    affinity: ''
    alias: ''
    comment: ''
    decim: '1'
    fbw: '0'
    interp: audio_samp_rate//samp_rate
    maxoutbuf: '0'
    minoutbuf: '0'
    taps: ''
    type: ccf
  states:
    bus_sink: false
    bus_source: false
    bus_structure: null
    coordinate: [912, 236.0]
    rotation: 0
    state: true

connections:
- [analog_sig_source_x_0, '0', blocks_multiply_xx_0, '0']
- [analog_sig_source_x_0_0, '0', blocks_multiply_xx_0_0, '1']
- [analog_sig_source_x_0_0_0, '0', blocks_multiply_xx_0_1_0, '1']
- [analog_sig_source_x_0_1, '0', blocks_multiply_xx_0_1, '1']
- [audio_source_0, '0', blocks_multiply_xx_0_1, '0']
- [audio_source_0, '0', blocks_multiply_xx_0_1_0, '0']
- [blocks_add_xx_0, '0', audio_sink_0, '0']
- [blocks_add_xx_0, '0', blocks_null_sink_0, '0']
- [blocks_add_xx_0, '0', blocks_wavfile_sink_0, '0']
- [blocks_complex_to_float_0, '0', blocks_multiply_xx_0, '1']
- [blocks_complex_to_float_0, '1', blocks_multiply_xx_0_0, '0']
- [blocks_file_source_0, '0', blocks_throttle_0, '0']
- [blocks_float_to_complex_0, '0', digital_ofdm_rx_0, '0']
- [blocks_float_to_complex_0, '0', qtgui_freq_sink_x_0, '0']
- [blocks_multiply_xx_0, '0', blocks_add_xx_0, '0']
- [blocks_multiply_xx_0_0, '0', blocks_add_xx_0, '1']
- [blocks_multiply_xx_0_1, '0', low_pass_filter_0, '0']
- [blocks_multiply_xx_0_1_0, '0', low_pass_filter_0_0, '0']
- [blocks_stream_to_tagged_stream_0, '0', digital_ofdm_tx_0, '0']
- [blocks_throttle_0, '0', blocks_stream_to_tagged_stream_0, '0']
- [digital_ofdm_rx_0, '0', blocks_udp_sink_0, '0']
- [digital_ofdm_tx_0, '0', rational_resampler_xxx_0, '0']
- [low_pass_filter_0, '0', blocks_float_to_complex_0, '0']
- [low_pass_filter_0_0, '0', blocks_float_to_complex_0, '1']
- [rational_resampler_xxx_0, '0', blocks_complex_to_float_0, '0']

metadata:
  file_format: 1


All Articles