Привет, Хабр.
Данный текст можно считать продолжением статьи "Разбираем звук Dial-up модема", в которой разбирался метод установки связи между модемами. Сегодня мы пойдем дальше, и посмотрим на практике как передаются данные, для чего создадим простую реализацию модема с помощью OFDM и GNU Radio.
Данные мы будем передавать по воздуху, в прямом смысле этого слова — для приема и передачи будет достаточно динамика и микрофона.
Для тех, кому интересно как это работает, продолжение под катом.
Итак, наша задача — сделать простейший модем, способный передать данные из точки А в точку Б. Существует много способов модуляции цифрового сигнала, мы воспользуемся OFDM — методом, широко используемым в современных системах связи. В OFDM цифровой сигнал с помощью преобразования Фурье преобразуется в несколько параллельных поднесущих, что обеспечивает высокую скорость и эффективность использования канала передачи. OFDM используется много где, от цифрового телевидения и радио, до LTE. Наш аудиоканал гораздо уже и скромнее по параметрам, так что и скорости будут поменьше, но принципиально суть, в общем, не меняется. Строго говоря, OFDM не предназначен для передачи данных по воздуху, хотя для небольших расстояний обычного микрофона и динамика будет вполне достаточно.
Минимальный граф для тестирования приема и передачи показан ниже:

Исходный код для GNU Radio 3.8:
В качестве источника данных используется обычный текстовый файл (в моем случае он содержит строку «Hello Habr!!»), затем данные разбиваются на блоки, которые подаются на OFDM Transmitter. OFDM это достаточно сложный вид модуляции, в настройках OFDM-кодера нужно указать достаточно много не совсем очевидных параметров.

Более детальный разбор значений можно найти здесь. Разумеется, параметры блока OFDM Receiver должны совпадать с параметрами передачи.
Блок Channel Model используется для симуляции канала связи, блок QT GUI Frequency Sink используется для визуализации спектра. Также стоит обратить внимание на невысокую частоту дискретизации (sample rate = 2400), это специально сделано для того, чтобы сигнал занимал небольшую полосу спектра, пригодную для передачи по аудиоканалу.
К сожалению, встроенного блока для отображения принимаемых данных в GNU Radio я не нашел, так что приходится использовать UDP. Блок UDP Sink используется для вывода данных, для их приема используется программа на языке Python:
Это позволяет выводить принимаемые данные в консоли, что достаточно удобно. Возможно есть более простой способ вывода в GNU Radio, если кто знает, напишите в комментариях.
Если все было сделано правильно, мы можем запустить GNU Radio и наш скрипт для приема, результат должен выглядеть примерно так:

Казалось бы, тему можно закрывать? Нет, все интересное только начинается.
В вышеприведенном примере все довольно просто. Но есть одно «но» — GNU Radio работает с так называемым «комплексным сигналом», фактически представляющим собой пары чисел, сдвинутых по фазе на 90 градусов. Это удобно для компьютерной обработки, но мы не можем просто взять и передать в эфир комплексное число.
И тут есть два варианта. Владельцы SDR-трансмиттеров (HackRF, LimeSDR, USRP и пр) могут дальше не читать, а просто взять готовый блок для GNU Radio, в котором все делается «автоматом». Но т.к. мы собираемся передать сигнал с помощью звуковой карты, мы должны сделать преобразование самостоятельно, для чего воспользуемся блок-схемой, которая есть в любой статье по ЦОС:
Здесь OFDM это наш передатчик, Fc частота несущей, мы зададим её равной 4КГц, чтобы сигнал попадал в максимум чувствительности колонок и микрофона. Блок-схема графа для передачи также соответственно, усложняется:

Для удобства тестирования я использую WAV File Sink, чтобы сохраненный файл можно было записать и воспроизводить отдельно. Также мы можем открыть файл и посмотреть его спектр, можно убедиться что центральная частота действительно равна 4КГц:

И наконец, последний шаг: создадим блок-схему для приема сигнала. Тут фактически все то же самое, только в обратном порядке.

Мы домножаем исходный сигнал на сдвинутые по фазе опорные сигналы, затем с помощью LPF отсекаем высокочастотные компоненты. На выходе получается комплексный сигнал, который может использоваться для дальнейшей обработки.
Граф для приема в GNU Radio имеет следующий вид:

Стоит отметить блок Audio Source для приема данных из звуковой карты, блок QT GUI Frequency Sink используется для визуализации принимаемого сигнала.
Для тестирования, я записал WAV-файл на смартфон, при поднесении его к микрофону компьютера, на экране появляется декодированный текст:

