Rebase RS decoders, switch to soft-decision demodulation.

pull/277/head
Mark Jessop 2020-06-20 14:05:13 +09:30
rodzic b664553d96
commit 9b66012fdb
15 zmienionych plików z 1082 dodań i 1889 usunięć

Wyświetl plik

@ -17,7 +17,7 @@ except ImportError:
# MINOR - New sonde type support, other fairly big changes that may result in telemetry or config file incompatability issus.
# PATCH - Small changes, or minor feature additions.
__version__ = "1.3.2-beta2"
__version__ = "1.3.2-beta3"
# Global Variables

Wyświetl plik

@ -465,9 +465,9 @@ class SondeDecoder(object):
if self.save_decode_iq:
demod_cmd += " tee decode_IQ_%s.bin |" % str(self.device_idx)
demod_cmd += "./fsk_demod --cs16 -b %d -u %d --stats=%d 2 %d %d - -" % (_lower, _upper, _stats_rate, _sdr_rate, _baud_rate)
demod_cmd += "./fsk_demod --cs16 -b %d -u %d -s --stats=%d 2 %d %d - -" % (_lower, _upper, _stats_rate, _sdr_rate, _baud_rate)
decode_cmd = "./rs41mod --ptu --json --bin 2>/dev/null"
decode_cmd = "./rs41mod --ptu --json --softin -i 2>/dev/null"
# RS41s transmit pulsed beacons - average over the last 2 frames, and use a peak-hold
demod_stats = FSKDemodStats(averaging_time=2.0, peak_hold=True)
@ -520,15 +520,9 @@ class SondeDecoder(object):
if self.save_decode_iq:
demod_cmd += " tee decode_IQ_%s.bin |" % str(self.device_idx)
demod_cmd += "./fsk_demod --cs16 -b %d -u %d --stats=%d 2 %d %d - -" % (_lower, _upper, _stats_rate, _sdr_rate, _baud_rate)
demod_cmd += "./fsk_demod --cs16 -b %d -u %d -s --stats=%d 2 %d %d - -" % (_lower, _upper, _stats_rate, _sdr_rate, _baud_rate)
decode_cmd = " python ./test/bit_to_samples.py %d %d | sox -t raw -r %d -e unsigned-integer -b 8 -c 1 - -r %d -b 8 -t wav - 2>/dev/null|" % (_output_rate, _baud_rate, _output_rate, _output_rate)
# Add in tee command to save audio to disk if debugging is enabled.
if self.save_decode_audio:
decode_cmd += " tee decode_%s.wav |" % str(self.device_idx)
decode_cmd += "./rs92mod -vx -v --crc --ecc --vel --json %s 2>/dev/null" % _rs92_gps_data
decode_cmd = "./rs92mod -vx -v --crc --ecc --vel --json --softin -i %s 2>/dev/null" % _rs92_gps_data
# RS92s transmit continuously - average over the last 2 frames, and use a mean
demod_stats = FSKDemodStats(averaging_time=2.0, peak_hold=False)
@ -550,15 +544,10 @@ class SondeDecoder(object):
if self.save_decode_iq:
demod_cmd += " tee decode_IQ_%s.bin |" % str(self.device_idx)
demod_cmd += "./fsk_demod --cs16 -b %d -u %d --stats=%d 2 %d %d - -" % (_lower, _upper, _stats_rate, _sdr_rate, _baud_rate)
decode_cmd = ""
# Add in tee command to save audio to disk if debugging is enabled.
if self.save_decode_audio:
decode_cmd += " tee decode_%s.wav |" % str(self.device_idx)
demod_cmd += "./fsk_demod --cs16 -b %d -u %d -s --stats=%d 2 %d %d - -" % (_lower, _upper, _stats_rate, _sdr_rate, _baud_rate)
# DFM decoder
decode_cmd += "./dfm09mod -vv --ecc --json --dist --auto --bin 2>/dev/null"
decode_cmd = "./dfm09mod -vv --ecc --json --dist --auto --softin -i 2>/dev/null"
# DFM sondes transmit continuously - average over the last 2 frames, and use a mean
demod_stats = FSKDemodStats(averaging_time=1.0, peak_hold=False)
@ -581,16 +570,10 @@ class SondeDecoder(object):
if self.save_decode_iq:
demod_cmd += " tee decode_IQ_%s.bin |" % str(self.device_idx)
demod_cmd += "./fsk_demod --cs16 -b %d -u %d --stats=%d 2 %d %d - -" % (_lower, _upper, _stats_rate, _sdr_rate, _baud_rate)
decode_cmd = " python ./test/bit_to_samples.py %d %d | sox -t raw -r %d -e unsigned-integer -b 8 -c 1 - -r %d -b 8 -t wav - 2>/dev/null| " % (_sdr_rate, _baud_rate, _sdr_rate, _sdr_rate)
# Add in tee command to save audio to disk if debugging is enabled.
if self.save_decode_audio:
decode_cmd += " tee decode_%s.wav |" % str(self.device_idx)
demod_cmd += "./fsk_demod --cs16 -b %d -u %d -s -p 5 --stats=%d 2 %d %d - -" % (_lower, _upper, _stats_rate, _sdr_rate, _baud_rate)
# M10 decoder
decode_cmd += "./m10mod --json --ptu -vvv 2>/dev/null"
decode_cmd = "./m10mod --json --ptu -vvv --softin -i 2>/dev/null"
# M10 sondes transmit in short, irregular pulses - average over the last 2 frames, and use a peak hold
demod_stats = FSKDemodStats(averaging_time=2.0, peak_hold=True)
@ -611,15 +594,9 @@ class SondeDecoder(object):
if self.save_decode_iq:
demod_cmd += " tee decode_IQ_%s.bin |" % str(self.device_idx)
demod_cmd += "./fsk_demod --cs16 -b %d -u %d --stats=%d 2 %d %d - -" % (_lower, _upper, _stats_rate, _sdr_rate, _baud_rate)
decode_cmd = " python ./test/bit_to_samples.py %d %d | sox -t raw -r %d -e unsigned-integer -b 8 -c 1 - -r %d -b 8 -t wav - 2>/dev/null|" % (_output_rate, _baud_rate, _output_rate, _output_rate)
# Add in tee command to save audio to disk if debugging is enabled.
if self.save_decode_audio:
decode_cmd += " tee decode_%s.wav |" % str(self.device_idx)
demod_cmd += "./fsk_demod --cs16 -b %d -u %d -s --stats=%d 2 %d %d - -" % (_lower, _upper, _stats_rate, _sdr_rate, _baud_rate)
decode_cmd += "./lms6Xmod --json 2>/dev/null"
decode_cmd = "./lms6Xmod --json --softin -i 2>/dev/null"
# LMS sondes transmit continuously - average over the last 2 frames, and use a mean
demod_stats = FSKDemodStats(averaging_time=2.0, peak_hold=False)

Wyświetl plik

@ -28,11 +28,13 @@ CSV_DIR = "./results/"
# 'M10': {'csv':'m10_rtlfm.txt', 'packets': 120, 'color': 'C3'},
# }
sonde_types = {
'RS41': {'csv':'rs41_fsk_demod.txt', 'packets': 120, 'color': 'C0'},
'RS92': {'csv':'rs92_fsk_demod.txt', 'packets': 120, 'color': 'C1'},
'DFM09': {'csv':'dfm_fsk_demod.txt', 'packets': 96, 'color': 'C2'},
'M10': {'csv':'m10_fsk_demod.txt', 'packets': 120, 'color': 'C3'},
'RS41': {'csv':'rs41_fsk_demod_soft.txt', 'packets': 118, 'color': 'C0'},
'RS92': {'csv':'rs92_fsk_demod_soft.txt', 'packets': 120, 'color': 'C1'},
'DFM09': {'csv':'dfm_fsk_demod_soft.txt', 'packets': 96, 'color': 'C2'},
'M10': {'csv':'m10_fsk_demod_soft.txt', 'packets': 120, 'color': 'C3'},
'LMS6-400': {'csv':'lms6-400_fsk_demod_soft.txt', 'packets': 120, 'color': 'C4'},
}
@ -60,7 +62,7 @@ def read_csv(filename):
# Sort list of sonde types.
_types = sonde_types.keys()
_types = list(sonde_types.keys())
_types.sort()
@ -80,5 +82,5 @@ plt.legend()
plt.grid()
plt.ylabel("Packet Error Rate")
plt.xlabel("Eb/No (dB)")
plt.title("auto_rx Decode Chain Performance - fsk_demod test 1")
plt.title("auto_rx Decode Chain Performance - fsk_demod")
plt.show()

Wyświetl plik

