kopia lustrzana https://github.com/projecthorus/radiosonde_auto_rx
Initial add of demod testing code.
rodzic
89e21976fa
commit
5fc4f25072
|
@ -5,7 +5,7 @@
|
|||
# Copyright (C) 2018 Mark Jessop <vk5qi@rfhead.net>
|
||||
# Released under GNU GPL v3 or later
|
||||
#
|
||||
__version__ = "20190211-beta"
|
||||
__version__ = "20190227-beta"
|
||||
|
||||
# Global Variables
|
||||
|
||||
|
|
|
@ -246,12 +246,13 @@ class SondeDecoder(object):
|
|||
# DFM06/DFM09 Sondes.
|
||||
# As of 2019-02-10, dfm09ecc auto-detects if the signal is inverted,
|
||||
# so we don't need to specify an invert flag.
|
||||
# 2019-02-27: Added the --dist flag, which should reduce bad positions a bit.
|
||||
|
||||
# Note: Have removed a 'highpass 20' filter from the sox line, will need to re-evaluate if adding that is useful in the future.
|
||||
decode_cmd = "%s %s-p %d -d %s %s-M fm -F9 -s 15k -f %d 2>/dev/null |" % (self.sdr_fm, bias_option, int(self.ppm), str(self.device_idx), gain_param, self.sonde_freq)
|
||||
decode_cmd += "sox -t raw -r 15k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - highpass 20 lowpass 2000 2>/dev/null |"
|
||||
# DFM decoder
|
||||
decode_cmd += "./dfm09ecc -vv --ecc --json --auto 2>/dev/null"
|
||||
decode_cmd += "./dfm09ecc -vv --ecc --json --dist --auto 2>/dev/null"
|
||||
|
||||
elif self.sonde_type == "M10":
|
||||
# M10 Sondes
|
||||
|
|
|
@ -7,13 +7,14 @@
|
|||
echo "Building rs_detect"
|
||||
cd ../scan/
|
||||
gcc rs_detect.c -lm -o rs_detect
|
||||
gcc dft_detect.c -lm -o dft_detect
|
||||
|
||||
echo "Building RS92/RS41/DFM Demodulators"
|
||||
cd ../demod/
|
||||
gcc -c demod.c
|
||||
gcc -c demod_dft.c
|
||||
gcc rs92dm_dft.c demod_dft.o -lm -o rs92ecc -I../ecc/ -I../rs92
|
||||
gcc rs41dm_dft.c demod_dft.o -lm -o rs41ecc -I../ecc/ -I../rs41
|
||||
gcc rs41dm_dft.c demod_dft.o -lm -o rs41ecc -I../ecc/ -I../rs41 -w
|
||||
gcc dfm09dm_dft.c demod_dft.o -lm -o dfm09ecc -I../ecc/ -I../dfm
|
||||
# Build M10 decoder
|
||||
echo "Building M10 Demodulator."
|
||||
|
@ -25,6 +26,7 @@ g++ M10.cpp M10Decoder.cpp M10GeneralParser.cpp M10GtopParser.cpp M10TrimblePars
|
|||
echo "Copying files into auto_rx directory."
|
||||
cd ../auto_rx/
|
||||
cp ../scan/rs_detect .
|
||||
cp ../scan/dft_detect .
|
||||
cp ../demod/rs92ecc .
|
||||
cp ../demod/rs41ecc .
|
||||
cp ../demod/dfm09ecc .
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
# Radiosonde Demodulator Testing Scripts
|
||||
|
||||
For these scripts to work, we need:
|
||||
* The following directories created: samples, generated
|
||||
* The various demodulator binaries (rs41ecc, rs_detect, etc... ) located in ../ Currently using:
|
||||
* dfm09ecc, m10 (from radiosonde_auto_rx), rs41ecc, rs92ecc, rs_detect, dft_detect
|
||||
* The above can just be built using the auto_rx build.sh script.
|
||||
* CSDR installed and available on $PATH: https://github.com/simonyiszk/csdr
|
||||
* The base high-snr samples located in ./samples/. These can be downloaded from http://rfhead.net/sondes/sonde_samples.tar.gz
|
||||
* Python (2, will probably work in 3), with numpy available.
|
||||
|
||||
## generate_lowsnr.py
|
||||
This script generates a set of low-SNR samples based on the base high-SNR samples in ./samples/
|
||||
Calibrated-level noise is added to the sample to produce a file with a user-defined Eb/No ('SNR per-bit').
|
||||
If everything works 'perfectly', we should expect all the different modems to have similar PER vs Eb/No performance.
|
||||
However, real-world factors such as packet length, transmitter deviation, filter widths, etc will mess this up.
|
||||
I wouldn't try and make too many comparions of the performance between different sonde demodulators. Better to strike
|
||||
a baseline of current performance, and then try and improve on it.
|
||||
|
||||
The level of noise to add is determined based on the variance of the sample. Some checking of Eb/No of generated
|
||||
samples has been performed with David Rowe's fsk demod, though only for the RS41 samples so far.
|
||||
|
||||
Modify the EBNO_RANGE variable to change the range of Eb/No values to generate. FSK demods generally fall over between about 10 and 16 dB.
|
||||
Uncomment the various elements in the SAMPLES array to choose what sample to process.
|
||||
|
||||
Then, run with:
|
||||
```
|
||||
$ cd scripts
|
||||
$ python generate_lowsnr.py
|
||||
```
|
||||
|
||||
|
||||
Notes:
|
||||
* I suspect the variance measurement for the m10 sample is off. Its performing suspiciously better than the other sondes.
|
||||
|
||||
|
||||
## test_demod.py
|
||||
This script run the generated samples above through different demodulation chains.
|
||||
|
||||
Check the processing_type dict in the script for the differnet demodulation options.
|
||||
|
||||
Example:
|
||||
```
|
||||
# Demodulate all RS41 samples.
|
||||
$ python test_demod.py -m rs41_csdr_fm_decode -f "../generated/rs41*.bin"
|
||||
|
||||
# Run dft_detect across all samples.
|
||||
# python test_demod.py -m csdr_fm_dftdetect -f "../generated/*.bin"
|
||||
```
|
||||
|
||||
The output is a csv of: filename, result
|
||||
|
||||
Depending on the mode, the result could be a packet count, or it could be a success/no success (in the case of the detection utilities).
|
||||
|
||||
|
||||
# Sample Capture Information
|
||||
- All captures have radiosonde signal at DC, or as close to DC as practicable.
|
||||
|
||||
- Captured using: rtl_sdr -f 402500400 -s 960k -g 49.6 -n 115200000 rs41_960k.bin
|
||||
- Converted to 96k float IQ using: cat rs41_960k.bin | csdr convert_u8_f | csdr fir_decimate_cc 10 0.005 HAMMING > rs41_96k_float.bin
|
||||
|
||||
|
||||
rs41_96k_float.bin - Vaisala RS41, Serial Number N3920808, 120 packets
|
||||
rs92_96k_float.bin - Vaisala RS92, Serial Number M2513116, 120 packets
|
||||
dfm09_96k_float.bin - Graw DFM09, Serial Number 637797, 96 Packets
|
||||
m10_96k_float.bin - Meteomodem M10, 120 packets
|
||||
imet4_96k_float.bin - iMet-4, Serial Number 15236, 119 packets
|
||||
|
||||
|
||||
# Older Notes
|
||||
|
||||
## Reading data into Python
|
||||
```
|
||||
import numpy as np
|
||||
data = np.fromfile('rs41_96k_float.bin', dtype='c8')
|
||||
```
|
||||
|
||||
|
||||
## Demodulation Examples
|
||||
To run these examples, you will need csdr available on the path, and will need the various radiosonde demodulators as built by auto_rx.
|
||||
Run the build.sh script in radiosonde_auto_rx/auto_rx to build these, then copy them to your working directory.
|
||||
|
||||
NOTE: These are not optimised. Have a look in the test_demod.py script for the 'optimal' demodulation commands.
|
||||
|
||||
### RS41
|
||||
|
||||
#### Using csdr as a FM demodulator:
|
||||
$ cat samples/rs41_96k_float.bin | csdr fir_decimate_cc 2 0.005 HAMMING | csdr bandpass_fir_fft_cc -0.18 0.18 0.05 | csdr fmdemod_quadri_cf | csdr limit_ff | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -b 8 -t wav - | ../rs41ecc --ecc --ptu --crc
|
||||
|
||||
|
||||
#### Using nanorx as a FM demodulator:
|
||||
NOTE - Nanorx seems to invert the FM output, hence the -i option on rs41ecc
|
||||
NOTE - As of v0.85, nanorx's FM demodulators are likely corrupting the RS41 signal
|
||||
|
||||
$ cat rs41_96k_float.bin | csdr convert_f_s16 | ./nanorx -i stdin -r 96k -m FM -t 10 -o - | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -b 8 -t wav - | ../rs41ecc --ecc --ptu --crc -i
|
||||
|
||||
|
||||
### RS92
|
||||
|
||||
#### Using csdr as a FM demodulator:
|
||||
$ cat rs92_96k_float.bin | csdr fir_decimate_cc 2 0.005 HAMMING | csdr bandpass_fir_fft_cc -0.18 0.18 0.05 | csdr fmdemod_quadri_cf | csdr limit_ff | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -b 8 -t wav - | ../rs92ecc
|
||||
|
||||
|
||||
### DFM09
|
||||
|
||||
#### Using csdr as a FM demodulator:
|
||||
$ cat dfm09_96k_float.bin | csdr fir_decimate_cc 2 0.005 HAMMING | csdr bandpass_fir_fft_cc -0.18 0.18 0.05 | csdr fmdemod_quadri_cf | csdr limit_ff | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -b 8 -t wav - | ../dfm09ecc --auto
|
||||
|
||||
|
||||
### iMet 4
|
||||
Note that the imet decoder isn't used in auto_rx yet. Build from the imet directory using:
|
||||
$ gcc imet1rs_dft.c -lm -o imet1rs_dft
|
||||
|
||||
#### Using csdr as a FM demodulator:
|
||||
$ cat imet4_96k_float.bin | csdr fir_decimate_cc 2 0.005 HAMMING | csdr bandpass_fir_fft_cc -0.18 0.18 0.05 | csdr fmdemod_quadri_cf | csdr limit_ff | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -b 8 -t wav - | ../imet1rs_dft
|
||||
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Generate Noisy Sonde Samples, with a calibrated Eb/No
|
||||
#
|
||||
# Run from ./scripts/ with
|
||||
# $ python generate_lowsnr.py
|
||||
#
|
||||
# The generated files will end up in the 'generated' directory.
|
||||
#
|
||||
# Mark Jessop 2019-02
|
||||
#
|
||||
import numpy as np
|
||||
import os
|
||||
|
||||
|
||||
# Where to find the samples files.
|
||||
# These are all expected to be 96khz float (dtype='c8') files.
|
||||
SAMPLE_DIR = "./samples"
|
||||
|
||||
# Directory to output generated files
|
||||
GENERATED_DIR = "./generated"
|
||||
|
||||
# Range of Eb/N0 SNRs to produce.
|
||||
# 10-20 dB seems to be the range where the demodulators fall over.
|
||||
EBNO_RANGE = np.arange(10,20,0.5)
|
||||
|
||||
|
||||
# List of samples
|
||||
# [filename, baud_date, threshold, sample_rate]
|
||||
# filename = string, without path
|
||||
# baud_rate = integer
|
||||
# threshold = threshold for calculating variance. Deterimined by taking 20*np.log10(np.abs(data)) and looking for packets.
|
||||
# sample_rate = input file sample rate.
|
||||
|
||||
SAMPLES = [
|
||||
['rs41_96k_float.bin', 4800, -25.0, 96000],
|
||||
['rs92_96k_float.bin', 2400, -100, 96000], # No threshold set, as signal is continuous.
|
||||
['dfm09_96k_float.bin', 2500, -100, 96000], # Weird baud rate. No threshold set, as signal is continuous.
|
||||
['m10_96k_float.bin', 9616, -18.0, 96000] # Really weird baud rate. WARNING - Samples output by this are a bit questionable at the moment.
|
||||
]
|
||||
|
||||
|
||||
|
||||
def load_sample(filename):
|
||||
_filename = os.path.join(SAMPLE_DIR, filename)
|
||||
return np.fromfile(_filename, dtype='c8')
|
||||
|
||||
|
||||
def save_sample(data, filename):
|
||||
_filename = os.path.join(GENERATED_DIR, filename)
|
||||
# We have to make sure to convert to complex64..
|
||||
data.astype(dtype='c8').tofile(_filename)
|
||||
|
||||
# TODO: Allow saving as complex s16 - see view solution here: https://stackoverflow.com/questions/47086134/how-to-convert-a-numpy-complex-array-to-a-two-element-float-array
|
||||
|
||||
|
||||
|
||||
def calculate_variance(data, threshold=-100.0):
|
||||
# Calculate the variance of a set of radiosonde samples.
|
||||
# Optionally use a threshold to limit the sample the variance
|
||||
# is calculated over to ones that actually have sonde packets in them.
|
||||
|
||||
_data_log = 20*np.log10(np.abs(data))
|
||||
|
||||
return np.var(data[_data_log>threshold])
|
||||
|
||||
|
||||
def add_noise(data, variance, baud_rate, ebno, fs=96000, bitspersymbol=1.0):
|
||||
# Add calibrated noise to a sample.
|
||||
|
||||
# Calculate Eb/No in linear units.
|
||||
_ebno = 10.0**(ebno/10.0)
|
||||
|
||||
# Calculate the noise variance we need to add
|
||||
_noise_variance = variance*fs/(baud_rate*_ebno*bitspersymbol)
|
||||
|
||||
# Generate complex random samples
|
||||
_rand_i = np.sqrt(_noise_variance/2.0)*np.random.randn(len(data))
|
||||
_rand_q = np.sqrt(_noise_variance/2.0)*np.random.randn(len(data))
|
||||
|
||||
return (data + (1j*_rand_i + _rand_q))
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
for _sample in SAMPLES:
|
||||
# Extract the stuff we need from the entry.
|
||||
_source = _sample[0]
|
||||
_baud_rate = _sample[1]
|
||||
_threshold = _sample[2]
|
||||
_fs = _sample[3]
|
||||
|
||||
print("Generating samples for: %s" % _source)
|
||||
|
||||
# Read in source file.
|
||||
_data = load_sample(_source)
|
||||
|
||||
# Calculate variance
|
||||
_var = calculate_variance(_data, _threshold)
|
||||
print("Calculated Variance: %.5f" % _var)
|
||||
|
||||
# Now loop through the ebno's and generate the output.
|
||||
for ebno in EBNO_RANGE:
|
||||
_data_noise = add_noise(_data, variance=_var, baud_rate=_baud_rate, ebno=ebno, fs=_fs)
|
||||
|
||||
_out_file = _source.split('.bin')[0] + "_%.1fdB"%ebno + ".bin"
|
||||
|
||||
save_sample(_data_noise, _out_file)
|
||||
print("Saved file: %s" % _out_file)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
# Run a set of files through a processing and decode chain, and handle the output.
|
||||
#
|
||||
# Mark Jessop 2019-02
|
||||
#
|
||||
# Refer to the README.md in this directory for instructions on use.
|
||||
#
|
||||
import glob
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import subprocess
|
||||
|
||||
|
||||
# Dictionary of available processing types.
|
||||
|
||||
processing_type = {
|
||||
# RS41 Decoding
|
||||
'rs41_csdr_fm_decode': {
|
||||
# Decode a RS41 using a CSDR processing chain to do FM demodulation
|
||||
# Decimate to 48 khz, filter, then demodulate.
|
||||
#'demod' : "| csdr fir_decimate_cc 2 0.005 HAMMING 2>/dev/null | csdr bandpass_fir_fft_cc -0.18 0.18 0.05 2>/dev/null | csdr fmdemod_quadri_cf | csdr limit_ff | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -b 8 -t wav - 2>/dev/null| ",
|
||||
# Decimate to a 24 kHz channel, demod, then interpolate back up to 48 kHz.
|
||||
#'demod' : "| csdr fir_decimate_cc 4 0.005 HAMMING 2>/dev/null | csdr fmdemod_quadri_cf | csdr limit_ff | csdr rational_resampler_ff 2 1 0.005 HAMMING | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -b 8 -t wav - 2>/dev/null| ",
|
||||
# Decimate to a 12 khz channel, demod, then interpolate back up to 48 kHz. - WORKS BEST
|
||||
'demod' : "| csdr fir_decimate_cc 8 0.005 HAMMING 2>/dev/null | csdr fmdemod_quadri_cf | csdr limit_ff | csdr rational_resampler_ff 4 1 0.005 HAMMING | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -b 8 -t wav - 2>/dev/null| ",
|
||||
# Decode using rs41ecc
|
||||
'decode': "../rs41ecc --ecc --ptu --crc 2>/dev/null",
|
||||
# Count the number of telemetry lines.
|
||||
"post_process" : " | grep N3920808 | wc -l"
|
||||
},
|
||||
# RS92 Decoding
|
||||
'rs92_csdr_fm_decode': {
|
||||
# Decode a RS92 using a CSDR processing chain to do FM demodulation
|
||||
# Decimate to 48 khz, filter to +/-4.8kHz, then demodulate. - WORKS BEST
|
||||
'demod' : "| csdr fir_decimate_cc 2 0.005 HAMMING 2>/dev/null | csdr bandpass_fir_fft_cc -0.10 0.10 0.05 2>/dev/null | csdr fmdemod_quadri_cf | csdr limit_ff | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -b 8 -t wav - 2>/dev/null| ",
|
||||
# Decimate to a 24 kHz channel, demod, then interpolate back up to 48 kHz.
|
||||
#'demod' : "| csdr fir_decimate_cc 4 0.005 HAMMING 2>/dev/null | csdr fmdemod_quadri_cf | csdr limit_ff | csdr rational_resampler_ff 2 1 0.005 HAMMING | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -b 8 -t wav - 2>/dev/null| ",
|
||||
# Decimate to a 12 khz channel, demod, then interpolate back up to 48 kHz.
|
||||
#'demod' : "| csdr fir_decimate_cc 8 0.005 HAMMING 2>/dev/null | csdr fmdemod_quadri_cf | csdr limit_ff | csdr rational_resampler_ff 4 1 0.005 HAMMING | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -b 8 -t wav - 2>/dev/null| ",
|
||||
# Decode using rs41ecc
|
||||
'decode': "../rs92ecc -vx -v --crc --ecc --vel 2>/dev/null",
|
||||
# Count the number of telemetry lines.
|
||||
"post_process" : " | grep M2513116 | wc -l"
|
||||
},
|
||||
# DFM Decoding
|
||||
'dfm_csdr_fm_decode': {
|
||||
# Decode a DFM using a CSDR processing chain to do FM demodulation
|
||||
# Decimate to 48 khz, filter to +/-6kHz, then demodulate.
|
||||
#'demod' : "| csdr fir_decimate_cc 2 0.005 HAMMING 2>/dev/null | csdr bandpass_fir_fft_cc -0.12 0.12 0.05 2>/dev/null | csdr fmdemod_quadri_cf | csdr limit_ff | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -b 8 -t wav - 2>/dev/null| ",
|
||||
# Decimate to a 24 kHz channel, demod, then interpolate back up to 48 kHz.
|
||||
#'demod' : "| csdr fir_decimate_cc 4 0.005 HAMMING 2>/dev/null | csdr fmdemod_quadri_cf | csdr limit_ff | csdr rational_resampler_ff 2 1 0.005 HAMMING | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -b 8 -t wav - 2>/dev/null| ",
|
||||
# Decimate to a 12 khz channel, demod, then interpolate back up to 48 kHz. - WORKS BEST
|
||||
'demod' : "| csdr fir_decimate_cc 8 0.005 HAMMING 2>/dev/null | csdr fmdemod_quadri_cf | csdr limit_ff | csdr rational_resampler_ff 4 1 0.005 HAMMING | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -b 8 -t wav - 2>/dev/null| ",
|
||||
# Decode using rs41ecc
|
||||
'decode': "../dfm09ecc -vv --ecc --json --dist --auto 2>/dev/null",
|
||||
# Count the number of telemetry lines.
|
||||
"post_process" : " | grep frame | wc -l"
|
||||
},
|
||||
# M10 Radiosonde decoding.
|
||||
'm10_csdr_fm_decode': {
|
||||
# M10 Decoding
|
||||
# Use a CSDR processing chain to do FM demodulation
|
||||
# Decimate to 48 khz, filter, then demodulate. - WORKS BEST
|
||||
'demod' : "| csdr fir_decimate_cc 2 0.005 HAMMING 2>/dev/null | csdr bandpass_fir_fft_cc -0.23 0.23 0.05 2>/dev/null | csdr fmdemod_quadri_cf | csdr limit_ff | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -b 8 -t wav - 2>/dev/null| ",
|
||||
# Decimate to a 24 kHz channel, demod, then interpolate back up to 48 kHz.
|
||||
#'demod' : "| csdr fir_decimate_cc 4 0.005 HAMMING 2>/dev/null | csdr fmdemod_quadri_cf | csdr limit_ff | csdr rational_resampler_ff 2 1 0.005 HAMMING | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -b 8 -t wav - 2>/dev/null| ",
|
||||
# Decode using rs41ecc
|
||||
'decode': "../m10 -b -b2 2>/dev/null",
|
||||
# Count the number of telemetry lines.
|
||||
"post_process" : "| wc -l"
|
||||
},
|
||||
# rs_detect - Sonde Detection.
|
||||
# Current approach in auto_rx uses rtl_fm with a 22 khz sample rate (channel bw?) setting,
|
||||
# then resamples up to 48 khz sampes to feed into rs_detect.
|
||||
#
|
||||
'csdr_fm_rsdetect': {
|
||||
# Use a CSDR processing chain to do FM demodulation
|
||||
# Using a ~22kHz wide filter, and 20 Hz high-pass
|
||||
# Decimate to 48 khz, filter to ~22 kHz BW, then demod.
|
||||
# rs_detect seem to like this better than the decimation approach.
|
||||
#'demod' : "| csdr fir_decimate_cc 2 0.005 HAMMING 2>/dev/null | csdr bandpass_fir_fft_cc -0.23 0.23 0.05 2>/dev/null | csdr fmdemod_quadri_cf | csdr limit_ff | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -t wav - highpass 20 2>/dev/null| ",
|
||||
# Decimate to 24 khz before passing into the FM demod. This is roughly equivalent to rtl_fm -r 22k
|
||||
'demod' : "| csdr fir_decimate_cc 4 0.005 HAMMING 2>/dev/null | csdr fmdemod_quadri_cf | csdr limit_ff | csdr rational_resampler_ff 2 1 0.005 HAMMING | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -t wav - highpass 20 2>/dev/null| ",
|
||||
# Decode using rs41ecc
|
||||
'decode': "../rs_detect -z -t 8 2> /dev/null",
|
||||
# Grep out the line containing the detected sonde type.
|
||||
"post_process" : " | grep found"
|
||||
},
|
||||
# dft_detect - Sonde detection using DFT correlation
|
||||
#
|
||||
'csdr_fm_dftdetect': {
|
||||
# Use a CSDR processing chain to do FM demodulation
|
||||
# Filter to 22 khz channel bandwidth, then demodulate.
|
||||
#'demod' : "| csdr fir_decimate_cc 2 0.005 HAMMING 2>/dev/null | csdr bandpass_fir_fft_cc -0.23 0.23 0.05 2>/dev/null | csdr fmdemod_quadri_cf | csdr limit_ff | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -t wav - 2>/dev/null| ",
|
||||
# Decimate to a 24 kHz bandwidth, demodulator, then interpolate back up to 48 kHz.
|
||||
'demod' : "| csdr fir_decimate_cc 4 0.005 HAMMING 2>/dev/null | csdr fmdemod_quadri_cf | csdr limit_ff | csdr rational_resampler_ff 2 1 0.005 HAMMING | csdr convert_f_s16 | sox -t raw -r 48k -e signed-integer -b 16 -c 1 - -r 48000 -t wav - highpass 20 2>/dev/null| ",
|
||||
# Decode using rs41ecc
|
||||
'decode': "../dft_detect 2>/dev/null",
|
||||
# Grep out the line containing the detected sonde type.
|
||||
"post_process" : " | grep \:"
|
||||
},
|
||||
# RS41 Decoding
|
||||
'rs41_fsk_demod': {
|
||||
# Shift up to ~24 khz, and then pass into fsk_demod.
|
||||
'demod' : "| csdr shift_addition_cc 0.25 2>/dev/null | csdr convert_f_s16 | ../bin/fsk_demod --cs16 -b 1 -u 45000 2 96000 4800 - - 2>/dev/null | python ../bin/bit_to_samples.py 48000 4800 | sox -t raw -r 48k -e unsigned-integer -b 8 -c 1 - -r 48000 -b 8 -t wav - 2>/dev/null| ",
|
||||
|
||||
# Decode using rs41ecc
|
||||
'decode': "../rs41ecc --ecc --ptu --crc 2>/dev/null",
|
||||
# Count the number of telemetry lines.
|
||||
"post_process" : " | grep N3920808 | wc -l"
|
||||
},
|
||||
# RS92 Decoding
|
||||
'rs92_fsk_demod': {
|
||||
# Not currently working - need to resolve segfault in dfk_demod when using 96 kHz Fs ans 2400 Rb
|
||||
# Shift up to ~24 khz, and then pass into fsk_demod.
|
||||
'demod' : "| csdr shift_addition_cc 0.25 2>/dev/null | csdr convert_f_s16 | ../bin/fsk_demod --cs16 -b 1 -u 45000 2 96000 2400 - - 2>/dev/null | python ../bin/bit_to_samples.py 48000 2400 | sox -t raw -r 48k -e unsigned-integer -b 8 -c 1 - -r 48000 -b 8 -t wav - 2>/dev/null| ",
|
||||
|
||||
# Decode using rs41ecc
|
||||
'decode': ".../rs92ecc -vx -v --crc --ecc --vel 2>/dev/null",
|
||||
# Count the number of telemetry lines.
|
||||
"post_process" : " | grep M2513116 | wc -l"
|
||||
},
|
||||
'm10_fsk_demod': {
|
||||
# Not currently working due to weird baud rate (9614). Doesnt work even with fractional resampling (slow down signal to make it appear to be 9600 baud).
|
||||
# Shift up to ~24 khz, and then pass into fsk_demod.
|
||||
'demod' : "| csdr shift_addition_cc 0.25 2>/dev/null | csdr convert_f_s16 | ../bin/tsrc - - 0.99854 -c | ../bin/fsk_demod --cs16 -b 1 -u 45000 2 96000 9600 - - 2>/dev/null | python ../bin/bit_to_samples.py 48000 9600 | sox -t raw -r 48k -e unsigned-integer -b 8 -c 1 - -r 48000 -b 8 -t wav - 2>/dev/null| ",
|
||||
'decode': "../m10 -b -b2 2>/dev/null",
|
||||
# Count the number of telemetry lines.
|
||||
"post_process" : "| wc -l"
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
||||
def run_analysis(mode, file_list, shift=0.0):
|
||||
|
||||
_mode = processing_type[mode]
|
||||
|
||||
_first = True
|
||||
|
||||
# Calculate the frequency offset to apply, if defined.
|
||||
_shiftcmd = "| csdr shift_addition_cc %.5f 2>/dev/null" % (shift/96000.0)
|
||||
|
||||
# Iterate over the files in the supplied list.
|
||||
for _file in file_list:
|
||||
|
||||
# Generate the command to run.
|
||||
_cmd = "cat %s "%_file
|
||||
|
||||
# Add in an optional frequency error if supplied.
|
||||
if shift != 0.0:
|
||||
_cmd += _shiftcmd
|
||||
|
||||
# Add on the rest of the demodulation and decoding commands.
|
||||
_cmd += _mode['demod'] + _mode['decode'] + _mode['post_process']
|
||||
|
||||
|
||||
if _first:
|
||||
print("Command: %s" % _cmd)
|
||||
_first = False
|
||||
|
||||
# Run the command.
|
||||
try:
|
||||
_output = subprocess.check_output(_cmd, shell=True, stderr=None)
|
||||
except:
|
||||
_output = "error"
|
||||
|
||||
print("%s, %s" % (os.path.basename(_file), _output.strip()))
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-m", "--mode", type=str, default="rs41_csdr_fm_decode", help="Operation mode.")
|
||||
parser.add_argument("-f", "--files", type=str, default="./generated/*.bin", help="Glob-path to files to run over.")
|
||||
parser.add_argument("--shift", type=float, default=0.0, help="Shift the signal-under test by x Hz. Default is 0.")
|
||||
args = parser.parse_args()
|
||||
|
||||
# Check the mode is valid.
|
||||
if args.mode not in processing_type:
|
||||
print("Error - invalid operating mode.")
|
||||
print("Valid Modes: %s" % str(processing_type.keys()))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
# Get the list of files.
|
||||
_file_list = glob.glob(args.files)
|
||||
if len(_file_list) == 0:
|
||||
print("No files found matching supplied path.")
|
||||
sys.exit(1)
|
||||
|
||||
# Sort the list of files.
|
||||
_file_list.sort()
|
||||
|
||||
run_analysis(args.mode, _file_list, shift=args.shift)
|
Ładowanie…
Reference in New Issue