Как можно видеть, прием и передача сигналов с помощью GNU Radio достаточно интересен и нагляден. OFDM имеет достаточно большое число параметров, желающие могут поэспериментировать самостоятельно с размером блока FFT, числом несущих, частотой передачи и пр.
Всем спасибо за внимание, и удачных экспериментов.
Для желающих, исходник под спойлером.
Данный текст можно считать продолжением статьи "Разбираем звук Dial-up модема", в которой разбирался метод установки связи между модемами. Сегодня мы пойдем дальше, и посмотрим на практике как передаются данные, для чего создадим простую реализацию модема с помощью OFDM и GNU Radio.
Данные мы будем передавать по воздуху, в прямом смысле этого слова — для приема и передачи будет достаточно динамика и микрофона.
Для тех, кому интересно как это работает, продолжение под катом.
Итак, наша задача — сделать простейший модем, способный передать данные из точки А в точку Б. Существует много способов модуляции цифрового сигнала, мы воспользуемся OFDM — методом, широко используемым в современных системах связи. В OFDM цифровой сигнал с помощью преобразования Фурье преобразуется в несколько параллельных поднесущих, что обеспечивает высокую скорость и эффективность использования канала передачи. OFDM используется много где, от цифрового телевидения и радио, до LTE. Наш аудиоканал гораздо уже и скромнее по параметрам, так что и скорости будут поменьше, но принципиально суть, в общем, не меняется. Строго говоря, OFDM не предназначен для передачи данных по воздуху, хотя для небольших расстояний обычного микрофона и динамика будет вполне достаточно.
OFDM в GNU Radio
Минимальный граф для тестирования приема и передачи показан ниже:

Исходный код для 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
В качестве источника данных используется обычный текстовый файл (в моем случае он содержит строку «Hello Habr!!»), затем данные разбиваются на блоки, которые подаются на OFDM Transmitter. OFDM это достаточно сложный вид модуляции, в настройках OFDM-кодера нужно указать достаточно много не совсем очевидных параметров.

Более детальный разбор значений можно найти здесь. Разумеется, параметры блока OFDM Receiver должны совпадать с параметрами передачи.
Блок Channel Model используется для симуляции канала связи, блок QT GUI Frequency Sink используется для визуализации спектра. Также стоит обратить внимание на невысокую частоту дискретизации (sample rate = 2400), это специально сделано для того, чтобы сигнал занимал небольшую полосу спектра, пригодную для передачи по аудиоканалу.
К сожалению, встроенного блока для отображения принимаемых данных в GNU Radio я не нашел, так что приходится использовать UDP. Блок UDP Sink используется для вывода данных, для их приема используется программа на языке Python:
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
Это позволяет выводить принимаемые данные в консоли, что достаточно удобно. Возможно есть более простой способ вывода в GNU Radio, если кто знает, напишите в комментариях.
Если все было сделано правильно, мы можем запустить GNU Radio и наш скрипт для приема, результат должен выглядеть примерно так:

Казалось бы, тему можно закрывать? Нет, все интересное только начинается.
Выходим в эфир
В вышеприведенном примере все довольно просто. Но есть одно «но» — GNU Radio работает с так называемым «комплексным сигналом», фактически представляющим собой пары чисел, сдвинутых по фазе на 90 градусов. Это удобно для компьютерной обработки, но мы не можем просто взять и передать в эфир комплексное число.
И тут есть два варианта. Владельцы SDR-трансмиттеров (HackRF, LimeSDR, USRP и пр) могут дальше не читать, а просто взять готовый блок для GNU Radio, в котором все делается «автоматом». Но т.к. мы собираемся передать сигнал с помощью звуковой карты, мы должны сделать преобразование самостоятельно, для чего воспользуемся блок-схемой, которая есть в любой статье по ЦОС:
Здесь OFDM это наш передатчик, Fc частота несущей, мы зададим её равной 4КГц, чтобы сигнал попадал в максимум чувствительности колонок и микрофона. Блок-схема графа для передачи также соответственно, усложняется:

Для удобства тестирования я использую WAV File Sink, чтобы сохраненный файл можно было записать и воспроизводить отдельно. Также мы можем открыть файл и посмотреть его спектр, можно убедиться что центральная частота действительно равна 4КГц:

Прием
И наконец, последний шаг: создадим блок-схему для приема сигнала. Тут фактически все то же самое, только в обратном порядке.

Мы домножаем исходный сигнал на сдвинутые по фазе опорные сигналы, затем с помощью LPF отсекаем высокочастотные компоненты. На выходе получается комплексный сигнал, который может использоваться для дальнейшей обработки.
Граф для приема в GNU Radio имеет следующий вид:

Стоит отметить блок Audio Source для приема данных из звуковой карты, блок QT GUI Frequency Sink используется для визуализации принимаемого сигнала.
Для тестирования, я записал WAV-файл на смартфон, при поднесении его к микрофону компьютера, на экране появляется декодированный текст:

Заключение
Как можно видеть, прием и передача сигналов с помощью GNU Radio достаточно интересен и нагляден. OFDM имеет достаточно большое число параметров, желающие могут поэспериментировать самостоятельно с размером блока FFT, числом несущих, частотой передачи и пр.
Всем спасибо за внимание, и удачных экспериментов.
Для желающих, исходник под спойлером.
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