@ -142,7 +142,7 @@ processing_type = {
},
'm10_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 | ../tsrc - - 1.0016666 -c | ../fsk_demod --cs16 -b 1 -u 45000 --stats=5 2 96160 9616 - - 2>stats.txt | python ./bit_to_samples.py 57696 9616 | sox -t raw -r 57696 -e unsigned-integer -b 8 -c 1 - -r 57696 -b 8 -t wav - 2>/dev/null| ",
'demod' : "| csdr shift_addition_cc 0.125 2>/dev/null | csdr convert_f_s16 | ../tsrc - - 0.50083333333 -c | ../fsk_demod --cs16 -b 1 -u 45000 -p 5 --stats=5 2 48080 9616 - - 2>stats.txt | python ./bit_to_samples.py 57696 9616 | sox -t raw -r 57696 -e unsigned-integer -b 8 -c 1 - -r 57696 -b 8 -t wav - 2>/dev/null| ",
'decode': "tee test.wav | ../m10mod --json -vvv 2>/dev/null",
# Count the number of telemetry lines.
"post_process" : "| grep aprsid | wc -l",
@ -188,77 +188,59 @@ processing_type = {
# No low-SNR samples for this sonde available yet.
'files' : "./generated/lms6-1680*"
},
## Tests for the updated fsk_demod (2020-06)
'rs41_fsk_demod_new': {
'rs41_fsk_demod_soft': {
# Shift up to ~24 khz, and then pass into fsk_demod.
'demod' : "| csdr shift_addition_cc 0.125 2>/dev/null | csdr convert_f_s16 | ./tsrc - - 0.500 | ../fsk_demod --cs16 -b 1 -u 24000 --stats=5 2 48000 4800 - - 2>stats.txt |",
'demod' : "| csdr shift_addition_cc 0.125 2>/dev/null | csdr convert_f_s16 | ./tsrc - - 0.500 | ../fsk_demod --cs16 -b 1 -u 24000 -s --stats=5 2 48000 4800 - - 2>stats.txt |",
# Decode using rs41ecc
'decode': "../rs41mod --ecc --ptu --crc --bin --json 2>/dev/null",
'decode': "../rs41mod --ecc --ptu --crc --softin -i --json 2>/dev/null",
# Count the number of telemetry lines.
"post_process" : " | grep frame | wc -l",
'files' : "./generated/rs41*"
},
# # RS92 Decoding
'rs92_fsk_demod_new': {
'rs92_fsk_demod_soft': {
# 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 | ../fsk_demod --cs16 -b 1 -u 45000 --stats=5 2 96000 4800 - - 2>stats.txt | python ./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|",
'demod' : "| csdr shift_addition_cc 0.25 2>/dev/null | csdr convert_f_s16 | ../fsk_demod --cs16 -b 1 -u 45000 -s --stats=5 2 96000 4800 - - 2>stats.txt |",
# Decode using rs41ecc
'decode': "../rs92mod -vx -v --crc --ecc --vel 2>/dev/null",
'decode': "../rs92mod -vx -v --crc --ecc --vel --softin -i 2>/dev/null",
# Count the number of telemetry lines.
"post_process" : " | grep M2513116 | wc -l",
'files' : "./generated/rs92*"
},
'm10_fsk_demod_new': {
'm10_fsk_demod_soft': {
# 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 | ../tsrc - - 1.0016666 -c | ../fsk_demod --cs16 -b 1 -u 45000 --stats=5 2 96160 9616 - - 2>stats.txt | python ./bit_to_samples.py 57696 9616 | sox -t raw -r 57696 -e unsigned-integer -b 8 -c 1 - -r 57696 -b 8 -t wav - 2>/dev/null| ",
'decode': "tee test.wav | ../m10mod --json -vvv 2>/dev/null",
'demod' : "| csdr shift_addition_cc 0.125 2>/dev/null | csdr convert_f_s16 | ../tsrc - - 0.50083333333 -c | ../fsk_demod --cs16 -b 1 -p 5 -u 23000 -s --stats=5 2 48080 9616 - - 2>stats.txt |",
'decode': "../m10mod --json --softin -i -vvv 2>/dev/null",
# Count the number of telemetry lines.
"post_process" : "| grep aprsid | wc -l",
'files' : "./generated/m10*"
},
'dfm_fsk_demod_new': {
'dfm_fsk_demod_soft': {
# cat ./generated/dfm09_96k_float_15.0dB.bin | csdr shift_addition_cc 0.25000 2>/dev/null | csdr convert_f_s16 |
#./tsrc - - 1.041666 | ../fsk_demod --cs16 -b 1 -u 45000 2 100000 2500 - - 2>/dev/null |
#python ./bit_to_samples.py 50000 2500 | sox -t raw -r 50k -e unsigned-integer -b 8 -c 1 - -r 50000 -b 8 -t wav - 2>/dev/null|
#../dfm09ecc -vv --json --dist --auto
'demod': '| csdr shift_addition_cc 0.125000 2>/dev/null | csdr convert_f_s16 | ../tsrc - - 0.5208| ../fsk_demod --cs16 -b 1250 -u 23750 --stats=5 2 50000 2500 - - 2>stats.txt |',#' python ./bit_to_samples.py 50000 2500 | sox -t raw -r 50k -e unsigned-integer -b 8 -c 1 - -r 50000 -b 8 -t wav - 2>/dev/null| ',
'decode': '../dfm09mod -vv --json --dist --auto --bin 2>/dev/null',
'demod': '| csdr shift_addition_cc 0.125000 2>/dev/null | csdr convert_f_s16 | ../tsrc - - 0.5208| ../fsk_demod --cs16 -b 1250 -u 23750 -s --stats=5 2 50000 2500 - - 2>stats.txt |',#' python ./bit_to_samples.py 50000 2500 | sox -t raw -r 50k -e unsigned-integer -b 8 -c 1 - -r 50000 -b 8 -t wav - 2>/dev/null| ',
'decode': '../dfm09mod -vv --json --dist --auto --softin -i 2>/dev/null',
"post_process" : " | grep frame | wc -l", # ECC
#"post_process" : "| grep -o '\[OK\]' | wc -l", # No ECC
'files' : "./generated/dfm*.bin"
},
# LMS6-400 Decoding
'lms6-400_fsk_demod_new': {
'lms6-400_fsk_demod_soft': {
# 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 | ../fsk_demod --cs16 -b 1 -u 45000 --stats=5 2 96000 4800 - - 2>stats.txt | python ./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|",
'demod' : "| csdr shift_addition_cc 0.25 2>/dev/null | csdr convert_f_s16 | ../fsk_demod --cs16 -b 1 -u 45000 -s --stats=5 2 96000 4800 - - 2>stats.txt |",
# Decode using rs41ecc
'decode': "../lms6Xmod --json 2>/dev/null",
'decode': "../lms6Xmod --json --softin -i 2>/dev/null",
# Count the number of telemetry lines.
"post_process" : "| grep frame | wc -l",
'files' : "./generated/lms6-400*",
},
'lms6-1680_fsk_demod_new': {
# This is a weird one.
# The baud rate is ~9616 Baud, but the deviation is *huge* (~170 kHz occupied bandwidth).
# The recording bandwidth needs to be correspondingly huge, with ~480 kHz sample rate required to capture the signal.
# We need to resample up to a multiple of 9616 Hz to be able to get fsk_demod to decode.
# fsk_demod does not decode these types reliably at the moment.
'demod' : "| csdr shift_addition_cc 0.25 2>/dev/null | csdr convert_f_s16 | ./tsrc - - 1.00166666 | ../fsk_demod --cs16 -b 5000 -u 230000 --stats=5 2 480800 9616 - - 2>stats.txt | python ./bit_to_samples.py 57696 9616 | sox -t raw -r 57696 -e unsigned-integer -b 8 -c 1 - -r 57696 -b 8 -t wav - 2>/dev/null|",
# Decode using rs41ecc
'decode': "../mk2a_lms1680 -i --json 2>/dev/null",
# Count the number of telemetry lines.
"post_process" : " | grep frame | wc -l",
# No low-SNR samples for this sonde available yet.
'files' : "./generated/lms6-1680*"
},
}
@ -721,7 +703,7 @@ if __name__ == "__main__":
sys.exit(1)
batch_modes = ['dfm_fsk_demod', 'rs41_fsk_demod', 'm10_fsk_demod', 'rs92_fsk_demod', 'lms6-400_fsk_demod', 'imet4_rtlfm']
batch_modes = ['dfm_fsk_demod_soft', 'rs41_fsk_demod_soft', 'm10_fsk_demod_soft', 'rs92_fsk_demod_soft', 'lms6-400_fsk_demod_soft']#, 'imet4_rtlfm']
if args.batch:
for _mode in batch_modes:

Wyświetl plik

@ -59,4 +59,9 @@ alternative decoders using cross-correlation for better header-synchronization
The difference between hard and soft viterbi becomes only apparent at lower SNR. The inner convolutional
code does most of the error correction. The concatenated outer Reed-Solomon code kicks in only at low SNR.
soft input:<br />
Option `--softin` expects float32 symbols as input, with `s>0` corresponding to `bit=1`.<br />
(remark/caution: often soft bits are defined as `bit=0 -> s=+1` and `bit=1 -> s=-1` such that the identity element `0`
for addition mod 2 corresponds to the identity element `+1` for multiplication.)

Wyświetl plik

@ -24,6 +24,8 @@
/* ------------------------------------------------------------------------------------ */
#ifndef EXT_FSK
static void raw_dft(dft_t *dft, float complex *Z) {
int s, l, l2, i, j, k;
float complex w1, w2, T;
@ -126,7 +128,7 @@ static int dft_window(dft_t *dft, int w) {
dft->win[n] = 0.5 * ( 1.0 - cos(2*M_PI*n/(float)(dft->N2-1)) );
break ;
case 2: // Hamming
dft->win[n] = 25/46.0 + (1.0 - 25/46.0)*cos(2*M_PI*n / (float)(dft->N2-1));
dft->win[n] = 25/46.0 - (1.0 - 25/46.0)*cos(2*M_PI*n / (float)(dft->N2-1));
break ;
case 3: // Blackmann
dft->win[n] = 7938/18608.0
@ -942,6 +944,96 @@ int read_softbit(dsp_t *dsp, hsbit_t *shb, int inv, int ofs, int pos, float l, i
return 0;
}
int read_softbit2p(dsp_t *dsp, hsbit_t *shb, int inv, int ofs, int pos, float l, int spike, hsbit_t *shb1) {
// symlen==2: manchester2 10->0,01->1: 2.bit
float sample, sample1;
float avg;
float ths = 0.5, scale = 0.27;
double sum = 0.0, sum1 = 0.0;
double mid;
//double l = 1.0;
double bg = pos*dsp->symlen*dsp->sps;
double dc = 0.0;
ui8_t bit = 0, bit1 = 0;
if (dsp->opt_dc && dsp->opt_iq < 2) dc = dsp->dc;
if (pos == 0) {
bg = 0;
dsp->sc = 0;
}
if (dsp->symlen == 2) {
mid = bg + (dsp->sps-1)/2.0;
bg += dsp->sps;
do {
if (dsp->buffered > 0) dsp->buffered -= 1;
else if (f32buf_sample(dsp, inv) == EOF) return EOF;
sample = dsp->bufs[(dsp->sample_out-dsp->buffered + ofs + dsp->M) % dsp->M];
sample1 = dsp->bufs[(dsp->sample_out-dsp->buffered + ofs-1 + dsp->M) % dsp->M];
if (spike && fabs(sample - avg) > ths) {
avg = 0.5*(dsp->bufs[(dsp->sample_out-dsp->buffered-1 + ofs + dsp->M) % dsp->M]
+dsp->bufs[(dsp->sample_out-dsp->buffered+1 + ofs + dsp->M) % dsp->M]);
sample = avg + scale*(sample - avg); // spikes
}
sample -= dc;
sample1 -= dc;
if (l < 0 || (mid-l < dsp->sc && dsp->sc < mid+l)) {
sum -= sample;
sum1 -= sample1;
}
dsp->sc++;
} while (dsp->sc < bg); // n < dsp->sps
}
mid = bg + (dsp->sps-1)/2.0;
bg += dsp->sps;
do {
if (dsp->buffered > 0) dsp->buffered -= 1;
else if (f32buf_sample(dsp, inv) == EOF) return EOF;
sample = dsp->bufs[(dsp->sample_out-dsp->buffered + ofs + dsp->M) % dsp->M];
sample1 = dsp->bufs[(dsp->sample_out-dsp->buffered + ofs-1 + dsp->M) % dsp->M];
if (spike && fabs(sample - avg) > ths) {
avg = 0.5*(dsp->bufs[(dsp->sample_out-dsp->buffered-1 + ofs + dsp->M) % dsp->M]
+dsp->bufs[(dsp->sample_out-dsp->buffered+1 + ofs + dsp->M) % dsp->M]);
sample = avg + scale*(sample - avg); // spikes
}
sample -= dc;
sample1 -= dc;
if (l < 0 || (mid-l < dsp->sc && dsp->sc < mid+l)) {
sum += sample;
sum1 += sample1;
}
dsp->sc++;
} while (dsp->sc < bg); // n < dsp->sps
if (sum >= 0) bit = 1;
else bit = 0;
shb->hb = bit;
shb->sb = (float)sum;
if (sum1 >= 0) bit1 = 1;
else bit1 = 0;
shb1->hb = bit1;
shb1->sb = (float)sum1;
return 0;
}
/* -------------------------------------------------------------------------- */
#define IF_SAMPLE_RATE 48000
@ -1275,12 +1367,6 @@ int free_buffers(dsp_t *dsp) {
/* ------------------------------------------------------------------------------------ */
ui32_t get_sample(dsp_t *dsp) {
return dsp->sample_out;
}
/* ------------------------------------------------------------------------------------ */
int find_header(dsp_t *dsp, float thres, int hdmax, int bitofs, int opt_dc) {
ui32_t k = 0;
@ -1345,3 +1431,145 @@ int find_header(dsp_t *dsp, float thres, int hdmax, int bitofs, int opt_dc) {
return EOF;
}
/* ------------------------------------------------------------------------------------ */
#else
// external FSK demod: read float32 soft symbols
float read_wav_header(pcm_t *pcm, FILE *fp) {}
int f32buf_sample(dsp_t *dsp, int inv) {}
int read_slbit(dsp_t *dsp, int *bit, int inv, int ofs, int pos, float l, int spike) {}
int read_softbit(dsp_t *dsp, hsbit_t *shb, int inv, int ofs, int pos, float l, int spike) {}
int read_softbit2p(dsp_t *dsp, hsbit_t *shb, int inv, int ofs, int pos, float l, int spike, hsbit_t *shb1) {}
int init_buffers(dsp_t *dsp) {}
int free_buffers(dsp_t *dsp) {}
int find_header(dsp_t *dsp, float thres, int hdmax, int bitofs, int opt_dc) {}
#endif
static float cmp_hdb(hdb_t *hdb) { // bit-errors?
int i, j;
int headlen = hdb->len;
int berrs1 = 0, berrs2 = 0;
i = 0;
j = hdb->bufpos;
while (i < headlen) {
if (j < 0) j = headlen-1;
if (hdb->buf[j] != hdb->hdr[headlen-1-i]) berrs1 += 1;
j--;
i++;
}
i = 0;
j = hdb->bufpos;
while (i < headlen) {
if (j < 0) j = headlen-1;
if ((hdb->buf[j]^0x01) != hdb->hdr[headlen-1-i]) berrs2 += 1;
j--;
i++;
}
if (berrs2 < berrs1) return (-headlen+berrs2)/(float)headlen;
else return ( headlen-berrs1)/(float)headlen;
return 0;
}
int find_binhead(FILE *fp, hdb_t *hdb, float *score) {
int bit;
int headlen = hdb->len;
float mv;
//*score = 0.0;
while ( (bit = fgetc(fp)) != EOF )
{
bit &= 1;
hdb->bufpos = (hdb->bufpos+1) % headlen;
hdb->buf[hdb->bufpos] = 0x30 | bit; // Ascii
mv = cmp_hdb(hdb);
if ( fabs(mv) > hdb->thb ) {
*score = mv;
return 1;
}
}
return EOF;
}
static float corr_softhdb(hdb_t *hdb) { // max score in window probably not needed
int i, j;
int headlen = hdb->len;
double sum = 0.0;
double normx = 0.0,
normy = 0.0;
float x, y;
i = 0;
j = hdb->bufpos + 1;
while (i < headlen) {
if (j >= headlen) j = 0;
x = hdb->sbuf[j];
y = 2.0*(hdb->hdr[i]&0x1) - 1.0;
sum += y * hdb->sbuf[j];
normx += x*x;
normy += y*y;
j++;
i++;
}
sum /= sqrt(normx*normy);
return sum;
}
int f32soft_read(FILE *fp, float *s) {
unsigned int word = 0;
short *b = (short*)&word;
float *f = (float*)&word;
int bps = 32;
if (fread( &word, bps/8, 1, fp) != 1) return EOF;
if (bps == 32) {
*s = *f;
}
else {
if (bps == 8) { *b -= 128; }
*s = *b/128.0;
if (bps == 16) { *s /= 256.0; }
}
return 0;
}
int find_softbinhead(FILE *fp, hdb_t *hdb, float *score) {
int headlen = hdb->len;
float sbit;
float mv;
//*score = 0.0;
while ( f32soft_read(fp, &sbit) != EOF )
{
hdb->bufpos = (hdb->bufpos+1) % headlen;
hdb->sbuf[hdb->bufpos] = sbit;
mv = corr_softhdb(hdb);
if ( fabs(mv) > hdb->ths ) {
*score = mv;
return 1;
}
}
return EOF;
}

Wyświetl plik

@ -144,16 +144,30 @@ typedef struct {
} hsbit_t;
typedef struct {
char *hdr;
char *buf;
float *sbuf;
int len;
int bufpos;
float thb;
float ths;
} hdb_t;
float read_wav_header(pcm_t *, FILE *);
int f32buf_sample(dsp_t *, int);
int read_slbit(dsp_t *, int*, int, int, int, float, int);
int read_softbit(dsp_t *, hsbit_t *, int, int, int, float, int );
int read_softbit(dsp_t *, hsbit_t *, int, int, int, float, int);
int read_softbit2p(dsp_t *dsp, hsbit_t *shb, int inv, int ofs, int pos, float l, int spike, hsbit_t *shb1);
int init_buffers(dsp_t *);
int free_buffers(dsp_t *);
ui32_t get_sample(dsp_t *);
int find_header(dsp_t *, float, int, int, int);
int f32soft_read(FILE *fp, float *s);
int find_binhead(FILE *fp, hdb_t *hdb, float *score);
int find_softbinhead(FILE *fp, hdb_t *hdb, float *score);

Wyświetl plik

@ -52,6 +52,12 @@ typedef struct {
ui32_t chX[2];
} sn_t;
typedef struct {
ui32_t prn; // SVs used (PRN)
float dMSL; // Alt_MSL - Alt_ellipsoid = -N = - geoid_height = ellipsoid - geoid
ui8_t nSV; // numSVs used
} gpsdat_t;
#define BITFRAME_LEN 280
typedef struct {
@ -74,6 +80,7 @@ typedef struct {
pcksts_t pck[9];
option_t option;
int ptu_out;
gpsdat_t gps;
} gpx_t;
@ -294,6 +301,9 @@ static int dat_out(gpx_t *gpx, ui8_t *dat_bits, int ec) {
}
}
// GPS data
// SiRF msg ID 41: Geodetic Navigation Data
if (fr_id == 0) {
//start = 0x1000;
frnr = bits2val(dat_bits+24, 8);
@ -301,7 +311,8 @@ static int dat_out(gpx_t *gpx, ui8_t *dat_bits, int ec) {
}
if (fr_id == 1) {
// 00..31: ? GPS-Sats in Sicht?
// 00..31: GPS-Sats in solution (bitmap)
gpx->gps.prn = bits2val(dat_bits, 32); // SV/PRN used
msek = bits2val(dat_bits+32, 16); // UTC (= GPS - 18sec ab 1.1.2017)
gpx->sek = msek/1000.0;
}
@ -328,6 +339,8 @@ static int dat_out(gpx_t *gpx, ui8_t *dat_bits, int ec) {
}
if (fr_id == 5) {
short dMSL = bits2val(dat_bits, 16);
gpx->gps.dMSL = dMSL/1e2;
}
if (fr_id == 6) { // sat data
@ -342,6 +355,7 @@ static int dat_out(gpx_t *gpx, ui8_t *dat_bits, int ec) {
gpx->tag = bits2val(dat_bits+16, 5);
gpx->std = bits2val(dat_bits+21, 5);
gpx->min = bits2val(dat_bits+26, 6);
gpx->gps.nSV = bits2val(dat_bits+32, 8);
}
ret = fr_id;
@ -733,6 +747,16 @@ static void print_gpx(gpx_t *gpx) {
}
printf("\n");
if (gpx->option.sat) {
printf(" ");
printf(" dMSL: %+.2f", gpx->gps.dMSL); // MSL = alt + gps.dMSL
printf(" sats: %d", gpx->gps.nSV);
printf(" (");
for (j = 0; j < 32; j++) { if ((gpx->gps.prn >> j)&1) printf(" %02d", j+1); }
printf(" )");
printf("\n");
}
if (gpx->option.jsn && jsonout)
{
// JSON Buffer to store sonde ID
@ -861,67 +885,6 @@ static int print_frame(gpx_t *gpx) {
/* -------------------------------------------------------------------------- */
// header bit buffer
typedef struct {
char *hdr;
char *buf;
char len;
int bufpos;
float ths;
} hdb_t;
static float cmp_hdb(hdb_t *hdb) { // bit-errors?
int i, j;
int headlen = hdb->len;
int berrs1 = 0, berrs2 = 0;
i = 0;
j = hdb->bufpos;
while (i < headlen) {
if (j < 0) j = headlen-1;
if (hdb->buf[j] != hdb->hdr[headlen-1-i]) berrs1 += 1;
j--;
i++;
}
i = 0;
j = hdb->bufpos;
while (i < headlen) {
if (j < 0) j = headlen-1;
if ((hdb->buf[j]^0x01) != hdb->hdr[headlen-1-i]) berrs2 += 1;
j--;
i++;
}
if (berrs2 < berrs1) return (-headlen+berrs2)/(float)headlen;
else return ( headlen-berrs1)/(float)headlen;
return 0;
}
static int find_binhead(FILE *fp, hdb_t *hdb, float *score) {
int bit;
int headlen = hdb->len;
float mv;
//*score = 0.0;
while ( (bit = fgetc(fp)) != EOF )
{
bit &= 1;
hdb->bufpos = (hdb->bufpos+1) % headlen;
hdb->buf[hdb->bufpos] = 0x30 | bit; // Ascii
mv = cmp_hdb(hdb);
if ( fabs(mv) > hdb->ths ) {
*score = mv;
return 1;
}
}
return EOF;
}
int main(int argc, char **argv) {
@ -937,6 +900,7 @@ int main(int argc, char **argv) {
int option_lp = 0;
int option_dc = 0;
int option_bin = 0;
int option_softin = 0;
int option_json = 0; // JSON blob output (for auto_rx)
int option_pcmraw = 0;
int wavloaded = 0;
@ -1018,12 +982,13 @@ int main(int argc, char **argv) {
else if ( (strcmp(*argv, "--spike") == 0) ) {
spike = 1;
}
else if ( (strcmp(*argv, "--auto") == 0) ) { option_auto = 1; }
else if (strcmp(*argv, "--bin") == 0) { option_bin = 1; } // bit/byte binary input
else if ( (strcmp(*argv, "--dist") == 0) ) { option_dist = 1; option_ecc = 1; }
else if ( (strcmp(*argv, "--json") == 0) ) { option_json = 1; option_ecc = 1; }
else if ( (strcmp(*argv, "--ch2") == 0) ) { sel_wavch = 1; } // right channel (default: 0=left)
else if ( (strcmp(*argv, "--ths") == 0) ) {
else if (strcmp(*argv, "--auto") == 0) { option_auto = 1; }
else if (strcmp(*argv, "--bin") == 0) { option_bin = 1; } // bit/byte binary input
else if (strcmp(*argv, "--softin") == 0) { option_softin = 1; } // float32 soft input
else if (strcmp(*argv, "--dist") == 0) { option_dist = 1; option_ecc = 1; }
else if (strcmp(*argv, "--json") == 0) { option_json = 1; option_ecc = 1; }
else if (strcmp(*argv, "--ch2") == 0) { sel_wavch = 1; } // right channel (default: 0=left)
else if (strcmp(*argv, "--ths") == 0) {
++argv;
if (*argv) {
thres = atof(*argv);
@ -1058,6 +1023,7 @@ int main(int argc, char **argv) {
option_min = 1;
}
else if (strcmp(*argv, "--dbg") == 0) { gpx.option.dbg = 1; }
else if (strcmp(*argv, "--sat") == 0) { gpx.option.sat = 1; }
else if (strcmp(*argv, "-") == 0) {
int sample_rate = 0, bits_sample = 0, channels = 0;
++argv;
@ -1122,11 +1088,17 @@ int main(int argc, char **argv) {
gpx.option.dst = option_dist;
gpx.option.jsn = option_json;
headerlen = strlen(dfm_rawheader);
if (!option_bin) {
#ifdef EXT_FSK
if (!option_bin && !option_softin) {
option_softin = 1;
fprintf(stderr, "reading float32 soft symbols\n");
}
#endif
if (!option_bin && !option_softin) {
if (option_iq == 0 && option_pcmraw) {
fclose(fp);
@ -1174,38 +1146,48 @@ int main(int argc, char **argv) {
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low\n");
}
k = init_buffers(&dsp);
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
}
bitofs += shift;
}
else {
if (option_bin && option_softin) option_bin = 0;
// init circular header bit buffer
hdb.hdr = dfm_rawheader;
hdb.len = strlen(dfm_rawheader);
hdb.ths = 1.0 - 2.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen // max 1.1 !!
hdb.thb = 1.0 - 2.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen // max 1.1 !!
hdb.bufpos = -1;
hdb.buf = calloc(hdb.len, sizeof(char));
if (hdb.buf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1;
}
hdb.ths = 0.7; // caution/test false positive
hdb.sbuf = calloc(hdb.len, sizeof(float));
if (hdb.sbuf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1;
}
}
k = init_buffers(&dsp);
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
};
bitofs += shift;
while ( 1 )
{
if (option_bin) { // aka find_binrawhead()
header_found = find_binhead(fp, &hdb, &_mv); // symbols or bits?
hdrcnt += nfrms;
}
else { // FM-audio:
else if (option_softin) {
header_found = find_softbinhead(fp, &hdb, &_mv);
hdrcnt += nfrms;
}
else { //2 (false positive) // FM-audio:
header_found = find_header(&dsp, thres, 2, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0
_mv = dsp.mv;
}
@ -1227,7 +1209,7 @@ int main(int argc, char **argv) {
frm = 0;
while ( frm < nfrms ) { // nfrms=1,2,4,8
if (option_bin) {
if (option_bin || option_softin) {
gpx._frmcnt = hdrcnt + frm;
}
else {
@ -1247,19 +1229,28 @@ int main(int argc, char **argv) {
hsbit.sb = 2*hsbit.hb - 1;
}
}
else if (option_softin) {
float s1 = 0.0;
float s2 = 0.0;
float s = 0.0;
bitQ = f32soft_read(fp, &s1);
if (bitQ != EOF) {
bitQ = f32soft_read(fp, &s2);
if (bitQ != EOF) {
s = s2-s1; // integrate both symbols // only 2nd Manchester symbol: s2
hsbit.sb = s;
hsbit.hb = (s>=0.0);
}
}
}
else {
if (option_iq >= 2) {
float bl = -1;
if (option_iq > 2) bl = 4.0;
bitQ = read_softbit(&dsp, &hsbit, 0, bitofs, bitpos, bl, 0);
}
else {
bitQ = read_softbit(&dsp, &hsbit, 0, bitofs, bitpos, -1, spike);
}
float bl = -1;
if (option_iq >= 2) spike = 0;
if (option_iq > 2) bl = 4.0;
bitQ = read_softbit(&dsp, &hsbit, 0, bitofs, bitpos, bl, spike); // symlen=2
// optional:
// normalize soft bit s_j by
// rhsbit.sb /= dsp._spb+1; // all samples in [-1,+1]
}
if ( bitQ == EOF ) { frm = nfrms; break; } // liest 2x EOF
@ -1285,12 +1276,12 @@ int main(int argc, char **argv) {
pos = headerlen;
}
if (!option_bin) free_buffers(&dsp);
if (!option_bin && !option_softin) free_buffers(&dsp);
else {
if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; }
}
fclose(fp);
return 0;

Wyświetl plik

@ -3,6 +3,10 @@
* LMS6
* (403 MHz)
*
* soft decision test:
* IQ-decoding: --vit2 (soft decision) better performance (low dB)
* FM-decoding: --vit1 (hard decision) better than --vit2
*
* sync header: correlation/matched filter
* files: lms6Xmod.c demod_mod.c demod_mod.h bch_ecc_mod.c bch_ecc_mod.h
* compile, either (a) or (b):
@ -16,7 +20,8 @@
*
* usage:
* ./lms6Xmod --vit --ecc <audio.wav>
* ( --vit recommended)
* ./lms6Xmod --vit2 --ecc --IQ 0.0 <iq_data.wav>
* ( --vit/--vit2 recommended)
* author: zilog80
*/
@ -116,12 +121,11 @@ typedef struct {
ui8_t bIn;
ui8_t codeIn;
ui8_t prevState; // 0..M=64
int w; // > 255 : if (w>250): w=250 ?
//float sw;
float w;
} states_t;
typedef struct {
char rawbits[RAWBITFRAME_LEN+OVERLAP*BITS*2 +8];
hsbit_t rawbits[RAWBITFRAME_LEN+OVERLAP*BITS*2 +8];
states_t state[RAWBITFRAME_LEN+OVERLAP +8][M];
states_t d[N];
} VIT_t;
@ -138,7 +142,7 @@ typedef struct {
double lat; double lon; double alt;
double vH; double vD; double vV;
double vE; double vN; double vU;
char blk_rawbits[RAWBITBLOCK_LEN+SYNC_LEN*BITS*2 +9];
hsbit_t blk_rawbits[RAWBITBLOCK_LEN+SYNC_LEN*BITS*2 +9];
ui8_t frame[FRM_LEN]; // = { 0x24, 0x54, 0x00, 0x00}; // dataheader
int frm_pos; // ecc_blk <-> frm_blk
int sf6;
@ -213,12 +217,16 @@ static int vit_initCodes(gpx_t *gpx) {
return 0;
}
static int vit_dist(int c, char *rc) {
return (((c>>1)^rc[0])&1) + ((c^rc[1])&1);
static float vit_dist2(int c, hsbit_t *rc) {
int c0 = 2*((c>>1) & 1)-1; // {0,1} -> {-1,+1}
int c1 = 2*(c & 1)-1;
float d2 = (c0-rc[0].sb)*(c0-rc[0].sb) + (c1-rc[1].sb)*(c1-rc[1].sb);
return d2;
}
static int vit_start(VIT_t *vit, char *rc) {
int t, m, j, c, d;
static int vit_start(VIT_t *vit, hsbit_t *rc) {
int t, m, j, c;
float d;
t = L-1;
m = M;
@ -236,7 +244,7 @@ static int vit_start(VIT_t *vit, char *rc) {
c = vit_code[j];
vit->state[t][j].bIn = j % 2;
vit->state[t][j].codeIn = c;
d = vit_dist( c, rc+2*(t-1) );
d = vit_dist2( c, rc+2*(t-1) );
vit->state[t][j].w = vit->state[t-1][vit->state[t][j].prevState].w + d;
}
m *= 2;
@ -245,7 +253,7 @@ static int vit_start(VIT_t *vit, char *rc) {
return t;
}
static int vit_next(VIT_t *vit, int t, char *rc) {
static int vit_next(VIT_t *vit, int t, hsbit_t *rc) {
int b, nstate;
int j, index;
@ -255,7 +263,7 @@ static int vit_next(VIT_t *vit, int t, char *rc) {
vit->d[nstate].bIn = b;
vit->d[nstate].codeIn = vit_code[nstate];
vit->d[nstate].prevState = j;
vit->d[nstate].w = vit->state[t][j].w + vit_dist( vit->d[nstate].codeIn, rc );
vit->d[nstate].w = vit->state[t][j].w + vit_dist2( vit->d[nstate].codeIn, rc );
}
}
@ -272,11 +280,11 @@ static int vit_next(VIT_t *vit, int t, char *rc) {
static int vit_path(VIT_t *vit, int j, int t) {
int c;
vit->rawbits[2*t] = '\0';
vit->rawbits[2*t].hb = '\0';
while (t > 0) {
c = vit->state[t][j].codeIn;
vit->rawbits[2*t -2] = 0x30 + ((c>>1) & 1);
vit->rawbits[2*t -1] = 0x30 + (c & 1);
vit->rawbits[2*t -2].hb = 0x30 + ((c>>1) & 1);
vit->rawbits[2*t -1].hb = 0x30 + (c & 1);
j = vit->state[t][j].prevState;
t--;
}
@ -284,13 +292,20 @@ static int vit_path(VIT_t *vit, int j, int t) {
return 0;
}
static int viterbi(VIT_t *vit, char *rc) {
static int hbstr_len(hsbit_t *hsbit) {
int len = 0;
while (hsbit[len].hb) len++;
return len;
}
static int viterbi(VIT_t *vit, hsbit_t *rc) {
int t, tmax;
int j, j_min, w_min;
int j, j_min;
float w_min;
vit_start(vit, rc);
tmax = strlen(rc)/2;
tmax = hbstr_len(rc)/2;
for (t = L-1; t < tmax; t++)
{
@ -315,15 +330,15 @@ static int viterbi(VIT_t *vit, char *rc) {
// ------------------------------------------------------------------------
static int deconv(char* rawbits, char *bits) {
static int deconv(hsbit_t *rawbits, char *bits) {
int j, n, bitA, bitB;
char *p;
hsbit_t *p;
int len;
int errors = 0;
int m = L-1;
len = strlen(rawbits);
len = hbstr_len(rawbits);
for (j = 0; j < m; j++) bits[j] = '0';
n = 0;
while ( 2*(m+n) < len ) {
@ -333,10 +348,10 @@ static int deconv(char* rawbits, char *bits) {
bitA ^= (bits[n+j]&1) & (polyA[j]&1);
bitB ^= (bits[n+j]&1) & (polyB[j]&1);
}
if ( (bitA^(p[0]&1))==(polyA[m]&1) && (bitB^(p[1]&1))==(polyB[m]&1) ) bits[n+m] = '1';
else if ( (bitA^(p[0]&1))==0 && (bitB^(p[1]&1))==0 ) bits[n+m] = '0';
if ( (bitA^(p[0].hb&1))==(polyA[m]&1) && (bitB^(p[1].hb&1))==(polyB[m]&1) ) bits[n+m] = '1';
else if ( (bitA^(p[0].hb&1))==0 && (bitB^(p[1].hb&1))==0 ) bits[n+m] = '0';
else {
if ( (bitA^(p[0]&1))!=(polyA[m]&1) && (bitB^(p[1]&1))==(polyB[m]&1) ) bits[n+m] = 0x39;
if ( (bitA^(p[0].hb&1))!=(polyA[m]&1) && (bitB^(p[1].hb&1))==(polyB[m]&1) ) bits[n+m] = 0x39;
else bits[n+m] = 0x38;
errors = n;
break;
@ -795,7 +810,7 @@ static void proc_frame(gpx_t *gpx, int len) {
ui8_t block_bytes[FRAME_LEN+8];
ui8_t rs_cw[rs_N];
char frame_bits[BITFRAME_LEN+OVERLAP*BITS +8]; // init L-1 bits mit 0
char *rawbits = NULL;
hsbit_t *rawbits = NULL;
int i, j;
int err = 0;
int errs = 0;
@ -804,13 +819,17 @@ static void proc_frame(gpx_t *gpx, int len) {
if ((len % 8) > 4) {
while (len % 8) gpx->blk_rawbits[len++] = '0';
while (len % 8) {
gpx->blk_rawbits[len].hb = '0';
gpx->blk_rawbits[len].sb = -1;
len++;
}
}
gpx->blk_rawbits[len] = '\0';
gpx->blk_rawbits[len].hb = '\0';
flen = len / (2*BITS);
if (gpx->option.vit == 1) {
if (gpx->option.vit) {
viterbi(gpx->vit, gpx->blk_rawbits);
rawbits = gpx->vit->rawbits;
}
@ -922,6 +941,8 @@ static void proc_frame(gpx_t *gpx, int len) {
}
/* -------------------------------------------------------------------------- */
int main(int argc, char **argv) {
@ -930,6 +951,7 @@ int main(int argc, char **argv) {
int option_iq = 0;
int option_lp = 0;
int option_dc = 0;
int option_softin = 0;
int option_pcmraw = 0;
int wavloaded = 0;
int sel_wavch = 0; // audio channel: left
@ -940,7 +962,7 @@ int main(int argc, char **argv) {
int k;
int bit, rbit;
hsbit_t hsbit, rhsbit, rhsbit1;
int bitpos = 0;
int bitQ;
int pos;
@ -948,15 +970,17 @@ int main(int argc, char **argv) {
int header_found = 0;
float thres = 0.76;
float thres = 0.65;
float _mv = 0.0;
float lpIQ_bw = 16e3;
int symlen = 1;
int bitofs = 0;
int shift = 0;
int bitofs6 = 1; // +1 .. +2
int bitofsX = 0; // 0 .. +1
int bitofs6 = 0; // -1 .. +2
int bitofsX = 0; // -1 .. +1
unsigned int bc = 0;
@ -966,17 +990,21 @@ int main(int argc, char **argv) {
pcm_t pcm = {0};
dsp_t dsp = {0}; //memset(&dsp, 0, sizeof(dsp));
/*
hdb_t hdb = {0};
/*
// gpx_t _gpx = {0}; gpx_t *gpx = &_gpx; // stack size ...
gpx_t *gpx = NULL;
gpx = calloc(1, sizeof(gpx_t));
//memset(gpx, 0, sizeof(gpx_t));
*/
*/
gpx_t _gpx = {0}; gpx_t *gpx = &_gpx;
gpx->auto_detect = 1;
gpx->reset_dsp = 0;
#ifdef CYGWIN
_setmode(fileno(stdin), _O_BINARY); // _setmode(_fileno(stdin), _O_BINARY);
#endif
@ -1010,7 +1038,9 @@ int main(int argc, char **argv) {
gpx->option.raw = 1; // bytes - rs_ecc_codewords
}
else if (strcmp(*argv, "--ecc" ) == 0) { gpx->option.ecc = 1; } // RS-ECC
else if (strcmp(*argv, "--vit" ) == 0) { gpx->option.vit = 1; } // viterbi
else if (strcmp(*argv, "--ecc3") == 0) { gpx->option.ecc = 3; } // RS-ECC
else if (strcmp(*argv, "--vit" ) == 0) { gpx->option.vit = 1; } // viterbi-hard
else if (strcmp(*argv, "--vit2" ) == 0) { gpx->option.vit = 2; } // viterbi-soft
else if ( (strcmp(*argv, "--gpsweek") == 0) ) {
++argv;
if (*argv) {
@ -1022,8 +1052,9 @@ int main(int argc, char **argv) {
else if ( (strcmp(*argv, "-i") == 0) || (strcmp(*argv, "--invert") == 0) ) {
option_inv = 1; // nicht noetig
}
else if ( (strcmp(*argv, "--ch2") == 0) ) { sel_wavch = 1; } // right channel (default: 0=left)
else if ( (strcmp(*argv, "--ths") == 0) ) {
else if (strcmp(*argv, "--ch2") == 0) { sel_wavch = 1; } // right channel (default: 0=left)
else if (strcmp(*argv, "--softin") == 0) { option_softin = 1; } // float32 soft input
else if (strcmp(*argv, "--ths") == 0) {
++argv;
if (*argv) {
thres = atof(*argv);
@ -1053,6 +1084,14 @@ int main(int argc, char **argv) {
option_iq = 5;
}
else if (strcmp(*argv, "--lp") == 0) { option_lp = 1; } // IQ lowpass
else if (strcmp(*argv, "--lpbw") == 0) { // IQ lowpass BW / kHz
double bw = 0.0;
++argv;
if (*argv) bw = atof(*argv);
else return -1;
if (bw > 4.6 && bw < 24.0) lpIQ_bw = bw*1e3;
option_lp = 1;
}
else if (strcmp(*argv, "--dc") == 0) { option_dc = 1; }
else if (strcmp(*argv, "--min") == 0) {
option_min = 1;
@ -1094,71 +1133,113 @@ int main(int argc, char **argv) {
if (gpx->option.raw == 4) gpx->option.ecc = 1;
// init gpx
memcpy(gpx->blk_rawbits, blk_syncbits, sizeof(blk_syncbits));
memcpy(gpx->frame, frm_sync6, sizeof(frm_sync6));
gpx->frm_pos = 0; // ecc_blk <-> frm_blk
gpx->sf6 = 0;
gpx->sfX = 0;
//memcpy(gpx->blk_rawbits, blk_syncbits, sizeof(blk_syncbits));
for (k = 0; k < strlen(blk_syncbits); k++) { // strlen(blk_syncbits)=BLOCKSTART
int hbit = blk_syncbits[k] & 1;
gpx->blk_rawbits[k].hb = hbit + 0x30;
gpx->blk_rawbits[k].sb = 2*hbit-1;
}
gpx->option.inv = option_inv; // irrelevant
gpx->week = gpsweek;
if (option_iq == 0 && option_pcmraw) {
fclose(fp);
fprintf(stderr, "error: raw data not IQ\n");
return -1;
}
if (option_iq) sel_wavch = 0;
pcm.sel_ch = sel_wavch;
if (option_pcmraw == 0) {
k = read_wav_header(&pcm, fp);
if ( k < 0 ) {
#ifdef EXT_FSK
if (!option_softin) {
option_softin = 1;
fprintf(stderr, "reading float32 soft symbols\n");
}
#endif
if (!option_softin) {
if (option_iq == 0 && option_pcmraw) {
fclose(fp);
fprintf(stderr, "error: wav header\n");
fprintf(stderr, "error: raw data not IQ\n");
return -1;
}
if (option_iq == 0 && gpx->option.vit == 2) { // FM-demodulated data not recommended
gpx->option.vit = 1; // for soft-decoding
fprintf(stderr, "info: soft decoding only for IQ\n");
}
if (option_iq) sel_wavch = 0;
pcm.sel_ch = sel_wavch;
if (option_pcmraw == 0) {
k = read_wav_header(&pcm, fp);
if ( k < 0 ) {
fclose(fp);
fprintf(stderr, "error: wav header\n");
return -1;
}
}
symlen = 1;
// init dsp
//
dsp.fp = fp;
dsp.sr = pcm.sr;
dsp.bps = pcm.bps;
dsp.nch = pcm.nch;
dsp.ch = pcm.sel_ch;
dsp.br = (float)BAUD_RATE6;
dsp.sps = (float)dsp.sr/dsp.br;
dsp.symlen = symlen;
dsp.symhd = 1;
dsp._spb = dsp.sps*symlen;
dsp.hdr = rawheader;
dsp.hdrlen = strlen(rawheader);
dsp.BT = 1.2; // bw/time (ISI) // 1.0..2.0 // BT(lmsX) < BT(lms6) ? -> init_buffers()
dsp.h = 0.9; // 0.95 modulation index
dsp.opt_iq = option_iq;
dsp.opt_lp = option_lp;
dsp.lpIQ_bw = lpIQ_bw; // 16e3; // IF lowpass bandwidth // soft decoding?
dsp.lpFM_bw = 6e3; // FM audio lowpass
dsp.opt_dc = option_dc;
dsp.opt_IFmin = option_min;
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
}
//headerlen = dsp.hdrlen;
k = init_buffers(&dsp); // baud difference not significant
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
}
}
symlen = 1;
// init dsp
//
dsp.fp = fp;
dsp.sr = pcm.sr;
dsp.bps = pcm.bps;
dsp.nch = pcm.nch;
dsp.ch = pcm.sel_ch;
dsp.br = (float)BAUD_RATE6;
dsp.sps = (float)dsp.sr/dsp.br;
dsp.symlen = symlen;
dsp.symhd = 1;
dsp._spb = dsp.sps*symlen;
dsp.hdr = rawheader;
dsp.hdrlen = strlen(rawheader);
dsp.BT = 1.2; // bw/time (ISI) // 1.0..2.0 // BT(lmsX) < BT(lms6) ? -> init_buffers()
dsp.h = 0.9; // 0.95 modulation index
dsp.opt_iq = option_iq;
dsp.opt_lp = option_lp;
dsp.lpIQ_bw = 8e3; // IF lowpass bandwidth
dsp.lpFM_bw = 6e3; // FM audio lowpass
dsp.opt_dc = option_dc;
dsp.opt_IFmin = option_min;
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
else {
// init circular header bit buffer
hdb.hdr = rawheader;
hdb.len = strlen(rawheader);
//hdb.thb = 1.0 - 3.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen
hdb.bufpos = -1;
hdb.buf = NULL;
/*
calloc(hdb.len, sizeof(char));
if (hdb.buf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1;
}
*/
hdb.ths = 0.7; // caution/test false positive
hdb.sbuf = calloc(hdb.len, sizeof(float));
if (hdb.sbuf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1;
}
}
//headerlen = dsp.hdrlen;
k = init_buffers(&dsp); // baud difference not significant
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
};
if (gpx->option.vit) {
k = vit_initCodes(gpx);
@ -1194,9 +1275,13 @@ int main(int argc, char **argv) {
while ( 1 )
{
// FM-audio:
header_found = find_header(&dsp, thres, 3, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0
_mv = dsp.mv;
if (option_softin) {
header_found = find_softbinhead(fp, &hdb, &_mv);
}
else { // FM-audio:
header_found = find_header(&dsp, thres, 10, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0
_mv = dsp.mv;
}
if (header_found == EOF) break;
@ -1220,19 +1305,49 @@ int main(int argc, char **argv) {
while ( pos < rawbitblock_len ) {
bitQ = read_slbit(&dsp, &rbit, 0, bitofs, bitpos, -1, 0); // symlen=1
if (option_softin) {
float s = 0.0;
bitQ = f32soft_read(fp, &s);
if (bitQ != EOF) {
rhsbit.sb = s;
rhsbit.hb = (s>=0.0);
}
}
else {
//bitQ = read_softbit(&dsp, &rhsbit, 0, bitofs, bitpos, -1, 0); // symlen=1
bitQ = read_softbit2p(&dsp, &rhsbit, 0, bitofs, bitpos, -1, 0, &rhsbit1); // symlen=1
if (gpx->option.ecc == 3) {
if (rhsbit.sb*rhsbit1.sb < 0) {
rhsbit.sb += rhsbit1.sb;
rhsbit.hb = (rhsbit.sb>=0.0);
}
}
}
if (bitQ == EOF) { break; }
bit = rbit ^ (bc%2); // (c0,inv(c1))
gpx->blk_rawbits[pos] = 0x30 + bit;
// optional:
// normalize soft bit s_j by
// rhsbit.sb /= dsp._spb+1; // all samples in [-1,+1]
// or at the end by max|s_j| over all bits in rawframe
// (only if |sj| >> 1 by factor 100)
hsbit.hb = rhsbit.hb ^ (bc%2); // (c0,inv(c1))
int sgn = -2*(((unsigned int)bc)%2)+1;
hsbit.sb = sgn * rhsbit.sb;
if (gpx->option.vit == 1) { // hard decision
hsbit.sb = 2*hsbit.hb -1;
}
gpx->blk_rawbits[pos] = hsbit;
gpx->blk_rawbits[pos].hb += 0x30;
bc++;
pos++;
bitpos += 1;
}
gpx->blk_rawbits[pos] = '\0';
gpx->blk_rawbits[pos].hb = '\0';
time_elapsed_sec = dsp.sample_in / (double)dsp.sr;
proc_frame(gpx, pos);
@ -1276,7 +1391,11 @@ int main(int argc, char **argv) {
}
free_buffers(&dsp);
if (!option_softin) free_buffers(&dsp);
else {
if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; }
}
if (gpx->vit) { free(gpx->vit); gpx->vit = NULL; }
fclose(fp);

Plik diff jest za duży Load Diff

Wyświetl plik

@ -1102,6 +1102,8 @@ static int print_frame(gpx_t *gpx, int pos) {
return (gpx->frame_bytes[0]<<8)|gpx->frame_bytes[1];
}
/* -------------------------------------------------------------------------- */
int main(int argc, char **argv) {
@ -1115,6 +1117,8 @@ int main(int argc, char **argv) {
int option_iq = 0;
int option_lp = 0;
int option_dc = 0;
int option_chk = 0;
int option_softin = 0;
int option_pcmraw = 0;
int wavloaded = 0;
int sel_wavch = 0; // audio channel: left
@ -1129,6 +1133,7 @@ int main(int argc, char **argv) {
int bitpos = 0;
int bitQ;
int pos;
hsbit_t hsbit, hsbit1;
//int headerlen = 0;
@ -1144,6 +1149,8 @@ int main(int argc, char **argv) {
pcm_t pcm = {0};
dsp_t dsp = {0}; //memset(&dsp, 0, sizeof(dsp));
hdb_t hdb = {0};
gpx_t gpx = {0};
@ -1185,8 +1192,10 @@ int main(int argc, char **argv) {
else if ( (strcmp(*argv, "--spike") == 0) ) {
spike = 1;
}
else if ( (strcmp(*argv, "--ch2") == 0) ) { sel_wavch = 1; } // right channel (default: 0=left)
else if ( (strcmp(*argv, "--ths") == 0) ) {
else if (strcmp(*argv, "--chk3") == 0) { option_chk = 3; }
else if (strcmp(*argv, "--ch2") == 0) { sel_wavch = 1; } // right channel (default: 0=left)
else if (strcmp(*argv, "--softin") == 0) { option_softin = 1; } // float32 soft input
else if (strcmp(*argv, "--ths") == 0) {
++argv;
if (*argv) {
thres = atof(*argv);
@ -1250,6 +1259,7 @@ int main(int argc, char **argv) {
if (!wavloaded) fp = stdin;
// init gpx
gpx.option.inv = option_inv; // irrelevant
gpx.option.vbs = option_verbose;
gpx.option.raw = option_raw;
@ -1257,71 +1267,105 @@ int main(int argc, char **argv) {
gpx.option.col = option_color;
// init gpx
if (option_iq == 0 && option_pcmraw) {
fclose(fp);
fprintf(stderr, "error: raw data not IQ\n");
return -1;
#ifdef EXT_FSK
if (!option_softin) {
option_softin = 1;
fprintf(stderr, "reading float32 soft symbols\n");
}
if (option_iq) sel_wavch = 0;
#endif
pcm.sel_ch = sel_wavch;
if (option_pcmraw == 0) {
k = read_wav_header(&pcm, fp);
if ( k < 0 ) {
if (!option_softin) {
if (option_iq == 0 && option_pcmraw) {
fclose(fp);
fprintf(stderr, "error: wav header\n");
fprintf(stderr, "error: raw data not IQ\n");
return -1;
}
if (option_iq) sel_wavch = 0;
pcm.sel_ch = sel_wavch;
if (option_pcmraw == 0) {
k = read_wav_header(&pcm, fp);
if ( k < 0 ) {
fclose(fp);
fprintf(stderr, "error: wav header\n");
return -1;
}
}
// m10: BT>1?, h=1.2 ?
symlen = 2;
// init dsp
//
dsp.fp = fp;
dsp.sr = pcm.sr;
dsp.bps = pcm.bps;
dsp.nch = pcm.nch;
dsp.ch = pcm.sel_ch;
dsp.br = (float)BAUD_RATE;
dsp.sps = (float)dsp.sr/dsp.br;
dsp.symlen = symlen;
dsp.symhd = 1; // M10!header
dsp._spb = dsp.sps*symlen;
dsp.hdr = rawheader;
dsp.hdrlen = strlen(rawheader);
dsp.BT = 1.8; // bw/time (ISI) // 1.0..2.0
dsp.h = 0.9; // 1.2 modulation index
dsp.opt_iq = option_iq;
dsp.opt_lp = option_lp;
dsp.lpIQ_bw = 24e3; // IF lowpass bandwidth
dsp.lpFM_bw = 10e3; // FM audio lowpass
dsp.opt_dc = option_dc;
dsp.opt_IFmin = option_min;
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
}
//headerlen = dsp.hdrlen;
k = init_buffers(&dsp);
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
}
bitofs += shift;
}
else {
// init circular header bit buffer
hdb.hdr = rawheader;
hdb.len = strlen(rawheader);
//hdb.thb = 1.0 - 3.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen
hdb.bufpos = -1;
hdb.buf = NULL;
/*
calloc(hdb.len, sizeof(char));
if (hdb.buf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1;
}
*/
hdb.ths = 0.8; // caution 0.7: false positive / offset
hdb.sbuf = calloc(hdb.len, sizeof(float));
if (hdb.sbuf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1;
}
}
// m10: BT>1?, h=1.2 ?
symlen = 2;
// init dsp
//
dsp.fp = fp;
dsp.sr = pcm.sr;
dsp.bps = pcm.bps;
dsp.nch = pcm.nch;
dsp.ch = pcm.sel_ch;
dsp.br = (float)BAUD_RATE;
dsp.sps = (float)dsp.sr/dsp.br;
dsp.symlen = symlen;
dsp.symhd = 1; // M10!header
dsp._spb = dsp.sps*symlen;
dsp.hdr = rawheader;
dsp.hdrlen = strlen(rawheader);
dsp.BT = 1.8; // bw/time (ISI) // 1.0..2.0
dsp.h = 0.9; // 1.2 modulation index
dsp.opt_iq = option_iq;
dsp.opt_lp = option_lp;
dsp.lpIQ_bw = 24e3; // IF lowpass bandwidth
dsp.lpFM_bw = 10e3; // FM audio lowpass
dsp.opt_dc = option_dc;
dsp.opt_IFmin = option_min;
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
}
//headerlen = dsp.hdrlen;
k = init_buffers(&dsp);
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
};
bitofs += shift;
while ( 1 )
{
// FM-audio:
header_found = find_header(&dsp, thres, 2, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0
_mv = dsp.mv;
if (option_softin) {
header_found = find_softbinhead(fp, &hdb, &_mv);
}
else { // FM-audio:
header_found = find_header(&dsp, thres, 2, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0
_mv = dsp.mv;
}
if (header_found == EOF) break;
@ -1339,15 +1383,31 @@ int main(int argc, char **argv) {
while ( pos < BITFRAME_LEN+BITAUX_LEN ) {
if (option_iq >= 2) {
float bl = -1;
if (option_iq > 2) bl = 4.0;
bitQ = read_slbit(&dsp, &bit, 0/*gpx.option.inv*/, bitofs, bitpos, bl, 0);
if (option_softin) {
float s1 = 0.0;
float s2 = 0.0;
float s = 0.0;
bitQ = f32soft_read(fp, &s1);
if (bitQ != EOF) {
bitQ = f32soft_read(fp, &s2);
if (bitQ != EOF) {
s = s2-s1; // integrate both symbols // only 2nd Manchester symbol: s2
bit = (s>=0.0); // no soft decoding
}
}
}
else {
bitQ = read_slbit(&dsp, &bit, 0/*gpx.option.inv*/, bitofs, bitpos, -1, spike); // symlen=2
float bl = -1;
if (option_iq >= 2) spike = 0;
if (option_iq > 2) bl = 4.0;
//bitQ = read_slbit(&dsp, &bit, 0, bitofs, bitpos, bl, spike); // symlen=2
bitQ = read_softbit2p(&dsp, &hsbit, 0, bitofs, bitpos, bl, spike, &hsbit1); // symlen=1
bit = hsbit.hb;
if (option_chk == 3 && option_iq) {
//if (hsbit.sb*hsbit1.sb < 0)
bit = (hsbit.sb+0.25*hsbit1.sb)>=0;
}
}
if ( bitQ == EOF ) { break; }
gpx.frame_bits[pos] = 0x31 ^ (bit0 ^ bit);
@ -1364,7 +1424,13 @@ int main(int argc, char **argv) {
// bis Ende der Sekunde vorspulen; allerdings Doppel-Frame alle 10 sek
if (gpx.option.vbs < 3) { // && (regulare frame) // print_frame-return?
while ( bitpos < 5*BITFRAME_LEN ) {
bitQ = read_slbit(&dsp, &bit, 0/*gpx.option.inv*/, bitofs, bitpos, -1, spike); // symlen=2
if (option_softin) {
float s = 0.0;
bitQ = f32soft_read(fp, &s);
}
else {
bitQ = read_slbit(&dsp, &bit, 0, bitofs, bitpos, -1, 0); // symlen=2
}
if ( bitQ == EOF) break;
bitpos++;
}
@ -1374,7 +1440,11 @@ int main(int argc, char **argv) {
}
}
free_buffers(&dsp);
if (!option_softin) free_buffers(&dsp);
else {
if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; }
}
fclose(fp);

Wyświetl plik

@ -192,7 +192,8 @@ frame[0x44..0x45]: frame check
#define pos_GPSvE 0x0B // 2 byte
#define pos_GPSvN 0x0D // 2 byte
#define pos_GPSvU 0x18 // 2 byte
#define pos_Cnt 0x15 // 1 byte
#define pos_SN 0x12 // 3 byte
#define pos_CNT 0x15 // 1 byte
#define pos_BlkChk 0x16 // 2 byte
#define pos_Check (stdFLEN-1) // 2 byte
@ -209,6 +210,7 @@ frame[0x44..0x45]: frame check
#define XTERM_COLOR_BROWN "\x1b[38;5;94m" // 38;5;{0..255}m
#define col_Mtype "\x1b[38;5;250m" // 1 byte
#define col_GPSweek "\x1b[38;5;20m" // 2 byte
#define col_GPSTOW "\x1b[38;5;27m" // 3 byte
#define col_GPSdate "\x1b[38;5;94m" //111
@ -217,6 +219,7 @@ frame[0x44..0x45]: frame check
#define col_GPSalt "\x1b[38;5;82m" // 3 byte
#define col_GPSvel "\x1b[38;5;36m" // 6 byte
#define col_SN "\x1b[38;5;58m" // 3 byte
#define col_CNT "\x1b[38;5;172m" // 1 byte
#define col_Check "\x1b[38;5;11m" // 2 byte
#define col_TXT "\x1b[38;5;244m"
#define col_FRTXT "\x1b[38;5;244m"
@ -530,7 +533,7 @@ static int print_pos(gpx_t *gpx, int bcOK, int csOK) {
if (gpx->option.col) {
fprintf(stdout, col_TXT);
if (gpx->option.vbs >= 3) {
fprintf(stdout, "[%3d]", gpx->frame_bytes[pos_Cnt]);
fprintf(stdout, "[%3d]", gpx->frame_bytes[pos_CNT]);
fprintf(stdout, " (W "col_GPSweek"%d"col_TXT") ", gpx->week);
}
fprintf(stdout, col_GPSTOW"%s"col_TXT" ", weekday[gpx->wday]);
@ -543,14 +546,14 @@ static int print_pos(gpx_t *gpx, int bcOK, int csOK) {
fprintf(stdout, " vH: "col_GPSvel"%.1f"col_TXT" D: "col_GPSvel"%.1f"col_TXT" vV: "col_GPSvel"%.1f"col_TXT" ", gpx->vH, gpx->vD, gpx->vV);
}
if (gpx->option.vbs >= 3 && (bcOK || csOK)) { // SN
ui8_t b0 = gpx->frame_bytes[0x12];
ui32_t s2 = (gpx->frame_bytes[0x14]<<8) | gpx->frame_bytes[0x13];
ui8_t b0 = gpx->frame_bytes[pos_SN]; //0x12
ui32_t s2 = (gpx->frame_bytes[pos_SN+2]<<8) | gpx->frame_bytes[pos_SN+1];
ui8_t ym = b0 & 0x7F; // #{0x0,..,0x77}=120=10*12
ui8_t y = ym / 12;
ui8_t m = (ym % 12)+1; // there is b0=0x69<0x80 from 2018-09-19 ...
fprintf(stdout, " (%u%02u", y, m); // more samples needed
fprintf(stdout, " _ "); // (b0>>7)+1? (s2&0x3)+2?
fprintf(stdout, "_"); // ? (s2>>13)&0x3 ?? (s2&0x3)?
fprintf(stdout, "_"); // ?(s2>>(2+13))&0x1 ?? (s2&0x3)?
fprintf(stdout, "%04u)", (s2>>2)&0x1FFF);
}
if (gpx->option.vbs >= 2) {
@ -570,7 +573,7 @@ static int print_pos(gpx_t *gpx, int bcOK, int csOK) {
}
else {
if (gpx->option.vbs >= 3) {
fprintf(stdout, "[%3d]", gpx->frame_bytes[pos_Cnt]);
fprintf(stdout, "[%3d]", gpx->frame_bytes[pos_CNT]);
fprintf(stdout, " (W %d) ", gpx->week);
}
fprintf(stdout, "%s ", weekday[gpx->wday]);
@ -629,6 +632,7 @@ static int print_frame(gpx_t *gpx, int pos) {
fprintf(stdout, col_FRTXT);
for (i = 0; i < FRAME_LEN+gpx->auxlen; i++) {
byte = gpx->frame_bytes[i];
if (i == 1) fprintf(stdout, col_Mtype);
if ((i >= pos_GPSTOW) && (i < pos_GPSTOW+3)) fprintf(stdout, col_GPSTOW);
if ((i >= pos_GPSlat) && (i < pos_GPSlat+4)) fprintf(stdout, col_GPSlat);
if ((i >= pos_GPSlon) && (i < pos_GPSlon+4)) fprintf(stdout, col_GPSlon);
@ -637,6 +641,8 @@ static int print_frame(gpx_t *gpx, int pos) {
if ((i >= pos_GPSvE) && (i < pos_GPSvE+2)) fprintf(stdout, col_GPSvel);
if ((i >= pos_GPSvN) && (i < pos_GPSvN+2)) fprintf(stdout, col_GPSvel);
if ((i >= pos_GPSvU) && (i < pos_GPSvU+2)) fprintf(stdout, col_GPSvel);
if ((i >= pos_SN) && (i < pos_SN+3)) fprintf(stdout, col_SN);
if (i == pos_CNT) fprintf(stdout, col_CNT);
if ((i >= pos_BlkChk) && (i < pos_BlkChk+2)) fprintf(stdout, col_Check);
if ((i >= pos_Check+gpx->auxlen) && (i < pos_Check+gpx->auxlen+2)) fprintf(stdout, col_Check);
fprintf(stdout, "%02x", byte);

Wyświetl plik

@ -212,6 +212,7 @@ int main(int argc, char **argv) {
int option_iq = 0;
int option_lp = 0;
int option_dc = 0;
int option_softin = 0;
int option_pcmraw = 0;
int sel_wavch = 0;
int wavloaded = 0;
@ -267,6 +268,8 @@ int main(int argc, char **argv) {
pcm_t pcm = {0};
dsp_t dsp = {0}; //memset(&dsp, 0, sizeof(dsp));
hdb_t hdb = {0};
gpx_t gpx = {0};
@ -308,8 +311,9 @@ int main(int argc, char **argv) {
}
else return -1;
}
else if ( (strcmp(*argv, "--ch2") == 0) ) { sel_wavch = 1; } // right channel (default: 0=left)
else if ( (strcmp(*argv, "--ths") == 0) ) {
else if (strcmp(*argv, "--ch2") == 0) { sel_wavch = 1; } // right channel (default: 0=left)
else if (strcmp(*argv, "--softin") == 0) { option_softin = 1; } // float32 soft input
else if (strcmp(*argv, "--ths") == 0) {
++argv;
if (*argv) {
thres = atof(*argv);
@ -378,63 +382,98 @@ int main(int argc, char **argv) {
if (!wavloaded) fp = stdin;
if (option_iq == 0 && option_pcmraw) {
fclose(fp);
fprintf(stderr, "error: raw data not IQ\n");
return -1;
#ifdef EXT_FSK
if (!option_softin) {
option_softin = 1;
fprintf(stderr, "reading float32 soft symbols\n");
}
if (option_iq) sel_wavch = 0;
#endif
pcm.sel_ch = sel_wavch;
if (option_pcmraw == 0) {
k = read_wav_header(&pcm, fp);
if ( k < 0 ) {
if (!option_softin) {
if (option_iq == 0 && option_pcmraw) {
fclose(fp);
fprintf(stderr, "error: wav header\n");
fprintf(stderr, "error: raw data not IQ\n");
return -1;
}
if (option_iq) sel_wavch = 0;
pcm.sel_ch = sel_wavch;
if (option_pcmraw == 0) {
k = read_wav_header(&pcm, fp);
if ( k < 0 ) {
fclose(fp);
fprintf(stderr, "error: wav header\n");
return -1;
}
}
symlen = 1;
// init dsp
//
dsp.fp = fp;
dsp.sr = pcm.sr;
dsp.bps = pcm.bps;
dsp.nch = pcm.nch;
dsp.ch = pcm.sel_ch;
dsp.br = (float)BAUD_RATE;
dsp.sps = (float)dsp.sr/dsp.br;
dsp.symlen = symlen;
dsp.symhd = 1;
dsp._spb = dsp.sps*symlen;
dsp.hdr = rawheader;
dsp.hdrlen = strlen(rawheader);
dsp.BT = 1.2; // bw/time (ISI) // 1.0..2.0
dsp.h = 2.4; // 2.8
dsp.opt_iq = option_iq;
dsp.opt_lp = option_lp;
dsp.lpIQ_bw = 16e3; // IF lowpass bandwidth
dsp.lpFM_bw = 4e3; // FM audio lowpass
dsp.opt_dc = option_dc;
dsp.opt_IFmin = option_min;
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
}
if (baudrate > 0) {
dsp.br = (float)baudrate;
dsp.sps = (float)dsp.sr/dsp.br;
fprintf(stderr, "sps corr: %.4f\n", dsp.sps);
}
k = init_buffers(&dsp);
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
}
bitofs += shift;
}
else {
// init circular header bit buffer
hdb.hdr = rawheader;
hdb.len = strlen(rawheader);
//hdb.thb = 1.0 - 3.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen
hdb.bufpos = -1;
hdb.buf = NULL;
/*
calloc(hdb.len, sizeof(char));
if (hdb.buf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1;
}
*/
hdb.ths = 0.8; // caution/test false positive
hdb.sbuf = calloc(hdb.len, sizeof(float));
if (hdb.sbuf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1;
}
}
symlen = 1;
// init dsp
//
dsp.fp = fp;
dsp.sr = pcm.sr;
dsp.bps = pcm.bps;
dsp.nch = pcm.nch;
dsp.ch = pcm.sel_ch;
dsp.br = (float)BAUD_RATE;
dsp.sps = (float)dsp.sr/dsp.br;
dsp.symlen = symlen;
dsp.symhd = 1;
dsp._spb = dsp.sps*symlen;
dsp.hdr = rawheader;
dsp.hdrlen = strlen(rawheader);
dsp.BT = 1.2; // bw/time (ISI) // 1.0..2.0
dsp.h = 2.4; // 2.8
dsp.opt_iq = option_iq;
dsp.opt_lp = option_lp;
dsp.lpIQ_bw = 16e3; // IF lowpass bandwidth
dsp.lpFM_bw = 4e3; // FM audio lowpass
dsp.opt_dc = option_dc;
dsp.opt_IFmin = option_min;
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
}
if (baudrate > 0) {
dsp.br = (float)baudrate;
dsp.sps = (float)dsp.sr/dsp.br;
fprintf(stderr, "sps corr: %.4f\n", dsp.sps);
}
k = init_buffers(&dsp);
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
};
if (option_ecc) {
rs_init_BCH64(&gpx.RS);
@ -442,14 +481,16 @@ int main(int argc, char **argv) {
gpx.sn = -1;
bitofs += shift;
while ( 1 )
{
// FM-audio:
header_found = find_header(&dsp, thres, 1, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0
_mv = dsp.mv;
if (option_softin) {
header_found = find_softbinhead(fp, &hdb, &_mv);
}
else { // FM-audio:
header_found = find_header(&dsp, thres, 1, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0
_mv = dsp.mv;
}
if (header_found == EOF) break;
@ -462,9 +503,14 @@ int main(int argc, char **argv) {
while (bitpos < RAWBITFRAME_LEN/2-RAWHEADLEN) { // 2*600-48
bitQ = read_slbit(&dsp, &bit, 0, bitofs, bitpos, -1, 0); // symlen=1
if (option_softin) {
float s = 0.0;
bitQ = f32soft_read(fp, &s);
if (bitQ != EOF) bit = (s>=0.0); // no soft decoding
}
else {
bitQ = read_slbit(&dsp, &bit, 0, bitofs, bitpos, -1, 0); // symlen=1
}
if (bitQ == EOF) { break; }
gpx.frame_rawbits[bitpos] = 0x30 + bit;
@ -768,7 +814,11 @@ int main(int argc, char **argv) {
printf("\n");
free_buffers(&dsp);
if (!option_softin) free_buffers(&dsp);
else {
if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; }
}
fclose(fp);

Wyświetl plik

@ -87,6 +87,7 @@ typedef struct {
float T; float RH;
ui32_t crc;
ui8_t frame[FRAME_LEN];
ui8_t dfrm[FRAME_LEN];
ui8_t calibytes[51*16];
ui8_t calfrchk[51];
float ptu_Rf1; // ref-resistor f1 (750 Ohm)
@ -1006,7 +1007,27 @@ static int rs41_ecc(gpx_t *gpx, int frmlen) {
errors2 = rs_decode(&gpx->RS, cw2, err_pos2, err_val2);
if (gpx->option.ecc == 2 && (errors1 < 0 || errors2 < 0))
if (gpx->option.ecc >= 2) // option_softin: mark weak dfrm[]
{ // 2nd pass
if (errors1 < 0) {
for (i = 0; i < frmlen/2; i++) gpx->frame[2*i] ^= gpx->dfrm[2*i];
for (i = 0; i < rs_K; i++) cw1[rs_R+i] = gpx->frame[cfg_rs41.msgpos+2*i ];
errors1 = rs_decode(&gpx->RS, cw1, err_pos1, err_val1);
if (errors1 < 0) {
for (i = 0; i < frmlen/2; i++) gpx->frame[2*i] ^= gpx->dfrm[2*i];
}
}
if (errors2 < 0) {
for (i = 0; i < frmlen/2; i++) gpx->frame[2*i+1] ^= gpx->dfrm[2*i+1];
for (i = 0; i < rs_K; i++) cw2[rs_R+i] = gpx->frame[cfg_rs41.msgpos+2*i+1];
errors2 = rs_decode(&gpx->RS, cw2, err_pos2, err_val2);
if (errors2 < 0) {
for (i = 0; i < frmlen/2; i++) gpx->frame[2*i+1] ^= gpx->dfrm[2*i+1];
}
}
}
if (gpx->option.ecc >= 2 && (errors1 < 0 || errors2 < 0))
{ // 2nd pass
gpx->frame[pos_FRAME] = (pck_FRAME>>8)&0xFF; gpx->frame[pos_FRAME+1] = pck_FRAME&0xFF;
gpx->frame[pos_PTU] = (pck_PTU >>8)&0xFF; gpx->frame[pos_PTU +1] = pck_PTU &0xFF;
@ -1032,6 +1053,14 @@ static int rs41_ecc(gpx_t *gpx, int frmlen) {
errors2 = rs_decode(&gpx->RS, cw2, err_pos2, err_val2);
}
if (gpx->option.ecc >= 3)
{ // 3nd pass: erasures ...
if (errors1 < 0) {
}
if (errors2 < 0) {
}
}
// Wenn Fehler im 00-padding korrigiert wurden,
// war entweder der frame zu kurz, oder
@ -1448,7 +1477,7 @@ static void print_frame(gpx_t *gpx, int len) {
}
if (gpx->option.ecc) {
if (ec >= 0) fprintf(stdout, " [OK]"); else fprintf(stdout, " [NO]");
if (gpx->option.ecc /*== 2*/) {
if (gpx->option.ecc /*>= 2*/) {
if (ec > 0) fprintf(stdout, " (%d)", ec);
if (ec < 0) {
if (ec == -1) fprintf(stdout, " (-+)");
@ -1467,69 +1496,6 @@ static void print_frame(gpx_t *gpx, int len) {
/* -------------------------------------------------------------------------- */
// header bit buffer
typedef struct {
char *hdr;
char *buf;
char len;
int bufpos;
float ths;
} hdb_t;
static float cmp_hdb(hdb_t *hdb) { // bit-errors?
int i, j;
int headlen = hdb->len;
int berrs1 = 0, berrs2 = 0;
i = 0;
j = hdb->bufpos;
while (i < headlen) {
if (j < 0) j = headlen-1;
if (hdb->buf[j] != hdb->hdr[headlen-1-i]) berrs1 += 1;
j--;
i++;
}
i = 0;
j = hdb->bufpos;
while (i < headlen) {
if (j < 0) j = headlen-1;
if ((hdb->buf[j]^0x01) != hdb->hdr[headlen-1-i]) berrs2 += 1;
j--;
i++;
}
if (berrs2 < berrs1) return (-headlen+berrs2)/(float)headlen;
else return ( headlen-berrs1)/(float)headlen;
return 0;
}
static int find_binhead(FILE *fp, hdb_t *hdb, float *score) {
int bit;
int headlen = hdb->len;
float mv;
//*score = 0.0;
while ( (bit = fgetc(fp)) != EOF )
{
bit &= 1;
hdb->bufpos = (hdb->bufpos+1) % headlen;
hdb->buf[hdb->bufpos] = 0x30 | bit; // Ascii
mv = cmp_hdb(hdb);
if ( fabs(mv) > hdb->ths ) {
*score = mv;
return 1;
}
}
return EOF;
}
int main(int argc, char *argv[]) {
//int option_inv = 0; // invertiert Signal
@ -1538,6 +1504,7 @@ int main(int argc, char *argv[]) {
int option_lp = 0;
int option_dc = 0;
int option_bin = 0;
int option_softin = 0;
int option_pcmraw = 0;
int wavloaded = 0;
int sel_wavch = 0; // audio channel: left
@ -1554,12 +1521,16 @@ int main(int argc, char *argv[]) {
byte_count = FRAMESTART;
int bit, byte;
int bitQ;
int difbyte = 0;
hsbit_t hsbit, hsbit1;
int header_found = 0;
float thres = 0.7; // dsp.mv threshold
float _mv = 0.0;
float lpIQ_bw = 7.4e3;
int symlen = 1;
int bitofs = 2; // +0 .. +3
int shift = 0;
@ -1608,12 +1579,14 @@ int main(int argc, char *argv[]) {
}
else if (strcmp(*argv, "--ecc" ) == 0) { gpx.option.ecc = 1; }
else if (strcmp(*argv, "--ecc2") == 0) { gpx.option.ecc = 2; }
else if (strcmp(*argv, "--ecc3") == 0) { gpx.option.ecc = 3; }
else if (strcmp(*argv, "--sat") == 0) { gpx.option.sat = 1; }
else if (strcmp(*argv, "--ptu") == 0) { gpx.option.ptu = 1; }
else if (strcmp(*argv, "--silent") == 0) { gpx.option.slt = 1; }
else if (strcmp(*argv, "--ch2") == 0) { sel_wavch = 1; } // right channel (default: 0=left)
else if (strcmp(*argv, "--auto") == 0) { gpx.option.aut = 1; }
else if (strcmp(*argv, "--bin") == 0) { option_bin = 1; } // bit/byte binary input
else if (strcmp(*argv, "--bin") == 0) { option_bin = 1; } // bit/byte binary input
else if (strcmp(*argv, "--softin") == 0) { option_softin = 1; } // float32 soft input
else if (strcmp(*argv, "--ths") == 0) {
++argv;
if (*argv) {
@ -1644,6 +1617,14 @@ int main(int argc, char *argv[]) {
option_iq = 5;
}
else if (strcmp(*argv, "--lp") == 0) { option_lp = 1; } // IQ lowpass
else if (strcmp(*argv, "--lpbw") == 0) { // IQ lowpass BW / kHz
double bw = 0.0;
++argv;
if (*argv) bw = atof(*argv);
else return -1;
if (bw > 4.6 && bw < 24.0) lpIQ_bw = bw*1e3;
option_lp = 1;
}
else if (strcmp(*argv, "--dc") == 0) { option_dc = 1; }
else if (strcmp(*argv, "--min") == 0) {
option_min = 1;
@ -1694,9 +1675,16 @@ int main(int argc, char *argv[]) {
memcpy(gpx.frame, rs41_header_bytes, sizeof(rs41_header_bytes)); // 8 header bytes
#ifdef EXT_FSK
if (!option_bin && !option_softin) {
option_softin = 1;
fprintf(stderr, "reading float32 soft symbols\n");
}
#endif
if (!rawhex) {
if (!option_bin) {
if (!option_bin && !option_softin) {
if (option_iq == 0 && option_pcmraw) {
fclose(fp);
@ -1736,7 +1724,7 @@ int main(int argc, char *argv[]) {
dsp.h = 0.6; //0.7; // 0.7..0.8? modulation index abzgl. BT
dsp.opt_iq = option_iq;
dsp.opt_lp = option_lp;
dsp.lpIQ_bw = 8e3; // IF lowpass bandwidth
dsp.lpIQ_bw = lpIQ_bw; // 7.4e3 (6e3..8e3) // IF lowpass bandwidth
dsp.lpFM_bw = 6e3; // FM audio lowpass
dsp.opt_dc = option_dc;
dsp.opt_IFmin = option_min;
@ -1744,37 +1732,48 @@ int main(int argc, char *argv[]) {
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
}
k = init_buffers(&dsp); // BT=0.5 (IQ-Int: BT > 0.5 ?)
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
}
//if (option_iq >= 2) bitofs += 1; // FM: +1 , IQ: +2
bitofs += shift;
}
else {
if (option_bin && option_softin) option_bin = 0;
// init circular header bit buffer
hdb.hdr = rs41_header;
hdb.len = strlen(rs41_header);
hdb.ths = 1.0 - 3.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen
hdb.thb = 1.0 - 3.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen
hdb.bufpos = -1;
hdb.buf = calloc(hdb.len, sizeof(char));
if (hdb.buf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1;
}
hdb.ths = 0.7; // caution/test false positive
hdb.sbuf = calloc(hdb.len, sizeof(float));
if (hdb.sbuf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1;
}
}
k = init_buffers(&dsp); // BT=0.5 (IQ-Int: BT > 0.5 ?)
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
};
//if (option_iq >= 2) bitofs += 1; // FM: +1 , IQ: +2
bitofs += shift;
while ( 1 )
{
if (option_bin) {
header_found = find_binhead(fp, &hdb, &_mv);
}
else if (option_softin) {
header_found = find_softbinhead(fp, &hdb, &_mv);
}
else { // FM-audio:
header_found = find_header(&dsp, thres, 3, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0
header_found = find_header(&dsp, thres, 4, bitofs, dsp.opt_dc); // optional 2nd pass: dc=0
_mv = dsp.mv;
}
if (header_found == EOF) break;
@ -1790,6 +1789,7 @@ int main(int argc, char *argv[]) {
byte_count = FRAMESTART;
bitpos = 0; // byte_count*8-HEADLEN
b8pos = 0;
difbyte = 0;
while ( byte_count < FRAME_LEN )
{
@ -1797,14 +1797,21 @@ int main(int argc, char *argv[]) {
bitQ = fgetc(fp);
if (bitQ != EOF) bit = bitQ & 0x1;
}
else if (option_softin) {
float s = 0.0;
bitQ = f32soft_read(fp, &s);
if (bitQ != EOF) bit = (s>=0.0); // no soft decoding
}
else {
if (option_iq >= 2) {
float bl = -1;
if (option_iq > 2) bl = 1.0;
bitQ = read_slbit(&dsp, &bit, 0/*gpx.option.inv*/, bitofs, bitpos, bl, 0);
}
else {
bitQ = read_slbit(&dsp, &bit, 0/*gpx.option.inv*/, bitofs, bitpos, -1, 0);
float bl = -1;
if (option_iq > 2) bl = 2.0;
//bitQ = read_slbit(&dsp, &bit, 0, bitofs, bitpos, bl, 0); // symlen=1
bitQ = read_softbit2p(&dsp, &hsbit, 0, bitofs, bitpos, bl, 0, &hsbit1); // symlen=1
bit = hsbit.hb;
if (gpx.option.ecc == 3) bit = (hsbit.sb+hsbit1.sb)>=0;
if (bitpos < FRAME_LEN*BITS && hsbit.sb*hsbit1.sb < 0) {
difbyte |= 1<<b8pos;
}
}
if ( bitQ == EOF ) break; // liest 2x EOF
@ -1818,6 +1825,8 @@ int main(int argc, char *argv[]) {
b8pos = 0;
byte = bits2byte(bitbuf);
gpx.frame[byte_count] = byte ^ mask[byte_count % MASK_LEN];
gpx.dfrm[byte_count] = difbyte;
difbyte = 0;
byte_count++;
}
}
@ -1828,7 +1837,7 @@ int main(int argc, char *argv[]) {
}
}
if (!option_bin) free_buffers(&dsp);
if (!option_bin && !option_softin) free_buffers(&dsp);
else {
if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; }
}

Wyświetl plik

@ -1221,11 +1221,13 @@ static void print_frame(gpx_t *gpx, int len) {
if (ec < 0) fprintf(stdout, " (-)");
}
fprintf(stdout, "\n");
// fprintf(stdout, "\n");
// fprintf(stdout, "\n");
}
else print_position(gpx, ec);
}
/* -------------------------------------------------------------------------- */
int main(int argc, char *argv[]) {
@ -1237,6 +1239,7 @@ int main(int argc, char *argv[]) {
int option_iq = 0;
int option_lp = 0;
int option_dc = 0;
int option_softin = 0;
int option_pcmraw = 0;
int sel_wavch = 0; // audio channel: left
int spike = 0;
@ -1265,6 +1268,8 @@ int main(int argc, char *argv[]) {
pcm_t pcm = {0};
dsp_t dsp = {0}; //memset(&dsp, 0, sizeof(dsp));
hdb_t hdb = {0};
gpx_t gpx = {0};
gpx.gps.prn32toggle = 0x1;
@ -1375,18 +1380,19 @@ int main(int argc, char *argv[]) {
}
else return -1;
}
else if (strcmp(*argv, "-g1") == 0) { gpx.gps.opt_vergps = 1; } // verbose1 GPS
else if (strcmp(*argv, "-g2") == 0) { gpx.gps.opt_vergps = 2; } // verbose2 GPS (bancroft)
else if (strcmp(*argv, "-gg") == 0) { gpx.gps.opt_vergps = 8; } // vverbose GPS
else if (strcmp(*argv, "--json") == 0) {
else if (strcmp(*argv, "-g1") == 0) { gpx.gps.opt_vergps = 1; } // verbose1 GPS
else if (strcmp(*argv, "-g2") == 0) { gpx.gps.opt_vergps = 2; } // verbose2 GPS (bancroft)
else if (strcmp(*argv, "-gg") == 0) { gpx.gps.opt_vergps = 8; } // vverbose GPS
else if (strcmp(*argv, "--json") == 0) {
gpx.option.jsn = 1;
gpx.option.ecc = 2;
gpx.option.crc = 1;
gpx.gps.opt_vel = 4;
}
else if (strcmp(*argv, "--spike") == 0) { spike = 1; }
else if (strcmp(*argv, "--ch2") == 0) { sel_wavch = 1; } // right channel (default: 0=left)
else if (strcmp(*argv, "--ths") == 0) {
else if (strcmp(*argv, "--spike") == 0) { spike = 1; }
else if (strcmp(*argv, "--ch2") == 0) { sel_wavch = 1; } // right channel (default: 0=left)
else if (strcmp(*argv, "--softin") == 0) { option_softin = 1; } // float32 soft input
else if (strcmp(*argv, "--ths") == 0) {
++argv;
if (*argv) {
thres = atof(*argv);
@ -1480,70 +1486,112 @@ int main(int argc, char *argv[]) {
// init gpx
memcpy(gpx.frame, rs92_header_bytes, sizeof(rs92_header_bytes)); // 6 header bytes
if (option_iq == 0 && option_pcmraw) {
fclose(fp);
fprintf(stderr, "error: raw data not IQ\n");
return -1;
}
if (option_iq) sel_wavch = 0;
pcm.sel_ch = sel_wavch;
if (option_pcmraw == 0) {
k = read_wav_header(&pcm, fp);
if ( k < 0 ) {
#ifdef EXT_FSK
if (!option_softin) {
option_softin = 1;
fprintf(stderr, "reading float32 soft symbols\n");
}
#endif
if (!option_softin) {
if (option_iq == 0 && option_pcmraw) {
fclose(fp);
fprintf(stderr, "error: wav header\n");
fprintf(stderr, "error: raw data not IQ\n");
return -1;
}
if (option_iq) sel_wavch = 0;
pcm.sel_ch = sel_wavch;
if (option_pcmraw == 0) {
k = read_wav_header(&pcm, fp);
if ( k < 0 ) {
fclose(fp);
fprintf(stderr, "error: wav header\n");
return -1;
}
}
// rs92-sgp: BT=0.5, h=1.0 ?
symlen = 2;
// init dsp
//
dsp.fp = fp;
dsp.sr = pcm.sr;
dsp.bps = pcm.bps;
dsp.nch = pcm.nch;
dsp.ch = pcm.sel_ch;
dsp.br = (float)BAUD_RATE;
dsp.sps = (float)dsp.sr/dsp.br;
dsp.symlen = symlen;
dsp.symhd = symlen;
dsp._spb = dsp.sps*symlen;
dsp.hdr = rs92_rawheader;
dsp.hdrlen = strlen(rs92_rawheader);
dsp.BT = 0.5; // bw/time (ISI) // 0.3..0.5
dsp.h = 0.8; // 1.0 modulation index abzgl. BT
dsp.opt_iq = option_iq;
dsp.opt_lp = option_lp;
dsp.lpIQ_bw = 8e3; // IF lowpass bandwidth
dsp.lpFM_bw = 6e3; // FM audio lowpass
dsp.opt_dc = option_dc;
dsp.opt_IFmin = option_min;
if (gpx.option.ngp) { // L-band rs92-ngp
dsp.h = 3.8; // RS92-NGP: 1680/400=4.2, 4.2*0.9=3.8=4.75*0.8
dsp.lpIQ_bw = 32e3; // IF lowpass bandwidth // 32e3=4.2*7.6e3
}
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
}
k = init_buffers(&dsp); // BT=0.5 (IQ-Int: BT > 0.5 ?)
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
};
bitofs += shift;
}
else {
// init circular header bit buffer
hdb.hdr = rs92_rawheader;
hdb.len = strlen(rs92_rawheader);
//hdb.thb = 1.0 - 3.1/(float)hdb.len; // 1.0-max_bit_errors/hdrlen
hdb.bufpos = -1;
hdb.buf = NULL;
/*
calloc(hdb.len, sizeof(char));
if (hdb.buf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1;
}
*/
// caution ths=0.7: -3 byte offset, false positive
// 2A 2A 2A 2A 2A 10|65 10 ..
// header sync could be extended into the frame
hdb.ths = 0.8;
hdb.sbuf = calloc(hdb.len, sizeof(float));
if (hdb.sbuf == NULL) {
fprintf(stderr, "error: malloc\n");
return -1;
}
}
// rs92-sgp: BT=0.5, h=1.0 ?
symlen = 2;
// init dsp
//
dsp.fp = fp;
dsp.sr = pcm.sr;
dsp.bps = pcm.bps;
dsp.nch = pcm.nch;
dsp.ch = pcm.sel_ch;
dsp.br = (float)BAUD_RATE;
dsp.sps = (float)dsp.sr/dsp.br;
dsp.symlen = symlen;
dsp.symhd = symlen;
dsp._spb = dsp.sps*symlen;
dsp.hdr = rs92_rawheader;
dsp.hdrlen = strlen(rs92_rawheader);
dsp.BT = 0.5; // bw/time (ISI) // 0.3..0.5
dsp.h = 0.8; // 1.0 modulation index abzgl. BT
dsp.opt_iq = option_iq;
dsp.opt_lp = option_lp;
dsp.lpIQ_bw = 8e3; // IF lowpass bandwidth
dsp.lpFM_bw = 6e3; // FM audio lowpass
dsp.opt_dc = option_dc;
dsp.opt_IFmin = option_min;
if (gpx.option.ngp) { // L-band rs92-ngp
dsp.h = 3.8; // RS92-NGP: 1680/400=4.2, 4.2*0.9=3.8=4.75*0.8
dsp.lpIQ_bw = 32e3; // IF lowpass bandwidth // 32e3=4.2*7.6e3
}
if ( dsp.sps < 8 ) {
fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps);
}
k = init_buffers(&dsp); // BT=0.5 (IQ-Int: BT > 0.5 ?)
if ( k < 0 ) {
fprintf(stderr, "error: init buffers\n");
return -1;
};
bitofs += shift;
while ( 1 ) {
header_found = find_header(&dsp, thres, 3, bitofs, dsp.opt_dc);
_mv = dsp.mv;
while ( 1 )
{
if (option_softin) {
for (k = 0; k < hdb.len; k++) hdb.sbuf[k] = 0.0;
header_found = find_softbinhead(fp, &hdb, &_mv);
}
else {
header_found = find_header(&dsp, thres, 3, bitofs, dsp.opt_dc);
_mv = dsp.mv;
}
if (header_found == EOF) break;
@ -1560,9 +1608,25 @@ int main(int argc, char *argv[]) {
b8pos = 0;
while ( byte_count < FRAME_LEN ) {
float bl = -1;
if (option_iq > 2) bl = 4.0;
bitQ = read_slbit(&dsp, &bit, 0/*gpx.option.inv*/, bitofs, bitpos, bl, spike);
if (option_softin) {
float s1 = 0.0;
float s2 = 0.0;
float s = 0.0;
bitQ = f32soft_read(fp, &s1);
if (bitQ != EOF) {
bitQ = f32soft_read(fp, &s2);
if (bitQ != EOF) {
s = s2-s1; // integrate both symbols // only 2nd Manchester symbol: s2
bit = (s>=0.0); // no soft decoding
}
}
}
else {
float bl = -1;
if (option_iq > 2) bl = 4.0;
bitQ = read_slbit(&dsp, &bit, 0, bitofs, bitpos, bl, spike); // symlen=2
}
if ( bitQ == EOF) break;
if (gpx.option.inv) bit ^= 1;
@ -1586,9 +1650,13 @@ int main(int argc, char *argv[]) {
}
free_buffers(&dsp);
if (!option_softin) free_buffers(&dsp);
else {
if (hdb.buf) { free(hdb.buf); hdb.buf = NULL; }
}
if (gpx.gps.ephs) free(gpx.gps.ephs);
fclose(fp);
return 0;