PySDR: BPSK Timing and Frequency Synchronization
Companion to the Synchronization chapter of PySDR
- Author Marc
- Category Digital
- Blocks 21
- Connections 10
- File
digital/synchronization_bpsk_recovery.grc
Blocks used
| Block | Module | Used |
|---|---|---|
| Variable | GNU Radio | 4 |
| QT GUI Constellation Sink | GNU Radio | 3 |
| QT GUI Range | GNU Radio | 3 |
| AGC2 | GNU Radio | 1 |
| Channel Model | GNU Radio | 1 |
| Constellation Modulator | GNU Radio | 1 |
| Constellation Object | GNU Radio | 1 |
| Costas Loop | GNU Radio | 1 |
| GUI Layout | GNU Radio | 1 |
| Note | GNU Radio | 1 |
| Polyphase Clock Sync | GNU Radio | 1 |
| QT GUI Time Sink | GNU Radio | 1 |
| Random Uniform Source | GNU Radio | 1 |
| Throttle | GNU Radio | 1 |
Notes in this flowgraph
- Receiver: the same steps the chapter writes by hand in Python Transmitter: random bits -> BPSK -> RRC pulse shaping Channel: noise + carrier frequency offset + sample clock offset Try adding more noise or more frequency offset
Flowgraph source
digital/synchronization_bpsk_recovery.grc
options:
parameters:
author: Marc
comment: ''
copyright: ''
description: Companion to the Synchronization chapter of PySDR
generate_options: qt_gui
id: PySDR__BPSK_Timing_and_Frequency_Synchronization
title: 'PySDR: BPSK Timing and Frequency Synchronization'
states:
coordinate: [10, 10]
rotation: 0
state: enabled
blocks:
- name: freq_offset
id: variable_qtgui_range
parameters:
comment: ''
label: Frequency offset (cycles/sample)
min_len: '200'
orient: QtCore.Qt.Horizontal
rangeType: float
start: '-0.03'
step: '0.002'
stop: '0.03'
value: '0.005'
widget: counter_slider
states:
coordinate: [610, 10]
rotation: 0
state: enabled
- name: nfilts
id: variable
parameters:
comment: ''
value: '16'
states:
coordinate: [900, 10]
rotation: 0
state: enabled
- name: noise_volt
id: variable_qtgui_range
parameters:
comment: ''
label: Noise voltage
min_len: '200'
orient: QtCore.Qt.Horizontal
rangeType: float
start: '0'
step: '0.01'
stop: '3'
value: '0.1'
widget: counter_slider
states:
coordinate: [1070, 10]
rotation: 0
state: enabled
- name: rrc_taps
id: variable
parameters:
comment: ''
value: firdes.root_raised_cosine(nfilts, nfilts, 1.0/float(sps), 0.35, 11*sps*nfilts)
states:
coordinate: [1320, 10]
rotation: 0
state: enabled
- name: samp_rate
id: variable
parameters:
comment: ''
value: '50000'
states:
coordinate: [10, 230]
rotation: 0
state: enabled
- name: sps
id: variable
parameters:
comment: ''
value: '8'
states:
coordinate: [180, 230]
rotation: 0
state: enabled
- name: time_offset
id: variable_qtgui_range
parameters:
comment: ''
label: Timing offset (epsilon)
min_len: '200'
orient: QtCore.Qt.Horizontal
rangeType: float
start: '0.999'
step: '0.0001'
stop: '1.001'
value: '1.0002'
widget: counter_slider
states:
coordinate: [350, 230]
rotation: 0
state: enabled
- name: agc
id: analog_agc2_xx
parameters:
affinity: ''
alias: ''
attack_rate: '0.06'
comment: ''
decay_rate: '0.001'
gain: '1'
max_gain: '65536'
maxoutbuf: '0'
minoutbuf: '0'
reference: '1'
type: complex
states:
coordinate: [80, 790]
rotation: 0
state: enabled
- name: bpsk
id: variable_constellation
parameters:
affinity: ''
alias: ''
comment: ''
const_points: '[-1, 1]'
dims: '1'
normalization: digital.constellation.AMPLITUDE_NORMALIZATION
npwr: '1'
precision: '8'
rot_sym: '2'
soft_dec_lut: None
sym_map: '[0, 1]'
type: bpsk
states:
coordinate: [630, 230]
rotation: 0
state: enabled
- name: bpsk_mod
id: digital_constellation_modulator
parameters:
affinity: ''
alias: ''
comment: ''
constellation: bpsk
differential: 'False'
excess_bw: '0.35'
log: 'False'
maxoutbuf: '0'
minoutbuf: '0'
samples_per_symbol: sps
truncate: 'False'
verbose: 'False'
states:
coordinate: [380, 510]
rotation: 0
state: enabled
- name: channel
id: channels_channel_model
parameters:
affinity: ''
alias: ''
block_tags: 'False'
comment: ''
epsilon: time_offset
freq_offset: freq_offset
maxoutbuf: '0'
minoutbuf: '0'
noise_voltage: noise_volt
seed: '0'
taps: '[1.0]'
states:
coordinate: [760, 520]
rotation: 0
state: enabled
- name: clock_sync
id: digital_pfb_clock_sync_xxx
parameters:
affinity: ''
alias: ''
comment: ''
filter_size: nfilts
init_phase: '8'
loop_bw: '0.0628'
max_dev: '1.5'
maxoutbuf: '0'
minoutbuf: '0'
osps: '1'
sps: sps
taps: rrc_taps
type: ccf
states:
coordinate: [460, 770]
rotation: 0
state: enabled
- name: const_rx
id: qtgui_const_sink_x
parameters:
affinity: ''
alias: ''
alpha1: '1'
alpha10: '1'
alpha2: '1'
alpha3: '1'
alpha4: '1'
alpha5: '1'
alpha6: '1'
alpha7: '1'
alpha8: '1'
alpha9: '1'
autoscale: 'False'
axislabels: 'True'
color1: '"blue"'
color10: '"dark blue"'
color2: '"red"'
color3: '"green"'
color4: '"black"'
color5: '"cyan"'
color6: '"magenta"'
color7: '"yellow"'
color8: '"dark red"'
color9: '"dark green"'
comment: ''
grid: 'True'
label1: ''
label10: ''
label2: ''
label3: ''
label4: ''
label5: ''
label6: ''
label7: ''
label8: ''
label9: ''
legend: 'True'
marker1: '0'
marker10: '-1'
marker2: '-1'
marker3: '-1'
marker4: '-1'
marker5: '-1'
marker6: '-1'
marker7: '-1'
marker8: '-1'
marker9: '-1'
name: '"1. Received (offset + noise)"'
nconnections: '1'
size: '1024'
style1: '0'
style10: '1'
style2: '1'
style3: '1'
style4: '1'
style5: '1'
style6: '1'
style7: '1'
style8: '1'
style9: '1'
tr_chan: '0'
tr_level: '0'
tr_mode: qtgui.TRIG_MODE_FREE
tr_slope: qtgui.TRIG_SLOPE_POS
tr_tag: '""'
update_time: '0.1'
width1: '1'
width10: '1'
width2: '1'
width3: '1'
width4: '1'
width5: '1'
width6: '1'
width7: '1'
width8: '1'
width9: '1'
xmax: '2'
xmin: '-2'
ymax: '2'
ymin: '-2'
states:
coordinate: [80, 950]
rotation: 0
state: enabled
- name: const_synced
id: qtgui_const_sink_x
parameters:
affinity: ''
alias: ''
alpha1: '1'
alpha10: '1'
alpha2: '1'
alpha3: '1'
alpha4: '1'
alpha5: '1'
alpha6: '1'
alpha7: '1'
alpha8: '1'
alpha9: '1'
autoscale: 'False'
axislabels: 'True'
color1: '"blue"'
color10: '"dark blue"'
color2: '"red"'
color3: '"green"'
color4: '"black"'
color5: '"cyan"'
color6: '"magenta"'
color7: '"yellow"'
color8: '"dark red"'
color9: '"dark green"'
comment: ''
grid: 'True'
label1: ''
label10: ''
label2: ''
label3: ''
label4: ''
label5: ''
label6: ''
label7: ''
label8: ''
label9: ''
legend: 'True'
marker1: '0'
marker10: '-1'
marker2: '-1'
marker3: '-1'
marker4: '-1'
marker5: '-1'
marker6: '-1'
marker7: '-1'
marker8: '-1'
marker9: '-1'
name: '"3. After Costas loop"'
nconnections: '1'
size: '1024'
style1: '0'
style10: '1'
style2: '1'
style3: '1'
style4: '1'
style5: '1'
style6: '1'
style7: '1'
style8: '1'
style9: '1'
tr_chan: '0'
tr_level: '0'
tr_mode: qtgui.TRIG_MODE_FREE
tr_slope: qtgui.TRIG_SLOPE_POS
tr_tag: '""'
update_time: '0.1'
width1: '1'
width10: '1'
width2: '1'
width3: '1'
width4: '1'
width5: '1'
width6: '1'
width7: '1'
width8: '1'
width9: '1'
xmax: '2'
xmin: '-2'
ymax: '2'
ymin: '-2'
states:
coordinate: [1310, 730]
rotation: 0
state: enabled
- name: const_timed
id: qtgui_const_sink_x
parameters:
affinity: ''
alias: ''
alpha1: '1'
alpha10: '1'
alpha2: '1'
alpha3: '1'
alpha4: '1'
alpha5: '1'
alpha6: '1'
alpha7: '1'
alpha8: '1'
alpha9: '1'
autoscale: 'False'
axislabels: 'True'
color1: '"blue"'
color10: '"dark blue"'
color2: '"red"'
color3: '"green"'
color4: '"black"'
color5: '"cyan"'
color6: '"magenta"'
color7: '"yellow"'
color8: '"dark red"'
color9: '"dark green"'
comment: ''
grid: 'True'
label1: ''
label10: ''
label2: ''
label3: ''
label4: ''
label5: ''
label6: ''
label7: ''
label8: ''
label9: ''
legend: 'True'
marker1: '0'
marker10: '-1'
marker2: '-1'
marker3: '-1'
marker4: '-1'
marker5: '-1'
marker6: '-1'
marker7: '-1'
marker8: '-1'
marker9: '-1'
name: '"2. After clock recovery"'
nconnections: '1'
size: '1024'
style1: '0'
style10: '1'
style2: '1'
style3: '1'
style4: '1'
style5: '1'
style6: '1'
style7: '1'
style8: '1'
style9: '1'
tr_chan: '0'
tr_level: '0'
tr_mode: qtgui.TRIG_MODE_FREE
tr_slope: qtgui.TRIG_SLOPE_POS
tr_tag: '""'
update_time: '0.1'
width1: '1'
width10: '1'
width2: '1'
width3: '1'
width4: '1'
width5: '1'
width6: '1'
width7: '1'
width8: '1'
width9: '1'
xmax: '2'
xmin: '-2'
ymax: '2'
ymin: '-2'
states:
coordinate: [880, 930]
rotation: 0
state: enabled
- name: costas
id: digital_costas_loop_cc
parameters:
affinity: ''
alias: ''
comment: ''
maxoutbuf: '0'
minoutbuf: '0'
order: '2'
use_snr: 'False'
w: '0.0628'
states:
coordinate: [880, 750]
rotation: 0
state: enabled
- name: note_rx
id: note
parameters:
affinity: ''
alias: ''
comment: ''
note: "Receiver: the same steps the chapter writes by hand in Python\n\nTransmitter: random bits -> BPSK -> RRC pulse shaping\n\nChannel: noise + carrier frequency offset + sample clock offset\n\nTry adding more noise or more frequency offset"
states:
coordinate: [950, 230]
rotation: 0
state: enabled
- name: random_bits
id: analog_random_uniform_source_x
parameters:
affinity: ''
alias: ''
comment: ''
maximum: '256'
maxoutbuf: '0'
minimum: '0'
minoutbuf: '0'
seed: '0'
type: byte
states:
coordinate: [10, 550]
rotation: 0
state: enabled
- name: throttle
id: blocks_throttle2
parameters:
affinity: ''
alias: ''
comment: ''
ignoretag: 'True'
limit: auto
maximum: '0.1'
maxoutbuf: '0'
minoutbuf: '0'
samples_per_second: samp_rate
type: complex
vlen: '1'
states:
coordinate: [1120, 540]
rotation: 0
state: enabled
- name: time_symbols
id: qtgui_time_sink_x
parameters:
affinity: ''
alias: ''
alpha1: '1'
alpha10: '1'
alpha2: '1'
alpha3: '1'
alpha4: '1'
alpha5: '1'
alpha6: '1'
alpha7: '1'
alpha8: '1'
alpha9: '1'
autoscale: 'False'
axislabels: 'True'
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'
grid: 'True'
label1: Signal 1
label10: Signal 10
label2: Signal 2
label3: Signal 3
label4: Signal 4
label5: Signal 5
label6: Signal 6
label7: Signal 7
label8: Signal 8
label9: Signal 9
legend: 'True'
marker1: '0'
marker10: '-1'
marker2: '-1'
marker3: '-1'
marker4: '-1'
marker5: '-1'
marker6: '-1'
marker7: '-1'
marker8: '-1'
marker9: '-1'
name: '"Recovered symbols"'
nconnections: '1'
samp_rate: samp_rate/sps
size: '256'
stemplot: 'False'
style1: '0'
style10: '1'
style2: '1'
style3: '1'
style4: '1'
style5: '1'
style6: '1'
style7: '1'
style8: '1'
style9: '1'
tr_chan: '0'
tr_delay: '0'
tr_level: '0'
tr_mode: qtgui.TRIG_MODE_FREE
tr_slope: qtgui.TRIG_SLOPE_POS
tr_tag: '""'
type: complex
update_time: '0.1'
width1: '1'
width10: '1'
width2: '1'
width3: '1'
width4: '1'
width5: '1'
width6: '1'
width7: '1'
width8: '1'
width9: '1'
ylabel: Amplitude
ymax: '2'
ymin: '-2'
yunit: '""'
states:
coordinate: [1310, 870]
rotation: 0
state: enabled
- name: wasm_gui_layout_0
id: wasm_gui_layout
parameters:
affinity: ''
alias: ''
columns: '12'
comment: ''
layout: '{"const_rx":[0,2,4,3],"const_synced":[8,2,4,3],"const_timed":[4,2,4,3],"freq_offset":[0,0,5,1],"noise_volt":[0,1,12,1],"time_offset":[7,0,5,1],"time_symbols":[0,5,12,3]}'
row_height: '60'
states:
coordinate: [320, 10]
rotation: 0
state: enabled
connections:
- [agc, '0', clock_sync, '0']
- [bpsk_mod, '0', channel, '0']
- [channel, '0', throttle, '0']
- [clock_sync, '0', const_timed, '0']
- [clock_sync, '0', costas, '0']
- [costas, '0', const_synced, '0']
- [costas, '0', time_symbols, '0']
- [random_bits, '0', bpsk_mod, '0']
- [throttle, '0', agc, '0']
- [throttle, '0', const_rx, '0']
metadata:
file_format: 1
grc_version: 3.11.0.0