Update to latest upstream decoders. Use --json options on decoders. Respect inverted DFM flag.

pull/114/head
Mark Jessop 2019-02-02 15:23:26 +10:30
rodzic 9d7205a323
commit 1d04aeaa5a
15 zmienionych plików z 3854 dodań i 108 usunięć

Wyświetl plik

@ -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

Wyświetl plik

@ -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.

Wyświetl plik

@ -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)

27
demod/README.md 100644
Wyświetl plik

@ -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 />

Wyświetl plik

@ -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;

Wyświetl plik

@ -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);

883
demod/demod_iq.c 100644
Wyświetl plik

@ -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;
}

19
demod/demod_iq.h 100644
Wyświetl plik

@ -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);

Wyświetl plik

@ -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");

1065
demod/lms6dm_dft.c 100644

Plik diff jest za duży Load Diff

Wyświetl plik

@ -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; }

Wyświetl plik

@ -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");

1390
demod/rs41dm_iq.c 100644

Plik diff jest za duży Load Diff

Wyświetl plik

@ -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");

Wyświetl plik

@ -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);