kopia lustrzana https://github.com/M17-Project/M17_Implementations
Add files via upload
rodzic
2a7484fef2
commit
b0c9e568d5
|
@ -0,0 +1,271 @@
|
|||
options:
|
||||
parameters:
|
||||
author: SP5WWP
|
||||
catch_exceptions: 'True'
|
||||
category: '[GRC Hier Blocks]'
|
||||
cmake_opt: ''
|
||||
comment: ''
|
||||
copyright: M17 Project, Dec 2022
|
||||
description: ''
|
||||
gen_cmake: 'On'
|
||||
gen_linking: dynamic
|
||||
generate_options: qt_gui
|
||||
hier_block_src_path: '.:'
|
||||
id: m17_streamer
|
||||
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: M17 data streamer
|
||||
window_size: (1000,1000)
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [520, 12.0]
|
||||
rotation: 0
|
||||
state: enabled
|
||||
|
||||
blocks:
|
||||
- name: blocks_file_sink_0
|
||||
id: blocks_file_sink
|
||||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
append: 'False'
|
||||
comment: ''
|
||||
file: ../stream_fifo
|
||||
type: byte
|
||||
unbuffered: 'False'
|
||||
vlen: '1'
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [680, 172.0]
|
||||
rotation: 0
|
||||
state: true
|
||||
- name: blocks_stream_mux_0
|
||||
id: blocks_stream_mux
|
||||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
comment: ''
|
||||
lengths: (6, 6, 2, 14, 16)
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
num_inputs: '5'
|
||||
type: byte
|
||||
vlen: '1'
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [360, 128.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: (6+6+2+14+16)*8*(1000/40)
|
||||
type: byte
|
||||
vlen: '1'
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [528, 188.0]
|
||||
rotation: 0
|
||||
state: enabled
|
||||
- name: blocks_vector_source_x_0
|
||||
id: blocks_vector_source_x
|
||||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
comment: ''
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
repeat: 'True'
|
||||
tags: '[]'
|
||||
type: byte
|
||||
vector: (0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF)
|
||||
vlen: '1'
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [112, 12.0]
|
||||
rotation: 0
|
||||
state: true
|
||||
- name: blocks_vector_source_x_0_0
|
||||
id: blocks_vector_source_x
|
||||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
comment: ''
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
repeat: 'True'
|
||||
tags: '[]'
|
||||
type: byte
|
||||
vector: (0x00, 0x00, 0x1F, 0x24, 0x5D, 0x51)
|
||||
vlen: '1'
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [112, 92.0]
|
||||
rotation: 0
|
||||
state: true
|
||||
- name: blocks_vector_source_x_0_1
|
||||
id: blocks_vector_source_x
|
||||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
comment: ''
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
repeat: 'True'
|
||||
tags: '[]'
|
||||
type: byte
|
||||
vector: (0x00, 0x05)
|
||||
vlen: '1'
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [112, 172.0]
|
||||
rotation: 0
|
||||
state: true
|
||||
- name: blocks_vector_source_x_0_2
|
||||
id: blocks_vector_source_x
|
||||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
comment: ''
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
repeat: 'True'
|
||||
tags: '[]'
|
||||
type: byte
|
||||
vector: (0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00)
|
||||
vlen: '1'
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [112, 332.0]
|
||||
rotation: 0
|
||||
state: true
|
||||
- name: blocks_vector_source_x_0_2_0
|
||||
id: blocks_vector_source_x
|
||||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
comment: ''
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
repeat: 'True'
|
||||
tags: '[]'
|
||||
type: byte
|
||||
vector: (0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00)
|
||||
vlen: '1'
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [112, 252.0]
|
||||
rotation: 0
|
||||
state: true
|
||||
- name: note_0
|
||||
id: note
|
||||
parameters:
|
||||
alias: ''
|
||||
comment: ''
|
||||
note: DST
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [16, 28.0]
|
||||
rotation: 0
|
||||
state: true
|
||||
- name: note_0_0
|
||||
id: note
|
||||
parameters:
|
||||
alias: ''
|
||||
comment: ''
|
||||
note: SRC
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [16, 108.0]
|
||||
rotation: 0
|
||||
state: true
|
||||
- name: note_0_1
|
||||
id: note
|
||||
parameters:
|
||||
alias: ''
|
||||
comment: ''
|
||||
note: TYPE
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [16, 188.0]
|
||||
rotation: 0
|
||||
state: true
|
||||
- name: note_0_2
|
||||
id: note
|
||||
parameters:
|
||||
alias: ''
|
||||
comment: ''
|
||||
note: DATA
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [16, 348.0]
|
||||
rotation: 0
|
||||
state: true
|
||||
- name: note_0_2_0
|
||||
id: note
|
||||
parameters:
|
||||
alias: ''
|
||||
comment: ''
|
||||
note: META
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [16, 268.0]
|
||||
rotation: 0
|
||||
state: true
|
||||
|
||||
connections:
|
||||
- [blocks_stream_mux_0, '0', blocks_throttle_0, '0']
|
||||
- [blocks_throttle_0, '0', blocks_file_sink_0, '0']
|
||||
- [blocks_vector_source_x_0, '0', blocks_stream_mux_0, '0']
|
||||
- [blocks_vector_source_x_0_0, '0', blocks_stream_mux_0, '1']
|
||||
- [blocks_vector_source_x_0_1, '0', blocks_stream_mux_0, '2']
|
||||
- [blocks_vector_source_x_0_2, '0', blocks_stream_mux_0, '4']
|
||||
- [blocks_vector_source_x_0_2_0, '0', blocks_stream_mux_0, '3']
|
||||
|
||||
metadata:
|
||||
file_format: 1
|
||||
grc_version: 3.10.4.0
|
|
@ -0,0 +1,511 @@
|
|||
options:
|
||||
parameters:
|
||||
author: SP5WWP
|
||||
catch_exceptions: 'True'
|
||||
category: '[GRC Hier Blocks]'
|
||||
cmake_opt: ''
|
||||
comment: ''
|
||||
copyright: M17 Project, Dec 2022
|
||||
description: ''
|
||||
gen_cmake: 'On'
|
||||
gen_linking: dynamic
|
||||
generate_options: qt_gui
|
||||
hier_block_src_path: '.:'
|
||||
id: symbol_recovery
|
||||
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: M17 symbol recovery and sync
|
||||
window_size: (1000,1000)
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [8, 8]
|
||||
rotation: 0
|
||||
state: enabled
|
||||
|
||||
blocks:
|
||||
- name: symbol_rate
|
||||
id: variable
|
||||
parameters:
|
||||
comment: ''
|
||||
value: '4800'
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [184, 12]
|
||||
rotation: 0
|
||||
state: enabled
|
||||
- name: analog_quadrature_demod_cf_0
|
||||
id: analog_quadrature_demod_cf
|
||||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
comment: ''
|
||||
gain: 24000/(2*math.pi*800)
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [392, 388.0]
|
||||
rotation: 0
|
||||
state: true
|
||||
- name: blocks_char_to_float_0
|
||||
id: blocks_char_to_float
|
||||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
comment: ''
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
scale: '128.0'
|
||||
vlen: '1'
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [216, 244.0]
|
||||
rotation: 0
|
||||
state: disabled
|
||||
- name: blocks_file_sink_0
|
||||
id: blocks_file_sink
|
||||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
append: 'False'
|
||||
comment: ''
|
||||
file: /home/sp5wwp/Desktop/symb_fifo
|
||||
type: float
|
||||
unbuffered: 'True'
|
||||
vlen: '1'
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [1144, 180.0]
|
||||
rotation: 0
|
||||
state: enabled
|
||||
- name: blocks_file_source_0
|
||||
id: blocks_file_source
|
||||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
begin_tag: pmt.PMT_NIL
|
||||
comment: ''
|
||||
file: /dev/ttyUSB0
|
||||
length: '0'
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
offset: '0'
|
||||
repeat: 'False'
|
||||
type: byte
|
||||
vlen: '1'
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [16, 212.0]
|
||||
rotation: 0
|
||||
state: disabled
|
||||
- name: blocks_file_source_0_0
|
||||
id: blocks_file_source
|
||||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
begin_tag: pmt.PMT_NIL
|
||||
comment: ''
|
||||
file: debug_null_payload.bin
|
||||
length: '2200'
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
offset: '0'
|
||||
repeat: 'False'
|
||||
type: byte
|
||||
vlen: '1'
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [24, 500.0]
|
||||
rotation: 0
|
||||
state: disabled
|
||||
- name: blocks_repack_bits_bb_0
|
||||
id: blocks_repack_bits_bb
|
||||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
align_output: 'False'
|
||||
comment: ''
|
||||
endianness: gr.GR_MSB_FIRST
|
||||
k: '8'
|
||||
l: '2'
|
||||
len_tag_key: '""'
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [216, 524.0]
|
||||
rotation: 0
|
||||
state: disabled
|
||||
- name: digital_chunks_to_symbols_xx_0
|
||||
id: digital_chunks_to_symbols_xx
|
||||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
comment: ''
|
||||
dimension: '1'
|
||||
in_type: byte
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
num_ports: '1'
|
||||
out_type: float
|
||||
symbol_table: (1.0, 3.0, -1.0, -3.0)
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [400, 536.0]
|
||||
rotation: 0
|
||||
state: disabled
|
||||
- name: digital_symbol_sync_xx_0
|
||||
id: digital_symbol_sync_xx
|
||||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
comment: ''
|
||||
constellation: digital.constellation_bpsk().base()
|
||||
damping: '1.0'
|
||||
loop_bw: '0.05'
|
||||
max_dev: '1.5'
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
nfilters: '128'
|
||||
osps: '1'
|
||||
pfb_mf_taps: '[]'
|
||||
resamp_type: digital.IR_MMSE_8TAP
|
||||
sps: '5'
|
||||
ted_gain: '1.0'
|
||||
ted_type: digital.TED_GARDNER
|
||||
type: ff
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [824, 188.0]
|
||||
rotation: 0
|
||||
state: enabled
|
||||
- name: qtgui_eye_sink_x_0
|
||||
id: qtgui_eye_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'
|
||||
axislabels: 'True'
|
||||
color1: blue
|
||||
color10: blue
|
||||
color2: blue
|
||||
color3: blue
|
||||
color4: blue
|
||||
color5: blue
|
||||
color6: blue
|
||||
color7: blue
|
||||
color8: blue
|
||||
color9: blue
|
||||
comment: ''
|
||||
ctrlpanel: 'False'
|
||||
entags: 'True'
|
||||
grid: 'False'
|
||||
gui_hint: ''
|
||||
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: '-1'
|
||||
marker10: '-1'
|
||||
marker2: '-1'
|
||||
marker3: '-1'
|
||||
marker4: '-1'
|
||||
marker5: '-1'
|
||||
marker6: '-1'
|
||||
marker7: '-1'
|
||||
marker8: '-1'
|
||||
marker9: '-1'
|
||||
nconnections: '1'
|
||||
samp_per_symbol: '1'
|
||||
size: 200*1
|
||||
srate: symbol_rate*1
|
||||
style1: '1'
|
||||
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.0'
|
||||
tr_mode: qtgui.TRIG_MODE_FREE
|
||||
tr_slope: qtgui.TRIG_SLOPE_POS
|
||||
tr_tag: '""'
|
||||
type: float
|
||||
update_time: '0.10'
|
||||
width1: '1'
|
||||
width10: '1'
|
||||
width2: '1'
|
||||
width3: '1'
|
||||
width4: '1'
|
||||
width5: '1'
|
||||
width6: '1'
|
||||
width7: '1'
|
||||
width8: '1'
|
||||
width9: '1'
|
||||
ylabel: Amplitude
|
||||
ymax: '5'
|
||||
ymin: '-5'
|
||||
yunit: '""'
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [1144, 268.0]
|
||||
rotation: 0
|
||||
state: enabled
|
||||
- name: qtgui_time_sink_x_0
|
||||
id: qtgui_time_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'
|
||||
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'
|
||||
entags: 'True'
|
||||
grid: 'False'
|
||||
gui_hint: ''
|
||||
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: '-1'
|
||||
marker10: '-1'
|
||||
marker2: '-1'
|
||||
marker3: '-1'
|
||||
marker4: '-1'
|
||||
marker5: '-1'
|
||||
marker6: '-1'
|
||||
marker7: '-1'
|
||||
marker8: '-1'
|
||||
marker9: '-1'
|
||||
name: '""'
|
||||
nconnections: '1'
|
||||
size: '1024'
|
||||
srate: symbol_rate*5
|
||||
stemplot: 'False'
|
||||
style1: '1'
|
||||
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.0'
|
||||
tr_mode: qtgui.TRIG_MODE_FREE
|
||||
tr_slope: qtgui.TRIG_SLOPE_POS
|
||||
tr_tag: '""'
|
||||
type: float
|
||||
update_time: '0.10'
|
||||
width1: '1'
|
||||
width10: '1'
|
||||
width2: '1'
|
||||
width3: '1'
|
||||
width4: '1'
|
||||
width5: '1'
|
||||
width6: '1'
|
||||
width7: '1'
|
||||
width8: '1'
|
||||
width9: '1'
|
||||
ylabel: Amplitude
|
||||
ymax: '5'
|
||||
ymin: '-5'
|
||||
yunit: '""'
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [824, 100.0]
|
||||
rotation: 0
|
||||
state: disabled
|
||||
- name: rational_resampler_xxx_0
|
||||
id: rational_resampler_xxx
|
||||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
comment: ''
|
||||
decim: '80'
|
||||
fbw: '0'
|
||||
interp: '1'
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
taps: '[]'
|
||||
type: ccf
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [224, 364.0]
|
||||
rotation: 0
|
||||
state: true
|
||||
- name: root_raised_cosine_filter_0
|
||||
id: root_raised_cosine_filter
|
||||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
alpha: '0.5'
|
||||
comment: ''
|
||||
decim: '1'
|
||||
gain: '1'
|
||||
interp: '1'
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
ntaps: 8*5+1
|
||||
samp_rate: '5'
|
||||
sym_rate: '1'
|
||||
type: fir_filter_fff
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [560, 348.0]
|
||||
rotation: 0
|
||||
state: enabled
|
||||
- name: root_raised_cosine_filter_0_0
|
||||
id: root_raised_cosine_filter
|
||||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
alpha: '0.5'
|
||||
comment: ''
|
||||
decim: '1'
|
||||
gain: 1/0.12
|
||||
interp: '1'
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
ntaps: 8*5+1
|
||||
samp_rate: '5'
|
||||
sym_rate: '1'
|
||||
type: fir_filter_fff
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [560, 204.0]
|
||||
rotation: 0
|
||||
state: disabled
|
||||
- name: soapy_rtlsdr_source_0
|
||||
id: soapy_rtlsdr_source
|
||||
parameters:
|
||||
affinity: ''
|
||||
agc: 'True'
|
||||
alias: ''
|
||||
center_freq: '439950000'
|
||||
comment: ''
|
||||
dev_args: ''
|
||||
freq_correction: '-2'
|
||||
gain: '20'
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
samp_rate: 24000*80
|
||||
type: fc32
|
||||
states:
|
||||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [24, 380.0]
|
||||
rotation: 0
|
||||
state: true
|
||||
|
||||
connections:
|
||||
- [analog_quadrature_demod_cf_0, '0', root_raised_cosine_filter_0, '0']
|
||||
- [blocks_char_to_float_0, '0', root_raised_cosine_filter_0_0, '0']
|
||||
- [blocks_file_source_0, '0', blocks_char_to_float_0, '0']
|
||||
- [blocks_file_source_0_0, '0', blocks_repack_bits_bb_0, '0']
|
||||
- [blocks_repack_bits_bb_0, '0', digital_chunks_to_symbols_xx_0, '0']
|
||||
- [digital_chunks_to_symbols_xx_0, '0', blocks_file_sink_0, '0']
|
||||
- [digital_chunks_to_symbols_xx_0, '0', qtgui_eye_sink_x_0, '0']
|
||||
- [digital_symbol_sync_xx_0, '0', blocks_file_sink_0, '0']
|
||||
- [digital_symbol_sync_xx_0, '0', qtgui_eye_sink_x_0, '0']
|
||||
- [rational_resampler_xxx_0, '0', analog_quadrature_demod_cf_0, '0']
|
||||
- [root_raised_cosine_filter_0, '0', digital_symbol_sync_xx_0, '0']
|
||||
- [root_raised_cosine_filter_0, '0', qtgui_time_sink_x_0, '0']
|
||||
- [root_raised_cosine_filter_0_0, '0', digital_symbol_sync_xx_0, '0']
|
||||
- [root_raised_cosine_filter_0_0, '0', qtgui_time_sink_x_0, '0']
|
||||
- [soapy_rtlsdr_source_0, '0', rational_resampler_xxx_0, '0']
|
||||
|
||||
metadata:
|
||||
file_format: 1
|
||||
grc_version: 3.10.4.0
|
|
@ -0,0 +1,93 @@
|
|||
#ifndef M17_CONSTS
|
||||
#define M17_CONSTS
|
||||
|
||||
#define FLT_LEN 81 //baseband filter length (number of taps)
|
||||
#define SW_LEN 80 //syncword detector length
|
||||
#define XC_LEN 90 //cross-correlator lookback length in samples
|
||||
#define SYM_PER_PLD 184 //symbols per payload in a frame
|
||||
|
||||
//syncword patterns (RX) TODO:Compute those at runtime from the consts below
|
||||
const int8_t str_sync[8]={-3, -3, -3, -3, +3, +3, -3, +3};
|
||||
const int8_t lsf_sync[8]={+3, +3, +3, +3, -3, -3, +3, -3};
|
||||
|
||||
//symbol levels (RX)
|
||||
const float symbs[4]={-3.0, -1.0, +1.0, +3.0};
|
||||
|
||||
//dibits-symbols map (TX)
|
||||
const int8_t symbol_map[4]={+1, +3, -1, -3};
|
||||
|
||||
//syncwords
|
||||
const uint16_t SYNC_LSF = 0x55F7;
|
||||
const uint16_t SYNC_STR = 0xFF5D;
|
||||
const uint16_t SYNC_PKT = 0x75FF;
|
||||
const uint16_t SYNC_BER = 0xDF55;
|
||||
const uint16_t EOT_MRKR = 0x555D;
|
||||
|
||||
//RRC filter - 10 samples per symbol, 8 symbols span
|
||||
const float taps[FLT_LEN]=
|
||||
{
|
||||
-0.003195702904062073, -0.002930279157647190, -0.001940667871554463,
|
||||
-0.000356087678023658, 0.001547011339077758, 0.003389554791179751,
|
||||
0.004761898604225673, 0.005310860846138910, 0.004824746306020221,
|
||||
0.003297923526848786, 0.000958710871218619, -0.001749908029791816,
|
||||
-0.004238694106631223, -0.005881783042101693, -0.006150256456781309,
|
||||
-0.004745376707651645, -0.001704189656473565, 0.002547854551539951,
|
||||
0.007215575568844704, 0.011231038205363532, 0.013421952197060707,
|
||||
0.012730475385624438, 0.008449554307303753, 0.000436744366018287,
|
||||
-0.010735380379191660, -0.023726883538258272, -0.036498030780605324,
|
||||
-0.046500883189991064, -0.050979050575999614, -0.047340680079891187,
|
||||
-0.033554880492651755, -0.008513823955725943, 0.027696543159614194,
|
||||
0.073664520037517042, 0.126689053778116234, 0.182990955139333916,
|
||||
0.238080025892859704, 0.287235637987091563, 0.326040247765297220,
|
||||
0.350895727088112619, 0.359452932027607974, 0.350895727088112619,
|
||||
0.326040247765297220, 0.287235637987091563, 0.238080025892859704,
|
||||
0.182990955139333916, 0.126689053778116234, 0.073664520037517042,
|
||||
0.027696543159614194, -0.008513823955725943, -0.033554880492651755,
|
||||
-0.047340680079891187, -0.050979050575999614, -0.046500883189991064,
|
||||
-0.036498030780605324, -0.023726883538258272, -0.010735380379191660,
|
||||
0.000436744366018287, 0.008449554307303753, 0.012730475385624438,
|
||||
0.013421952197060707, 0.011231038205363532, 0.007215575568844704,
|
||||
0.002547854551539951, -0.001704189656473565, -0.004745376707651645,
|
||||
-0.006150256456781309, -0.005881783042101693, -0.004238694106631223,
|
||||
-0.001749908029791816, 0.000958710871218619, 0.003297923526848786,
|
||||
0.004824746306020221, 0.005310860846138910, 0.004761898604225673,
|
||||
0.003389554791179751, 0.001547011339077758, -0.000356087678023658,
|
||||
-0.001940667871554463, -0.002930279157647190, -0.003195702904062073
|
||||
};
|
||||
|
||||
//randomizing pattern
|
||||
const uint8_t rand_seq[46]=
|
||||
{
|
||||
0xD6, 0xB5, 0xE2, 0x30, 0x82, 0xFF, 0x84, 0x62, 0xBA, 0x4E, 0x96, 0x90, 0xD8, 0x98, 0xDD, 0x5D, 0x0C, 0xC8, 0x52, 0x43, 0x91, 0x1D, 0xF8,
|
||||
0x6E, 0x68, 0x2F, 0x35, 0xDA, 0x14, 0xEA, 0xCD, 0x76, 0x19, 0x8D, 0xD5, 0x80, 0xD1, 0x33, 0x87, 0x13, 0x57, 0x18, 0x2D, 0x29, 0x78, 0xC3
|
||||
};
|
||||
|
||||
//interleaver pattern
|
||||
const uint16_t intrl_seq[368]=
|
||||
{
|
||||
0, 137, 90, 227, 180, 317, 270, 39, 360, 129, 82, 219, 172, 309, 262, 31,
|
||||
352, 121, 74, 211, 164, 301, 254, 23, 344, 113, 66, 203, 156, 293, 246, 15,
|
||||
336, 105, 58, 195, 148, 285, 238, 7, 328, 97, 50, 187, 140, 277, 230, 367,
|
||||
320, 89, 42, 179, 132, 269, 222, 359, 312, 81, 34, 171, 124, 261, 214, 351,
|
||||
304, 73, 26, 163, 116, 253, 206, 343, 296, 65, 18, 155, 108, 245, 198, 335,
|
||||
288, 57, 10, 147, 100, 237, 190, 327, 280, 49, 2, 139, 92, 229, 182, 319,
|
||||
272, 41, 362, 131, 84, 221, 174, 311, 264, 33, 354, 123, 76, 213, 166, 303,
|
||||
256, 25, 346, 115, 68, 205, 158, 295, 248, 17, 338, 107, 60, 197, 150, 287,
|
||||
240, 9, 330, 99, 52, 189, 142, 279, 232, 1, 322, 91, 44, 181, 134, 271,
|
||||
224, 361, 314, 83, 36, 173, 126, 263, 216, 353, 306, 75, 28, 165, 118, 255,
|
||||
208, 345, 298, 67, 20, 157, 110, 247, 200, 337, 290, 59, 12, 149, 102, 239,
|
||||
192, 329, 282, 51, 4, 141, 94, 231, 184, 321, 274, 43, 364, 133, 86, 223,
|
||||
176, 313, 266, 35, 356, 125, 78, 215, 168, 305, 258, 27, 348, 117, 70, 207,
|
||||
160, 297, 250, 19, 340, 109, 62, 199, 152, 289, 242, 11, 332, 101, 54, 191,
|
||||
144, 281, 234, 3, 324, 93, 46, 183, 136, 273, 226, 363, 316, 85, 38, 175,
|
||||
128, 265, 218, 355, 308, 77, 30, 167, 120, 257, 210, 347, 300, 69, 22, 159,
|
||||
112, 249, 202, 339, 292, 61, 14, 151, 104, 241, 194, 331, 284, 53, 6, 143,
|
||||
96, 233, 186, 323, 276, 45, 366, 135, 88, 225, 178, 315, 268, 37, 358, 127,
|
||||
80, 217, 170, 307, 260, 29, 350, 119, 72, 209, 162, 299, 252, 21, 342, 111,
|
||||
64, 201, 154, 291, 244, 13, 334, 103, 56, 193, 146, 283, 236, 5, 326, 95,
|
||||
48, 185, 138, 275, 228, 365, 318, 87, 40, 177, 130, 267, 220, 357, 310, 79,
|
||||
32, 169, 122, 259, 212, 349, 302, 71, 24, 161, 114, 251, 204, 341, 294, 63,
|
||||
16, 153, 106, 243, 196, 333, 286, 55, 8, 145, 98, 235, 188, 325, 278, 47
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,70 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../inc/m17.h"
|
||||
|
||||
struct LSF
|
||||
{
|
||||
uint8_t dst[6];
|
||||
uint8_t src[6];
|
||||
uint8_t type[2];
|
||||
uint8_t meta[112/8];
|
||||
uint8_t crc[2];
|
||||
} lsf;
|
||||
|
||||
uint8_t data[16];
|
||||
|
||||
uint16_t fn=0; //16-bit Frame Number (for the stream mode)
|
||||
|
||||
uint8_t got_lsf=0; //have we filled the LSF struct yet?
|
||||
|
||||
|
||||
//main routine
|
||||
int main(void)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
if(got_lsf) //stream frames
|
||||
{
|
||||
//we could discard the data we already have
|
||||
while(read(STDIN_FILENO, &(lsf.dst), 6)<6);
|
||||
while(read(STDIN_FILENO, &(lsf.src), 6)<6);
|
||||
while(read(STDIN_FILENO, &(lsf.type), 2)<2);
|
||||
while(read(STDIN_FILENO, &(lsf.meta), 14)<14);
|
||||
while(read(STDIN_FILENO, data, 16)<16);
|
||||
|
||||
printf("\tDATA: ");
|
||||
for(uint8_t i=0; i<16; i++)
|
||||
printf("%02X", data[i]);
|
||||
printf("\n");
|
||||
}
|
||||
else //LSF
|
||||
{
|
||||
while(read(STDIN_FILENO, &(lsf.dst), 6)<6);
|
||||
while(read(STDIN_FILENO, &(lsf.src), 6)<6);
|
||||
while(read(STDIN_FILENO, &(lsf.type), 2)<2);
|
||||
while(read(STDIN_FILENO, &(lsf.meta), 14)<14);
|
||||
while(read(STDIN_FILENO, data, 16)<16);
|
||||
|
||||
got_lsf=1;
|
||||
|
||||
printf("DST: ");
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
printf("%02X", lsf.dst[i]);
|
||||
printf(" SRC: ");
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
printf("%02X", lsf.src[i]);
|
||||
printf(" TYPE: ");
|
||||
for(uint8_t i=0; i<2; i++)
|
||||
printf("%02X", lsf.type[i]);
|
||||
printf(" META: ");
|
||||
for(uint8_t i=0; i<14; i++)
|
||||
printf("%02X", lsf.meta[i]);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,228 @@
|
|||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include "golay.h"
|
||||
|
||||
const uint16_t encode_matrix[12]=
|
||||
{
|
||||
0x8eb, 0x93e, 0xa97, 0xdc6, 0x367, 0x6cd,
|
||||
0xd99, 0x3da, 0x7b4, 0xf68, 0x63b, 0xc75
|
||||
};
|
||||
|
||||
const uint16_t decode_matrix[12]=
|
||||
{
|
||||
0xc75, 0x49f, 0x93e, 0x6e3, 0xdc6, 0xf13,
|
||||
0xab9, 0x1ed, 0x3da, 0x7b4, 0xf68, 0xa4f
|
||||
};
|
||||
|
||||
//0 index - LSB
|
||||
void IntToSoft(uint16_t* out, const uint16_t in, uint8_t len)
|
||||
{
|
||||
for(uint8_t i=0; i<len; i++)
|
||||
{
|
||||
(in>>i)&1 ? (out[i]=0xFFFF) : (out[i]=0);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t SoftToInt(const uint16_t* in, uint8_t len)
|
||||
{
|
||||
uint16_t tmp=0;
|
||||
|
||||
for(uint8_t i=0; i<len; i++)
|
||||
{
|
||||
if(in[i]>0x7FFF)
|
||||
tmp|=(1<<i);
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
//Quadrant I fixed point division with saturation
|
||||
//result=a/b
|
||||
uint16_t Div16(uint16_t a, uint16_t b)
|
||||
{
|
||||
uint32_t aa=a<<16;
|
||||
uint32_t r=aa/b;
|
||||
|
||||
if(r<=0xFFFF)
|
||||
return r;
|
||||
else
|
||||
return 0xFFFF;
|
||||
}
|
||||
|
||||
//Quadrant I fixed point multiplication
|
||||
//result=a/b
|
||||
uint16_t Mul16(uint16_t a, uint16_t b)
|
||||
{
|
||||
return (uint16_t)(((uint32_t)a*b)>>16);
|
||||
}
|
||||
|
||||
//use bilinear interpolation for XOR
|
||||
uint16_t SoftBitXOR(const uint16_t a, const uint16_t b)
|
||||
{
|
||||
return Mul16(Div16(0xFFFF-b, 0xFFFF), Div16(a, 0xFFFF)) + Mul16(Div16(b, 0xFFFF), Div16(0xFFFF-a, 0xFFFF));
|
||||
}
|
||||
|
||||
//soft XOR
|
||||
void SoftXOR(uint16_t* out, const uint16_t* a, const uint16_t* b, uint8_t len)
|
||||
{
|
||||
for(uint8_t i=0; i<len; i++)
|
||||
out[i]=SoftBitXOR(a[i], b[i]);
|
||||
}
|
||||
|
||||
//soft equivalent of popcount
|
||||
uint32_t spopcount(const uint16_t* in, uint8_t siz)
|
||||
{
|
||||
uint32_t tmp=0;
|
||||
|
||||
for(uint8_t i=0; i<siz; i++)
|
||||
tmp+=in[i];
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void calcChecksumS(uint16_t* out, const uint16_t* value)
|
||||
{
|
||||
uint16_t checksum[12];
|
||||
uint16_t soft_em[12]; //soft valued encoded matrix entry
|
||||
|
||||
for(uint8_t i=0; i<12; i++)
|
||||
checksum[i]=0;
|
||||
|
||||
for(uint8_t i=0; i<12; i++)
|
||||
{
|
||||
IntToSoft(soft_em, encode_matrix[i], 12);
|
||||
|
||||
if(value[i]>0x7FFF)
|
||||
{
|
||||
SoftXOR(checksum, checksum, soft_em, 12);
|
||||
}
|
||||
}
|
||||
|
||||
memcpy((uint8_t*)out, (uint8_t*)checksum, 12*2);
|
||||
}
|
||||
|
||||
uint32_t SdetectErrors(const uint16_t* codeword)
|
||||
{
|
||||
uint16_t data[12];
|
||||
uint16_t parity[12];
|
||||
uint16_t cksum[12];
|
||||
uint16_t syndrome[12];
|
||||
uint32_t weight; //for soft popcount
|
||||
|
||||
memcpy((uint8_t*)data, (uint8_t*)&codeword[12], 2*12);
|
||||
memcpy((uint8_t*)parity, (uint8_t*)&codeword[0], 2*12);
|
||||
|
||||
calcChecksumS(cksum, data);
|
||||
SoftXOR(syndrome, parity, cksum, 12);
|
||||
|
||||
weight=spopcount(syndrome, 12);
|
||||
|
||||
//all (less than 4) errors in the parity part
|
||||
if(weight < 4*0xFFFE)
|
||||
{
|
||||
//printf("1: %1.2f\n", (float)weight/0xFFFF);
|
||||
return SoftToInt(syndrome, 12);
|
||||
}
|
||||
|
||||
//one of the errors in data part, up to 3 in parity
|
||||
for(uint8_t i = 0; i<12; i++)
|
||||
{
|
||||
uint16_t e = 1<<i;
|
||||
uint16_t coded_error = encode_matrix[i];
|
||||
uint16_t scoded_error[12]; //soft coded_error
|
||||
uint16_t sc[12]; //syndrome^coded_error
|
||||
|
||||
IntToSoft(scoded_error, coded_error, 12);
|
||||
SoftXOR(sc, syndrome, scoded_error, 12);
|
||||
weight=spopcount(sc, 12);
|
||||
|
||||
if(weight < 3*0xFFFE)
|
||||
{
|
||||
//printf("2: %1.2f\n", (float)weight/0xFFFF+1);
|
||||
uint16_t s=SoftToInt(syndrome, 12);
|
||||
return (e << 12) | (s ^ coded_error);
|
||||
}
|
||||
}
|
||||
|
||||
//two of the errors in data part and up to 2 in parity
|
||||
for(uint8_t i = 0; i<11; i++)
|
||||
{
|
||||
for(uint8_t j = i+1; j<12; j++)
|
||||
{
|
||||
uint16_t e = (1<<i) | (1<<j);
|
||||
uint16_t coded_error = encode_matrix[i]^encode_matrix[j];
|
||||
uint16_t scoded_error[12]; //soft coded_error
|
||||
uint16_t sc[12]; //syndrome^coded_error
|
||||
|
||||
IntToSoft(scoded_error, coded_error, 12);
|
||||
SoftXOR(sc, syndrome, scoded_error, 12);
|
||||
weight=spopcount(sc, 12);
|
||||
|
||||
if(weight < 2*0xFFFF)
|
||||
{
|
||||
//printf("3: %1.2f\n", (float)weight/0xFFFF+2);
|
||||
uint16_t s=SoftToInt(syndrome, 12);
|
||||
return (e << 12) | (s ^ coded_error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//algebraic decoding magic
|
||||
uint16_t inv_syndrome[12]={0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
uint16_t dm[12]; //soft decode matrix
|
||||
|
||||
for(uint8_t i=0; i<12; i++)
|
||||
{
|
||||
if(syndrome[i] > 0x7FFF)
|
||||
{
|
||||
IntToSoft(dm, decode_matrix[i], 12);
|
||||
SoftXOR(inv_syndrome, inv_syndrome, dm, 12);
|
||||
}
|
||||
}
|
||||
|
||||
//all (less than 4) errors in the data part
|
||||
weight=spopcount(inv_syndrome, 12);
|
||||
if(weight < 4*0xFFFF)
|
||||
{
|
||||
//printf("4: %1.2f\n", (float)weight/0xFFFF);
|
||||
return SoftToInt(inv_syndrome, 12) << 12;
|
||||
}
|
||||
|
||||
//one error in parity bits, up to 3 in data - this part has some quirks, the reason remains unknown
|
||||
for(uint8_t i=0; i<12; i++)
|
||||
{
|
||||
uint16_t e = 1<<i;
|
||||
uint16_t coding_error = decode_matrix[i];
|
||||
|
||||
uint16_t ce[12]; //soft coding error
|
||||
uint16_t tmp[12];
|
||||
|
||||
IntToSoft(ce, coding_error, 12);
|
||||
SoftXOR(tmp, inv_syndrome, ce, 12);
|
||||
weight=spopcount(tmp, 12);
|
||||
|
||||
if(weight < 3*(0xFFFF+2))
|
||||
{
|
||||
//printf("5: %1.2f\n", (float)weight/0xFFFF+1);
|
||||
return ((SoftToInt(inv_syndrome, 12) ^ coding_error) << 12) | e;
|
||||
}
|
||||
}
|
||||
|
||||
return 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
//soft decode
|
||||
uint16_t golay24_sdecode(const uint16_t* codeword)
|
||||
{
|
||||
//match the bit order in M17
|
||||
uint16_t cw[24];
|
||||
for(uint8_t i=0; i<24; i++)
|
||||
cw[i]=codeword[23-i];
|
||||
|
||||
uint32_t errors = SdetectErrors(cw);
|
||||
|
||||
if(errors == 0xFFFFFFFF)
|
||||
return 0xFFFF;
|
||||
|
||||
return (((SoftToInt(&cw[0], 16) | (SoftToInt(&cw[16], 8) << 16)) ^ errors) >> 12) & 0x0FFF;
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef GOLAY_H
|
||||
#define GOLAY_H
|
||||
|
||||
void IntToSoft(uint16_t* out, const uint16_t in, uint8_t len);
|
||||
uint16_t SoftToInt(const uint16_t* in, uint8_t len);
|
||||
uint16_t Div16(uint16_t a, uint16_t b);
|
||||
uint16_t Mul16(uint16_t a, uint16_t b);
|
||||
uint16_t SoftBitXOR(const uint16_t a, const uint16_t b);
|
||||
void SoftXOR(uint16_t* out, const uint16_t* a, const uint16_t* b, uint8_t len);
|
||||
uint32_t spopcount(const uint16_t* in, uint8_t siz);
|
||||
void calcChecksumS(uint16_t* out, const uint16_t* value);
|
||||
uint32_t SdetectErrors(const uint16_t* codeword);
|
||||
uint16_t golay24_sdecode(const uint16_t* codeword);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,229 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../inc/m17.h"
|
||||
#include "golay.h"
|
||||
#include "viterbi.h"
|
||||
|
||||
float sample; //last raw sample from the stdin
|
||||
float last[8]; //look-back buffer for finding syncwords
|
||||
float xcorr; //cross correlation for finding syncwords
|
||||
float pld[SYM_PER_PLD]; //raw frame symbols
|
||||
uint16_t soft_bit[2*SYM_PER_PLD]; //raw frame soft bits
|
||||
uint16_t d_soft_bit[2*SYM_PER_PLD]; //deinterleaved soft bits
|
||||
|
||||
uint8_t lsf[30]; //complete LSF
|
||||
uint16_t lich_chunk[96]; //raw, soft LSF chunk extracted from the LICH
|
||||
uint8_t lich_b[6]; //48-bit decoded LICH
|
||||
uint8_t lich_cnt; //LICH_CNT
|
||||
uint8_t lich_chunks_rcvd=0; //flags set for each LSF chunk received
|
||||
|
||||
uint16_t enc_data[272]; //raw frame data soft bits
|
||||
uint8_t frame_data[19]; //decoded frame data, 144 bits (16+128), plus 4 flushing bits
|
||||
|
||||
uint8_t syncd=0; //syncword found?
|
||||
uint8_t pushed; //counter for pushed symbols
|
||||
|
||||
extern const uint8_t P2_pat[12];
|
||||
|
||||
//soft decodes LICH into a 6-byte array
|
||||
//input - soft bits
|
||||
//output - an array of packed bits
|
||||
void decode_LICH(uint8_t* outp, const uint16_t* inp)
|
||||
{
|
||||
uint16_t tmp;
|
||||
|
||||
memset(outp, 0, 5);
|
||||
|
||||
tmp=golay24_sdecode(&inp[0]);
|
||||
outp[0]=(tmp>>4)&0xFF;
|
||||
outp[1]|=(tmp&0xF)<<4;
|
||||
tmp=golay24_sdecode(&inp[1*24]);
|
||||
outp[1]|=(tmp>>8)&0xF;
|
||||
outp[2]=tmp&0xFF;
|
||||
tmp=golay24_sdecode(&inp[2*24]);
|
||||
outp[3]=(tmp>>4)&0xFF;
|
||||
outp[4]|=(tmp&0xF)<<4;
|
||||
tmp=golay24_sdecode(&inp[3*24]);
|
||||
outp[4]|=(tmp>>8)&0xF;
|
||||
outp[5]=tmp&0xFF;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
//wait for another symbol
|
||||
while(read(STDIN_FILENO, (uint8_t*)&sample, 4)<4);
|
||||
|
||||
if(!syncd)
|
||||
{
|
||||
//push new symbol
|
||||
for(uint8_t i=0; i<7; i++)
|
||||
{
|
||||
last[i]=last[i+1];
|
||||
}
|
||||
|
||||
last[7]=sample;
|
||||
|
||||
//calculate cross-correlation
|
||||
xcorr=0;
|
||||
for(uint8_t i=0; i<8; i++)
|
||||
{
|
||||
xcorr+=last[i]*str_sync[i];
|
||||
}
|
||||
|
||||
//printf("%f\n", xcorr);
|
||||
|
||||
if(xcorr>62.0)
|
||||
{
|
||||
syncd=1;
|
||||
pushed=0;
|
||||
}
|
||||
else if(xcorr<-62)
|
||||
{
|
||||
printf("LSF\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pld[pushed++]=sample;
|
||||
|
||||
if(pushed==SYM_PER_PLD)
|
||||
{
|
||||
//decode symbols to soft dibits
|
||||
for(uint8_t i=0; i<SYM_PER_PLD; i++)
|
||||
{
|
||||
//bit 0
|
||||
if(pld[i]>=symbs[3])
|
||||
{
|
||||
soft_bit[i*2+1]=0xFFFF;
|
||||
}
|
||||
else if(pld[i]>=symbs[2])
|
||||
{
|
||||
soft_bit[i*2+1]=-(float)0xFFFF/(symbs[3]-symbs[2])*symbs[2]+pld[i]*(float)0xFFFF/(symbs[3]-symbs[2]);
|
||||
}
|
||||
else if(pld[i]>=symbs[1])
|
||||
{
|
||||
soft_bit[i*2+1]=0x0000;
|
||||
}
|
||||
else if(pld[i]>=symbs[0])
|
||||
{
|
||||
soft_bit[i*2+1]=(float)0xFFFF/(symbs[1]-symbs[0])*symbs[1]-pld[i]*(float)0xFFFF/(symbs[1]-symbs[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
soft_bit[i*2+1]=0xFFFF;
|
||||
}
|
||||
|
||||
//bit 1
|
||||
if(pld[i]>=symbs[2])
|
||||
{
|
||||
soft_bit[i*2]=0x0000;
|
||||
}
|
||||
else if(pld[i]>=symbs[1])
|
||||
{
|
||||
soft_bit[i*2]=0x7FFF-pld[i]*(float)0xFFFF/(symbs[2]-symbs[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
soft_bit[i*2]=0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
//derandomize
|
||||
for(uint16_t i=0; i<SYM_PER_PLD*2; i++)
|
||||
{
|
||||
if((rand_seq[i/8]>>(7-(i%8)))&1) //soft XOR. flip soft bit if "1"
|
||||
soft_bit[i]=0xFFFF-soft_bit[i];
|
||||
}
|
||||
|
||||
//deinterleave
|
||||
for(uint16_t i=0; i<SYM_PER_PLD*2; i++)
|
||||
{
|
||||
d_soft_bit[i]=soft_bit[intrl_seq[i]];
|
||||
}
|
||||
|
||||
//extract LICH
|
||||
for(uint16_t i=0; i<96; i++)
|
||||
{
|
||||
lich_chunk[i]=d_soft_bit[i];
|
||||
}
|
||||
|
||||
//Golay decoder
|
||||
decode_LICH(lich_b, lich_chunk);
|
||||
lich_cnt=lich_b[5]>>5;
|
||||
lich_chunks_rcvd|=(1<<lich_cnt);
|
||||
memcpy(&lsf[lich_cnt*5], lich_b, 5);
|
||||
|
||||
//debug - dump LICH
|
||||
if(lich_chunks_rcvd==0x3F)
|
||||
{
|
||||
/*//DST
|
||||
printf("DST: ");
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
printf("%02X", lsf[i]);
|
||||
printf(" ");
|
||||
|
||||
//SRC
|
||||
printf("SRC: ");
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
printf("%02X", lsf[6+i]);
|
||||
printf(" ");
|
||||
|
||||
//TYPE
|
||||
printf("TYPE: ");
|
||||
for(uint8_t i=0; i<2; i++)
|
||||
printf("%02X", lsf[12+i]);
|
||||
printf(" ");
|
||||
|
||||
//META
|
||||
printf("META: ");
|
||||
for(uint8_t i=0; i<14; i++)
|
||||
printf("%02X", lsf[14+i]);
|
||||
printf(" ");
|
||||
|
||||
//CRC
|
||||
printf("CRC: ");
|
||||
for(uint8_t i=0; i<2; i++)
|
||||
printf("%02X", lsf[28+i]);
|
||||
printf("\n");*/
|
||||
|
||||
lich_chunks_rcvd=0; //reset all flags
|
||||
}
|
||||
|
||||
//extract data
|
||||
for(uint16_t i=0; i<272; i++)
|
||||
{
|
||||
enc_data[i]=d_soft_bit[96+i];
|
||||
}
|
||||
|
||||
//decode
|
||||
uint32_t e=decodePunctured(frame_data, enc_data, P2_pat, 272, 12);
|
||||
|
||||
//dump data - first byte is empty
|
||||
/*printf("FN: %02X%02X PLD: ", frame_data[1], frame_data[2]);
|
||||
for(uint8_t i=3; i<19; i++)
|
||||
{
|
||||
printf("%02X", frame_data[i]);
|
||||
}
|
||||
printf(" e=%1.1f\n", (float)e/0xFFFF);*/
|
||||
|
||||
//send codec2 stream to stdout
|
||||
//write(STDOUT_FILENO, &frame_data[3], 16);
|
||||
|
||||
//job done
|
||||
syncd=0;
|
||||
pushed=0;
|
||||
|
||||
for(uint8_t i=0; i<8; i++)
|
||||
last[i]=0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../inc/m17.h"
|
||||
|
||||
int16_t sample; //raw S16_LE baseband sample
|
||||
int16_t flt_buff[FLT_LEN]; //root-nyquist filter buffer
|
||||
int16_t sw_buff[SW_LEN]; //syncword detection buffer
|
||||
int16_t xc_buff[XC_LEN]; //cross-correlation buffer
|
||||
int16_t mac; //multiply-accumulate
|
||||
|
||||
//states
|
||||
uint8_t pre_syncd=0;
|
||||
uint8_t syncd=0;
|
||||
int8_t phase=0;
|
||||
|
||||
int main(void)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
//wait for another baseband sample
|
||||
while(read(STDIN_FILENO, (uint8_t*)&sample, 2)<2);
|
||||
|
||||
//push the root-nyquist filter's buffer
|
||||
for(uint8_t i=0; i<FLT_LEN-1; i++)
|
||||
{
|
||||
flt_buff[i]=flt_buff[i+1];
|
||||
}
|
||||
|
||||
flt_buff[FLT_LEN-1]=sample;
|
||||
|
||||
//calculate the filter's output
|
||||
mac=0;
|
||||
for(uint8_t i=0; i<FLT_LEN; i++)
|
||||
mac+=flt_buff[i]*taps[i];
|
||||
|
||||
for(uint8_t i=0; i<FLT_LEN-2; i++)
|
||||
{
|
||||
sw_buff[i]=sw_buff[i+1];
|
||||
}
|
||||
|
||||
sw_buff[FLT_LEN-2]=mac;
|
||||
|
||||
//detect syncword using cross-correlation
|
||||
int32_t xcorr=0;
|
||||
|
||||
for(uint8_t i=0; i<XC_LEN; i+=10)
|
||||
{
|
||||
xcorr+=sw_buff[i]*str_sync[i/10];
|
||||
}
|
||||
|
||||
//push the xcorr value to the buffer
|
||||
for(uint8_t i=0; i<XC_LEN-1; i++)
|
||||
{
|
||||
xc_buff[i]=xc_buff[i+1];
|
||||
}
|
||||
|
||||
xc_buff[XC_LEN-1]=xcorr/24;
|
||||
|
||||
//detect peak
|
||||
if(xc_buff[XC_LEN-1]>0.4*INT16_MAX)
|
||||
{
|
||||
uint8_t msg[64];
|
||||
uint8_t len=sprintf(msg, "SYNC\n");
|
||||
write(STDERR_FILENO, msg, len);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,216 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "viterbi.h"
|
||||
|
||||
#define K 5 //constraint length
|
||||
#define NUM_STATES (1 << (K - 1)) //number of states
|
||||
|
||||
const uint8_t P2_pat[12]={1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0}; //P_2 puncturing pattern for stream frames
|
||||
|
||||
//vars
|
||||
uint32_t prevMetrics[NUM_STATES];
|
||||
uint32_t currMetrics[NUM_STATES];
|
||||
|
||||
uint32_t prevMetricsData[NUM_STATES];
|
||||
uint32_t currMetricsData[NUM_STATES];
|
||||
|
||||
uint16_t history[244];
|
||||
|
||||
/**
|
||||
* Decode unpunctured convolutionally encoded data.
|
||||
*
|
||||
* @param out: destination array where decoded data is written.
|
||||
* @param in: input data.
|
||||
* @param len: input length in bits
|
||||
* @return number of bit errors corrected.
|
||||
*/
|
||||
uint32_t decode(uint8_t* out, const uint16_t* in, uint16_t len)
|
||||
{
|
||||
if(len > 244*2)
|
||||
fprintf((FILE*)STDERR_FILENO, "Input size exceeds max history\n");
|
||||
|
||||
reset();
|
||||
|
||||
size_t pos = 0;
|
||||
for(size_t i = 0; i < len; i += 2)
|
||||
{
|
||||
uint16_t s0 = in[i];
|
||||
uint16_t s1 = in[i + 1];
|
||||
|
||||
decodeBit(s0, s1, pos);
|
||||
pos++;
|
||||
}
|
||||
|
||||
return chainback(out, pos, len/2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode punctured convolutionally encoded data.
|
||||
*
|
||||
* @param out: destination array where decoded data is written.
|
||||
* @param in: input data.
|
||||
* @param punct: puncturing matrix.
|
||||
* @param in_len: input data length.
|
||||
* @param p_len: puncturing matrix length (entries).
|
||||
* @return number of bit errors corrected.
|
||||
*/
|
||||
uint32_t decodePunctured(uint8_t* out, const uint16_t* in, const uint8_t* punct, uint16_t in_len, uint16_t p_len) //input length, puncturing pattern length
|
||||
{
|
||||
if(in_len > 244*2)
|
||||
fprintf((FILE*)STDERR_FILENO, "Input size exceeds max history\n");
|
||||
|
||||
uint16_t umsg[244*2]; //unpunctured message
|
||||
uint8_t p=0; //puncturer matrix entry
|
||||
uint16_t u=0; //bits count - unpunctured message
|
||||
uint16_t i=0; //bits read from the input message
|
||||
|
||||
while(i<in_len)
|
||||
{
|
||||
if(punct[p])
|
||||
{
|
||||
umsg[u]=in[i];
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
umsg[u]=0x7FFF;
|
||||
}
|
||||
|
||||
u++;
|
||||
p++;
|
||||
p%=p_len;
|
||||
}
|
||||
|
||||
return decode(out, umsg, u) - (u-in_len)*0x7FFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode one bit and update trellis.
|
||||
*
|
||||
* @param s0: cost of the first symbol.
|
||||
* @param s1: cost of the second symbol.
|
||||
* @param pos: bit position in history.
|
||||
*/
|
||||
void decodeBit(uint16_t s0, uint16_t s1, size_t pos)
|
||||
{
|
||||
static const uint16_t COST_TABLE_0[] = {0, 0, 0, 0, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
|
||||
static const uint16_t COST_TABLE_1[] = {0, 0xFFFF, 0xFFFF, 0, 0, 0xFFFF, 0xFFFF, 0};
|
||||
|
||||
for(uint8_t i = 0; i < NUM_STATES/2; i++)
|
||||
{
|
||||
uint32_t metric = q_AbsDiff(COST_TABLE_0[i], s0)
|
||||
+ q_AbsDiff(COST_TABLE_1[i], s1);
|
||||
|
||||
|
||||
uint32_t m0 = prevMetrics[i] + metric;
|
||||
uint32_t m1 = prevMetrics[i + NUM_STATES/2] + (0x1FFFE - metric);
|
||||
|
||||
uint32_t m2 = prevMetrics[i] + (0x1FFFE - metric);
|
||||
uint32_t m3 = prevMetrics[i + NUM_STATES/2] + metric;
|
||||
|
||||
uint8_t i0 = 2 * i;
|
||||
uint8_t i1 = i0 + 1;
|
||||
|
||||
if(m0 >= m1)
|
||||
{
|
||||
history[pos]|=(1<<i0);
|
||||
currMetrics[i0] = m1;
|
||||
}
|
||||
else
|
||||
{
|
||||
history[pos]&=~(1<<i0);
|
||||
currMetrics[i0] = m0;
|
||||
}
|
||||
|
||||
if(m2 >= m3)
|
||||
{
|
||||
history[pos]|=(1<<i1);
|
||||
currMetrics[i1] = m3;
|
||||
}
|
||||
else
|
||||
{
|
||||
history[pos]&=~(1<<i1);
|
||||
currMetrics[i1] = m2;
|
||||
}
|
||||
}
|
||||
|
||||
//swap
|
||||
uint32_t tmp[NUM_STATES];
|
||||
for(uint8_t i=0; i<NUM_STATES; i++)
|
||||
{
|
||||
tmp[i]=currMetrics[i];
|
||||
}
|
||||
for(uint8_t i=0; i<NUM_STATES; i++)
|
||||
{
|
||||
currMetrics[i]=prevMetrics[i];
|
||||
prevMetrics[i]=tmp[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* History chainback to obtain final byte array.
|
||||
*
|
||||
* @param out: destination byte array for decoded data.
|
||||
* @param pos: starting position for the chainback.
|
||||
* @param len: length of the output in bits.
|
||||
* @return minimum Viterbi cost at the end of the decode sequence.
|
||||
*/
|
||||
uint32_t chainback(uint8_t* out, size_t pos, uint16_t len)
|
||||
{
|
||||
uint8_t state = 0;
|
||||
size_t bitPos = len+4;
|
||||
|
||||
memset(out, 0, (len-1)/8+1);
|
||||
|
||||
while(bitPos > 0)
|
||||
{
|
||||
bitPos--;
|
||||
pos--;
|
||||
uint16_t bit = history[pos]&((1<<(state>>4)));
|
||||
state >>= 1;
|
||||
if(bit)
|
||||
{
|
||||
state |= 0x80;
|
||||
out[bitPos/8]|=1<<(7-(bitPos%8));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t cost = prevMetrics[0];
|
||||
|
||||
for(size_t i = 0; i < NUM_STATES; i++)
|
||||
{
|
||||
uint32_t m = prevMetrics[i];
|
||||
if(m < cost) cost = m;
|
||||
}
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function to compute the absolute value of a difference between
|
||||
* two fixed-point values.
|
||||
*
|
||||
* @param v1: first value
|
||||
* @param v2: second value
|
||||
* @return abs(v1-v2)
|
||||
*/
|
||||
uint16_t q_AbsDiff(const uint16_t v1, const uint16_t v2)
|
||||
{
|
||||
if(v2 > v1) return v2 - v1;
|
||||
return v1 - v2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the decoder state.
|
||||
*
|
||||
*/
|
||||
void reset(void)
|
||||
{
|
||||
memset((uint8_t*)history, 0, 2*244);
|
||||
memset((uint8_t*)currMetrics, 0, 4*NUM_STATES);
|
||||
memset((uint8_t*)prevMetrics, 0, 4*NUM_STATES);
|
||||
memset((uint8_t*)currMetricsData, 0, 4*NUM_STATES);
|
||||
memset((uint8_t*)prevMetricsData, 0, 4*NUM_STATES);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef VITERBI_H
|
||||
#define VITERBI_H
|
||||
|
||||
uint32_t decode(uint8_t* out, const uint16_t* in, uint16_t len);
|
||||
uint32_t decodePunctured(uint8_t* out, const uint16_t* in, const uint8_t* punct, uint16_t in_len, uint16_t p_len);
|
||||
void decodeBit(uint16_t s0, uint16_t s1, size_t pos);
|
||||
uint32_t chainback(uint8_t* out, size_t pos, uint16_t len);
|
||||
uint16_t q_AbsDiff(const uint16_t v1, const uint16_t v2);
|
||||
void reset(void);
|
||||
|
||||
#endif
|
Ładowanie…
Reference in New Issue