Hacer un módem: transmita datos digitales por aire usando OFDM y GNU Radio

Hola Habr

Este texto puede considerarse una continuación del artículo "Analizamos el sonido del módem de acceso telefónico ", que trató el método de establecer comunicación entre módems. Hoy iremos más allá y veremos en la práctica cómo se transmiten los datos, para lo cual crearemos una implementación de módem simple usando OFDM y GNU Radio.

Transmitiremos los datos por aire, en el sentido literal de la palabra: un altavoz y un micrófono serán suficientes para la recepción y la transmisión.

Para aquellos que estén interesados ​​en cómo funciona esto, continuó bajo el corte.

Por lo tanto, nuestra tarea es hacer que el módem más simple sea capaz de transmitir datos desde el punto A al punto B. Hay muchas formas de modular una señal digital, usaremos OFDM , un método ampliamente utilizado en los sistemas de comunicación modernos. En OFDM, una señal digital transformada de Fourier se convierte en varias subportadoras paralelas, lo que garantiza la alta velocidad y eficiencia del canal de transmisión. OFDM se usa mucho donde, desde la televisión digital y la radio, hasta LTE. Nuestro canal de audio es mucho más estrecho y más modesto en términos de parámetros, por lo que las velocidades serán más bajas, pero básicamente la esencia, en general, no cambia. Estrictamente hablando, OFDM no está diseñado para transmitir datos por el aire, aunque para distancias pequeñas un micrófono y un altavoz convencionales serán suficientes.

OFDM en GNU Radio


El gráfico mínimo para probar la recepción y la transmisión se muestra a continuación:



Código fuente de 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


Se utiliza un archivo de texto sin formato como fuente de datos (en mi caso, contiene la cadena "¡Hola Habr!"), Luego los datos se dividen en bloques que se envían al transmisor OFDM . OFDM es un tipo de modulación bastante complicado, en la configuración del codificador OFDM necesita especificar muchos parámetros no bastante obvios.



Un análisis más detallado de los valores se puede encontrar aquí . Por supuesto, los parámetros del bloque del receptor OFDM deben coincidir con los parámetros de transmisión.

El bloque de modelo de canal se utiliza para simular el canal de comunicación, el bloque de sumidero de frecuencia GUI QTusado para visualizar el espectro. También vale la pena prestar atención a la baja frecuencia de muestreo (frecuencia de muestreo = 2400), esto se hace especialmente para que la señal ocupe una pequeña banda del espectro adecuada para la transmisión a través del canal de audio.

Desafortunadamente, no encontré una unidad integrada para mostrar los datos recibidos en GNU Radio, así que tengo que usar UDP. El bloque UDP Sink se usa para generar datos; un programa Python se usa para recibir datos:

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

Esto le permite mostrar los datos recibidos en la consola, lo cual es bastante conveniente. Quizás haya una manera más fácil de enviar a GNU Radio, si alguien lo sabe, escriba los comentarios.

Si todo se hizo correctamente, podemos ejecutar GNU Radio y nuestro script para la recepción, el resultado debería verse así:



¿Parece que puede cerrar el tema? No, todo lo interesante acaba de comenzar.

Ir al aire


En el ejemplo anterior, todo es bastante simple. Pero hay un "pero": GNU Radio funciona con la llamada "señal compleja", que en realidad es un par de números 90 grados fuera de fase. Esto es conveniente para el procesamiento por computadora, pero no podemos simplemente tomar y transmitir un número complejo.

Y hay dos opciones. Los propietarios de transmisores SDR (HackRF, LimeSDR, USRP, etc.) pueden no leer más, sino simplemente tomar un bloque listo para GNU Radio, en el que todo se hace "automáticamente". Pero desde vamos a transmitir una señal usando una tarjeta de sonido, debemos hacer la conversión nosotros mismos, para lo cual usamos el diagrama de flujo que se encuentra en cualquier artículo sobre DSP:



Aquí OFDM es nuestro transmisor, frecuencia portadora Fc, lo configuraremos a 4KHz para que la señal alcance la máxima sensibilidad de los altavoces y el micrófono. El diagrama de flujo del gráfico para la transferencia también es correspondientemente complicado:



por conveniencia de prueba, utilizo el archivo WAV Sink para que el archivo guardado se pueda grabar y reproducir por separado. También podemos abrir el archivo y ver su espectro, podemos asegurarnos de que la frecuencia central sea realmente 4KHz:



Recepción


Y finalmente, el último paso: crear un diagrama de bloques para recibir una señal. Aquí, de hecho, todo es igual, solo en el orden inverso.



Multiplicamos la señal original por señales de referencia con desplazamiento de fase, luego cortamos los componentes de alta frecuencia usando LPF. La salida es una señal compleja que se puede utilizar para su posterior procesamiento.

El gráfico para la recepción en Radio GNU es el siguiente:



Vale la pena señalar el bloque Fuente de audio para recibir datos de una tarjeta de sonido, el bloque Fregadero de frecuencia GUI QT se utiliza para visualizar la señal recibida.

Para las pruebas, grabé un archivo WAV en un teléfono inteligente; cuando lo llevo al micrófono de una computadora, aparece un texto decodificado en la pantalla:



Conclusión


Como puede ver, recibir y transmitir señales usando GNU Radio es bastante interesante y claro. OFDM tiene una cantidad bastante grande de parámetros; aquellos que lo deseen pueden experimentar por su cuenta con el tamaño del bloque FFT, la cantidad de portadores, la frecuencia de transmisión, etc.

Gracias a todos por su atención y experimentos exitosos.

Para aquellos que lo deseen, la fuente está bajo el 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