kopia lustrzana https://github.com/projecthorus/radiosonde_auto_rx
Update to latest upstream decoders. Use --json options on decoders. Respect inverted DFM flag.
rodzic
9d7205a323
commit
1d04aeaa5a
|
@ -231,11 +231,21 @@ def handle_scan_results():
|
|||
# Already decoding this sonde, continue.
|
||||
continue
|
||||
else:
|
||||
logging.info("Detected new %s sonde on %.3f MHz!" % (_type, _freq/1e6))
|
||||
|
||||
# Handle an inverted sonde detection.
|
||||
if _type.startswith('-'):
|
||||
_inverted = " (Inverted)"
|
||||
_check_type = _type[1:]
|
||||
else:
|
||||
_check_type = _type
|
||||
_inverted = ""
|
||||
|
||||
# Note: We don't indicate if it's been detected as inverted here.
|
||||
logging.info("Detected new %s sonde on %.3f MHz!" % (_check_type, _freq/1e6))
|
||||
|
||||
# Break if we don't support this sonde type.
|
||||
if (_type not in VALID_SONDE_TYPES):
|
||||
logging.error("Unsupported sonde type: %s" % _type)
|
||||
if (_check_type not in VALID_SONDE_TYPES):
|
||||
logging.error("Unsupported sonde type: %s" % _check_type)
|
||||
continue
|
||||
|
||||
if allocate_sdr(check_only=True) is not None :
|
||||
|
@ -355,7 +365,12 @@ def telemetry_filter(telemetry):
|
|||
if vaisala_callsign_valid or dfm_callsign_valid:
|
||||
return True
|
||||
else:
|
||||
logging.warning("Payload ID %s does not match regex. Discarding." % telemetry['id'])
|
||||
_id_msg = "Payload ID %s is invalid." % telemetry['id']
|
||||
# Add in a note about DFM sondes and their oddness...
|
||||
if 'DFM' in telemetry['id']:
|
||||
_id_msg += " Note: DFM sondes may take a while to get an ID."
|
||||
|
||||
logging.warning(_id_msg)
|
||||
return False
|
||||
|
||||
|
||||
|
|
|
@ -120,6 +120,14 @@ class SondeDecoder(object):
|
|||
# This will become our decoder thread.
|
||||
self.decoder = None
|
||||
|
||||
# Detect if we have an 'inverted' sonde.
|
||||
if self.sonde_type.startswith('-'):
|
||||
self.inverted = True
|
||||
# Strip off the leading '-' character'
|
||||
self.sonde_type = self.sonde_type[1:]
|
||||
else:
|
||||
self.inverted = False
|
||||
|
||||
# Check if the sonde type is valid.
|
||||
if self.sonde_type not in self.VALID_SONDE_TYPES:
|
||||
self.log_error("Unsupported sonde type: %s" % self.sonde_type)
|
||||
|
@ -201,7 +209,7 @@ class SondeDecoder(object):
|
|||
# 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 - lowpass 2600 2>/dev/null |"
|
||||
decode_cmd += "./rs41ecc --crc --ecc --ptu 2>/dev/null"
|
||||
decode_cmd += "./rs41ecc --crc --ecc --ptu --json 2>/dev/null"
|
||||
|
||||
elif self.sonde_type == "RS92":
|
||||
# Decoding a RS92 requires either an ephemeris or an almanac file.
|
||||
|
@ -232,16 +240,30 @@ class SondeDecoder(object):
|
|||
# rtl_fm -p 0 -g 26.0 -M fm -F9 -s 12k -f 400500000 | sox -t raw -r 12k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - highpass 20 lowpass 2500 2>/dev/null | ./rs92ecc -vx -v --crc --ecc --vel -e ephemeris.dat
|
||||
decode_cmd = "%s %s-p %d -d %s %s-M fm -F9 -s 12k -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 12k -e s -b 16 -c 1 - -r 48000 -b 8 -t wav - lowpass 2500 highpass 20 2>/dev/null |"
|
||||
decode_cmd += "./rs92ecc -vx -v --crc --ecc --vel %s 2>/dev/null" % _rs92_gps_data
|
||||
decode_cmd += "./rs92ecc -vx -v --crc --ecc --vel --json %s 2>/dev/null" % _rs92_gps_data
|
||||
|
||||
elif self.sonde_type == "DFM":
|
||||
# DFM06/DFM09 Sondes
|
||||
# DFM06/DFM09 Sondes.
|
||||
|
||||
# We need to handle inversion of DFM sondes in a bit of an odd way.
|
||||
# Using our current receive chain (rtl_fm), rs_detect will detect:
|
||||
# DFM06's as non-inverted ('DFM')
|
||||
# DFM09's as inverted ('-DFM')
|
||||
# HOWEVER, dfm09dm_ecc makes the assumption that the incoming signal is a DFM09, and
|
||||
# inverts by default.
|
||||
# So, to be able to support DFM06s, we need to flip the invert flag.
|
||||
self.inverted = not self.inverted
|
||||
|
||||
if self.inverted:
|
||||
_invert_flag = "-i"
|
||||
else:
|
||||
_invert_flag = ""
|
||||
|
||||
# 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 2>/dev/null"
|
||||
decode_cmd += "./dfm09ecc -vv --ecc --json %s 2>/dev/null" % _invert_flag
|
||||
|
||||
|
||||
else:
|
||||
|
@ -257,6 +279,8 @@ class SondeDecoder(object):
|
|||
# Timeout Counter.
|
||||
_last_packet = time.time()
|
||||
|
||||
self.log_debug("Decoder Command: %s" % self.decoder_command )
|
||||
|
||||
# Start the thread.
|
||||
self.decode_process = subprocess.Popen(self.decoder_command, shell=True, stdin=None, stdout=subprocess.PIPE, preexec_fn=os.setsid)
|
||||
self.async_reader = AsynchronousFileReader(self.decode_process.stdout, autostart=True)
|
||||
|
@ -362,7 +386,7 @@ class SondeDecoder(object):
|
|||
try:
|
||||
_telemetry['datetime_dt'] = parse(_telemetry['datetime'])
|
||||
except Exception as e:
|
||||
self.log_error("Invalid date/time in telemetry dict - %s" % str(e))
|
||||
self.log_error("Invalid date/time in telemetry dict - %s (Sonde may not have GPS lock" % str(e))
|
||||
return False
|
||||
|
||||
# Add in the sonde frequency and type fields.
|
||||
|
|
|
@ -191,8 +191,8 @@ def detect_sonde(frequency, rs_path="./", dwell_time=10, sdr_fm='rtl_fm', device
|
|||
else:
|
||||
gain_param = ''
|
||||
|
||||
rx_test_command = "timeout %ds %s %s-p %d -d %s %s-M fm -F9 -s 15k -f %d 2>/dev/null |" % (dwell_time, sdr_fm, bias_option, int(ppm), str(device_idx), gain_param, frequency)
|
||||
rx_test_command += "sox -t raw -r 15k -e s -b 16 -c 1 - -r 48000 -t wav - highpass 20 2>/dev/null |"
|
||||
rx_test_command = "timeout %ds %s %s-p %d -d %s %s-M fm -F9 -s 22k -f %d 2>/dev/null |" % (dwell_time, sdr_fm, bias_option, int(ppm), str(device_idx), gain_param, frequency)
|
||||
rx_test_command += "sox -t raw -r 22k -e s -b 16 -c 1 - -r 48000 -t wav - highpass 20 2>/dev/null |"
|
||||
rx_test_command += os.path.join(rs_path,"rs_detect") + " -z -t 8 2>/dev/null >/dev/null"
|
||||
|
||||
logging.debug("Scanner #%s - Attempting sonde detection on %.3f MHz" % (str(device_idx), frequency/1e6))
|
||||
|
@ -218,8 +218,8 @@ def detect_sonde(frequency, rs_path="./", dwell_time=10, sdr_fm='rtl_fm', device
|
|||
if (ret_code & 0x80) > 0:
|
||||
# If the inverted bit is set, we have to do some munging of the return code to get the sonde type.
|
||||
ret_code = abs(-1 * (0x100 - ret_code))
|
||||
# Currently ignoring the inverted flag, as rs_detect appears to detect some sondes as inverted incorrectly.
|
||||
#inv = "-"
|
||||
|
||||
inv = "-"
|
||||
|
||||
else:
|
||||
ret_code = abs(ret_code)
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
## Radiosonde decoders
|
||||
|
||||
alternative decoders using cross-correlation for better header-synchronization
|
||||
|
||||
#### Files
|
||||
|
||||
* `demod_dft.c`, `demod_dft.h`, <br />
|
||||
`rs41dm_dft.c`, `rs92dm_dft.c`, `dfm09dm_dft.c`, `m10dm_dft.c`, `lms6dm_dft.c`, <br />
|
||||
`RS/ecc/bch_ecc.c`
|
||||
|
||||
#### Compile
|
||||
(copy `bch_ecc.c`) <br />
|
||||
`gcc -c demod_dft.c` <br />
|
||||
`gcc rs41dm_dft.c demod_dft.o -lm -o rs41dm_dft` <br />
|
||||
`gcc dfm09dm_dft.c demod_dft.o -lm -o dfm09dm_dft` <br />
|
||||
`gcc m10dm_dft.c demod_dft.o -lm -o m10dm_dft` <br />
|
||||
`gcc lms6dm_dft.c demod_dft.o -lm -o lms6dm_dft` <br />
|
||||
`gcc rs92dm_dft.c demod_dft.o -lm -o rs92dm_dft` (needs `RS/rs92/nav_gps_vel.c`)
|
||||
|
||||
#### Usage/Examples
|
||||
`./rs41dm_dft --ecc2 --crc -vx --ptu <audio.wav>` <br />
|
||||
`./dfm09dm_dft --ecc -v --ptu <audio.wav>` (add `-i` for dfm06)<br />
|
||||
`./m10dm_dft --dc -vv --ptu -c <audio.wav>` <br />
|
||||
`./lms6dm_dft --vit --ecc -v <audio.wav>` <br />
|
||||
|
||||
|
|
@ -167,6 +167,7 @@ int getCorrDFT(int abs, int K, unsigned int pos, float *maxv, unsigned int *maxv
|
|||
|
||||
static int sample_rate = 0, bits_sample = 0, channels = 0;
|
||||
static float samples_per_bit = 0;
|
||||
static int wav_ch = 0; // 0: links bzw. mono; 1: rechts
|
||||
|
||||
static int findstr(char *buff, char *str, int pos) {
|
||||
int i;
|
||||
|
@ -176,7 +177,7 @@ static int findstr(char *buff, char *str, int pos) {
|
|||
return i;
|
||||
}
|
||||
|
||||
float read_wav_header(FILE *fp, float baudrate) {
|
||||
float read_wav_header(FILE *fp, float baudrate, int wav_channel) {
|
||||
char txt[4+1] = "\0\0\0\0";
|
||||
unsigned char dat[4];
|
||||
int byte, p=0;
|
||||
|
@ -224,6 +225,10 @@ float read_wav_header(FILE *fp, float baudrate) {
|
|||
fprintf(stderr, "bits : %d\n", bits_sample);
|
||||
fprintf(stderr, "channels : %d\n", channels);
|
||||
|
||||
if (wav_channel >= 0 && wav_channel < channels) wav_ch = wav_channel;
|
||||
else wav_ch = 0;
|
||||
fprintf(stderr, "channel-In : %d\n", wav_ch+1);
|
||||
|
||||
if ((bits_sample != 8) && (bits_sample != 16)) return -1;
|
||||
|
||||
samples_per_bit = sample_rate/baudrate;
|
||||
|
@ -241,7 +246,7 @@ static int f32read_sample(FILE *fp, float *s) {
|
|||
|
||||
if (fread( &b, bits_sample/8, 1, fp) != 1) return EOF;
|
||||
|
||||
if (i == 0) { // i = 0: links bzw. mono
|
||||
if (i == wav_ch) { // i = 0: links bzw. mono
|
||||
//if (bits_sample == 8) sint = b-128; // 8bit: 00..FF, centerpoint 0x80=128
|
||||
//if (bits_sample == 16) sint = (short)b;
|
||||
|
||||
|
@ -411,6 +416,92 @@ int read_sbit(FILE *fp, int symlen, int *bit, int inv, int ofs, int reset, int c
|
|||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int read_softbit(FILE *fp, int symlen, int *bit, float *sb, float level, int inv, int ofs, int reset, int cm) {
|
||||
// symlen==2: manchester2 10->0,01->1: 2.bit
|
||||
|
||||
static double bitgrenze;
|
||||
static unsigned long scount;
|
||||
|
||||
float sample;
|
||||
|
||||
double sum = 0.0;
|
||||
int n = 0;
|
||||
|
||||
if (reset) {
|
||||
scount = 0;
|
||||
bitgrenze = 0;
|
||||
}
|
||||
|
||||
if (symlen == 2) {
|
||||
bitgrenze += samples_per_bit;
|
||||
do {
|
||||
if (buffered > 0) buffered -= 1;
|
||||
else if (f32buf_sample(fp, inv, cm) == EOF) return EOF;
|
||||
|
||||
sample = bufs[(sample_out-buffered + ofs + M) % M];
|
||||
if (scount > bitgrenze-samples_per_bit && scount < bitgrenze-2)
|
||||
{
|
||||
sum -= sample;
|
||||
n++;
|
||||
}
|
||||
scount++;
|
||||
} while (scount < bitgrenze); // n < samples_per_bit
|
||||
}
|
||||
|
||||
bitgrenze += samples_per_bit;
|
||||
do {
|
||||
if (buffered > 0) buffered -= 1;
|
||||
else if (f32buf_sample(fp, inv, cm) == EOF) return EOF;
|
||||
|
||||
sample = bufs[(sample_out-buffered + ofs + M) % M];
|
||||
if (scount > bitgrenze-samples_per_bit && scount < bitgrenze-2)
|
||||
{
|
||||
sum += sample;
|
||||
n++;
|
||||
}
|
||||
scount++;
|
||||
} while (scount < bitgrenze); // n < samples_per_bit
|
||||
|
||||
if (sum >= 0) *bit = 1;
|
||||
else *bit = 0;
|
||||
|
||||
*sb = sum / n;
|
||||
|
||||
if (*sb > +2.5*level) *sb = +0.8*level;
|
||||
if (*sb > +level) *sb = +level;
|
||||
|
||||
if (*sb < -2.5*level) *sb = -0.8*level;
|
||||
if (*sb < -level) *sb = -level;
|
||||
|
||||
*sb /= level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float header_level(char hdr[], int hLen, unsigned int pos, int inv) {
|
||||
int n, bitn;
|
||||
int sgn = 0;
|
||||
double s = 0.0;
|
||||
double sum = 0.0;
|
||||
|
||||
n = 0;
|
||||
bitn = 0;
|
||||
while ( bitn < hLen && (n < N) ) {
|
||||
sgn = (hdr[bitn]&1)*2-1; // {'0','1'} -> {-1,1}
|
||||
s = bufs[(pos-N + n + M) % M];
|
||||
if (inv) s = -s;
|
||||
sum += s * sgn;
|
||||
n++;
|
||||
bitn = n / samples_per_bit;
|
||||
}
|
||||
sum /= n;
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
static double norm2_match() {
|
||||
int i;
|
||||
double x, y = 0.0;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
|
||||
float read_wav_header(FILE*, float);
|
||||
float read_wav_header(FILE*, float, int);
|
||||
int f32buf_sample(FILE*, int, int);
|
||||
int read_sbit(FILE*, int, int*, int, int, int, int);
|
||||
int read_softbit(FILE *fp, int symlen, int *bit, float *sb, float level, int inv, int ofs, int reset, int cm);
|
||||
float header_level(char hdr[], int hLen, unsigned int pos, int inv);
|
||||
|
||||
int getCorrDFT(int, int, unsigned int, float *, unsigned int *);
|
||||
int headcmp(int, char*, int, unsigned int, int, int);
|
||||
|
|
|
@ -0,0 +1,883 @@
|
|||
|
||||
/*
|
||||
* sync header: correlation/matched filter
|
||||
* compile:
|
||||
* gcc -c demod_iq.c
|
||||
*
|
||||
* author: zilog80
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------------------ */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
|
||||
typedef unsigned char ui8_t;
|
||||
typedef unsigned short ui16_t;
|
||||
typedef unsigned int ui32_t;
|
||||
typedef short i16_t;
|
||||
typedef int i32_t;
|
||||
|
||||
#include "demod_iq.h"
|
||||
|
||||
|
||||
static int sample_rate = 0, bits_sample = 0, channels = 0;
|
||||
static float samples_per_bit = 0;
|
||||
|
||||
static unsigned int sample_in, sample_out, delay;
|
||||
static int buffered = 0;
|
||||
|
||||
static int N, M;
|
||||
|
||||
static float *match = NULL,
|
||||
*bufs = NULL;
|
||||
|
||||
static char *rawbits = NULL;
|
||||
|
||||
static int Nvar = 0; // < M
|
||||
static double xsum=0, qsum=0;
|
||||
static float *xs = NULL,
|
||||
*qs = NULL;
|
||||
|
||||
|
||||
static float dc_ofs = 0.0;
|
||||
static float dc = 0.0;
|
||||
|
||||
static int option_iq = 0;
|
||||
|
||||
/* ------------------------------------------------------------------------------------ */
|
||||
|
||||
#include <complex.h>
|
||||
|
||||
static int LOG2N, N_DFT;
|
||||
static int M_DFT;
|
||||
|
||||
static float complex *ew;
|
||||
|
||||
static float complex *Fm, *X, *Z, *cx;
|
||||
static float *xn;
|
||||
|
||||
static float complex *Hann;
|
||||
|
||||
static int N_IQBUF;
|
||||
static float complex *raw_iqbuf = NULL;
|
||||
static float complex *rot_iqbuf = NULL;
|
||||
|
||||
static double df = 0.0;
|
||||
static int len_sq = 0;
|
||||
|
||||
static unsigned int sample_posframe = 0;
|
||||
static unsigned int sample_posnoise = 0;
|
||||
|
||||
static double V_noise = 0.0;
|
||||
static double V_signal = 0.0;
|
||||
static double SNRdB = 0.0;
|
||||
|
||||
|
||||
static void cdft(float complex *Z) {
|
||||
int s, l, l2, i, j, k;
|
||||
float complex w1, w2, T;
|
||||
|
||||
j = 1;
|
||||
for (i = 1; i < N_DFT; i++) {
|
||||
if (i < j) {
|
||||
T = Z[j-1];
|
||||
Z[j-1] = Z[i-1];
|
||||
Z[i-1] = T;
|
||||
}
|
||||
k = N_DFT/2;
|
||||
while (k < j) {
|
||||
j = j - k;
|
||||
k = k/2;
|
||||
}
|
||||
j = j + k;
|
||||
}
|
||||
|
||||
for (s = 0; s < LOG2N; s++) {
|
||||
l2 = 1 << s;
|
||||
l = l2 << 1;
|
||||
w1 = (float complex)1.0;
|
||||
w2 = ew[s]; // cexp(-I*M_PI/(float)l2)
|
||||
for (j = 1; j <= l2; j++) {
|
||||
for (i = j; i <= N_DFT; i += l) {
|
||||
k = i + l2;
|
||||
T = Z[k-1] * w1;
|
||||
Z[k-1] = Z[i-1] - T;
|
||||
Z[i-1] = Z[i-1] + T;
|
||||
}
|
||||
w1 = w1 * w2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rdft(float *x, float complex *Z) {
|
||||
int i;
|
||||
for (i = 0; i < N_DFT; i++) Z[i] = (float complex)x[i];
|
||||
cdft(Z);
|
||||
}
|
||||
|
||||
static void Nidft(float complex *Z, float complex *z) {
|
||||
int i;
|
||||
for (i = 0; i < N_DFT; i++) z[i] = conj(Z[i]);
|
||||
cdft(z);
|
||||
// idft():
|
||||
// for (i = 0; i < N_DFT; i++) z[i] = conj(z[i])/(float)N_DFT; // hier: z reell
|
||||
}
|
||||
|
||||
static float bin2freq(int k) {
|
||||
float fq = sample_rate * k / N_DFT;
|
||||
if (fq > sample_rate/2.0) fq -= sample_rate;
|
||||
return fq;
|
||||
}
|
||||
|
||||
static int max_bin(float complex *Z) {
|
||||
int k, kmax;
|
||||
double max;
|
||||
|
||||
max = 0; kmax = 0;
|
||||
for (k = 0; k < N_DFT; k++) {
|
||||
if (cabs(Z[k]) > max) {
|
||||
max = cabs(Z[k]);
|
||||
kmax = k;
|
||||
}
|
||||
}
|
||||
|
||||
return kmax;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------ */
|
||||
|
||||
int getCorrDFT(int abs, int K, unsigned int pos, float *maxv, unsigned int *maxvpos) {
|
||||
int i;
|
||||
int mp = -1;
|
||||
float mx = 0.0;
|
||||
float xnorm = 1;
|
||||
unsigned int mpos = 0;
|
||||
|
||||
dc = 0.0;
|
||||
|
||||
if (N + K > N_DFT/2 - 2) return -1;
|
||||
if (sample_in < delay+N+K) return -2;
|
||||
|
||||
if (pos == 0) pos = sample_out;
|
||||
|
||||
|
||||
for (i = 0; i < N+K; i++) xn[i] = bufs[(pos+M -(N+K-1) + i) % M];
|
||||
while (i < N_DFT) xn[i++] = 0.0;
|
||||
|
||||
rdft(xn, X);
|
||||
|
||||
dc = get_bufmu(pos-sample_out); //oder: dc = creal(X[0])/N_DFT;
|
||||
|
||||
for (i = 0; i < N_DFT; i++) Z[i] = X[i]*Fm[i];
|
||||
|
||||
Nidft(Z, cx);
|
||||
|
||||
|
||||
if (abs) {
|
||||
for (i = N; i < N+K; i++) {
|
||||
if (fabs(creal(cx[i])) > fabs(mx)) { // imag(cx)=0
|
||||
mx = creal(cx[i]);
|
||||
mp = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = N; i < N+K; i++) {
|
||||
if (creal(cx[i]) > mx) { // imag(cx)=0
|
||||
mx = creal(cx[i]);
|
||||
mp = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mp == N || mp == N+K-1) return -4; // Randwert
|
||||
|
||||
mpos = pos - ( N+K-1 - mp );
|
||||
xnorm = sqrt(qs[(mpos + 2*M) % M]);
|
||||
mx /= xnorm*N_DFT;
|
||||
|
||||
*maxv = mx;
|
||||
*maxvpos = mpos;
|
||||
|
||||
if (pos == sample_out) buffered = sample_out-mpos;
|
||||
|
||||
return mp;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------ */
|
||||
|
||||
static int wav_ch = 0; // 0: links bzw. mono; 1: rechts
|
||||
|
||||
static int findstr(char *buff, char *str, int pos) {
|
||||
int i;
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (buff[(pos+i)%4] != str[i]) break;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
float read_wav_header(FILE *fp, float baudrate, int wav_channel) {
|
||||
char txt[4+1] = "\0\0\0\0";
|
||||
unsigned char dat[4];
|
||||
int byte, p=0;
|
||||
|
||||
if (fread(txt, 1, 4, fp) < 4) return -1;
|
||||
if (strncmp(txt, "RIFF", 4)) return -1;
|
||||
if (fread(txt, 1, 4, fp) < 4) return -1;
|
||||
// pos_WAVE = 8L
|
||||
if (fread(txt, 1, 4, fp) < 4) return -1;
|
||||
if (strncmp(txt, "WAVE", 4)) return -1;
|
||||
// pos_fmt = 12L
|
||||
for ( ; ; ) {
|
||||
if ( (byte=fgetc(fp)) == EOF ) return -1;
|
||||
txt[p % 4] = byte;
|
||||
p++; if (p==4) p=0;
|
||||
if (findstr(txt, "fmt ", p) == 4) break;
|
||||
}
|
||||
if (fread(dat, 1, 4, fp) < 4) return -1;
|
||||
if (fread(dat, 1, 2, fp) < 2) return -1;
|
||||
|
||||
if (fread(dat, 1, 2, fp) < 2) return -1;
|
||||
channels = dat[0] + (dat[1] << 8);
|
||||
|
||||
if (fread(dat, 1, 4, fp) < 4) return -1;
|
||||
memcpy(&sample_rate, dat, 4); //sample_rate = dat[0]|(dat[1]<<8)|(dat[2]<<16)|(dat[3]<<24);
|
||||
|
||||
if (fread(dat, 1, 4, fp) < 4) return -1;
|
||||
if (fread(dat, 1, 2, fp) < 2) return -1;
|
||||
//byte = dat[0] + (dat[1] << 8);
|
||||
|
||||
if (fread(dat, 1, 2, fp) < 2) return -1;
|
||||
bits_sample = dat[0] + (dat[1] << 8);
|
||||
|
||||
// pos_dat = 36L + info
|
||||
for ( ; ; ) {
|
||||
if ( (byte=fgetc(fp)) == EOF ) return -1;
|
||||
txt[p % 4] = byte;
|
||||
p++; if (p==4) p=0;
|
||||
if (findstr(txt, "data", p) == 4) break;
|
||||
}
|
||||
if (fread(dat, 1, 4, fp) < 4) return -1;
|
||||
|
||||
|
||||
fprintf(stderr, "sample_rate: %d\n", sample_rate);
|
||||
fprintf(stderr, "bits : %d\n", bits_sample);
|
||||
fprintf(stderr, "channels : %d\n", channels);
|
||||
|
||||
if (wav_channel >= 0 && wav_channel < channels) wav_ch = wav_channel;
|
||||
else wav_ch = 0;
|
||||
fprintf(stderr, "channel-In : %d\n", wav_ch+1);
|
||||
|
||||
if ((bits_sample != 8) && (bits_sample != 16)) return -1;
|
||||
|
||||
samples_per_bit = sample_rate/baudrate;
|
||||
|
||||
fprintf(stderr, "samples/bit: %.2f\n", samples_per_bit);
|
||||
|
||||
return samples_per_bit;
|
||||
}
|
||||
|
||||
static int f32read_sample(FILE *fp, float *s) {
|
||||
int i;
|
||||
short b = 0;
|
||||
|
||||
for (i = 0; i < channels; i++) {
|
||||
|
||||
if (fread( &b, bits_sample/8, 1, fp) != 1) return EOF;
|
||||
|
||||
if (i == wav_ch) { // i = 0: links bzw. mono
|
||||
//if (bits_sample == 8) sint = b-128; // 8bit: 00..FF, centerpoint 0x80=128
|
||||
//if (bits_sample == 16) sint = (short)b;
|
||||
|
||||
if (bits_sample == 8) { b -= 128; }
|
||||
*s = b/128.0;
|
||||
if (bits_sample == 16) { *s /= 256.0; }
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int f32read_csample(FILE *fp, float complex *z) {
|
||||
short x = 0, y = 0;
|
||||
|
||||
if (fread( &x, bits_sample/8, 1, fp) != 1) return EOF;
|
||||
if (fread( &y, bits_sample/8, 1, fp) != 1) return EOF;
|
||||
|
||||
*z = x + I*y;
|
||||
|
||||
if (bits_sample == 8) { *z -= 128 + I*128; }
|
||||
*z /= 128.0;
|
||||
if (bits_sample == 16) { *z /= 256.0; }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float get_bufvar(int ofs) {
|
||||
float mu = xs[(sample_out+M + ofs) % M]/Nvar;
|
||||
float var = qs[(sample_out+M + ofs) % M]/Nvar - mu*mu;
|
||||
return var;
|
||||
}
|
||||
|
||||
float get_bufmu(int ofs) {
|
||||
float mu = xs[(sample_out+M + ofs) % M]/Nvar;
|
||||
return mu;
|
||||
}
|
||||
|
||||
int f32buf_sample(FILE *fp, int inv, int cm) {
|
||||
float s = 0.0;
|
||||
float xneu, xalt;
|
||||
|
||||
float complex z, w;
|
||||
static float complex z0; //= 1.0;
|
||||
double gain = 1.0;
|
||||
|
||||
double t = sample_in / (double)sample_rate;
|
||||
|
||||
|
||||
if (option_iq) {
|
||||
|
||||
if ( f32read_csample(fp, &z) == EOF ) return EOF;
|
||||
raw_iqbuf[sample_in % N_IQBUF] = z;
|
||||
|
||||
z *= cexp(-t*2*M_PI*df*I);
|
||||
w = z * conj(z0);
|
||||
s = gain * carg(w)/M_PI;
|
||||
z0 = z;
|
||||
rot_iqbuf[sample_in % N_IQBUF] = z;
|
||||
|
||||
if (sample_posnoise > 0)
|
||||
{
|
||||
if (sample_out >= sample_posframe && sample_out < sample_posframe+len_sq) {
|
||||
if (sample_out == sample_posframe) V_signal = 0.0;
|
||||
V_signal += cabs(rot_iqbuf[sample_out % N_IQBUF]);
|
||||
}
|
||||
if (sample_out == sample_posframe+len_sq) V_signal /= (double)len_sq;
|
||||
|
||||
if (sample_out >= sample_posnoise && sample_out < sample_posnoise+len_sq) {
|
||||
if (sample_out == sample_posnoise) V_noise = 0.0;
|
||||
V_noise += cabs(rot_iqbuf[sample_out % N_IQBUF]);
|
||||
}
|
||||
if (sample_out == sample_posnoise+len_sq) {
|
||||
V_noise /= (double)len_sq;
|
||||
if (V_signal > 0 && V_noise > 0) {
|
||||
// iq-samples/V [-1..1]
|
||||
// dBw = 2*dBv, P=c*U*U
|
||||
// dBw = 2*10*log10(V/V0)
|
||||
SNRdB = 20.0 * log10(V_signal/V_noise+1e-20);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (option_iq >= 2)
|
||||
{
|
||||
double xbit = 0.0;
|
||||
double h = 1.0; // modulation index, GFSK; h(rs41)=0.8? // rs-depend...
|
||||
//float complex xi = cexp(+I*M_PI*h/samples_per_bit);
|
||||
double f1 = -h*sample_rate/(2*samples_per_bit);
|
||||
double f2 = -f1;
|
||||
|
||||
float complex X1 = 0;
|
||||
float complex X2 = 0;
|
||||
|
||||
int n = samples_per_bit;
|
||||
while (n > 0) {
|
||||
n--;
|
||||
t = -n / (double)sample_rate;
|
||||
z = rot_iqbuf[(sample_in - n + N_IQBUF) % N_IQBUF]; // +1
|
||||
X1 += z*cexp(-t*2*M_PI*f1*I);
|
||||
X2 += z*cexp(-t*2*M_PI*f2*I);
|
||||
}
|
||||
|
||||
xbit = cabs(X2) - cabs(X1);
|
||||
|
||||
s = xbit / samples_per_bit;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (f32read_sample(fp, &s) == EOF) return EOF;
|
||||
}
|
||||
|
||||
if (inv) s = -s; // swap IQ?
|
||||
bufs[sample_in % M] = s - dc_ofs;
|
||||
|
||||
xneu = bufs[(sample_in ) % M];
|
||||
xalt = bufs[(sample_in+M - Nvar) % M];
|
||||
xsum += xneu - xalt; // + xneu - xalt
|
||||
qsum += (xneu - xalt)*(xneu + xalt); // + xneu*xneu - xalt*xalt
|
||||
xs[sample_in % M] = xsum;
|
||||
qs[sample_in % M] = qsum;
|
||||
|
||||
|
||||
if (0 && cm) {
|
||||
// direct correlation
|
||||
}
|
||||
|
||||
|
||||
sample_out = sample_in - delay;
|
||||
|
||||
sample_in += 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_bufbit(int symlen, char *bits, unsigned int mvp, int reset) {
|
||||
// symlen==2: manchester2 0->10,1->01->1: 2.bit
|
||||
|
||||
static unsigned int rcount;
|
||||
static float rbitgrenze;
|
||||
|
||||
double sum = 0.0;
|
||||
|
||||
if (reset) {
|
||||
rcount = 0;
|
||||
rbitgrenze = 0;
|
||||
}
|
||||
|
||||
|
||||
rbitgrenze += samples_per_bit;
|
||||
do {
|
||||
sum += bufs[(rcount + mvp + M) % M];
|
||||
rcount++;
|
||||
} while (rcount < rbitgrenze); // n < samples_per_bit
|
||||
|
||||
if (symlen == 2) {
|
||||
rbitgrenze += samples_per_bit;
|
||||
do {
|
||||
sum -= bufs[(rcount + mvp + M) % M];
|
||||
rcount++;
|
||||
} while (rcount < rbitgrenze); // n < samples_per_bit
|
||||
}
|
||||
|
||||
|
||||
if (symlen != 2) {
|
||||
if (sum >= 0) *bits = '1';
|
||||
else *bits = '0';
|
||||
}
|
||||
else {
|
||||
if (sum >= 0) strncpy(bits, "10", 2);
|
||||
else strncpy(bits, "01", 2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int headcmp(int symlen, char *hdr, int len, unsigned int mvp, int inv, int option_dc) {
|
||||
int errs = 0;
|
||||
int pos;
|
||||
int step = 1;
|
||||
char sign = 0;
|
||||
|
||||
if (symlen != 1) step = 2;
|
||||
if (inv) sign=1;
|
||||
|
||||
for (pos = 0; pos < len; pos += step) {
|
||||
read_bufbit(symlen, rawbits+pos, mvp+1-(int)(len*samples_per_bit), pos==0);
|
||||
}
|
||||
rawbits[pos] = '\0';
|
||||
|
||||
while (len > 0) {
|
||||
if ((rawbits[len-1]^sign) != hdr[len-1]) errs += 1;
|
||||
len--;
|
||||
}
|
||||
|
||||
if (option_dc && errs < 3) {
|
||||
dc_ofs += dc;
|
||||
}
|
||||
|
||||
return errs;
|
||||
}
|
||||
|
||||
int get_fqofs(int hdrlen, unsigned int mvp, float *freq, float *snr) {
|
||||
int j;
|
||||
int buf_start;
|
||||
int presamples = 256*samples_per_bit;
|
||||
|
||||
if (presamples > M_DFT) presamples = M_DFT;
|
||||
|
||||
buf_start = mvp - hdrlen*samples_per_bit - presamples;
|
||||
|
||||
while (buf_start < 0) buf_start += N_IQBUF;
|
||||
|
||||
for (j = 0; j < M_DFT; j++) {
|
||||
Z[j] = Hann[j]*raw_iqbuf[(buf_start+j) % N_IQBUF];
|
||||
}
|
||||
while (j < N_DFT) Z[j++] = 0;
|
||||
|
||||
cdft(Z);
|
||||
df = bin2freq(max_bin(Z));
|
||||
|
||||
// if |df|<eps, +-2400Hz dominant (rs41)
|
||||
if (fabs(df) > 1000.0) df = 0.0;
|
||||
|
||||
|
||||
sample_posframe = sample_in; //mvp - hdrlen*samples_per_bit;
|
||||
sample_posnoise = mvp + sample_rate*7/8.0;
|
||||
|
||||
|
||||
*freq = df;
|
||||
*snr = SNRdB;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int read_sbit(FILE *fp, int symlen, int *bit, int inv, int ofs, int reset, int cm) {
|
||||
// symlen==2: manchester2 10->0,01->1: 2.bit
|
||||
|
||||
static double bitgrenze;
|
||||
static unsigned long scount;
|
||||
|
||||
float sample;
|
||||
|
||||
double sum = 0.0;
|
||||
|
||||
if (reset) {
|
||||
scount = 0;
|
||||
bitgrenze = 0;
|
||||
}
|
||||
|
||||
if (symlen == 2) {
|
||||
bitgrenze += samples_per_bit;
|
||||
do {
|
||||
if (buffered > 0) buffered -= 1;
|
||||
else if (f32buf_sample(fp, inv, cm) == EOF) return EOF;
|
||||
|
||||
sample = bufs[(sample_out-buffered + ofs + M) % M];
|
||||
sum -= sample;
|
||||
|
||||
scount++;
|
||||
} while (scount < bitgrenze); // n < samples_per_bit
|
||||
}
|
||||
|
||||
bitgrenze += samples_per_bit;
|
||||
do {
|
||||
if (buffered > 0) buffered -= 1;
|
||||
else if (f32buf_sample(fp, inv, cm) == EOF) return EOF;
|
||||
|
||||
sample = bufs[(sample_out-buffered + ofs + M) % M];
|
||||
sum += sample;
|
||||
|
||||
scount++;
|
||||
} while (scount < bitgrenze); // n < samples_per_bit
|
||||
|
||||
if (sum >= 0) *bit = 1;
|
||||
else *bit = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int read_IDsbit(FILE *fp, int symlen, int *bit, int inv, int ofs, int reset, int cm) {
|
||||
// symlen==2: manchester2 10->0,01->1: 2.bit
|
||||
|
||||
static double bitgrenze;
|
||||
static unsigned long scount;
|
||||
|
||||
float sample;
|
||||
|
||||
double sum = 0.0;
|
||||
double mid;
|
||||
double l = 1.0;
|
||||
|
||||
if (reset) {
|
||||
scount = 0;
|
||||
bitgrenze = 0;
|
||||
}
|
||||
|
||||
if (symlen == 2) {
|
||||
mid = bitgrenze + (samples_per_bit-1)/2.0;
|
||||
bitgrenze += samples_per_bit;
|
||||
do {
|
||||
if (buffered > 0) buffered -= 1;
|
||||
else if (f32buf_sample(fp, inv, cm) == EOF) return EOF;
|
||||
|
||||
sample = bufs[(sample_out-buffered + ofs + M) % M];
|
||||
if (mid-l < scount && scount < mid+l) sum -= sample;
|
||||
|
||||
scount++;
|
||||
} while (scount < bitgrenze); // n < samples_per_bit
|
||||
}
|
||||
|
||||
mid = bitgrenze + (samples_per_bit-1)/2.0;
|
||||
bitgrenze += samples_per_bit;
|
||||
do {
|
||||
if (buffered > 0) buffered -= 1;
|
||||
else if (f32buf_sample(fp, inv, cm) == EOF) return EOF;
|
||||
|
||||
sample = bufs[(sample_out-buffered + ofs + M) % M];
|
||||
if (mid-l < scount && scount < mid+l) sum += sample;
|
||||
|
||||
scount++;
|
||||
} while (scount < bitgrenze); // n < samples_per_bit
|
||||
|
||||
if (sum >= 0) *bit = 1;
|
||||
else *bit = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
int read_softbit(FILE *fp, int symlen, int *bit, float *sb, float level, int inv, int ofs, int reset, int cm) {
|
||||
// symlen==2: manchester2 10->0,01->1: 2.bit
|
||||
|
||||
static double bitgrenze;
|
||||
static unsigned long scount;
|
||||
|
||||
float sample;
|
||||
|
||||
double sum = 0.0;
|
||||
int n = 0;
|
||||
|
||||
if (reset) {
|
||||
scount = 0;
|
||||
bitgrenze = 0;
|
||||
}
|
||||
|
||||
if (symlen == 2) {
|
||||
bitgrenze += samples_per_bit;
|
||||
do {
|
||||
if (buffered > 0) buffered -= 1;
|
||||
else if (f32buf_sample(fp, inv, cm) == EOF) return EOF;
|
||||
|
||||
sample = bufs[(sample_out-buffered + ofs + M) % M];
|
||||
if (scount > bitgrenze-samples_per_bit && scount < bitgrenze-2)
|
||||
{
|
||||
sum -= sample;
|
||||
n++;
|
||||
}
|
||||
scount++;
|
||||
} while (scount < bitgrenze); // n < samples_per_bit
|
||||
}
|
||||
|
||||
bitgrenze += samples_per_bit;
|
||||
do {
|
||||
if (buffered > 0) buffered -= 1;
|
||||
else if (f32buf_sample(fp, inv, cm) == EOF) return EOF;
|
||||
|
||||
sample = bufs[(sample_out-buffered + ofs + M) % M];
|
||||
if (scount > bitgrenze-samples_per_bit && scount < bitgrenze-2)
|
||||
{
|
||||
sum += sample;
|
||||
n++;
|
||||
}
|
||||
scount++;
|
||||
} while (scount < bitgrenze); // n < samples_per_bit
|
||||
|
||||
if (sum >= 0) *bit = 1;
|
||||
else *bit = 0;
|
||||
|
||||
*sb = sum / n;
|
||||
|
||||
if (*sb > +2.5*level) *sb = +0.8*level;
|
||||
if (*sb > +level) *sb = +level;
|
||||
|
||||
if (*sb < -2.5*level) *sb = -0.8*level;
|
||||
if (*sb < -level) *sb = -level;
|
||||
|
||||
*sb /= level;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
float header_level(char hdr[], int hLen, unsigned int pos, int inv) {
|
||||
int n, bitn;
|
||||
int sgn = 0;
|
||||
double s = 0.0;
|
||||
double sum = 0.0;
|
||||
|
||||
n = 0;
|
||||
bitn = 0;
|
||||
while ( bitn < hLen && (n < N) ) {
|
||||
sgn = (hdr[bitn]&1)*2-1; // {'0','1'} -> {-1,1}
|
||||
s = bufs[(pos-N + n + M) % M];
|
||||
if (inv) s = -s;
|
||||
sum += s * sgn;
|
||||
n++;
|
||||
bitn = n / samples_per_bit;
|
||||
}
|
||||
sum /= n;
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#define SQRT2 1.4142135624 // sqrt(2)
|
||||
// sigma = sqrt(log(2)) / (2*PI*BT):
|
||||
//#define SIGMA 0.2650103635 // BT=0.5: 0.2650103635 , BT=0.3: 0.4416839392
|
||||
|
||||
// Gaussian FM-pulse
|
||||
static double Q(double x) {
|
||||
return 0.5 - 0.5*erf(x/SQRT2);
|
||||
}
|
||||
static double pulse(double t, double sigma) {
|
||||
return Q((t-0.5)/sigma) - Q((t+0.5)/sigma);
|
||||
}
|
||||
|
||||
|
||||
static double norm2_match() {
|
||||
int i;
|
||||
double x, y = 0.0;
|
||||
for (i = 0; i < N; i++) {
|
||||
x = match[i];
|
||||
y += x*x;
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
int init_buffers(char hdr[], int hLen, float BT, int opt_iq) {
|
||||
//hLen = strlen(header) = HEADLEN;
|
||||
|
||||
int i, pos;
|
||||
float b0, b1, b2, b, t;
|
||||
float normMatch;
|
||||
double sigma = sqrt(log(2)) / (2*M_PI*BT);
|
||||
|
||||
int K;
|
||||
int n, k;
|
||||
float *m = NULL;
|
||||
|
||||
option_iq = opt_iq;
|
||||
|
||||
N = hLen * samples_per_bit + 0.5;
|
||||
M = 3*N;
|
||||
if (samples_per_bit < 6) M = 6*N;
|
||||
Nvar = N; //N/2; // = N/k
|
||||
|
||||
bufs = (float *)calloc( M+1, sizeof(float)); if (bufs == NULL) return -100;
|
||||
match = (float *)calloc( N+1, sizeof(float)); if (match == NULL) return -100;
|
||||
|
||||
xs = (float *)calloc( M+1, sizeof(float)); if (xs == NULL) return -100;
|
||||
qs = (float *)calloc( M+1, sizeof(float)); if (qs == NULL) return -100;
|
||||
|
||||
|
||||
rawbits = (char *)calloc( N+1, sizeof(char)); if (rawbits == NULL) return -100;
|
||||
|
||||
for (i = 0; i < M; i++) bufs[i] = 0.0;
|
||||
|
||||
|
||||
for (i = 0; i < N; i++) {
|
||||
pos = i/samples_per_bit;
|
||||
t = (i - pos*samples_per_bit)/samples_per_bit - 0.5;
|
||||
|
||||
b1 = ((hdr[pos] & 0x1) - 0.5)*2.0;
|
||||
b = b1*pulse(t, sigma);
|
||||
|
||||
if (pos > 0) {
|
||||
b0 = ((hdr[pos-1] & 0x1) - 0.5)*2.0;
|
||||
b += b0*pulse(t+1, sigma);
|
||||
}
|
||||
|
||||
if (pos < hLen) {
|
||||
b2 = ((hdr[pos+1] & 0x1) - 0.5)*2.0;
|
||||
b += b2*pulse(t-1, sigma);
|
||||
}
|
||||
|
||||
match[i] = b;
|
||||
}
|
||||
|
||||
normMatch = sqrt(norm2_match());
|
||||
for (i = 0; i < N; i++) {
|
||||
match[i] /= normMatch;
|
||||
}
|
||||
|
||||
|
||||
delay = N/16;
|
||||
sample_in = 0;
|
||||
|
||||
K = M-N - delay; //N/2 - delay; // N+K < M
|
||||
|
||||
LOG2N = 2 + (int)(log(N+K)/log(2));
|
||||
N_DFT = 1 << LOG2N;
|
||||
|
||||
while (N + K > N_DFT/2 - 2) {
|
||||
LOG2N += 1;
|
||||
N_DFT <<= 1;
|
||||
}
|
||||
|
||||
|
||||
xn = calloc(N_DFT+1, sizeof(float)); if (xn == NULL) return -1;
|
||||
|
||||
ew = calloc(LOG2N+1, sizeof(float complex)); if (ew == NULL) return -1;
|
||||
Fm = calloc(N_DFT+1, sizeof(float complex)); if (Fm == NULL) return -1;
|
||||
X = calloc(N_DFT+1, sizeof(float complex)); if (X == NULL) return -1;
|
||||
Z = calloc(N_DFT+1, sizeof(float complex)); if (Z == NULL) return -1;
|
||||
cx = calloc(N_DFT+1, sizeof(float complex)); if (cx == NULL) return -1;
|
||||
|
||||
M_DFT = M;
|
||||
Hann = calloc(N_DFT+1, sizeof(float complex)); if (Hann == NULL) return -1;
|
||||
for (i = 0; i < M_DFT; i++) Hann[i] = 0.5 * (1 - cos( 2 * M_PI * i / (double)(M_DFT-1) ) );
|
||||
|
||||
for (n = 0; n < LOG2N; n++) {
|
||||
k = 1 << n;
|
||||
ew[n] = cexp(-I*M_PI/(float)k);
|
||||
}
|
||||
|
||||
m = calloc(N_DFT+1, sizeof(float)); if (m == NULL) return -1;
|
||||
for (i = 0; i < N; i++) m[N-1 - i] = match[i];
|
||||
while (i < N_DFT) m[i++] = 0.0;
|
||||
rdft(m, Fm);
|
||||
|
||||
free(m); m = NULL;
|
||||
|
||||
|
||||
if (option_iq)
|
||||
{
|
||||
if (channels < 2) return -1;
|
||||
/*
|
||||
M_DFT = samples_per_bit*256+0.5;
|
||||
while ( (1 << LOG2N) < M_DFT ) LOG2N++;
|
||||
LOG2N++;
|
||||
N_DFT = (1 << LOG2N);
|
||||
N_IQBUF = M_DFT + samples_per_bit*(64+16);
|
||||
*/
|
||||
N_IQBUF = N_DFT;
|
||||
raw_iqbuf = calloc(N_IQBUF+1, sizeof(float complex)); if (raw_iqbuf == NULL) return -1;
|
||||
rot_iqbuf = calloc(N_IQBUF+1, sizeof(float complex)); if (rot_iqbuf == NULL) return -1;
|
||||
|
||||
len_sq = samples_per_bit*8;
|
||||
}
|
||||
|
||||
|
||||
return K;
|
||||
}
|
||||
|
||||
int free_buffers() {
|
||||
|
||||
if (match) { free(match); match = NULL; }
|
||||
if (bufs) { free(bufs); bufs = NULL; }
|
||||
if (xs) { free(xs); xs = NULL; }
|
||||
if (qs) { free(qs); qs = NULL; }
|
||||
if (rawbits) { free(rawbits); rawbits = NULL; }
|
||||
|
||||
if (xn) { free(xn); xn = NULL; }
|
||||
if (ew) { free(ew); ew = NULL; }
|
||||
if (Fm) { free(Fm); Fm = NULL; }
|
||||
if (X) { free(X); X = NULL; }
|
||||
if (Z) { free(Z); Z = NULL; }
|
||||
if (cx) { free(cx); cx = NULL; }
|
||||
|
||||
if (Hann) { free(Hann); Hann = NULL; }
|
||||
|
||||
if (option_iq)
|
||||
{
|
||||
if (raw_iqbuf) { free(raw_iqbuf); raw_iqbuf = NULL; }
|
||||
if (rot_iqbuf) { free(rot_iqbuf); rot_iqbuf = NULL; }
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------ */
|
||||
|
||||
unsigned int get_sample() {
|
||||
return sample_out;
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
float read_wav_header(FILE*, float, int);
|
||||
int f32buf_sample(FILE*, int, int);
|
||||
int read_sbit(FILE*, int, int*, int, int, int, int);
|
||||
int read_IDsbit(FILE*, int, int*, int, int, int, int);
|
||||
int read_softbit(FILE *fp, int symlen, int *bit, float *sb, float level, int inv, int ofs, int reset, int cm);
|
||||
float header_level(char hdr[], int hLen, unsigned int pos, int inv);
|
||||
|
||||
int getCorrDFT(int, int, unsigned int, float *, unsigned int *);
|
||||
int headcmp(int, char*, int, unsigned int, int, int);
|
||||
int get_fqofs(int, unsigned int, float *, float *);
|
||||
float get_bufvar(int);
|
||||
float get_bufmu(int);
|
||||
|
||||
int init_buffers(char*, int, float, int);
|
||||
int free_buffers(void);
|
||||
|
||||
unsigned int get_sample(void);
|
||||
|
|
@ -32,7 +32,7 @@ typedef struct {
|
|||
int frnr;
|
||||
int sonde_typ;
|
||||
ui32_t SN6;
|
||||
ui32_t SN9;
|
||||
ui32_t SN;
|
||||
int week; int gpssec;
|
||||
int jahr; int monat; int tag;
|
||||
int std; int min; float sek;
|
||||
|
@ -55,7 +55,11 @@ int option_verbose = 0, // ausfuehrliche Anzeige
|
|||
option_ecc = 0,
|
||||
option_ptu = 0,
|
||||
option_ths = 0,
|
||||
option_json = 0, // JSON blob output (for auto_rx)
|
||||
wavloaded = 0;
|
||||
int wav_channel = 0; // audio channel: left
|
||||
|
||||
int ptu_out = 0;
|
||||
|
||||
int start = 0;
|
||||
|
||||
|
@ -198,7 +202,7 @@ int dat_out(ui8_t *dat_bits) {
|
|||
|
||||
if (fr_id == 1) {
|
||||
// 00..31: ? GPS-Sats in Sicht?
|
||||
msek = bits2val(dat_bits+32, 16);
|
||||
msek = bits2val(dat_bits+32, 16); // UTC (= GPS - 18sec ab 1.1.2017)
|
||||
gpx.sek = msek/1000.0;
|
||||
}
|
||||
|
||||
|
@ -329,7 +333,7 @@ float get_Temp2(float *meas) { // meas[0..4]
|
|||
R = (f-f1)/g; // meas[0,3,4] > 0 ?
|
||||
if (R > 0) T = 1/(1/T0 + 1/B0 * log(R/R0));
|
||||
|
||||
if (option_ptu && option_verbose == 2) {
|
||||
if (option_ptu && ptu_out && option_verbose == 2) {
|
||||
printf(" (Rso: %.1f , Rb: %.1f)", Rs_o/1e3, Rb/1e3);
|
||||
}
|
||||
|
||||
|
@ -376,22 +380,30 @@ float get_Temp4(float *meas) { // meas[0..4]
|
|||
}
|
||||
|
||||
|
||||
#define SNbit 0x0100
|
||||
#define RSNbit 0x0100 // radiosonde DFM-06,DFM-09
|
||||
#define PSNbit 0x0200 // pilotsonde PS-15
|
||||
int conf_out(ui8_t *conf_bits) {
|
||||
int conf_id;
|
||||
int ret = 0;
|
||||
int val, hl;
|
||||
ui32_t SN6, SN;
|
||||
static int chAbit, chA[2];
|
||||
ui32_t SN6, SN9;
|
||||
static int chCbit, chC[2];
|
||||
static int chDbit, chD[2];
|
||||
static int ch7bit, ch7[2];
|
||||
static ui32_t SN_A, SN_C, SN_D, SN_7;
|
||||
|
||||
conf_id = bits2val(conf_bits, 4);
|
||||
|
||||
//if (conf_id > 6) gpx.SN6 = 0; //// gpx.sonde_typ & 0xF = 9; // SNbit?
|
||||
|
||||
if ((gpx.sonde_typ & 0xFF) < 9 && conf_id == 6) {
|
||||
SN6 = bits2val(conf_bits+4, 4*6); // DFM-06: Kanal 6
|
||||
if ( SN6 == gpx.SN6 ) { // nur Nibble-Werte 0..9
|
||||
gpx.sonde_typ = SNbit | 6;
|
||||
// gibt es Kanaele > 6 (2-teilige ID)?
|
||||
// if (conf_id > 6) gpx.SN6 = 0; // -> DFM-09,PS-15 // SNbit?
|
||||
//
|
||||
// SN/ID immer im letzten Kanal?
|
||||
if ((gpx.sonde_typ & 0xF) < 7 && conf_id == 6) {
|
||||
SN6 = bits2val(conf_bits+4, 4*6); // DFM-06: Kanal 6
|
||||
if ( SN6 == gpx.SN6 && SN6 != 0) { // nur Nibble-Werte 0..9
|
||||
gpx.sonde_typ = RSNbit | 6;
|
||||
ptu_out = 6;
|
||||
ret = 6;
|
||||
}
|
||||
else {
|
||||
|
@ -401,22 +413,84 @@ int conf_out(ui8_t *conf_bits) {
|
|||
}
|
||||
if (conf_id == 0xA) { // 0xACxxxxy
|
||||
val = bits2val(conf_bits+8, 4*5);
|
||||
hl = (val & 1) == 0;
|
||||
hl = (val & 1); // val&0xF 0,1?
|
||||
chA[hl] = (val >> 4) & 0xFFFF;
|
||||
chAbit |= 1 << hl;
|
||||
if (chAbit == 3) { // DFM-09: Kanal A
|
||||
SN9 = (chA[1] << 16) | chA[0];
|
||||
if ( SN9 == gpx.SN9 ) {
|
||||
gpx.sonde_typ = SNbit | 9;
|
||||
SN = (chA[0] << 16) | chA[1];
|
||||
if ( SN == SN_A ) {
|
||||
gpx.sonde_typ = RSNbit | 0xA;
|
||||
gpx.SN = SN;
|
||||
ptu_out = 9;
|
||||
ret = 9;
|
||||
}
|
||||
else {
|
||||
gpx.sonde_typ = 0;
|
||||
}
|
||||
gpx.SN9 = SN9;
|
||||
SN_A = SN;
|
||||
chAbit = 0;
|
||||
}
|
||||
}
|
||||
if (conf_id == 0xC) { // 0xCCxxxxy
|
||||
val = bits2val(conf_bits+8, 4*5);
|
||||
hl = (val & 1);
|
||||
chC[hl] = (val >> 4) & 0xFFFF;
|
||||
chCbit |= 1 << hl;
|
||||
if (chCbit == 3) { // DFM-17? Kanal C
|
||||
SN = (chC[0] << 16) | chC[1];
|
||||
if ( SN == SN_C ) {
|
||||
gpx.sonde_typ = RSNbit | 0xC;
|
||||
gpx.SN = SN;
|
||||
ptu_out = 9;
|
||||
ret = 17;
|
||||
}
|
||||
else {
|
||||
gpx.sonde_typ = 0;
|
||||
}
|
||||
SN_C = SN;
|
||||
chCbit = 0;
|
||||
}
|
||||
}
|
||||
if (conf_id == 0xD) { // 0xDCxxxxy
|
||||
val = bits2val(conf_bits+8, 4*5);
|
||||
hl = (val & 1);
|
||||
chD[hl] = (val >> 4) & 0xFFFF;
|
||||
chDbit |= 1 << hl;
|
||||
if (chDbit == 3) { // DFM-17? Kanal D
|
||||
SN = (chD[0] << 16) | chD[1];
|
||||
if ( SN == SN_D ) {
|
||||
gpx.sonde_typ = RSNbit | 0xD;
|
||||
gpx.SN = SN;
|
||||
ptu_out = 9;
|
||||
ret = 18;
|
||||
}
|
||||
else {
|
||||
gpx.sonde_typ = 0;
|
||||
}
|
||||
SN_D = SN;
|
||||
chDbit = 0;
|
||||
}
|
||||
}
|
||||
if (conf_id == 0x7) { // 0x70xxxxy
|
||||
val = bits2val(conf_bits+8, 4*5);
|
||||
hl = (val & 1);
|
||||
ch7[hl] = (val >> 4) & 0xFFFF;
|
||||
ch7bit |= 1 << hl;
|
||||
if (ch7bit == 3) { // PS-15: Kanal 7
|
||||
SN = (ch7[0] << 16) | ch7[1];
|
||||
if ( SN == SN_7 ) {
|
||||
gpx.sonde_typ = PSNbit | 0x7;
|
||||
gpx.SN = SN;
|
||||
ptu_out = 0;
|
||||
ret = 15;
|
||||
}
|
||||
else {
|
||||
gpx.sonde_typ = 0;
|
||||
}
|
||||
SN_7 = SN;
|
||||
ch7bit = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (conf_id >= 0 && conf_id <= 4) {
|
||||
val = bits2val(conf_bits+4, 4*6);
|
||||
|
@ -430,7 +504,7 @@ int conf_out(ui8_t *conf_bits) {
|
|||
}
|
||||
|
||||
// STM32-status: Bat, MCU-Temp
|
||||
if ((gpx.sonde_typ & 0xFF) == 9) { // DFM-09 (STM32)
|
||||
if ((gpx.sonde_typ & 0xF) == 0xA) { // DFM-09 (STM32)
|
||||
if (conf_id == 0x5) { // voltage
|
||||
val = bits2val(conf_bits+8, 4*4);
|
||||
gpx.status[0] = val/1000.0;
|
||||
|
@ -469,7 +543,7 @@ void print_gpx() {
|
|||
printf(" vH: %5.2f ", gpx.horiV);
|
||||
printf(" D: %5.1f ", gpx.dir);
|
||||
printf(" vV: %5.2f ", gpx.vertV);
|
||||
if (option_ptu) {
|
||||
if (option_ptu && ptu_out) {
|
||||
float t = get_Temp(gpx.meas24);
|
||||
if (t > -270.0) printf(" T=%.1fC ", t);
|
||||
if (option_verbose == 2) {
|
||||
|
@ -482,31 +556,47 @@ void print_gpx() {
|
|||
printf(" f4: %.2f ", gpx.meas24[4]);
|
||||
}
|
||||
}
|
||||
if (option_verbose == 2 && (gpx.sonde_typ & 0xFF) == 9) {
|
||||
if (option_verbose == 2 && (gpx.sonde_typ & 0xF) == 0xA) {
|
||||
printf(" U: %.2fV ", gpx.status[0]);
|
||||
printf(" Ti: %.1fK ", gpx.status[1]);
|
||||
}
|
||||
if (option_verbose && (gpx.sonde_typ & SNbit))
|
||||
if ( option_verbose )
|
||||
{
|
||||
if ((gpx.sonde_typ & 0xFF) == 6) {
|
||||
printf(" (ID%1d:%06X) ", gpx.sonde_typ & 0xF, gpx.SN6);
|
||||
sprintf(sonde_id, "DFM06-%06X", gpx.SN6);
|
||||
if (gpx.sonde_typ & RSNbit)
|
||||
{
|
||||
if ((gpx.sonde_typ & 0xF) == 6) { // DFM-06
|
||||
printf(" (ID6:%06X) ", gpx.SN6);
|
||||
sprintf(sonde_id, "DFM06-%06X", gpx.SN6);
|
||||
}
|
||||
if ((gpx.sonde_typ & 0xF) == 0xA) { // DFM-09
|
||||
printf(" (ID9:%06u) ", gpx.SN);
|
||||
sprintf(sonde_id, "DFM09-%06u", gpx.SN);
|
||||
}
|
||||
if ((gpx.sonde_typ & 0xF) == 0xC || // DFM-17?
|
||||
(gpx.sonde_typ & 0xF) == 0xD ) {
|
||||
printf(" (ID-%1X:%06u) ", gpx.sonde_typ & 0xF, gpx.SN);
|
||||
sprintf(sonde_id, "DFM17-%06u", gpx.SN);
|
||||
}
|
||||
gpx.sonde_typ ^= RSNbit;
|
||||
}
|
||||
if ((gpx.sonde_typ & 0xFF) == 9) {
|
||||
printf(" (ID%1d:%06u) ", gpx.sonde_typ & 0xF, gpx.SN9);
|
||||
sprintf(sonde_id, "DFM09-%06u", gpx.SN9);
|
||||
if (gpx.sonde_typ & PSNbit) {
|
||||
if ((gpx.sonde_typ & 0xF) == 0x7) { // PS-15?
|
||||
printf(" (ID15:%06u) ", gpx.SN);
|
||||
sprintf(sonde_id, "DFM15-%06u", gpx.SN);
|
||||
}
|
||||
gpx.sonde_typ ^= PSNbit;
|
||||
}
|
||||
gpx.sonde_typ ^= SNbit;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// Print JSON blob
|
||||
// Get temperature
|
||||
float t = get_Temp(gpx.meas24);
|
||||
printf("\n{ \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f, \"temp\":%.1f }\n", gpx.frnr, sonde_id, gpx.jahr, gpx.monat, gpx.tag, gpx.std, gpx.min, gpx.sek, gpx.lat, gpx.lon, gpx.alt, gpx.horiV, gpx.dir, gpx.vertV, t );
|
||||
|
||||
|
||||
if (option_json)
|
||||
{
|
||||
// Print JSON blob
|
||||
// Get temperature
|
||||
float t = get_Temp(gpx.meas24);
|
||||
printf("\n{ \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f, \"temp\":%.1f }\n", gpx.frnr, sonde_id, gpx.jahr, gpx.monat, gpx.tag, gpx.std, gpx.min, gpx.sek, gpx.lat, gpx.lon, gpx.alt, gpx.horiV, gpx.dir, gpx.vertV, t );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -636,6 +726,7 @@ int main(int argc, char **argv) {
|
|||
fprintf(stderr, " -i, --invert\n");
|
||||
fprintf(stderr, " --ecc (Hamming ECC)\n");
|
||||
fprintf(stderr, " --ths <x> (peak threshold; default=%.1f)\n", thres);
|
||||
fprintf(stderr, " --json (JSON output)\n");
|
||||
return 0;
|
||||
}
|
||||
else if ( (strcmp(*argv, "-v") == 0) || (strcmp(*argv, "--verbose") == 0) ) {
|
||||
|
@ -652,7 +743,9 @@ int main(int argc, char **argv) {
|
|||
option_inv = 0x1;
|
||||
}
|
||||
else if ( (strcmp(*argv, "--ecc") == 0) ) { option_ecc = 1; }
|
||||
else if ( (strcmp(*argv, "--ptu") == 0) ) { option_ptu = 1; }
|
||||
else if ( (strcmp(*argv, "--json") == 0) ) { option_json = 1; }
|
||||
else if ( (strcmp(*argv, "--ptu") == 0) ) { option_ptu = 1; ptu_out = 1; }
|
||||
else if ( (strcmp(*argv, "--ch2") == 0) ) { wav_channel = 1; } // right channel (default: 0=left)
|
||||
else if ( (strcmp(*argv, "--ths") == 0) ) {
|
||||
++argv;
|
||||
if (*argv) {
|
||||
|
@ -673,7 +766,7 @@ int main(int argc, char **argv) {
|
|||
if (!wavloaded) fp = stdin;
|
||||
|
||||
|
||||
spb = read_wav_header(fp, (float)BAUD_RATE);
|
||||
spb = read_wav_header(fp, (float)BAUD_RATE, wav_channel);
|
||||
if ( spb < 0 ) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "error: wav header\n");
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -50,6 +50,8 @@ int option_verbose = 0, // ausfuehrliche Anzeige
|
|||
option_ptu = 0,
|
||||
option_dc = 0,
|
||||
wavloaded = 0;
|
||||
int wav_channel = 0; // audio channel: left
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
/*
|
||||
|
@ -97,17 +99,23 @@ dduudduudduudduu duduudduuduudduu ddududuudduduudd uduuddududududud uudduduuddu
|
|||
#define HEADLEN 32 // HEADLEN+HEADOFS=32 <= strlen(header)
|
||||
#define HEADOFS 0
|
||||
// Sync-Header (raw) // Sonde-Header (bits)
|
||||
//char head[] = "11001100110011001010011001001100"; //"011001001001111100100000"; // M10: 64 9F 20 , M2K2: 64 8F 20
|
||||
//"011101101001111100100000"; // M??: 76 9F 20
|
||||
//"011001000100100100001001"; // M10-dop: 64 49 09
|
||||
//char head[] = "11001100110011001010011001001100"; //"0110010010011111"; // M10: 64 9F , M2K2: 64 8F
|
||||
//"0111011010011111"; // M10: 76 9F , w/ aux-data
|
||||
//"0110010001001001"; // M10-dop: 64 49 09
|
||||
//"0110010010101111"; // M10+: 64 AF w/ gtop-GPS
|
||||
char rawheader[] = "10011001100110010100110010011001";
|
||||
|
||||
#define FRAME_LEN 102
|
||||
#define FRAME_LEN (100+1) // 0x64+1
|
||||
#define BITFRAME_LEN (FRAME_LEN*BITS)
|
||||
|
||||
ui8_t frame_bytes[FRAME_LEN+10];
|
||||
#define AUX_LEN 20
|
||||
#define BITAUX_LEN (AUX_LEN*BITS)
|
||||
|
||||
char frame_bits[BITFRAME_LEN+4];
|
||||
ui8_t frame_bytes[FRAME_LEN+AUX_LEN+4];
|
||||
|
||||
char frame_bits[BITFRAME_LEN+BITAUX_LEN+8];
|
||||
|
||||
int auxlen = 0; // 0 .. 0x76-0x64
|
||||
|
||||
|
||||
int bits2bytes(char *bitstr, ui8_t *bytes) {
|
||||
|
@ -117,7 +125,7 @@ int bits2bytes(char *bitstr, ui8_t *bytes) {
|
|||
bitpos = 0;
|
||||
bytepos = 0;
|
||||
|
||||
while (bytepos < FRAME_LEN) {
|
||||
while (bytepos < FRAME_LEN+AUX_LEN) {
|
||||
|
||||
byteval = 0;
|
||||
d = 1;
|
||||
|
@ -134,24 +142,25 @@ int bits2bytes(char *bitstr, ui8_t *bytes) {
|
|||
|
||||
}
|
||||
|
||||
//while (bytepos < FRAME_LEN) bytes[bytepos++] = 0;
|
||||
//while (bytepos < FRAME_LEN+AUX_LEN) bytes[bytepos++] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#define stdFLEN 0x64 // pos[0]=0x64
|
||||
#define pos_GPSTOW 0x0A // 4 byte
|
||||
#define pos_GPSlat 0x0E // 4 byte
|
||||
#define pos_GPSlon 0x12 // 4 byte
|
||||
#define pos_GPSalt 0x16 // 4 byte
|
||||
#define pos_GPSweek 0x20 // 2 byte
|
||||
//Velocity East-North-Up (ENU)
|
||||
#define pos_GPSvO 0x04 // 2 byte
|
||||
#define pos_GPSvN 0x06 // 2 byte
|
||||
#define pos_GPSvV 0x08 // 2 byte
|
||||
#define pos_SN 0x5D // 2+3 byte
|
||||
#define pos_Check 0x63 // 2 byte
|
||||
#define pos_GPSvE 0x04 // 2 byte
|
||||
#define pos_GPSvN 0x06 // 2 byte
|
||||
#define pos_GPSvU 0x08 // 2 byte
|
||||
#define pos_SN 0x5D // 2+3 byte
|
||||
#define pos_Check (stdFLEN-1) // 2 byte
|
||||
|
||||
|
||||
#define ANSI_COLOR_RED "\x1b[31m"
|
||||
|
@ -314,7 +323,7 @@ int get_GPSvel() {
|
|||
const double ms2kn100 = 2e2; // m/s -> knots: 1 m/s = 3.6/1.852 kn = 1.94 kn
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
byte = frame_bytes[pos_GPSvO + i];
|
||||
byte = frame_bytes[pos_GPSvE + i];
|
||||
gpsVel_bytes[i] = byte;
|
||||
}
|
||||
vel16 = gpsVel_bytes[0] << 8 | gpsVel_bytes[1];
|
||||
|
@ -341,7 +350,7 @@ int get_GPSvel() {
|
|||
datum.vD = dir;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
byte = frame_bytes[pos_GPSvV + i];
|
||||
byte = frame_bytes[pos_GPSvU + i];
|
||||
gpsVel_bytes[i] = byte;
|
||||
}
|
||||
vel16 = gpsVel_bytes[0] << 8 | gpsVel_bytes[1];
|
||||
|
@ -637,8 +646,8 @@ int print_pos(int csOK) {
|
|||
if (option_verbose) {
|
||||
err |= get_GPSvel();
|
||||
if (!err) {
|
||||
//if (option_verbose == 2) fprintf(stdout, " "col_GPSvel"(%.1f , %.1f : %.1f°)"col_TXT" ", datum.vx, datum.vy, datum.vD2);
|
||||
fprintf(stdout, " vH: "col_GPSvel"%.1f"col_TXT" D: "col_GPSvel"%.1f°"col_TXT" vV: "col_GPSvel"%.1f"col_TXT" ", datum.vH, datum.vD, datum.vV);
|
||||
//if (option_verbose == 2) fprintf(stdout, " "col_GPSvel"(%.1f , %.1f : %.1f)"col_TXT" ", datum.vx, datum.vy, datum.vD2);
|
||||
fprintf(stdout, " vH: "col_GPSvel"%.1f"col_TXT" D: "col_GPSvel"%.1f"col_TXT"° vV: "col_GPSvel"%.1f"col_TXT" ", datum.vH, datum.vD, datum.vV);
|
||||
}
|
||||
if (option_verbose >= 2) {
|
||||
get_SN();
|
||||
|
@ -705,26 +714,33 @@ int print_frame(int pos) {
|
|||
int i;
|
||||
ui8_t byte;
|
||||
int cs1, cs2;
|
||||
int flen = stdFLEN; // stdFLEN=0x64, auxFLEN=0x76
|
||||
|
||||
bits2bytes(frame_bits, frame_bytes);
|
||||
flen = frame_bytes[0];
|
||||
if (flen == stdFLEN) auxlen = 0;
|
||||
else {
|
||||
auxlen = flen - stdFLEN;
|
||||
if (auxlen < 0 || auxlen > AUX_LEN) auxlen = 0;
|
||||
}
|
||||
|
||||
cs1 = (frame_bytes[pos_Check] << 8) | frame_bytes[pos_Check+1];
|
||||
cs2 = checkM10(frame_bytes, pos_Check);
|
||||
cs1 = (frame_bytes[pos_Check+auxlen] << 8) | frame_bytes[pos_Check+auxlen+1];
|
||||
cs2 = checkM10(frame_bytes, pos_Check+auxlen);
|
||||
|
||||
if (option_raw) {
|
||||
|
||||
if (option_color && frame_bytes[1] != 0x49) {
|
||||
fprintf(stdout, col_FRTXT);
|
||||
for (i = 0; i < FRAME_LEN-1; i++) {
|
||||
for (i = 0; i < FRAME_LEN+auxlen; i++) {
|
||||
byte = frame_bytes[i];
|
||||
if ((i >= pos_GPSTOW) && (i < pos_GPSTOW+4)) 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);
|
||||
if ((i >= pos_GPSalt) && (i < pos_GPSalt+4)) fprintf(stdout, col_GPSalt);
|
||||
if ((i >= pos_GPSweek) && (i < pos_GPSweek+2)) fprintf(stdout, col_GPSweek);
|
||||
if ((i >= pos_GPSvO) && (i < pos_GPSvO+6)) fprintf(stdout, col_GPSvel);
|
||||
if ((i >= pos_GPSvE) && (i < pos_GPSvE+6)) fprintf(stdout, col_GPSvel);
|
||||
if ((i >= pos_SN) && (i < pos_SN+5)) fprintf(stdout, col_SN);
|
||||
if ((i >= pos_Check) && (i < pos_Check+2)) fprintf(stdout, col_Check);
|
||||
if ((i >= pos_Check+auxlen) && (i < pos_Check+auxlen+2)) fprintf(stdout, col_Check);
|
||||
fprintf(stdout, "%02x", byte);
|
||||
fprintf(stdout, col_FRTXT);
|
||||
}
|
||||
|
@ -736,7 +752,7 @@ int print_frame(int pos) {
|
|||
fprintf(stdout, ANSI_COLOR_RESET"\n");
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < FRAME_LEN-1; i++) {
|
||||
for (i = 0; i < FRAME_LEN+auxlen; i++) {
|
||||
byte = frame_bytes[i];
|
||||
fprintf(stdout, "%02x", byte);
|
||||
}
|
||||
|
@ -750,7 +766,7 @@ int print_frame(int pos) {
|
|||
}
|
||||
else if (frame_bytes[1] == 0x49) {
|
||||
if (option_verbose == 3) {
|
||||
for (i = 0; i < FRAME_LEN-1; i++) {
|
||||
for (i = 0; i < FRAME_LEN+auxlen; i++) {
|
||||
byte = frame_bytes[i];
|
||||
fprintf(stdout, "%02x", byte);
|
||||
}
|
||||
|
@ -777,7 +793,7 @@ int main(int argc, char **argv) {
|
|||
int herrs, herr1;
|
||||
int headerlen = 0;
|
||||
|
||||
int k,K;
|
||||
int k, K;
|
||||
float mv;
|
||||
unsigned int mv_pos, mv0_pos;
|
||||
int mp = 0;
|
||||
|
@ -825,7 +841,8 @@ int main(int argc, char **argv) {
|
|||
else if ( (strcmp(*argv, "--dc") == 0) ) {
|
||||
option_dc = 1;
|
||||
}
|
||||
else if (strcmp(*argv, "--ths") == 0) {
|
||||
else if ( (strcmp(*argv, "--ch2") == 0) ) { wav_channel = 1; } // right channel (default: 0=left)
|
||||
else if ( (strcmp(*argv, "--ths") == 0) ) {
|
||||
++argv;
|
||||
if (*argv) {
|
||||
thres = atof(*argv);
|
||||
|
@ -845,7 +862,7 @@ int main(int argc, char **argv) {
|
|||
if (!wavloaded) fp = stdin;
|
||||
|
||||
|
||||
spb = read_wav_header(fp, (float)BAUD_RATE);
|
||||
spb = read_wav_header(fp, (float)BAUD_RATE, wav_channel);
|
||||
if ( spb < 0 ) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "error: wav header\n");
|
||||
|
@ -858,7 +875,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
symlen = 2;
|
||||
headerlen = strlen(rawheader);
|
||||
bitofs = 1; // +1 .. +2
|
||||
bitofs = 0; // 0 .. +2
|
||||
K = init_buffers(rawheader, headerlen, 1); // shape=0 (alt. shape=1)
|
||||
if ( K < 0 ) {
|
||||
fprintf(stderr, "error: init buffers\n");
|
||||
|
@ -886,10 +903,11 @@ int main(int argc, char **argv) {
|
|||
if (mv_pos > mv0_pos) {
|
||||
|
||||
header_found = 0;
|
||||
herrs = headcmp(1, rawheader, headerlen, mv_pos, mv<0, option_dc); // (symlen=2)
|
||||
herrs = headcmp(1, rawheader, headerlen, mv_pos, mv<0, option_dc); // header nicht manchester!
|
||||
herr1 = 0;
|
||||
if (herrs <= 3 && herrs > 0) {
|
||||
herr1 = headcmp(symlen, rawheader, headerlen, mv_pos+1, mv<0, option_dc);
|
||||
herr1 = headcmp(1, rawheader, headerlen, mv_pos+1, mv<0, option_dc);
|
||||
//int herr2 = headcmp(1, rawheader, headerlen, mv_pos-1, mv<0, option_dc);
|
||||
if (herr1 < herrs) {
|
||||
herrs = herr1;
|
||||
herr1 = 1;
|
||||
|
@ -904,7 +922,7 @@ int main(int argc, char **argv) {
|
|||
pos /= 2;
|
||||
bit0 = '0';
|
||||
|
||||
while ( pos < BITFRAME_LEN ) {
|
||||
while ( pos < BITFRAME_LEN+BITAUX_LEN ) {
|
||||
header_found = !(pos>=BITFRAME_LEN-10);
|
||||
bitQ = read_sbit(fp, symlen, &bit, option_inv, bitofs, bitpos==0, !header_found); // symlen=2, return: zeroX/bit
|
||||
if (bitQ == EOF) { break; }
|
||||
|
|
|
@ -69,7 +69,9 @@ int option_verbose = 0, // ausfuehrliche Anzeige
|
|||
option_sat = 0, // GPS sat data
|
||||
option_ptu = 0,
|
||||
option_ths = 0,
|
||||
option_json = 0, // JSON output (auto_rx)
|
||||
wavloaded = 0;
|
||||
int wav_channel = 0; // audio channel: left
|
||||
|
||||
|
||||
#define BITS 8
|
||||
|
@ -454,7 +456,7 @@ int get_FrameConf() {
|
|||
if (crc == 0) {
|
||||
calfr = framebyte(pos_CalData);
|
||||
if (calfrchk[calfr] == 0) // const?
|
||||
{
|
||||
{ // 0x32 not constant
|
||||
for (i = 0; i < 16; i++) {
|
||||
calibytes[calfr*16 + i] = framebyte(pos_CalData+1+i);
|
||||
}
|
||||
|
@ -842,8 +844,12 @@ int get_Calconf(int out) {
|
|||
|
||||
if (calfr == 0x02 && option_verbose /*== 2*/) {
|
||||
byte = framebyte(pos_Calburst);
|
||||
burst = byte; // fw >= 0x4ef5, BK irrelevant? (killtimer in 0x31?)
|
||||
burst = byte; // fw >= 0x4ef5, BK irrelevant? (burst-killtimer in 0x31?)
|
||||
fprintf(stdout, ": BK %02X ", burst);
|
||||
if (option_verbose == 3) { // killtimer
|
||||
int kt = frame[0x5A] + (frame[0x5B] << 8); // short?
|
||||
if ( kt != 0xFFFF ) fprintf(stdout, ": kt 0x%04x = %dsec = %.1fmin ", kt, kt, kt/60.0);
|
||||
}
|
||||
}
|
||||
|
||||
if (calfr == 0x00 && option_verbose) {
|
||||
|
@ -855,6 +861,12 @@ int get_Calconf(int out) {
|
|||
fprintf(stdout, ": fq %d ", freq);
|
||||
}
|
||||
|
||||
if (calfr == 0x31 && option_verbose == 3) {
|
||||
int bt = frame[0x59] + (frame[0x5A] << 8); // short?
|
||||
// fw >= 0x4ef5: default=[88 77]=0x7788sec=510min
|
||||
if ( bt != 0x0000 ) fprintf(stdout, ": bt 0x%04x = %dsec = %.1fmin ", bt, bt, bt/60.0);
|
||||
}
|
||||
|
||||
if (calfr == 0x21 && option_verbose /*== 2*/) { // eventuell noch zwei bytes in 0x22
|
||||
for (i = 0; i < 9; i++) sondetyp[i] = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
|
@ -974,7 +986,12 @@ int rs41_ecc(int frmlen) {
|
|||
|
||||
|
||||
ret = errors1 + errors2;
|
||||
if (errors1 < 0 || errors2 < 0) ret = -1;
|
||||
if (errors1 < 0 || errors2 < 0) {
|
||||
ret = 0;
|
||||
if (errors1 < 0) ret |= 0x1;
|
||||
if (errors2 < 0) ret |= 0x2;
|
||||
ret = -ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1020,6 +1037,10 @@ int print_position(int ec) {
|
|||
{
|
||||
//fprintf(stdout, " (%.1f %.1f %.1f) ", gpx.vN, gpx.vE, gpx.vU);
|
||||
fprintf(stdout," vH: %4.1f D: %5.1f° vV: %3.1f ", gpx.vH, gpx.vD, gpx.vU);
|
||||
}
|
||||
|
||||
if (option_json){
|
||||
// Print JSON output required by auto_rx.
|
||||
if (!err1 && !err2 && !err3){
|
||||
if (option_ptu && !err0 && gpx.T > -273.0) {
|
||||
printf("\n{ \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f, \"temp\":%.1f }\n", gpx.frnr, gpx.id, gpx.jahr, gpx.monat, gpx.tag, gpx.std, gpx.min, gpx.sek, gpx.lat, gpx.lon, gpx.alt, gpx.vH, gpx.vD, gpx.vU, gpx.T );
|
||||
|
@ -1037,10 +1058,34 @@ int print_position(int ec) {
|
|||
//if (output)
|
||||
{
|
||||
if (option_crc) {
|
||||
fprintf(stdout, " # [");
|
||||
for (i=0; i<5; i++) fprintf(stdout, "%d", (gpx.crc>>i)&1);
|
||||
fprintf(stdout, "]");
|
||||
if (option_ecc == 2 && ec > 0) fprintf(stdout, " (%d)", ec);
|
||||
fprintf(stdout, " # ");
|
||||
if (option_ecc && ec >= 0 && (gpx.crc & 0x1F) != 0) {
|
||||
int pos, blk, len, crc; // unexpected blocks
|
||||
int flen = NDATA_LEN;
|
||||
if (frametype() < 0) flen += XDATA_LEN;
|
||||
pos = pos_FRAME;
|
||||
while (pos < flen-1) {
|
||||
blk = frame[pos]; // 0x80XX: encrypted block
|
||||
len = frame[pos+1]; // 0x76XX: 00-padding block
|
||||
crc = check_CRC(pos, blk<<8);
|
||||
fprintf(stdout, " %02X%02X", frame[pos], frame[pos+1]);
|
||||
fprintf(stdout, "[%d]", crc&1);
|
||||
pos = pos+2+len+2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fprintf(stdout, "[");
|
||||
for (i=0; i<5; i++) fprintf(stdout, "%d", (gpx.crc>>i)&1);
|
||||
fprintf(stdout, "]");
|
||||
}
|
||||
if (option_ecc == 2) {
|
||||
if (ec > 0) fprintf(stdout, " (%d)", ec);
|
||||
if (ec < 0) {
|
||||
if (ec == -1) fprintf(stdout, " (-+)");
|
||||
else if (ec == -2) fprintf(stdout, " (+-)");
|
||||
else /*ec == -3*/ fprintf(stdout, " (--)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1159,6 +1204,7 @@ int main(int argc, char *argv[]) {
|
|||
fprintf(stderr, " --ecc (Reed-Solomon)\n");
|
||||
fprintf(stderr, " --std (std framelen)\n");
|
||||
fprintf(stderr, " --ths <x> (peak threshold; default=%.1f)\n", thres);
|
||||
fprintf(stderr, " --json (JSON output)\n");
|
||||
return 0;
|
||||
}
|
||||
else if ( (strcmp(*argv, "-v") == 0) || (strcmp(*argv, "--verbose") == 0) ) {
|
||||
|
@ -1181,6 +1227,8 @@ int main(int argc, char *argv[]) {
|
|||
else if (strcmp(*argv, "--std2") == 0) { frmlen = 518; } // NDATA_LEN+XDATA_LEN
|
||||
else if (strcmp(*argv, "--sat") == 0) { option_sat = 1; }
|
||||
else if (strcmp(*argv, "--ptu") == 0) { option_ptu = 1; }
|
||||
else if (strcmp(*argv, "--json") == 0) { option_json = 1; }
|
||||
else if (strcmp(*argv, "--ch2") == 0) { wav_channel = 1; } // right channel (default: 0=left)
|
||||
else if (strcmp(*argv, "--ths") == 0) {
|
||||
++argv;
|
||||
if (*argv) {
|
||||
|
@ -1201,7 +1249,7 @@ int main(int argc, char *argv[]) {
|
|||
if (!wavloaded) fp = stdin;
|
||||
|
||||
|
||||
spb = read_wav_header(fp, (float)BAUD_RATE);
|
||||
spb = read_wav_header(fp, (float)BAUD_RATE, wav_channel);
|
||||
if ( spb < 0 ) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "error: wav header\n");
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -79,7 +79,9 @@ int option_verbose = 0, // ausfuehrliche Anzeige
|
|||
option_aux = 0, // Aux/Ozon
|
||||
option_der = 0, // linErr
|
||||
option_ths = 0,
|
||||
option_json = 0, // JSON output (auto_rx)
|
||||
rawin = 0;
|
||||
int wav_channel = 0; // audio channel: left
|
||||
double dop_limit = 9.9;
|
||||
double d_err = 10000;
|
||||
|
||||
|
@ -1142,12 +1144,16 @@ int print_position() { // GPS-Hoehe ueber Ellipsoid
|
|||
}
|
||||
}
|
||||
}
|
||||
// Print out telemetry data as JSON, even if we don't have a valid GPS lock.
|
||||
if (!err1 && !err2){
|
||||
if (gpx.aux[0] != 0 || gpx.aux[1] != 0 || gpx.aux[2] != 0 || gpx.aux[3] != 0) {
|
||||
printf("\n{ \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f, \"aux\": \"%04x%04x%04x%04x\"}\n", gpx.frnr, gpx.id, gpx.jahr, gpx.monat, gpx.tag, gpx.std, gpx.min, gpx.sek, gpx.lat, gpx.lon, gpx.alt, gpx.vH, gpx.vD, gpx.vU , gpx.aux[0], gpx.aux[1], gpx.aux[2], gpx.aux[3]);
|
||||
} else {
|
||||
printf("\n{ \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f }\n", gpx.frnr, gpx.id, gpx.jahr, gpx.monat, gpx.tag, gpx.std, gpx.min, gpx.sek, gpx.lat, gpx.lon, gpx.alt, gpx.vH, gpx.vD, gpx.vU );
|
||||
|
||||
if (option_json)
|
||||
{
|
||||
// Print out telemetry data as JSON, even if we don't have a valid GPS lock.
|
||||
if (!err1 && !err2){
|
||||
if (gpx.aux[0] != 0 || gpx.aux[1] != 0 || gpx.aux[2] != 0 || gpx.aux[3] != 0) {
|
||||
printf("\n{ \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f, \"aux\": \"%04x%04x%04x%04x\"}\n", gpx.frnr, gpx.id, gpx.jahr, gpx.monat, gpx.tag, gpx.std, gpx.min, gpx.sek, gpx.lat, gpx.lon, gpx.alt, gpx.vH, gpx.vD, gpx.vU , gpx.aux[0], gpx.aux[1], gpx.aux[2], gpx.aux[3]);
|
||||
} else {
|
||||
printf("\n{ \"frame\": %d, \"id\": \"%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f }\n", gpx.frnr, gpx.id, gpx.jahr, gpx.monat, gpx.tag, gpx.std, gpx.min, gpx.sek, gpx.lat, gpx.lon, gpx.alt, gpx.vH, gpx.vD, gpx.vU );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1262,6 +1268,7 @@ int main(int argc, char *argv[]) {
|
|||
fprintf(stderr, " --crc (CRC check GPS)\n");
|
||||
fprintf(stderr, " --ecc (Reed-Solomon)\n");
|
||||
fprintf(stderr, " --ths <x> (peak threshold; default=%.1f)\n", thres);
|
||||
fprintf(stderr, " --json (JSON output)\n");
|
||||
return 0;
|
||||
}
|
||||
else if ( (strcmp(*argv, "--vel") == 0) ) {
|
||||
|
@ -1335,6 +1342,8 @@ int main(int argc, char *argv[]) {
|
|||
else if (strcmp(*argv, "-g2") == 0) { option_vergps = 2; } // verbose2 GPS (bancroft)
|
||||
else if (strcmp(*argv, "-gg") == 0) { option_vergps = 8; } // vverbose GPS
|
||||
else if (strcmp(*argv, "--ecc") == 0) { option_ecc = 1; }
|
||||
else if (strcmp(*argv, "--json") == 0) { option_json = 1; } // JSON output (for auto_rx)
|
||||
else if (strcmp(*argv, "--ch2") == 0) { wav_channel = 1; } // right channel (default: 0=left)
|
||||
else if (strcmp(*argv, "--ths") == 0) {
|
||||
++argv;
|
||||
if (*argv) {
|
||||
|
@ -1379,7 +1388,7 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
|
||||
spb = read_wav_header(fp, (float)BAUD_RATE);
|
||||
spb = read_wav_header(fp, (float)BAUD_RATE, wav_channel);
|
||||
if ( spb < 0 ) {
|
||||
fclose(fp);
|
||||
fprintf(stderr, "error: wav header\n");
|
||||
|
|
|
@ -10,8 +10,14 @@
|
|||
|
||||
Vaisala RS92, RS41:
|
||||
RS(255, 231), t=12
|
||||
f=X^8+X^4+X^3+X^2+1, b=0
|
||||
g(X) = (X-alpha^0)...(X-alpha^(2t-1))
|
||||
|
||||
LMS6:
|
||||
RS(255, 223), t=16 (CCSDS)
|
||||
f=X^8+X^7+X^2+X+1, b=112
|
||||
g(X) = (X-(alpha^11)^112)...(X-(alpha^11)^(112+2t-1))
|
||||
|
||||
Meisei:
|
||||
bin.BCH(63, 51), t=2
|
||||
g(X) = (X^6+X+1)(X^6+X^4+X^2+X+1)
|
||||
|
@ -66,6 +72,10 @@ static GF_t GF256RS = { 0x11D, // RS-GF(2^8): X^8 + X^4 + X^3 + X^2 + 1 : 0x11D
|
|||
256, // 2^8
|
||||
0x02 }; // generator: alpha = X
|
||||
|
||||
static GF_t GF256RSccsds = { 0x187, // RS-GF(2^8): X^8 + X^7 + X^2 + X + 1 : 0x187
|
||||
256, // 2^8
|
||||
0x02 }; // generator: alpha = X
|
||||
|
||||
static GF_t GF64BCH = { 0x43, // BCH-GF(2^6): X^6 + X + 1 : 0x43
|
||||
64, // 2^6
|
||||
0x02 }; // generator: alpha = X
|
||||
|
@ -85,12 +95,14 @@ typedef struct {
|
|||
ui8_t R; // RS: R=2t, BCH: R<=mt
|
||||
ui8_t K; // K=N-R
|
||||
ui8_t b;
|
||||
ui8_t p; ui8_t ip; // p*ip = 1 mod N
|
||||
ui8_t g[MAX_DEG+1]; // ohne g[] eventuell als init_return
|
||||
} RS_t;
|
||||
|
||||
|
||||
static RS_t RS256 = { 255, 12, 24, 231, 0, {0}};
|
||||
static RS_t BCH64 = { 63, 2, 12, 51, 1, {0}};
|
||||
static RS_t RS256 = { 255, 12, 24, 231, 0, 1, 1, {0}};
|
||||
static RS_t RS256ccsds = { 255, 16, 32, 223, 112, 11, 116, {0}};
|
||||
static RS_t BCH64 = { 63, 2, 12, 51, 1, 1, 1, {0}};
|
||||
|
||||
|
||||
static GF_t GF;
|
||||
|
@ -627,7 +639,7 @@ int era_sigma(int n, ui8_t era_pos[], ui8_t *sigma) {
|
|||
sig[0] = 1;
|
||||
Xa[0] = 1;
|
||||
for (i = 0; i < n; i++) { // n <= 2*RS.t
|
||||
a_i = exp_a[era_pos[i] % (GF.ord-1)];
|
||||
a_i = exp_a[(RS.p*era_pos[i]) % (GF.ord-1)];
|
||||
Xa[1] = a_i; // Xalp[0..1]: (1-alpha^(j_)X)
|
||||
poly_mul(sig, Xa, sig);
|
||||
}
|
||||
|
@ -642,9 +654,9 @@ int syndromes(ui8_t cw[], ui8_t *S) {
|
|||
int i, errors = 0;
|
||||
ui8_t a_i;
|
||||
|
||||
// syndromes: e_j=S(alpha^(b+i))
|
||||
// syndromes: e_j=S((alpha^p)^(b+i)) (wie in g(X))
|
||||
for (i = 0; i < 2*RS.t; i++) {
|
||||
a_i = exp_a[(RS.b+i) % (GF.ord-1)]; // alpha^(b+i)
|
||||
a_i = exp_a[(RS.p*(RS.b+i)) % (GF.ord-1)]; // (alpha^p)^(b+i)
|
||||
S[i] = poly_eval(cw, a_i);
|
||||
if (S[i]) errors = 1;
|
||||
}
|
||||
|
@ -718,7 +730,7 @@ int rs_init_RS255() {
|
|||
GF = GF256RS;
|
||||
check_gen = GF_genTab( GF, exp_a, log_a);
|
||||
|
||||
RS = RS256; // N=255, t=12, b=0
|
||||
RS = RS256; // N=255, t=12, b=0, p=1
|
||||
for (i = 0; i <= MAX_DEG; i++) RS.g[i] = 0;
|
||||
for (i = 0; i <= MAX_DEG; i++) Xalp[i] = 0;
|
||||
|
||||
|
@ -733,6 +745,55 @@ int rs_init_RS255() {
|
|||
return check_gen;
|
||||
}
|
||||
|
||||
int rs_init_RS255ccsds() {
|
||||
int i, check_gen;
|
||||
ui8_t Xalp[MAX_DEG+1];
|
||||
|
||||
GF = GF256RSccsds;
|
||||
check_gen = GF_genTab( GF, exp_a, log_a);
|
||||
|
||||
RS = RS256ccsds; // N=255, t=16, b=112, p=11
|
||||
for (i = 0; i <= MAX_DEG; i++) RS.g[i] = 0;
|
||||
for (i = 0; i <= MAX_DEG; i++) Xalp[i] = 0;
|
||||
|
||||
// beta=alpha^p primitive root of g(X)
|
||||
// beta^ip=alpha // N=255, p=11 -> ip=116
|
||||
for (i = 1; i < GF.ord-1; i++) {
|
||||
if ( (RS.p * i) % (GF.ord-1) == 1 ) {
|
||||
RS.ip = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// g(X)=(X-(alpha^p)^b)...(X-(alpha^p)^(b+2t-1)), b=112
|
||||
RS.g[0] = 0x01;
|
||||
Xalp[1] = 0x01; // X
|
||||
for (i = 0; i < 2*RS.t; i++) {
|
||||
Xalp[0] = exp_a[(RS.p*(RS.b+i)) % (GF.ord-1)]; // Xalp[0..1]: X - (alpha^p)^(b+i)
|
||||
poly_mul(RS.g, Xalp, RS.g);
|
||||
}
|
||||
/*
|
||||
RS.g[ 0] = RS.g[32] = exp_a[0];
|
||||
RS.g[ 1] = RS.g[31] = exp_a[249];
|
||||
RS.g[ 2] = RS.g[30] = exp_a[59];
|
||||
RS.g[ 3] = RS.g[29] = exp_a[66];
|
||||
RS.g[ 4] = RS.g[28] = exp_a[4];
|
||||
RS.g[ 5] = RS.g[27] = exp_a[43];
|
||||
RS.g[ 6] = RS.g[26] = exp_a[126];
|
||||
RS.g[ 7] = RS.g[25] = exp_a[251];
|
||||
RS.g[ 8] = RS.g[24] = exp_a[97];
|
||||
RS.g[ 9] = RS.g[23] = exp_a[30];
|
||||
RS.g[10] = RS.g[22] = exp_a[3];
|
||||
RS.g[11] = RS.g[21] = exp_a[213];
|
||||
RS.g[12] = RS.g[20] = exp_a[50];
|
||||
RS.g[13] = RS.g[19] = exp_a[66];
|
||||
RS.g[14] = RS.g[18] = exp_a[170];
|
||||
RS.g[15] = RS.g[17] = exp_a[5];
|
||||
RS.g[16] = exp_a[24];
|
||||
*/
|
||||
return check_gen;
|
||||
}
|
||||
|
||||
int rs_init_BCH64() {
|
||||
int i, check_gen;
|
||||
|
||||
|
@ -761,7 +822,7 @@ int rs_encode(ui8_t cw[]) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// 2*Errors + Erasure <= 2*RS.t
|
||||
// 2*Errors + Erasure <= 2*t
|
||||
int rs_decode_ErrEra(ui8_t cw[], int nera, ui8_t era_pos[],
|
||||
ui8_t *err_pos, ui8_t *err_val) {
|
||||
ui8_t x, gamma;
|
||||
|
@ -793,7 +854,7 @@ int rs_decode_ErrEra(ui8_t cw[], int nera, ui8_t era_pos[],
|
|||
if (nera > 0) {
|
||||
era_sigma(nera, era_pos, sigma);
|
||||
poly_mul(sigma, S, S);
|
||||
for (i = 2*RS.t; i <= MAX_DEG; i++) S[i] = 0; // S = sig*S mod x^12
|
||||
for (i = 2*RS.t; i <= MAX_DEG; i++) S[i] = 0; // S = sig*S mod x^2t
|
||||
}
|
||||
|
||||
if (errera)
|
||||
|
@ -823,7 +884,8 @@ int rs_decode_ErrEra(ui8_t cw[], int nera, ui8_t era_pos[],
|
|||
x = (ui8_t)i; // roll-over
|
||||
if (poly_eval(sigLam, x) == 0) { // Lambda(x)=0 fuer x in erasures[] moeglich
|
||||
// error location index
|
||||
err_pos[nerr] = log_a[GF_inv(x)];
|
||||
ui8_t x1 = GF_inv(x);
|
||||
err_pos[nerr] = (log_a[x1]*RS.ip) % (GF.ord-1);
|
||||
// error value; bin-BCH: err_val=1
|
||||
err_val[nerr] = forney(x, Omega, sigLam);
|
||||
//err_val[nerr] == 0, wenn era_val[pos]=0, d.h. cw[pos] schon korrekt
|
||||
|
@ -832,7 +894,7 @@ int rs_decode_ErrEra(ui8_t cw[], int nera, ui8_t era_pos[],
|
|||
if (nerr >= deg_sigLam) break;
|
||||
}
|
||||
|
||||
// 2*Errors + Erasure <= 2*RS.t
|
||||
// 2*Errors + Erasure <= 2*t
|
||||
if (nerr < deg_sigLam) errera = -1; // uncorrectable errors
|
||||
else {
|
||||
errera = nerr;
|
||||
|
@ -843,7 +905,7 @@ int rs_decode_ErrEra(ui8_t cw[], int nera, ui8_t era_pos[],
|
|||
return errera;
|
||||
}
|
||||
|
||||
// Errors <= RS.t
|
||||
// Errors <= t
|
||||
int rs_decode(ui8_t cw[], ui8_t *err_pos, ui8_t *err_val) {
|
||||
ui8_t tmp[1] = {0};
|
||||
return rs_decode_ErrEra(cw, 0, tmp, err_pos, err_val);
|
||||
|
|
Ładowanie…
Reference in New Issue