From 54e8f9c3130a6cd80a3f36374153f93b1cd041d2 Mon Sep 17 00:00:00 2001 From: Mark Jessop Date: Wed, 27 Feb 2019 20:55:46 +1030 Subject: [PATCH] Change scanner to use dft_detect. --- auto_rx/autorx/scan.py | 88 +-- auto_rx/build.sh | 1 - demod/demod_dft.c | 55 ++ demod/demod_dft.h | 1 + demod/demod_iq.c | 790 +++++++++++--------------- demod/demod_iq.h | 124 ++++- demod/dfm09dm_dft.c | 298 ++++++---- demod/m10dm_dft.c | 13 +- demod/rs41dm_dft.c | 83 ++- demod/rs41dm_iq.c | 1193 ++++++++++++++++++++-------------------- scan/dft_detect.c | 36 +- 11 files changed, 1443 insertions(+), 1239 deletions(-) diff --git a/auto_rx/autorx/scan.py b/auto_rx/autorx/scan.py index 0e63fb3..e77ac9d 100644 --- a/auto_rx/autorx/scan.py +++ b/auto_rx/autorx/scan.py @@ -191,54 +191,80 @@ def detect_sonde(frequency, rs_path="./", dwell_time=10, sdr_fm='rtl_fm', device else: gain_param = '' + # Sample Source (rtl_fm) 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) + # Sample filtering 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" + # Sample decoding / detection + rx_test_command += os.path.join(rs_path,"dft_detect") + " 2>/dev/null" + + #print(rx_test_command) logging.debug("Scanner #%s - Attempting sonde detection on %.3f MHz" % (str(device_idx), frequency/1e6)) try: FNULL = open(os.devnull, 'w') - ret_code = subprocess.call(rx_test_command, shell=True, stderr=FNULL) + ret_output = subprocess.check_output(rx_test_command, shell=True, stderr=FNULL) FNULL.close() + except subprocess.CalledProcessError as e: + # dft_detect returns a code of 1 if no sonde is detected. + # logging.debug("Scanner - dfm_detect return code: %s" % e.returncode) + if e.returncode >= 2: + ret_output = e.output + else: + return None except Exception as e: # Something broke when running the detection function. - logging.error("Scanner #%s - Error when running rs_detect - %s" % (str(device_idx), str(e))) + logging.error("Scanner #%s - Error when running dft_detect - %s" % (str(device_idx), str(e))) return None - # Shift down by a byte... for some reason. - # NOTE: For some reason, we don't need to do this when using subprocess.call vs when using os.system. - # Should probably figure out why this is the case at some point. - #ret_code = ret_code >> 8 + # Check for no output from dft_detect. + if ret_output is None or ret_output == "": + #logging.error("Scanner - dft_detect returned no output?") + return None - # Default is non-inverted FM. - inv = "" + # dft_detect return codes: + # 2 = DFM + # 3 = RS41 + # 4 = RS92 + # 5 = M10 + # 6 = IMET (AB) + # 7 = IMET (RS) + # 8 = LMS6 + # 9 = C34/C50 - # Check if the inverted bit is set - 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)) + # Split the line into sonde type and correlation score. + _fields = ret_output.split(':') - inv = "-" + if len(_fields) <2: + logging.error("Scanner - malformed output from dft_detect: %s" % ret_output.strip()) + return None - else: - ret_code = abs(ret_code) + _type = _fields[0] + _score = float(_fields[1].strip()) - if ret_code == 3: - logging.debug("Scanner #%s - Detected a RS41!" % str(device_idx)) - return inv+"RS41" - elif ret_code == 4: - logging.debug("Scanner #%s - Detected a RS92!" % str(device_idx)) - return inv+"RS92" - elif ret_code == 2: - logging.debug("Scanner #%s - Detected a DFM Sonde!" % str(device_idx)) - return inv+"DFM" - elif ret_code == 5: - logging.debug("Scanner #%s - Detected a M10 Sonde!" % str(device_idx)) - return inv+"M10" - elif ret_code == 6: - logging.debug("Scanner #%s - Detected a iMet Sonde! (Unsupported)" % str(device_idx)) - return inv+"iMet" + + if 'RS41' in _type: + logging.debug("Scanner #%s - Detected a RS41! (Score: %.2f)" % (str(device_idx), _score)) + return "RS41" + elif 'RS92' in _type: + logging.debug("Scanner #%s - Detected a RS92! (Score: %.2f)" % (str(device_idx), _score)) + return "RS92" + elif 'DFM' in _type: + logging.debug("Scanner #%s - Detected a DFM Sonde! (Score: %.2f)" % (str(device_idx), _score)) + return "DFM" + elif 'M10' in _type: + logging.debug("Scanner #%s - Detected a M10 Sonde! (Score: %.2f)" % (str(device_idx), _score)) + return "M10" + elif 'IMET' in _type: + logging.debug("Scanner #%s - Detected a iMet Sonde! (Unsupported, type %s) (Score: %.2f)" % (str(device_idx), _type, _score)) + return "iMet" + elif 'LMS6' in _type: + logging.debug("Scanner #%s - Detected a LMS6 Sonde! (Unsupported) (Score: %.2f)" % (str(device_idx), _score)) + return 'LMS6' + elif 'C34' in _type: + logging.debug("Scanner #%s - Detected a Meteolabor C34/C50 Sonde! (Unsupported) (Score: %.2f)" % (str(device_idx), _score)) + return 'C34C50' else: return None diff --git a/auto_rx/build.sh b/auto_rx/build.sh index d9ee130..24145fa 100755 --- a/auto_rx/build.sh +++ b/auto_rx/build.sh @@ -6,7 +6,6 @@ # Build rs_detect. echo "Building rs_detect" cd ../scan/ -gcc rs_detect.c -lm -o rs_detect gcc dft_detect.c -lm -o dft_detect echo "Building RS92/RS41/DFM Demodulators" diff --git a/demod/demod_dft.c b/demod/demod_dft.c index e90288b..e3452df 100644 --- a/demod/demod_dft.c +++ b/demod/demod_dft.c @@ -414,6 +414,61 @@ int read_sbit(FILE *fp, int symlen, int *bit, int inv, int ofs, int reset, int c return 0; } +int read_spkbit(FILE *fp, int symlen, int *bit, int inv, int ofs, int reset, int cm, int spike) { +// symlen==2: manchester2 10->0,01->1: 2.bit + + static double bitgrenze; + static unsigned long scount; + + float sample; + float avg; + float ths = 0.5, scale = 0.27; + + 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]; + avg = 0.5*(bufs[(sample_out-buffered-1 + ofs + M) % M] + +bufs[(sample_out-buffered+1 + ofs + M) % M]); + if (spike && fabs(sample - avg) > ths) sample = avg + scale*(sample - avg); // spikes + + 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]; + avg = 0.5*(bufs[(sample_out-buffered-1 + ofs + M) % M] + +bufs[(sample_out-buffered+1 + ofs + M) % M]); + if (spike && fabs(sample - avg) > ths) sample = avg + scale*(sample - avg); // spikes + + 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) { diff --git a/demod/demod_dft.h b/demod/demod_dft.h index b54221c..32a89db 100644 --- a/demod/demod_dft.h +++ b/demod/demod_dft.h @@ -2,6 +2,7 @@ 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_spkbit(FILE*, int, 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); diff --git a/demod/demod_iq.c b/demod/demod_iq.c index 1d2c12d..db0546c 100644 --- a/demod/demod_iq.c +++ b/demod/demod_iq.c @@ -12,83 +12,24 @@ #include #include #include -#include - - -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 -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) { +static void raw_dft(dft_t *dft, float complex *Z) { int s, l, l2, i, j, k; float complex w1, w2, T; j = 1; - for (i = 1; i < N_DFT; i++) { + for (i = 1; i < dft->N; i++) { if (i < j) { T = Z[j-1]; Z[j-1] = Z[i-1]; Z[i-1] = T; } - k = N_DFT/2; + k = dft->N/2; while (k < j) { j = j - k; k = k/2; @@ -96,13 +37,13 @@ static void cdft(float complex *Z) { j = j + k; } - for (s = 0; s < LOG2N; s++) { + for (s = 0; s < dft->LOG2N; s++) { l2 = 1 << s; l = l2 << 1; w1 = (float complex)1.0; - w2 = ew[s]; // cexp(-I*M_PI/(float)l2) + w2 = dft->ew[s]; // cexp(-I*M_PI/(float)l2) for (j = 1; j <= l2; j++) { - for (i = j; i <= N_DFT; i += l) { + for (i = j; i <= dft->N; i += l) { k = i + l2; T = Z[k-1] * w1; Z[k-1] = Z[i-1] - T; @@ -113,32 +54,48 @@ static void cdft(float complex *Z) { } } -static void rdft(float *x, float complex *Z) { +static void cdft(dft_t *dft, float complex *z, float complex *Z) { int i; - for (i = 0; i < N_DFT; i++) Z[i] = (float complex)x[i]; - cdft(Z); + for (i = 0; i < dft->N; i++) Z[i] = z[i]; + raw_dft(dft, Z); } -static void Nidft(float complex *Z, float complex *z) { +static void rdft(dft_t *dft, float *x, float complex *Z) { int i; - for (i = 0; i < N_DFT; i++) z[i] = conj(Z[i]); - cdft(z); + for (i = 0; i < dft->N; i++) Z[i] = (float complex)x[i]; + raw_dft(dft, Z); +} + +static void Nidft(dft_t *dft, float complex *Z, float complex *z) { + int i; + for (i = 0; i < dft->N; i++) z[i] = conj(Z[i]); + raw_dft(dft, z); // idft(): - // for (i = 0; i < N_DFT; i++) z[i] = conj(z[i])/(float)N_DFT; // hier: z reell + // for (i = 0; i < dft->N; i++) z[i] = conj(z[i])/(float)dft->N; // hier: z reell } -static float bin2freq(int k) { - float fq = sample_rate * k / N_DFT; - if (fq > sample_rate/2.0) fq -= sample_rate; +static float bin2freq0(dft_t *dft, int k) { + float fq = dft->sr * k / /*(float)*/dft->N; + if (fq >= dft->sr/2.0) fq -= dft->sr; + return fq; +} +static float bin2freq(dft_t *dft, int k) { + float fq = k / (float)dft->N; + if ( fq >= 0.5) fq -= 1.0; + return fq*dft->sr; +} +static float bin2fq(dft_t *dft, int k) { + float fq = k / (float)dft->N; + if ( fq >= 0.5) fq -= 1.0; return fq; } -static int max_bin(float complex *Z) { +static int max_bin(dft_t *dft, float complex *Z) { int k, kmax; double max; max = 0; kmax = 0; - for (k = 0; k < N_DFT; k++) { + for (k = 0; k < dft->N; k++) { if (cabs(Z[k]) > max) { max = cabs(Z[k]); kmax = k; @@ -148,69 +105,101 @@ static int max_bin(float complex *Z) { return kmax; } +static int dft_window(dft_t *dft, int w) { + int n; + + if (w < 0 || w > 3) return -1; + + for (n = 0; n < dft->N2; n++) { + switch (w) + { + case 0: // (boxcar) + dft->win[n] = 1.0; + break; + case 1: // Hann + dft->win[n] = 0.5 * ( 1.0 - cos(2*M_PI*n/(float)(dft->N2-1)) ); + break ; + case 2: // Hamming + dft->win[n] = 25/46.0 + (1.0 - 25/46.0)*cos(2*M_PI*n / (float)(dft->N2-1)); + break ; + case 3: // Blackmann + dft->win[n] = 7938/18608.0 + - 9240/18608.0*cos(2*M_PI*n / (float)(dft->N2-1)) + + 1430/18608.0*cos(4*M_PI*n / (float)(dft->N2-1)); + break ; + } + } + while (n < dft->N) dft->win[n++] = 0.0; + + return 0; +} + + /* ------------------------------------------------------------------------------------ */ -int getCorrDFT(int abs, int K, unsigned int pos, float *maxv, unsigned int *maxvpos) { +int getCorrDFT(dsp_t *dsp, int abs, ui32_t pos, float *maxv, ui32_t *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; + ui32_t mpos = 0; - 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; + dsp->dc = 0.0; - rdft(xn, X); + if (dsp->N + dsp->K > dsp->DFT.N/2 - 2) return -1; + if (dsp->sample_in < dsp->delay + dsp->N + dsp->K) return -2; - dc = get_bufmu(pos-sample_out); //oder: dc = creal(X[0])/N_DFT; + if (pos == 0) pos = dsp->sample_out; - for (i = 0; i < N_DFT; i++) Z[i] = X[i]*Fm[i]; + dsp->dc = get_bufmu(dsp, pos - dsp->sample_out); //oder unten: dft_dc = creal(X[0])/DFT_N; + // wenn richtige Stelle (Varianz pruefen, kein M10-carrier?), dann von bufs[] subtrahieren - Nidft(Z, cx); + + for (i = 0; i < dsp->N + dsp->K; i++) (dsp->DFT).xn[i] = dsp->bufs[(pos+dsp->M -(dsp->N + dsp->K - 1) + i) % dsp->M]; + while (i < (dsp->DFT).N) (dsp->DFT).xn[i++] = 0.0; + + rdft(&dsp->DFT, (dsp->DFT).xn, (dsp->DFT).X); + + // dft_dc = creal((dsp->DFT).X[0])/(dsp->DFT).N; + + for (i = 0; i < (dsp->DFT).N; i++) (dsp->DFT).Z[i] = (dsp->DFT).X[i]*(dsp->DFT).Fm[i]; + + Nidft(&dsp->DFT, (dsp->DFT).Z, (dsp->DFT).cx); if (abs) { - for (i = N; i < N+K; i++) { - if (fabs(creal(cx[i])) > fabs(mx)) { // imag(cx)=0 - mx = creal(cx[i]); + for (i = dsp->N; i < dsp->N + dsp->K; i++) { + if (fabs(creal((dsp->DFT).cx[i])) > fabs(mx)) { // imag(cx)=0 + mx = creal((dsp->DFT).cx[i]); mp = i; } } } else { - for (i = N; i < N+K; i++) { - if (creal(cx[i]) > mx) { // imag(cx)=0 - mx = creal(cx[i]); + for (i = dsp->N; i < dsp->N + dsp->K; i++) { + if (creal((dsp->DFT).cx[i]) > mx) { // imag(cx)=0 + mx = creal((dsp->DFT).cx[i]); mp = i; } } } - if (mp == N || mp == N+K-1) return -4; // Randwert + if (mp == dsp->N || mp == dsp->N + dsp->K - 1) return -4; // Randwert - mpos = pos - ( N+K-1 - mp ); - xnorm = sqrt(qs[(mpos + 2*M) % M]); - mx /= xnorm*N_DFT; + mpos = pos - ( dsp->N + dsp->K - 1 - mp ); + xnorm = sqrt(dsp->qs[(mpos + 2*dsp->M) % dsp->M]); + mx /= xnorm*(dsp->DFT).N; *maxv = mx; *maxvpos = mpos; - if (pos == sample_out) buffered = sample_out-mpos; + if (pos == dsp->sample_out) dsp->buffered = dsp->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++) { @@ -219,10 +208,11 @@ static int findstr(char *buff, char *str, int pos) { return i; } -float read_wav_header(FILE *fp, float baudrate, int wav_channel) { +float read_wav_header(pcm_t *pcm, FILE *fp) { char txt[4+1] = "\0\0\0\0"; unsigned char dat[4]; int byte, p=0; + int sample_rate = 0, bits_sample = 0, channels = 0; if (fread(txt, 1, 4, fp) < 4) return -1; if (strncmp(txt, "RIFF", 4)) return -1; @@ -267,190 +257,191 @@ float read_wav_header(FILE *fp, float baudrate, int wav_channel) { 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 (pcm->sel_ch < 0 || pcm->sel_ch >= channels) pcm->sel_ch = 0; // default channel: 0 + fprintf(stderr, "channel-In : %d\n", pcm->sel_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); + pcm->sr = sample_rate; + pcm->bps = bits_sample; + pcm->nch = channels; - return samples_per_bit; + return 0; } -static int f32read_sample(FILE *fp, float *s) { +static int f32read_sample(dsp_t *dsp, float *s) { int i; short b = 0; - for (i = 0; i < channels; i++) { + for (i = 0; i < dsp->nch; i++) { - if (fread( &b, bits_sample/8, 1, fp) != 1) return EOF; + if (fread( &b, dsp->bps/8, 1, dsp->fp) != 1) return EOF; - if (i == wav_ch) { // i = 0: links bzw. mono + if (i == dsp->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; } + if (dsp->bps == 8) { b -= 128; } *s = b/128.0; - if (bits_sample == 16) { *s /= 256.0; } + if (dsp->bps == 16) { *s /= 256.0; } } } return 0; } -static int f32read_csample(FILE *fp, float complex *z) { +static int f32read_csample(dsp_t *dsp, 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; + if (fread( &x, dsp->bps/8, 1, dsp->fp) != 1) return EOF; + if (fread( &y, dsp->bps/8, 1, dsp->fp) != 1) return EOF; *z = x + I*y; - if (bits_sample == 8) { *z -= 128 + I*128; } + if (dsp->bps == 8) { *z -= 128 + I*128; } *z /= 128.0; - if (bits_sample == 16) { *z /= 256.0; } + if (dsp->bps == 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; +float get_bufvar(dsp_t *dsp, int ofs) { + float mu = dsp->xs[(dsp->sample_out+dsp->M + ofs) % dsp->M]/dsp->Nvar; + float var = dsp->qs[(dsp->sample_out+dsp->M + ofs) % dsp->M]/dsp->Nvar - mu*mu; return var; } -float get_bufmu(int ofs) { - float mu = xs[(sample_out+M + ofs) % M]/Nvar; +float get_bufmu(dsp_t *dsp, int ofs) { + float mu = dsp->xs[(dsp->sample_out+dsp->M + ofs) % dsp->M]/dsp->Nvar; return mu; } -int f32buf_sample(FILE *fp, int inv, int cm) { - float s = 0.0; - float xneu, xalt; +static int get_SNR(dsp_t *dsp) { - 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 (dsp->opt_iq) + // if(dsp->rs_typ == RS41) + { + if (dsp->sample_posnoise > 0) // rs41 { - 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 (dsp->sample_out >= dsp->sample_posframe && dsp->sample_out < dsp->sample_posframe+dsp->len_sq) { + if (dsp->sample_out == dsp->sample_posframe) dsp->V_signal = 0.0; + dsp->V_signal += cabs(dsp->rot_iqbuf[dsp->sample_out % dsp->N_IQBUF]); } - if (sample_out == sample_posframe+len_sq) V_signal /= (double)len_sq; + if (dsp->sample_out == dsp->sample_posframe+dsp->len_sq) dsp->V_signal /= (double)dsp->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 (dsp->sample_out >= dsp->sample_posnoise && dsp->sample_out < dsp->sample_posnoise+dsp->len_sq) { + if (dsp->sample_out == dsp->sample_posnoise) dsp->V_noise = 0.0; + dsp->V_noise += cabs(dsp->rot_iqbuf[dsp->sample_out % dsp->N_IQBUF]); } - if (sample_out == sample_posnoise+len_sq) { - V_noise /= (double)len_sq; - if (V_signal > 0 && V_noise > 0) { + if (dsp->sample_out == dsp->sample_posnoise+dsp->len_sq) { + dsp->V_noise /= (double)dsp->len_sq; + if (dsp->V_signal > 0 && dsp->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); + dsp->SNRdB = 20.0 * log10(dsp->V_signal/dsp->V_noise+1e-20); } } } + } + else dsp->SNRdB = 0; + + return 0; +} + +int f32buf_sample(dsp_t *dsp, int inv) { + float s = 0.0; + float xneu, xalt; + + float complex z, w, z0; + //static float complex z0; //= 1.0; + double gain = 1.0; + + double t = dsp->sample_in / (double)dsp->sr; + + if (dsp->opt_iq) { + + if ( f32read_csample(dsp, &z) == EOF ) return EOF; + dsp->raw_iqbuf[dsp->sample_in % dsp->N_IQBUF] = z; + + z *= cexp(-t*2*M_PI*dsp->df*I); + z0 = dsp->rot_iqbuf[(dsp->sample_in-1 + dsp->N_IQBUF) % dsp->N_IQBUF]; + w = z * conj(z0); + s = gain * carg(w)/M_PI; + //z0 = z; + dsp->rot_iqbuf[dsp->sample_in % dsp->N_IQBUF] = z; + + get_SNR(dsp); - if (option_iq >= 2) + if (dsp->opt_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); + //float complex xi = cexp(+I*M_PI*dsp->h/dsp->sps); + double f1 = -dsp->h*dsp->sr/(2*dsp->sps); double f2 = -f1; float complex X1 = 0; float complex X2 = 0; - int n = samples_per_bit; + int n = dsp->sps; while (n > 0) { n--; - t = -n / (double)sample_rate; - z = rot_iqbuf[(sample_in - n + N_IQBUF) % N_IQBUF]; // +1 + t = -n / (double)dsp->sr; + z = dsp->rot_iqbuf[(dsp->sample_in - n + dsp->N_IQBUF) % dsp->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; + s = xbit / dsp->sps; } } else { - if (f32read_sample(fp, &s) == EOF) return EOF; + if (f32read_sample(dsp, &s) == EOF) return EOF; } if (inv) s = -s; // swap IQ? - bufs[sample_in % M] = s - dc_ofs; + dsp->bufs[dsp->sample_in % dsp->M] = s - dsp->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; + xneu = dsp->bufs[(dsp->sample_in ) % dsp->M]; + xalt = dsp->bufs[(dsp->sample_in+dsp->M - dsp->Nvar) % dsp->M]; + dsp->xsum += xneu - xalt; // + xneu - xalt + dsp->qsum += (xneu - xalt)*(xneu + xalt); // + xneu*xneu - xalt*xalt + dsp->xs[dsp->sample_in % dsp->M] = dsp->xsum; + dsp->qs[dsp->sample_in % dsp->M] = dsp->qsum; - if (0 && cm) { - // direct correlation - } + dsp->sample_out = dsp->sample_in - dsp->delay; - - sample_out = sample_in - delay; - - sample_in += 1; + dsp->sample_in += 1; return 0; } -static int read_bufbit(int symlen, char *bits, unsigned int mvp, int reset) { +static int read_bufbit(dsp_t *dsp, int symlen, char *bits, ui32_t mvp, int pos) { // symlen==2: manchester2 0->10,1->01->1: 2.bit - static unsigned int rcount; - static float rbitgrenze; + float rbitgrenze = pos*symlen*dsp->sps; + ui32_t rcount = rbitgrenze+0.99; // ceil double sum = 0.0; - if (reset) { - rcount = 0; - rbitgrenze = 0; - } - - rbitgrenze += samples_per_bit; + rbitgrenze += dsp->sps; do { - sum += bufs[(rcount + mvp + M) % M]; + sum += dsp->bufs[(rcount + mvp + dsp->M) % dsp->M]; rcount++; - } while (rcount < rbitgrenze); // n < samples_per_bit + } while (rcount < rbitgrenze); // n < dsp->sps if (symlen == 2) { - rbitgrenze += samples_per_bit; + rbitgrenze += dsp->sps; do { - sum -= bufs[(rcount + mvp + M) % M]; + sum -= dsp->bufs[(rcount + mvp + dsp->M) % dsp->M]; rcount++; - } while (rcount < rbitgrenze); // n < samples_per_bit + } while (rcount < rbitgrenze); // n < dsp->sps } @@ -466,154 +457,117 @@ static int read_bufbit(int symlen, char *bits, unsigned int mvp, int reset) { return 0; } -int headcmp(int symlen, char *hdr, int len, unsigned int mvp, int inv, int option_dc) { +int headcmp(dsp_t *dsp, int symlen, ui32_t mvp, int inv, int option_dc) { int errs = 0; int pos; int step = 1; char sign = 0; + int len = dsp->hdrlen; 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); + for (pos = 0; pos < len; pos += step) { // N = dsp->hdrlen * dsp->sps + 0.5; + //read_bufbit(dsp, symlen, dsp->rawbits+pos, mvp+1-(int)(len*dsp->sps), pos); + read_bufbit(dsp, symlen, dsp->rawbits+pos, mvp+1-dsp->N, pos); } - rawbits[pos] = '\0'; + dsp->rawbits[pos] = '\0'; while (len > 0) { - if ((rawbits[len-1]^sign) != hdr[len-1]) errs += 1; + if ((dsp->rawbits[len-1]^sign) != dsp->hdr[len-1]) errs += 1; len--; } if (option_dc && errs < 3) { - dc_ofs += dc; + dsp->dc_ofs += dsp->dc; } return errs; } -int get_fqofs(int hdrlen, unsigned int mvp, float *freq, float *snr) { +int get_fqofs_rs41(dsp_t *dsp, ui32_t mvp, float *freq, float *snr) { int j; int buf_start; - int presamples = 256*samples_per_bit; + int presamples; - if (presamples > M_DFT) presamples = M_DFT; + // if(dsp->rs_typ == RS41_PREAMBLE) ... + if (dsp->opt_iq) + { + presamples = 256*dsp->sps; - buf_start = mvp - hdrlen*samples_per_bit - presamples; + if (presamples > dsp->DFT.N2) presamples = dsp->DFT.N2; - while (buf_start < 0) buf_start += N_IQBUF; + buf_start = mvp - dsp->hdrlen*dsp->sps - presamples; - for (j = 0; j < M_DFT; j++) { - Z[j] = Hann[j]*raw_iqbuf[(buf_start+j) % N_IQBUF]; + while (buf_start < 0) buf_start += dsp->N_IQBUF; + + for (j = 0; j < dsp->DFT.N2; j++) { + dsp->DFT.Z[j] = dsp->DFT.win[j]*dsp->raw_iqbuf[(buf_start+j) % dsp->N_IQBUF]; + } + while (j < dsp->DFT.N) dsp->DFT.Z[j++] = 0; + + raw_dft(&dsp->DFT, dsp->DFT.Z); + dsp->df = bin2freq(&dsp->DFT, max_bin(&dsp->DFT, dsp->DFT.Z)); + + // if |df|df) > 1000.0) dsp->df = 0.0; + + + dsp->sample_posframe = dsp->sample_in; // > sample_out //mvp - dsp->hdrlen*dsp->sps; + dsp->sample_posnoise = mvp + dsp->sr*7/8.0; // rs41 + + + *freq = dsp->df; + *snr = dsp->SNRdB; } - while (j < N_DFT) Z[j++] = 0; - - cdft(Z); - df = bin2freq(max_bin(Z)); - - // if |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; + else return -1; return 0; } /* -------------------------------------------------------------------------- */ -int read_sbit(FILE *fp, int symlen, int *bit, int inv, int ofs, int reset, int cm) { +int read_slbit(dsp_t *dsp, int symlen, int *bit, int inv, int ofs, int pos, float l) { // 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 bitgrenze = pos*symlen*dsp->sps; + ui32_t scount = bitgrenze+0.99; // ceil float sample; double sum = 0.0; double mid; - double l = 1.0; + //double l = 0.5 .. 1.0 .. sps/2; - if (reset) { - scount = 0; - bitgrenze = 0; - } if (symlen == 2) { - mid = bitgrenze + (samples_per_bit-1)/2.0; - bitgrenze += samples_per_bit; + mid = bitgrenze + (dsp->sps-1)/2.0; + bitgrenze += dsp->sps; do { - if (buffered > 0) buffered -= 1; - else if (f32buf_sample(fp, inv, cm) == EOF) return EOF; + if (dsp->buffered > 0) dsp->buffered -= 1; + else if (f32buf_sample(dsp, inv) == EOF) return EOF; - sample = bufs[(sample_out-buffered + ofs + M) % M]; - if (mid-l < scount && scount < mid+l) sum -= sample; + sample = dsp->bufs[(dsp->sample_out-dsp->buffered + ofs + dsp->M) % dsp->M]; + + if ( l < 0 || (mid-l < scount && scount < mid+l)) sum -= sample; scount++; - } while (scount < bitgrenze); // n < samples_per_bit + } while (scount < bitgrenze); // n < dsp->sps } - mid = bitgrenze + (samples_per_bit-1)/2.0; - bitgrenze += samples_per_bit; + mid = bitgrenze + (dsp->sps-1)/2.0; + bitgrenze += dsp->sps; do { - if (buffered > 0) buffered -= 1; - else if (f32buf_sample(fp, inv, cm) == EOF) return EOF; + if (dsp->buffered > 0) dsp->buffered -= 1; + else if (f32buf_sample(dsp, inv) == EOF) return EOF; - sample = bufs[(sample_out-buffered + ofs + M) % M]; - if (mid-l < scount && scount < mid+l) sum += sample; + sample = dsp->bufs[(dsp->sample_out-dsp->buffered + ofs + dsp->M) % dsp->M]; + + if ( l < 0 || (mid-l < scount && scount < mid+l)) sum += sample; scount++; - } while (scount < bitgrenze); // n < samples_per_bit + } while (scount < bitgrenze); // n < dsp->sps + if (sum >= 0) *bit = 1; else *bit = 0; @@ -621,90 +575,6 @@ int read_IDsbit(FILE *fp, int symlen, int *bit, int inv, int ofs, int reset, int 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; -} /* -------------------------------------------------------------------------- */ @@ -722,154 +592,162 @@ static double pulse(double t, double sigma) { } -static double norm2_match() { +static double norm2_vect(float *vect, int n) { int i; double x, y = 0.0; - for (i = 0; i < N; i++) { - x = match[i]; + for (i = 0; i < n; i++) { + x = vect[i]; y += x*x; } return y; } -int init_buffers(char hdr[], int hLen, float BT, int opt_iq) { - //hLen = strlen(header) = HEADLEN; +int init_buffers(dsp_t *dsp) { int i, pos; float b0, b1, b2, b, t; float normMatch; - double sigma = sqrt(log(2)) / (2*M_PI*BT); + double sigma = sqrt(log(2)) / (2*M_PI*dsp->BT); - int K; + int K, N, M; int n, k; float *m = NULL; - option_iq = opt_iq; - N = hLen * samples_per_bit + 0.5; + N = dsp->hdrlen * dsp->sps + 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; + if (dsp->sps < 6) M = 6*N; - rawbits = (char *)calloc( N+1, sizeof(char)); if (rawbits == NULL) return -100; + dsp->bufs = (float *)calloc( M+1, sizeof(float)); if (dsp->bufs == NULL) return -100; + dsp->match = (float *)calloc( N+1, sizeof(float)); if (dsp->match == NULL) return -100; - for (i = 0; i < M; i++) bufs[i] = 0.0; + dsp->xs = (float *)calloc( M+1, sizeof(float)); if (dsp->xs == NULL) return -100; + dsp->qs = (float *)calloc( M+1, sizeof(float)); if (dsp->qs == NULL) return -100; + + dsp->rawbits = (char *)calloc( N+1, sizeof(char)); if (dsp->rawbits == NULL) return -100; + + + for (i = 0; i < M; i++) dsp->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; + pos = i/dsp->sps; + t = (i - pos*dsp->sps)/dsp->sps - 0.5; - b1 = ((hdr[pos] & 0x1) - 0.5)*2.0; + b1 = ((dsp->hdr[pos] & 0x1) - 0.5)*2.0; b = b1*pulse(t, sigma); if (pos > 0) { - b0 = ((hdr[pos-1] & 0x1) - 0.5)*2.0; + b0 = ((dsp->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; + if (pos < dsp->hdrlen-1) { + b2 = ((dsp->hdr[pos+1] & 0x1) - 0.5)*2.0; b += b2*pulse(t-1, sigma); } - match[i] = b; + dsp->match[i] = b; } - normMatch = sqrt(norm2_match()); + normMatch = sqrt( norm2_vect(dsp->match, N) ); for (i = 0; i < N; i++) { - match[i] /= normMatch; + dsp->match[i] /= normMatch; } - delay = N/16; - sample_in = 0; + dsp->N = N; + dsp->M = M; + dsp->Nvar = N; //N/2; // = N/k - K = M-N - delay; //N/2 - delay; // N+K < M + dsp->delay = N/16; + dsp->sample_in = 0; - LOG2N = 2 + (int)(log(N+K)/log(2)); - N_DFT = 1 << LOG2N; + K = M - N - dsp->delay; //N/2 - delay; // N+K < M + dsp->K = K; - while (N + K > N_DFT/2 - 2) { - LOG2N += 1; - N_DFT <<= 1; + dsp->DFT.sr = dsp->sr; + dsp->DFT.LOG2N = 2 + (int)(log(N+K)/log(2)); + dsp->DFT.N = 1 << dsp->DFT.LOG2N; + + while (N + K > dsp->DFT.N/2 - 2) { + dsp->DFT.LOG2N += 1; + dsp->DFT.N <<= 1; } + dsp->DFT.xn = calloc(dsp->DFT.N+1, sizeof(float)); if (dsp->DFT.xn == NULL) return -1; - xn = calloc(N_DFT+1, sizeof(float)); if (xn == NULL) return -1; + dsp->DFT.Fm = calloc(dsp->DFT.N+1, sizeof(float complex)); if (dsp->DFT.Fm == NULL) return -1; + dsp->DFT.X = calloc(dsp->DFT.N+1, sizeof(float complex)); if (dsp->DFT.X == NULL) return -1; + dsp->DFT.Z = calloc(dsp->DFT.N+1, sizeof(float complex)); if (dsp->DFT.Z == NULL) return -1; + dsp->DFT.cx = calloc(dsp->DFT.N+1, sizeof(float complex)); if (dsp->DFT.cx == 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; + dsp->DFT.ew = calloc(dsp->DFT.LOG2N+1, sizeof(float complex)); if (dsp->DFT.ew == 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) ) ); + // FFT window + // a) N2 = N + // b) N2 < N (interpolation) + dsp->DFT.win = calloc(dsp->DFT.N+1, sizeof(float complex)); if (dsp->DFT.win == NULL) return -1; // float real + dsp->DFT.N2 = dsp->DFT.N; + //dsp->DFT.N2 = dsp->DFT.N/2 - 1; // DFT_N=2^log2N + dft_window(&dsp->DFT, 1); - for (n = 0; n < LOG2N; n++) { + for (n = 0; n < dsp->DFT.LOG2N; n++) { k = 1 << n; - ew[n] = cexp(-I*M_PI/(float)k); + dsp->DFT.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); + m = calloc(dsp->DFT.N+1, sizeof(float)); if (m == NULL) return -1; + for (i = 0; i < N; i++) m[N-1 - i] = dsp->match[i]; + while (i < dsp->DFT.N) m[i++] = 0.0; + rdft(&dsp->DFT, m, dsp->DFT.Fm); free(m); m = NULL; - if (option_iq) + if (dsp->opt_iq) { - if (channels < 2) return -1; + if (dsp->nch < 2) return -1; /* - M_DFT = samples_per_bit*256+0.5; - while ( (1 << LOG2N) < M_DFT ) LOG2N++; + N2 = dsp->sps*256+0.5; + while ( (1 << LOG2N) < N2 ) LOG2N++; LOG2N++; - N_DFT = (1 << LOG2N); - N_IQBUF = M_DFT + samples_per_bit*(64+16); + N = (1 << LOG2N); + N_IQBUF = N2 + sps*(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; + dsp->N_IQBUF = dsp->DFT.N; + dsp->raw_iqbuf = calloc(dsp->N_IQBUF+1, sizeof(float complex)); if (dsp->raw_iqbuf == NULL) return -1; + dsp->rot_iqbuf = calloc(dsp->N_IQBUF+1, sizeof(float complex)); if (dsp->rot_iqbuf == NULL) return -1; - len_sq = samples_per_bit*8; + dsp->len_sq = dsp->sps*8; } return K; } -int free_buffers() { +int free_buffers(dsp_t *dsp) { - 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 (dsp->match) { free(dsp->match); dsp->match = NULL; } + if (dsp->bufs) { free(dsp->bufs); dsp->bufs = NULL; } + if (dsp->xs) { free(dsp->xs); dsp->xs = NULL; } + if (dsp->qs) { free(dsp->qs); dsp->qs = NULL; } + if (dsp->rawbits) { free(dsp->rawbits); dsp->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 (dsp->DFT.xn) { free(dsp->DFT.xn); dsp->DFT.xn = NULL; } + if (dsp->DFT.ew) { free(dsp->DFT.ew); dsp->DFT.ew = NULL; } + if (dsp->DFT.Fm) { free(dsp->DFT.Fm); dsp->DFT.Fm = NULL; } + if (dsp->DFT.X) { free(dsp->DFT.X); dsp->DFT.X = NULL; } + if (dsp->DFT.Z) { free(dsp->DFT.Z); dsp->DFT.Z = NULL; } + if (dsp->DFT.cx) { free(dsp->DFT.cx); dsp->DFT.cx = NULL; } - if (Hann) { free(Hann); Hann = NULL; } + if (dsp->DFT.win) { free(dsp->DFT.win); dsp->DFT.win = NULL; } - if (option_iq) + if (dsp->opt_iq) { - if (raw_iqbuf) { free(raw_iqbuf); raw_iqbuf = NULL; } - if (rot_iqbuf) { free(rot_iqbuf); rot_iqbuf = NULL; } + if (dsp->raw_iqbuf) { free(dsp->raw_iqbuf); dsp->raw_iqbuf = NULL; } + if (dsp->rot_iqbuf) { free(dsp->rot_iqbuf); dsp->rot_iqbuf = NULL; } } return 0; @@ -877,7 +755,7 @@ int free_buffers() { /* ------------------------------------------------------------------------------------ */ -unsigned int get_sample() { - return sample_out; +ui32_t get_sample(dsp_t *dsp) { + return dsp->sample_out; } diff --git a/demod/demod_iq.h b/demod/demod_iq.h index 6c5a2ae..877d28c 100644 --- a/demod/demod_iq.h +++ b/demod/demod_iq.h @@ -1,19 +1,115 @@ -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); +#include +#include -int init_buffers(char*, int, float, int); -int free_buffers(void); +typedef unsigned char ui8_t; +typedef unsigned short ui16_t; +typedef unsigned int ui32_t; +typedef char i8_t; +typedef short i16_t; +typedef int i32_t; -unsigned int get_sample(void); + +typedef struct { + int sr; // sample_rate + int LOG2N; + int N; + int N2; + float *xn; + float complex *ew; + float complex *Fm; + float complex *X; + float complex *Z; + float complex *cx; + float complex *win; // float real +} dft_t; + + +typedef struct { + FILE *fp; + // + int sr; // sample_rate + int bps; // bits/sample + int nch; // channels + int ch; // select channel + // + int symlen; + float sps; // samples per symbol + float _spb; // samples per bit + float br; // baud rate + // + ui32_t sample_in; + ui32_t sample_out; + ui32_t delay; + int buffered; + int N; + int M; + int K; + float *match; + float *bufs; + float dc_ofs; + float dc; + // + int N_norm; + int Nvar; + float xsum; + float qsum; + float *xs; + float *qs; + + // IQ-data + int opt_iq; + int N_IQBUF; + float complex *raw_iqbuf; + float complex *rot_iqbuf; + + // + char *rawbits; + char *hdr; + int hdrlen; + + // + float BT; // bw/time (ISI) + float h; // modulation index + + // DFT + dft_t DFT; + + double df; + int len_sq; + + ui32_t sample_posframe; + ui32_t sample_posnoise; + + double V_noise; + double V_signal; + double SNRdB; + +} dsp_t; + + +typedef struct { + int sr; // sample_rate + int bps; // bits_sample bits/sample + int nch; // channels + int sel_ch; // select wav channel +} pcm_t; + + + +float read_wav_header(pcm_t *, FILE *); +int f32buf_sample(dsp_t *, int); +int read_slbit(dsp_t *, int, int*, int, int, int, float); + +int getCorrDFT(dsp_t *, int, ui32_t, float *, ui32_t *); +int headcmp(dsp_t *, int, ui32_t, int, int); +int get_fqofs_rs41(dsp_t *, ui32_t, float *, float *); +float get_bufvar(dsp_t *, int); +float get_bufmu(dsp_t *, int); + +int init_buffers(dsp_t *); +int free_buffers(dsp_t *); + +ui32_t get_sample(dsp_t *); diff --git a/demod/dfm09dm_dft.c b/demod/dfm09dm_dft.c index fbbe064..8b0267e 100644 --- a/demod/dfm09dm_dft.c +++ b/demod/dfm09dm_dft.c @@ -41,7 +41,7 @@ typedef struct { float meas24[5]; float status[2]; float _frmcnt; - char sonde_id[16]; + char sonde_id[16]; // "ID__:xxxxxxxx\0\0" } gpx_t; gpx_t gpx; @@ -56,7 +56,7 @@ pcksts_t pck[9]; char dat_str[9][13+1]; // JSON Buffer to store sonde ID -char json_sonde_id[] = "DFMxx-xxxxxxxxyy"; +char json_sonde_id[] = "DFMxx-xxxxxxxx\0\0"; int option_verbose = 0, // ausfuehrliche Anzeige option_raw = 0, // rohe Frames @@ -409,122 +409,207 @@ float get_Temp4(float *meas) { // meas[0..4] #define SNbit 0x0100 int conf_out(ui8_t *conf_bits, int ec) { - int conf_id; int ret = 0; - int val, hl; + int val; + ui8_t conf_id; + ui8_t hl; ui32_t SN6, SN; static int chAbit, chA[2]; 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; + static ui8_t max_ch; + static ui8_t nul_ch; + static ui8_t sn2_ch, sn_ch; + static ui32_t SN_X; + static int chXbit, chX[2]; + static ui8_t dfm6typ; conf_id = bits2val(conf_bits, 4); - // 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 = SNbit | 6; - ptu_out = 6; - ret = 6; - sprintf(gpx.sonde_id, "ID06:%6X", gpx.SN6); - sprintf(json_sonde_id, "DFM06-%6X", gpx.SN6); - } - else { - gpx.sonde_typ = 0; - } - gpx.SN6 = SN6; + if (conf_id > 4 && bits2val(conf_bits+8, 4*5) == 0) nul_ch = bits2val(conf_bits, 8); + + dfm6typ = ((nul_ch & 0xF0)==0x50) && (nul_ch & 0x0F); + if (dfm6typ) ptu_out = 6; + if (dfm6typ && (gpx.sonde_typ & 0xF) > 6) + { // reset if 0x5A, 0x5B (DFM-06) + gpx.sonde_typ = 0; + max_ch = conf_id; } - if (conf_id == 0xA) { // 0xACxxxxy , DFM-09 - val = bits2val(conf_bits+8, 4*5); - hl = (val & 1); // val&0xF 0,1? - chA[hl] = (val >> 4) & 0xFFFF; - chAbit |= 1 << hl; - if (chAbit == 3) { // DFM-09: Kanal A - SN = (chA[0] << 16) | chA[1]; - if ( SN == SN_A ) { - gpx.sonde_typ = SNbit | 0xA; - gpx.SN = SN; - ptu_out = 9; - ret = 9; - sprintf(gpx.sonde_id, "ID09:%6u", gpx.SN); - sprintf(json_sonde_id, "DFM09-%6u", gpx.SN); + + if (conf_id > 4 && conf_id > max_ch) max_ch = conf_id; // mind. 5 Kanaele // reset? lower 0xsCaaaab? + + if (conf_id > 4 && conf_id == (nul_ch>>4)+1) + { + sn2_ch = bits2val(conf_bits, 8); + + if (option_auto) + { + sn_ch = ((sn2_ch>>4) & 0xF); + if (conf_id == sn_ch) + { + if ( (nul_ch & 0x58) == 0x58 ) { // 0x5A, 0x5B + 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 = SNbit | 6; + ptu_out = 6; + sprintf(gpx.sonde_id, "ID06:%6X", gpx.SN6); + sprintf(json_sonde_id, "DFM06-%6X", gpx.SN6); + } + else { // reset + gpx.sonde_typ = 0; + sprintf(json_sonde_id, "DFMxx-xxxxxxxx"); //json_sonde_id[0] = '\0'; + } + gpx.SN6 = SN6; + } + else if ( (sn2_ch & 0xF) == 0xC // 0xsCaaaab, s==sn_ch , s: 0xA=DFM-09 , 0xC=DFM-17? 0xD=? + || (sn2_ch & 0xF) == 0x0 ) // 0xs0aaaab, s==sn_ch , s: 0x7,0x8: pilotsonde PS-15? + { + val = bits2val(conf_bits+8, 4*5); + hl = (val & 1); + chX[hl] = (val >> 4) & 0xFFFF; + chXbit |= 1 << hl; + if (chXbit == 3) { + SN = (chX[0] << 16) | chX[1]; + if ( SN == SN_X || SN_X == 0 ) { + + gpx.sonde_typ = SNbit | sn_ch; + gpx.SN = SN; + + if (sn_ch == 0xA /*&& (sn2_ch & 0xF) == 0xC*/) ptu_out = 9; else ptu_out = 0; + // PS-15 ? (sn2_ch & 0xF) == 0x0 : ptu_out = 0 + // DFM-17? (sn_ch == 0xC) ptu_out = 9 ? // test 0xD ...? + + if ( (gpx.sonde_typ & 0xF) == 0xA) { + sprintf(gpx.sonde_id, "ID09:%6u", gpx.SN); + sprintf(json_sonde_id, "DFM09-%6u", gpx.SN); + } + else { + sprintf(gpx.sonde_id, "ID-%1X:%6u", gpx.sonde_typ & 0xF, gpx.SN); + sprintf(json_sonde_id, "DFMx%1X-%6u", gpx.sonde_typ & 0xF,gpx.SN); + } + } + else { // reset + gpx.sonde_typ = 0; + sprintf(json_sonde_id, "DFMxx-xxxxxxxx"); //json_sonde_id[0] = '\0'; + } + SN_X = SN; + chXbit = 0; + } + } + ret = (gpx.sonde_typ & 0xF); + } + } + } + + if (option_auto == 0) { + + // 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? davor xy00000-Kanal? (mind. 1) + 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 = SNbit | 6; + ptu_out = 6; + ret = 6; + sprintf(gpx.sonde_id, "ID06:%6X", gpx.SN6); + sprintf(json_sonde_id, "DFM06-%6X", gpx.SN6); } else { gpx.sonde_typ = 0; } - SN_A = SN; - chAbit = 0; + gpx.SN6 = SN6; } - } - if (conf_id == 0xC) { // 0xCCxxxxy , DFM-17? - 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 = SNbit | 0xC; - gpx.SN = SN; - ptu_out = 9; - ret = 17; - sprintf(gpx.sonde_id, "ID-%1X:%6u", gpx.sonde_typ & 0xF, gpx.SN); - sprintf(json_sonde_id, "DFM17-%6u", gpx.SN); + if (conf_id == 0xA) { // 0xACxxxxy , DFM-09 + val = bits2val(conf_bits+8, 4*5); + hl = (val & 1); // val&0xF 0,1? + chA[hl] = (val >> 4) & 0xFFFF; + chAbit |= 1 << hl; + if (chAbit == 3) { // DFM-09: Kanal A + SN = (chA[0] << 16) | chA[1]; + if ( SN == SN_A ) { + gpx.sonde_typ = SNbit | 0xA; + gpx.SN = SN; + ptu_out = 9; + ret = 9; + sprintf(gpx.sonde_id, "ID09:%6u", gpx.SN); + sprintf(json_sonde_id, "DFM09-%6u", gpx.SN); + } + else { + gpx.sonde_typ = 0; + } + SN_A = SN; + chAbit = 0; } - else { - gpx.sonde_typ = 0; - } - SN_C = SN; - chCbit = 0; } - } - if (conf_id == 0xD) { // 0xDCxxxxy , DFM-17? - 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 = SNbit | 0xD; - gpx.SN = SN; - ptu_out = 9; - ret = 18; - sprintf(gpx.sonde_id, "ID-%1X:%6u", gpx.sonde_typ & 0xF, gpx.SN); - sprintf(json_sonde_id, "DFM17-%6u", gpx.SN); + if (conf_id == 0xC) { // 0xCCxxxxy , DFM-17? + 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 = SNbit | 0xC; + gpx.SN = SN; + ptu_out = 9; // ? + ret = 17; + sprintf(gpx.sonde_id, "ID-%1X:%6u", gpx.sonde_typ & 0xF, gpx.SN); + sprintf(json_sonde_id, "DFM17-%6u", gpx.SN); + } + else { + gpx.sonde_typ = 0; + } + SN_C = SN; + chCbit = 0; } - else { - gpx.sonde_typ = 0; - } - SN_D = SN; - chDbit = 0; } - } - if (conf_id == 0x7) { // 0x70xxxxy , pilotsonde PS-15? - 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 = SNbit | 0x7; - gpx.SN = SN; - ptu_out = 0; - ret = 15; - sprintf(gpx.sonde_id, "ID15:%6u", gpx.SN); - sprintf(json_sonde_id, "DFM15-%6u", gpx.SN); + if (conf_id == 0xD) { // 0xDCxxxxy , DFM-17? + 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 = SNbit | 0xD; + gpx.SN = SN; + ptu_out = 0; // ... + ret = 18; + sprintf(gpx.sonde_id, "ID-%1X:%6u", gpx.sonde_typ & 0xF, gpx.SN); + sprintf(json_sonde_id, "DFM17-%6u", gpx.SN); + } + else { + gpx.sonde_typ = 0; + } + SN_D = SN; + chDbit = 0; } - else { - gpx.sonde_typ = 0; + } + if (conf_id == 0x7) { // 0x70xxxxy , pilotsonde PS-15? + 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 = SNbit | 0x7; + gpx.SN = SN; + ptu_out = 0; + ret = 15; + sprintf(gpx.sonde_id, "ID15:%6u", gpx.SN); + sprintf(json_sonde_id, "DFM15-%6u", gpx.SN); + } + else { + gpx.sonde_typ = 0; + } + SN_7 = SN; + ch7bit = 0; } - SN_7 = SN; - ch7bit = 0; } } @@ -561,8 +646,14 @@ void print_gpx() { int output = 0; int jsonout = 0; + output |= start; + if (option_json && start == 0) { // JSON: initial reset + sprintf(json_sonde_id, "DFMxx-xxxxxxxx"); //json_sonde_id[0] = '\0'; + } + + for (i = 0; i < 9/*8*/; i++) { // trigger: pck8 if ( !( (option_dist || option_json) && pck[i].ec < 0) ) { @@ -588,7 +679,7 @@ void print_gpx() { if (option_raw == 2) { for (i = 0; i < 9; i++) { printf(" %s", dat_str[i]); - if (option_ecc) printf(" [%1X] ", pck[i].ec&0xF); + if (option_ecc) printf(" (%1X) ", pck[i].ec&0xF); } for (i = 0; i < 9; i++) { for (j = 0; j < 13; j++) dat_str[i][j] = ' '; @@ -599,11 +690,11 @@ void print_gpx() { printf("[%3d] ", gpx.frnr); printf("%4d-%02d-%02d ", gpx.jahr, gpx.monat, gpx.tag); printf("%02d:%02d:%04.1f ", gpx.std, gpx.min, gpx.sek); - if (option_verbose >= 2 && option_ecc) printf("[%1X,%1X,%1X] ", pck[0].ec&0xF, pck[8].ec&0xF, pck[1].ec&0xF); + if (option_verbose >= 2 && option_ecc) printf("(%1X,%1X,%1X) ", pck[0].ec&0xF, pck[8].ec&0xF, pck[1].ec&0xF); printf(" "); - printf(" lat: %.5f ", gpx.lat); if (option_verbose >= 2 && option_ecc) printf("[%1X] ", pck[2].ec&0xF); - printf(" lon: %.5f ", gpx.lon); if (option_verbose >= 2 && option_ecc) printf("[%1X] ", pck[3].ec&0xF); - printf(" alt: %.1f ", gpx.alt); if (option_verbose >= 2 && option_ecc) printf("[%1X] ", pck[4].ec&0xF); + printf(" lat: %.5f ", gpx.lat); if (option_verbose >= 2 && option_ecc) printf("(%1X) ", pck[2].ec&0xF); + printf(" lon: %.5f ", gpx.lon); if (option_verbose >= 2 && option_ecc) printf("(%1X) ", pck[3].ec&0xF); + printf(" alt: %.1f ", gpx.alt); if (option_verbose >= 2 && option_ecc) printf("(%1X) ", pck[4].ec&0xF); printf(" vH: %5.2f ", gpx.horiV); printf(" D: %5.1f ", gpx.dir); printf(" vV: %5.2f ", gpx.vertV); @@ -798,7 +889,10 @@ 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; ptu_out = 1; } + else if ( (strcmp(*argv, "--ptu") == 0) ) { + option_ptu = 1; + //ptu_out = 1; // force ptu (non PS-15) + } else if ( (strcmp(*argv, "--auto") == 0) ) { option_auto = 1; } else if ( (strcmp(*argv, "--dist") == 0) ) { option_dist = 1; option_ecc = 1; } else if ( (strcmp(*argv, "--json") == 0) ) { option_json = 1; option_ecc = 1; } diff --git a/demod/m10dm_dft.c b/demod/m10dm_dft.c index 039449d..151290a 100644 --- a/demod/m10dm_dft.c +++ b/demod/m10dm_dft.c @@ -781,6 +781,8 @@ int print_frame(int pos) { int main(int argc, char **argv) { + int spike = 0; + FILE *fp = NULL; char *fpname = NULL; float spb = 0.0; @@ -841,6 +843,9 @@ int main(int argc, char **argv) { else if ( (strcmp(*argv, "--dc") == 0) ) { option_dc = 1; } + else if ( (strcmp(*argv, "--spike") == 0) ) { + spike = 1; + } else if ( (strcmp(*argv, "--ch2") == 0) ) { wav_channel = 1; } // right channel (default: 0=left) else if ( (strcmp(*argv, "--ths") == 0) ) { ++argv; @@ -906,8 +911,8 @@ int main(int argc, char **argv) { herrs = headcmp(1, rawheader, headerlen, mv_pos, mv<0, option_dc); // header nicht manchester! herr1 = 0; if (herrs <= 3 && herrs > 0) { - 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); + herr1 = headcmp(1, rawheader, headerlen, mv_pos+1, mv<0, 0); // nur 1x dc + //int herr2 = headcmp(1, rawheader, headerlen, mv_pos-1, mv<0, 0); if (herr1 < herrs) { herrs = herr1; herr1 = 1; @@ -924,7 +929,7 @@ int main(int argc, char **argv) { 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 + bitQ = read_spkbit(fp, symlen, &bit, option_inv, bitofs, bitpos==0, !header_found, spike); // symlen=2, return: zeroX/bit if (bitQ == EOF) { break; } frame_bits[pos] = 0x31 ^ (bit0 ^ bit); pos++; @@ -940,7 +945,7 @@ int main(int argc, char **argv) { // bis Ende der Sekunde vorspulen; allerdings Doppel-Frame alle 10 sek if (option_verbose < 3) { // && (regulare frame) // print_frame-return? while ( bitpos < 5*BITFRAME_LEN ) { - bitQ = read_sbit(fp, symlen, &bit, option_inv, bitofs, bitpos==0, 0); // symlen=2, return: zeroX/bit + bitQ = read_spkbit(fp, symlen, &bit, option_inv, bitofs, bitpos==0, 0, spike); // symlen=2, return: zeroX/bit if ( bitQ == EOF) break; bitpos++; } diff --git a/demod/rs41dm_dft.c b/demod/rs41dm_dft.c index 8982b2b..bd029fa 100644 --- a/demod/rs41dm_dft.c +++ b/demod/rs41dm_dft.c @@ -47,6 +47,7 @@ rscfg_t cfg_rs41 = { 41, (320-56)/2, 56, 8, 8, 320}; typedef struct { int frnr; char id[9]; + ui8_t numSV; int week; int gpssec; int jahr; int monat; int tag; int wday; @@ -326,6 +327,23 @@ int check_CRC(ui32_t pos, ui32_t pck) { #define crc_ZERO (1<<6) // LEN variable #define pck_ZERO 0x7600 +#define pck_ZEROstd 0x7611 // NDATA std-frm, no aux +#define pos_ZEROstd 0x12B // pos_AUX(0) + + +/* + frame[pos_FRAME-1] == 0x0F: len == NDATA_LEN(320) + frame[pos_FRAME-1] == 0xF0: len == FRAME_LEN(518) +*/ +int frametype() { // -4..+4: 0xF0 -> -4 , 0x0F -> +4 + int i; + ui8_t b = frame[pos_FRAME-1]; + int ft = 0; + for (i = 0; i < 4; i++) { + ft += ((b>>i)&1) - ((b>>(i+4))&1); + } + return ft; +} ui8_t calibytes[51*16]; @@ -345,7 +363,7 @@ int get_SatData() { int i, n; int sv; ui32_t minPR; - int Nfix; + int numSV; double pDOP, sAcc; fprintf(stdout, "[%d]\n", u2(frame+pos_FrameNb)); @@ -377,10 +395,10 @@ int get_SatData() { (i16_t)u2(frame+pos_GPSecefV+2), (i16_t)u2(frame+pos_GPSecefV+4)); - Nfix = frame[pos_numSats]; - sAcc = frame[pos_sAcc]/10.0; - pDOP = frame[pos_pDOP]/10.0; - fprintf(stdout, "numSatsFix: %2d sAcc: %.1f pDOP: %.1f\n", Nfix, sAcc, pDOP); + numSV = frame[pos_numSats]; + sAcc = frame[pos_sAcc]/10.0; if (frame[pos_sAcc] == 0xFF) sAcc = -1.0; + pDOP = frame[pos_pDOP]/10.0; if (frame[pos_pDOP] == 0xFF) pDOP = -1.0; + fprintf(stdout, "numSatsFix: %2d sAcc: %.1f pDOP: %.1f\n", numSV, sAcc, pDOP); fprintf(stdout, "CRC: "); @@ -749,6 +767,8 @@ int get_GPSkoord() { if (dir < 0) dir += 360; gpx.vD = dir; + gpx.numSV = frame[pos_numSats]; + return 0; } @@ -778,6 +798,8 @@ int get_Aux() { count7E = 0; pos7E = pos_AUX; + if (frametype(gpx) > 0) return 0; //pos7E == pos7611 ... + // 7Exx: xdata while ( pos7E < FRAME_LEN && framebyte(pos7E) == 0x7E ) { @@ -790,7 +812,8 @@ int get_Aux() { //fprintf(stdout, " # %02x : ", framebyte(pos7E+2)); for (i = 1; i < auxlen; i++) { - fprintf(stdout, "%c", framebyte(pos7E+2+i)); + ui8_t c = framebyte(pos7E+2+i); + if (c > 0x1E) fprintf(stdout, "%c", c); } count7E++; pos7E += 2+auxlen+2; @@ -880,20 +903,6 @@ int get_Calconf(int out) { return 0; } -/* - frame[pos_FRAME-1] == 0x0F: len == NDATA_LEN(320) - frame[pos_FRAME-1] == 0xF0: len == FRAME_LEN(518) -*/ -int frametype() { // -4..+4: 0xF0 -> -4 , 0x0F -> +4 - int i; - ui8_t b = frame[pos_FRAME-1]; - int ft = 0; - for (i = 0; i < 4; i++) { - ft += ((b>>i)&1) - ((b>>(i+4))&1); - } - return ft; -} - /* ------------------------------------------------------------------------------------ */ /* (uses fec-lib by KA9Q) @@ -946,15 +955,26 @@ int rs41_ecc(int frmlen) { errors2 = rs_decode(cw2, err_pos2, err_val2); - if (option_ecc == 2 && (errors1 < 0 || errors2 < 0)) { + if (option_ecc == 2 && (errors1 < 0 || errors2 < 0)) + { // 2nd pass frame[pos_FRAME] = (pck_FRAME>>8)&0xFF; frame[pos_FRAME+1] = pck_FRAME&0xFF; frame[pos_PTU] = (pck_PTU >>8)&0xFF; frame[pos_PTU +1] = pck_PTU &0xFF; frame[pos_GPS1] = (pck_GPS1 >>8)&0xFF; frame[pos_GPS1 +1] = pck_GPS1 &0xFF; frame[pos_GPS2] = (pck_GPS2 >>8)&0xFF; frame[pos_GPS2 +1] = pck_GPS2 &0xFF; frame[pos_GPS3] = (pck_GPS3 >>8)&0xFF; frame[pos_GPS3 +1] = pck_GPS3 &0xFF; - if (frametype() < -2) { + // AUX-frames mit vielen Fehlern besser mit 00 auffuellen + // std-O3-AUX-frame: NDATA+7 + if (frametype() < -2) { // ft >= 0: NDATA_LEN , ft < 0: FRAME_LEN for (i = NDATA_LEN + 7; i < FRAME_LEN-2; i++) frame[i] = 0; } + else { // std-frm (len=320): std_ZERO-frame (7611 00..00 ECC7) + for (i = NDATA_LEN; i < FRAME_LEN; i++) frame[i] = 0; + frame[pos_ZEROstd ] = 0x76; // pck_ZEROstd + frame[pos_ZEROstd+1] = 0x11; // pck_ZEROstd + for (i = pos_ZEROstd+2; i < NDATA_LEN-2; i++) frame[i] = 0; + frame[NDATA_LEN-2] = 0xEC; // crc(pck_ZEROstd) + frame[NDATA_LEN-1] = 0xC7; // crc(pck_ZEROstd) + } for (i = 0; i < rs_K; i++) cw1[rs_R+i] = frame[cfg_rs41.msgpos+2*i ]; for (i = 0; i < rs_K; i++) cw2[rs_R+i] = frame[cfg_rs41.msgpos+2*i+1]; errors1 = rs_decode(cw1, err_pos1, err_val1); @@ -1036,6 +1056,7 @@ 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_verbose == 3) fprintf(stdout," numSV: %02d ", gpx.numSV); } } if (option_ptu && !err0) { @@ -1085,9 +1106,9 @@ int print_position(int ec) { // Print JSON output required by auto_rx. if (!err && !err1 && !err3) { // frame-nb/id && gps-time && gps-position (crc-)ok; 3 CRCs, RS not needed if (option_ptu && !err0 && gpx.T > -273.0) { - printf("{ \"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 ); + printf("{ \"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, \"sats\": %d, \"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.numSV, gpx.T ); } else { - printf("{ \"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 ); + printf("{ \"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, \"sats\": %d }\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.numSV ); } printf("\n"); } @@ -1142,7 +1163,14 @@ void print_frame(int len) { } if (option_ecc) { if (ec >= 0) fprintf(stdout, " [OK]"); else fprintf(stdout, " [NO]"); - if (option_ecc == 2 && ec > 0) fprintf(stdout, " (%d)", ec); + 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, " (--)"); + } + } } fprintf(stdout, "\n"); } @@ -1179,8 +1207,8 @@ int main(int argc, char *argv[]) { float thres = 0.7; - int bitofs = 0; int symlen = 1; + int bitofs = 2; #ifdef CYGWIN @@ -1338,8 +1366,9 @@ int main(int argc, char *argv[]) { Qerror_count += 1; } } - header_found = 0; + print_frame(ft_len); + header_found = 0; while ( bit_count < BITS*(FRAME_LEN-8+24) ) { bitQ = read_sbit(fp, symlen, &bit, option_inv, bitofs, bit_count==0, 0); // symlen=1, return: zeroX/bit diff --git a/demod/rs41dm_iq.c b/demod/rs41dm_iq.c index f232dfc..abeb333 100644 --- a/demod/rs41dm_iq.c +++ b/demod/rs41dm_iq.c @@ -2,7 +2,7 @@ /* * rs41 * sync header: correlation/matched filter - * files: rs41dm_iq.c bch_ecc.c demod_iq.h demod_iq.c + * files: rs41dm_iq.c bch_ecc.c demod_iq.c demod_iq.h * compile: * gcc -c demod_iq.c * gcc rs41dm_iq.c demod_iq.o -lm -o rs41dm_iq @@ -20,18 +20,21 @@ #include #endif -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_dft.c" #include "demod_iq.h" #include "bch_ecc.c" // RS/ecc/ +typedef struct { + i8_t vbs; // verbose output + i8_t raw; // raw frames + i8_t crc; // CRC check output + i8_t ecc; // Reed-Solomon ECC + i8_t sat; // GPS sat data + i8_t ptu; // PTU: temperature +} option_t; + typedef struct { int typ; int msglen; @@ -41,12 +44,21 @@ typedef struct { int frmlen; } rscfg_t; -rscfg_t cfg_rs41 = { 41, (320-56)/2, 56, 8, 8, 320}; +rscfg_t cfg_rs41 = { 41, (320-56)/2, 56, 8, 8, 320}; // const: msgpos, parpos +#define NDATA_LEN 320 // std framelen 320 +#define XDATA_LEN 198 +#define FRAME_LEN (NDATA_LEN+XDATA_LEN) // max framelen 518 +/* +ui8_t //xframe[FRAME_LEN] = { 0x10, 0xB6, 0xCA, 0x11, 0x22, 0x96, 0x12, 0xF8}, = xorbyte( frame) + frame[FRAME_LEN] = { 0x86, 0x35, 0xf4, 0x40, 0x93, 0xdf, 0x1a, 0x60}; // = xorbyte(xframe) +*/ typedef struct { + int out; int frnr; char id[9]; + ui8_t numSV; int week; int gpssec; int jahr; int monat; int tag; int wday; @@ -56,65 +68,87 @@ typedef struct { double vH; double vD; double vD2; float T; ui32_t crc; + ui8_t frame[FRAME_LEN]; + ui8_t calibytes[51*16]; + ui8_t calfrchk[51]; + float ptu_Rf1; // ref-resistor f1 (750 Ohm) + float ptu_Rf2; // ref-resistor f2 (1100 Ohm) + float ptu_co1[3]; // { -243.911 , 0.187654 , 8.2e-06 } + float ptu_calT1[3]; // calibration T1 + float ptu_co2[3]; // { -243.911 , 0.187654 , 8.2e-06 } + float ptu_calT2[3]; // calibration T2-Hum + ui16_t conf_fw; // firmware + ui16_t conf_kt; // kill timer (sec) + ui16_t conf_bt; // burst timer (sec) + ui8_t conf_bk; // burst kill + ui32_t freq; // freq/kHz + char rstyp[9]; // RS41-SG, RS41-SGP + int aux; + char xdata[XDATA_LEN+16]; // xdata: aux_str1#aux_str2 ... + option_t option; } gpx_t; -gpx_t gpx; - -int option_verbose = 0, // ausfuehrliche Anzeige - option_raw = 0, // rohe Frames - option_inv = 0, // invertiert Signal - option_res = 0, // genauere Bitmessung - option_crc = 0, // check CRC - option_ecc = 0, // Reed-Solomon ECC - option_sat = 0, // GPS sat data - option_ptu = 0, - option_ths = 0, - option_iq = 0, - option_ofs = 0, - option_dbg = 0, - wavloaded = 0; -int wav_channel = 0; // audio channel: left - #define BITS 8 #define HEADLEN 64 #define FRAMESTART ((HEADLEN)/BITS) -/* 10 B6 CA 11 22 96 12 F8 */ -char header[] = "0000100001101101010100111000100001000100011010010100100000011111"; +/* 10 B6 CA 11 22 96 12 F8 */ +static char header[] = "0000100001101101010100111000100001000100011010010100100000011111"; - -#define NDATA_LEN 320 // std framelen 320 -#define XDATA_LEN 198 -#define FRAME_LEN (NDATA_LEN+XDATA_LEN) // max framelen 518 -ui8_t //xframe[FRAME_LEN] = { 0x10, 0xB6, 0xCA, 0x11, 0x22, 0x96, 0x12, 0xF8}, = xorbyte( frame) - frame[FRAME_LEN] = { 0x86, 0x35, 0xf4, 0x40, 0x93, 0xdf, 0x1a, 0x60}; // = xorbyte(xframe) - -float byteQ[FRAME_LEN]; +static ui8_t header_bytes[8] = { 0x86, 0x35, 0xf4, 0x40, 0x93, 0xdf, 0x1a, 0x60}; #define MASK_LEN 64 -ui8_t mask[MASK_LEN] = { 0x96, 0x83, 0x3E, 0x51, 0xB1, 0x49, 0x08, 0x98, - 0x32, 0x05, 0x59, 0x0E, 0xF9, 0x44, 0xC6, 0x26, - 0x21, 0x60, 0xC2, 0xEA, 0x79, 0x5D, 0x6D, 0xA1, - 0x54, 0x69, 0x47, 0x0C, 0xDC, 0xE8, 0x5C, 0xF1, - 0xF7, 0x76, 0x82, 0x7F, 0x07, 0x99, 0xA2, 0x2C, - 0x93, 0x7C, 0x30, 0x63, 0xF5, 0x10, 0x2E, 0x61, - 0xD0, 0xBC, 0xB4, 0xB6, 0x06, 0xAA, 0xF4, 0x23, - 0x78, 0x6E, 0x3B, 0xAE, 0xBF, 0x7B, 0x4C, 0xC1}; +static ui8_t mask[MASK_LEN] = { 0x96, 0x83, 0x3E, 0x51, 0xB1, 0x49, 0x08, 0x98, + 0x32, 0x05, 0x59, 0x0E, 0xF9, 0x44, 0xC6, 0x26, + 0x21, 0x60, 0xC2, 0xEA, 0x79, 0x5D, 0x6D, 0xA1, + 0x54, 0x69, 0x47, 0x0C, 0xDC, 0xE8, 0x5C, 0xF1, + 0xF7, 0x76, 0x82, 0x7F, 0x07, 0x99, 0xA2, 0x2C, + 0x93, 0x7C, 0x30, 0x63, 0xF5, 0x10, 0x2E, 0x61, + 0xD0, 0xBC, 0xB4, 0xB6, 0x06, 0xAA, 0xF4, 0x23, + 0x78, 0x6E, 0x3B, 0xAE, 0xBF, 0x7B, 0x4C, 0xC1}; /* LFSR: ab i=8 (mod 64): * m[16+i] = m[i] ^ m[i+2] ^ m[i+4] ^ m[i+6] * ________________3205590EF944C6262160C2EA795D6DA15469470CDCE85CF1 * F776827F0799A22C937C3063F5102E61D0BCB4B606AAF423786E3BAEBF7B4CC196833E51B1490898 */ +/* + frame[pos] = xframe[pos] ^ mask[pos % MASK_LEN]; +*/ /* ------------------------------------------------------------------------------------ */ #define BAUD_RATE 4800 /* ------------------------------------------------------------------------------------ */ +/* + * Convert GPS Week and Seconds to Modified Julian Day. + * - Adapted from sci.astro FAQ. + * - Ignores UTC leap seconds. + */ +// in : week, gpssec +// out: jahr, monat, tag +static void Gps2Date(gpx_t *gpx) { + long GpsDays, Mjd; + long J, C, Y, M; + GpsDays = gpx->week * 7 + (gpx->gpssec / 86400); + Mjd = 44244 + GpsDays; -int bits2byte(char bits[]) { + J = Mjd + 2468570; + C = 4 * J / 146097; + J = J - (146097 * C + 3) / 4; + Y = 4000 * (J + 1) / 1461001; + J = J - 1461 * Y / 4 + 31; + M = 80 * J / 2447; + gpx->tag = J - 2447 * M / 80; + J = M / 11; + gpx->monat = M + 2 - (12 * J); + gpx->jahr = 100 * (C - 49) + Y + J; +} +/* ------------------------------------------------------------------------------------ */ + +static int bits2byte(char bits[]) { int i, byteval=0, d=1; for (i = 0; i < 8; i++) { // little endian /* for (i = 7; i >= 0; i--) { // big endian */ @@ -126,58 +160,22 @@ int bits2byte(char bits[]) { return byteval; } - -/* -ui8_t xorbyte(int pos) { - return xframe[pos] ^ mask[pos % MASK_LEN]; -} -*/ -ui8_t framebyte(int pos) { - return frame[pos]; -} - - -/* ------------------------------------------------------------------------------------ */ -/* - * Convert GPS Week and Seconds to Modified Julian Day. - * - Adapted from sci.astro FAQ. - * - Ignores UTC leap seconds. - */ -void Gps2Date(long GpsWeek, long GpsSeconds, int *Year, int *Month, int *Day) { - - long GpsDays, Mjd; - long J, C, Y, M; - - GpsDays = GpsWeek * 7 + (GpsSeconds / 86400); - Mjd = 44244 + GpsDays; - - J = Mjd + 2468570; - C = 4 * J / 146097; - J = J - (146097 * C + 3) / 4; - Y = 4000 * (J + 1) / 1461001; - J = J - 1461 * Y / 4 + 31; - M = 80 * J / 2447; - *Day = J - 2447 * M / 80; - J = M / 11; - *Month = M + 2 - (12 * J); - *Year = 100 * (C - 49) + Y + J; -} /* ------------------------------------------------------------------------------------ */ -ui32_t u4(ui8_t *bytes) { // 32bit unsigned int +static ui32_t u4(ui8_t *bytes) { // 32bit unsigned int ui32_t val = 0; memcpy(&val, bytes, 4); return val; } -ui32_t u3(ui8_t *bytes) { // 24bit unsigned int +static ui32_t u3(ui8_t *bytes) { // 24bit unsigned int int val24 = 0; val24 = bytes[0] | (bytes[1]<<8) | (bytes[2]<<16); // = memcpy(&val, bytes, 3), val &= 0x00FFFFFF; return val24; } -int i3(ui8_t *bytes) { // 24bit signed int +static int i3(ui8_t *bytes) { // 24bit signed int int val = 0, val24 = 0; val = bytes[0] | (bytes[1]<<8) | (bytes[2]<<16); @@ -185,7 +183,7 @@ int i3(ui8_t *bytes) { // 24bit signed int return val24; } -ui32_t u2(ui8_t *bytes) { // 16bit unsigned int +static ui32_t u2(ui8_t *bytes) { // 16bit unsigned int return bytes[0] | (bytes[1]<<8); } @@ -203,31 +201,7 @@ float r4(ui8_t *bytes) { } */ -/* -int crc16x(int start, int len) { - int crc16poly = 0x1021; - int rem = 0xFFFF, i, j; - int xbyte; - - if (start+len+2 > FRAME_LEN) return -1; - - for (i = 0; i < len; i++) { - xbyte = xorbyte(start+i); - rem = rem ^ (xbyte << 8); - for (j = 0; j < 8; j++) { - if (rem & 0x8000) { - rem = (rem << 1) ^ crc16poly; - } - else { - rem = (rem << 1); - } - rem &= 0xFFFF; - } - } - return rem; -} -*/ -int crc16(int start, int len) { +static int crc16(gpx_t *gpx, int start, int len) { int crc16poly = 0x1021; int rem = 0xFFFF, i, j; int byte; @@ -235,7 +209,7 @@ int crc16(int start, int len) { if (start+len+2 > FRAME_LEN) return -1; for (i = 0; i < len; i++) { - byte = framebyte(start+i); + byte = gpx->frame[start+i]; rem = rem ^ (byte << 8); for (j = 0; j < 8; j++) { if (rem & 0x8000) { @@ -250,14 +224,14 @@ int crc16(int start, int len) { return rem; } -int check_CRC(ui32_t pos, ui32_t pck) { +static int check_CRC(gpx_t *gpx, ui32_t pos, ui32_t pck) { ui32_t crclen = 0, crcdat = 0; - if (((pck>>8) & 0xFF) != frame[pos]) return -1; - crclen = frame[pos+1]; + if (((pck>>8) & 0xFF) != gpx->frame[pos]) return -1; + crclen = gpx->frame[pos+1]; if (pos + crclen + 4 > FRAME_LEN) return -1; - crcdat = u2(frame+pos+2+crclen); - if ( crcdat != crc16(pos+2, crclen) ) { + crcdat = u2(gpx->frame+pos+2+crclen); + if ( crcdat != crc16(gpx, pos+2, crclen) ) { return 1; // CRC NO } else return 0; // CRC OK @@ -265,6 +239,8 @@ int check_CRC(ui32_t pos, ui32_t pck) { /* +GPS chip: ublox UBX-G6010-ST + Pos: SubHeader, 1+1 byte (ID+LEN) 0x039: 7928 FrameNumber+SondeID +(0x050: 0732 CalFrames 0x00..0x32) @@ -328,73 +304,82 @@ int check_CRC(ui32_t pos, ui32_t pck) { #define crc_ZERO (1<<6) // LEN variable #define pck_ZERO 0x7600 +#define pck_ZEROstd 0x7611 // NDATA std-frm, no aux +#define pos_ZEROstd 0x12B // pos_AUX(0) -ui8_t calibytes[51*16]; -ui8_t calfrchk[51]; -float Rf1, // ref-resistor f1 (750 Ohm) - Rf2, // ref-resistor f2 (1100 Ohm) - co1[3], // { -243.911 , 0.187654 , 8.2e-06 } - calT1[3], // calibration T1 - co2[3], // { -243.911 , 0.187654 , 8.2e-06 } - calT2[3]; // calibration T2-Hum +/* + frame[pos_FRAME-1] == 0x0F: len == NDATA_LEN(320) + frame[pos_FRAME-1] == 0xF0: len == FRAME_LEN(518) +*/ +static int frametype(gpx_t *gpx) { // -4..+4: 0xF0 -> -4 , 0x0F -> +4 + int i; + ui8_t b = gpx->frame[pos_FRAME-1]; + int ft = 0; + for (i = 0; i < 4; i++) { + ft += ((b>>i)&1) - ((b>>(i+4))&1); + } + return ft; +} -double c = 299.792458e6; -double L1 = 1575.42e6; +const double c = 299.792458e6; +const double L1 = 1575.42e6; -int get_SatData() { +static int get_SatData(gpx_t *gpx) { int i, n; int sv; ui32_t minPR; - int Nfix; + int numSV; double pDOP, sAcc; - fprintf(stdout, "[%d]\n", u2(frame+pos_FrameNb)); + fprintf(stdout, "[%d]\n", u2(gpx->frame+pos_FrameNb)); - fprintf(stdout, "iTOW: 0x%08X", u4(frame+pos_GPSiTOW)); - fprintf(stdout, " week: 0x%04X", u2(frame+pos_GPSweek)); + fprintf(stdout, "iTOW: 0x%08X", u4(gpx->frame+pos_GPSiTOW)); + fprintf(stdout, " week: 0x%04X", u2(gpx->frame+pos_GPSweek)); fprintf(stdout, "\n"); - minPR = u4(frame+pos_minPR); + minPR = u4(gpx->frame+pos_minPR); fprintf(stdout, "minPR: %d", minPR); fprintf(stdout, "\n"); for (i = 0; i < 12; i++) { n = i*7; - sv = frame[pos_satsN+2*i]; + sv = gpx->frame[pos_satsN+2*i]; if (sv == 0xFF) break; - fprintf(stdout, " SV: %2d # ", sv); - fprintf(stdout, "prMes: %.1f", u4(frame+pos_dataSats+n)/100.0 + minPR); + fprintf(stdout, " SV: %2d ", sv); + //fprintf(stdout, " (%02x) ", gpx->frame[pos_satsN+2*i+1]); + fprintf(stdout, "# "); + fprintf(stdout, "prMes: %.1f", u4(gpx->frame+pos_dataSats+n)/100.0 + minPR); fprintf(stdout, " "); - fprintf(stdout, "doMes: %.1f", -i3(frame+pos_dataSats+n+4)/100.0*L1/c); + fprintf(stdout, "doMes: %.1f", -i3(gpx->frame+pos_dataSats+n+4)/100.0*L1/c); fprintf(stdout, "\n"); } fprintf(stdout, "ECEF-POS: (%d,%d,%d)\n", - (i32_t)u4(frame+pos_GPSecefX), - (i32_t)u4(frame+pos_GPSecefY), - (i32_t)u4(frame+pos_GPSecefZ)); + (i32_t)u4(gpx->frame+pos_GPSecefX), + (i32_t)u4(gpx->frame+pos_GPSecefY), + (i32_t)u4(gpx->frame+pos_GPSecefZ)); fprintf(stdout, "ECEF-VEL: (%d,%d,%d)\n", - (i16_t)u2(frame+pos_GPSecefV+0), - (i16_t)u2(frame+pos_GPSecefV+2), - (i16_t)u2(frame+pos_GPSecefV+4)); + (i16_t)u2(gpx->frame+pos_GPSecefV+0), + (i16_t)u2(gpx->frame+pos_GPSecefV+2), + (i16_t)u2(gpx->frame+pos_GPSecefV+4)); - Nfix = frame[pos_numSats]; - sAcc = frame[pos_sAcc]/10.0; - pDOP = frame[pos_pDOP]/10.0; - fprintf(stdout, "numSatsFix: %2d sAcc: %.1f pDOP: %.1f\n", Nfix, sAcc, pDOP); + numSV = gpx->frame[pos_numSats]; + sAcc = gpx->frame[pos_sAcc]/10.0; if (gpx->frame[pos_sAcc] == 0xFF) sAcc = -1.0; + pDOP = gpx->frame[pos_pDOP]/10.0; if (gpx->frame[pos_pDOP] == 0xFF) pDOP = -1.0; + fprintf(stdout, "numSatsFix: %2d sAcc: %.1f pDOP: %.1f\n", numSV, sAcc, pDOP); fprintf(stdout, "CRC: "); fprintf(stdout, " %04X", pck_GPS1); - if (check_CRC(pos_GPS1, pck_GPS1)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]"); - //fprintf(stdout, "[%+d]", check_CRC(pos_GPS1, pck_GPS1)); + if (check_CRC(gpx, pos_GPS1, pck_GPS1)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]"); + //fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS1, pck_GPS1)); fprintf(stdout, " %04X", pck_GPS2); - if (check_CRC(pos_GPS2, pck_GPS2)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]"); - //fprintf(stdout, "[%+d]", check_CRC(pos_GPS2, pck_GPS2)); + if (check_CRC(gpx, pos_GPS2, pck_GPS2)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]"); + //fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS2, pck_GPS2)); fprintf(stdout, " %04X", pck_GPS3); - if (check_CRC(pos_GPS3, pck_GPS3)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]"); - //fprintf(stdout, "[%+d]", check_CRC(pos_GPS3, pck_GPS3)); + if (check_CRC(gpx, pos_GPS3, pck_GPS3)==0) fprintf(stdout, "[OK]"); else fprintf(stdout, "[NO]"); + //fprintf(stdout, "[%+d]", check_CRC(gpx, pos_GPS3, pck_GPS3)); fprintf(stdout, "\n"); fprintf(stdout, "\n"); @@ -403,105 +388,112 @@ int get_SatData() { } -int get_FrameNb() { +static int get_FrameNb(gpx_t *gpx) { int i; unsigned byte; ui8_t frnr_bytes[2]; int frnr; for (i = 0; i < 2; i++) { - byte = framebyte(pos_FrameNb + i); + byte = gpx->frame[pos_FrameNb + i]; frnr_bytes[i] = byte; } frnr = frnr_bytes[0] + (frnr_bytes[1] << 8); - gpx.frnr = frnr; + gpx->frnr = frnr; return 0; } -int get_SondeID(int crc) { +static int get_SondeID(gpx_t *gpx, int crc) { int i; unsigned byte; char sondeid_bytes[9]; if (crc == 0) { for (i = 0; i < 8; i++) { - byte = framebyte(pos_SondeID + i); + byte = gpx->frame[pos_SondeID + i]; //if ((byte < 0x20) || (byte > 0x7E)) return -1; sondeid_bytes[i] = byte; } sondeid_bytes[8] = '\0'; - if ( strncmp(gpx.id, sondeid_bytes, 8) != 0 ) { - //for (i = 0; i < 51; i++) calfrchk[i] = 0; - memset(calfrchk, 0, 51); - memcpy(gpx.id, sondeid_bytes, 8); - gpx.id[8] = '\0'; + if ( strncmp(gpx->id, sondeid_bytes, 8) != 0 ) { + //for (i = 0; i < 51; i++) gpx->calfrchk[i] = 0; + memset(gpx->calfrchk, 0, 51); + memcpy(gpx->id, sondeid_bytes, 8); + gpx->id[8] = '\0'; + // conf data + gpx->conf_fw = 0; + gpx->conf_kt = -1; + gpx->conf_bt = 0; + gpx->conf_bk = 0; + gpx->freq = 0; + memset(gpx->rstyp, 0, 9); } } return 0; } -int get_FrameConf() { +static int get_FrameConf(gpx_t *gpx) { int crc, err; ui8_t calfr; int i; - crc = check_CRC(pos_FRAME, pck_FRAME); - if (crc) gpx.crc |= crc_FRAME; + crc = check_CRC(gpx, pos_FRAME, pck_FRAME); + if (crc) gpx->crc |= crc_FRAME; err = crc; - err |= get_FrameNb(); - err |= get_SondeID(crc); + err |= get_FrameNb(gpx); + err |= get_SondeID(gpx, crc); if (crc == 0) { - calfr = framebyte(pos_CalData); - if (calfrchk[calfr] == 0) // const? - { // 0x32 not constant + calfr = gpx->frame[pos_CalData]; + if (gpx->calfrchk[calfr] == 0) // const? + { // 0x32 not constant for (i = 0; i < 16; i++) { - calibytes[calfr*16 + i] = framebyte(pos_CalData+1+i); + gpx->calibytes[calfr*16 + i] = gpx->frame[pos_CalData+1+i]; } - calfrchk[calfr] = 1; + gpx->calfrchk[calfr] = 1; } } return err; } -int get_CalData() { +static int get_CalData(gpx_t *gpx) { - memcpy(&Rf1, calibytes+61, 4); // 0x03*0x10+13 - memcpy(&Rf2, calibytes+65, 4); // 0x04*0x10+ 1 + memcpy(&(gpx->ptu_Rf1), gpx->calibytes+61, 4); // 0x03*0x10+13 + memcpy(&(gpx->ptu_Rf2), gpx->calibytes+65, 4); // 0x04*0x10+ 1 - memcpy(co1+0, calibytes+77, 4); // 0x04*0x10+13 - memcpy(co1+1, calibytes+81, 4); // 0x05*0x10+ 1 - memcpy(co1+2, calibytes+85, 4); // 0x05*0x10+ 5 + memcpy(gpx->ptu_co1+0, gpx->calibytes+77, 4); // 0x04*0x10+13 + memcpy(gpx->ptu_co1+1, gpx->calibytes+81, 4); // 0x05*0x10+ 1 + memcpy(gpx->ptu_co1+2, gpx->calibytes+85, 4); // 0x05*0x10+ 5 - memcpy(calT1+0, calibytes+89, 4); // 0x05*0x10+ 9 - memcpy(calT1+1, calibytes+93, 4); // 0x05*0x10+13 - memcpy(calT1+2, calibytes+97, 4); // 0x06*0x10+ 1 + memcpy(gpx->ptu_calT1+0, gpx->calibytes+89, 4); // 0x05*0x10+ 9 + memcpy(gpx->ptu_calT1+1, gpx->calibytes+93, 4); // 0x05*0x10+13 + memcpy(gpx->ptu_calT1+2, gpx->calibytes+97, 4); // 0x06*0x10+ 1 - memcpy(co2+0, calibytes+293, 4); // 0x12*0x10+ 5 - memcpy(co2+1, calibytes+297, 4); // 0x12*0x10+ 9 - memcpy(co2+2, calibytes+301, 4); // 0x12*0x10+13 + memcpy(gpx->ptu_co2+0, gpx->calibytes+293, 4); // 0x12*0x10+ 5 + memcpy(gpx->ptu_co2+1, gpx->calibytes+297, 4); // 0x12*0x10+ 9 + memcpy(gpx->ptu_co2+2, gpx->calibytes+301, 4); // 0x12*0x10+13 - memcpy(calT2+0, calibytes+305, 4); // 0x13*0x10+ 1 - memcpy(calT2+1, calibytes+309, 4); // 0x13*0x10+ 5 - memcpy(calT2+2, calibytes+313, 4); // 0x13*0x10+ 9 + memcpy(gpx->ptu_calT2+0, gpx->calibytes+305, 4); // 0x13*0x10+ 1 + memcpy(gpx->ptu_calT2+1, gpx->calibytes+309, 4); // 0x13*0x10+ 5 + memcpy(gpx->ptu_calT2+2, gpx->calibytes+313, 4); // 0x13*0x10+ 9 return 0; } -float get_Tc0(ui32_t f, ui32_t f1, ui32_t f2) { +static float get_Tc0(gpx_t *gpx, ui32_t f, ui32_t f1, ui32_t f2) { // y = (f - f1) / (f2 - f1); // y1 = (f - f1) / f2; // = (1 - f1/f2)*y float a = 3.9083e-3, // Pt1000 platinum resistance b = -5.775e-7, c = -4.183e-12; // below 0C, else C=0 - float *cal = calT1; - float Rb = (f1*Rf2-f2*Rf1)/(f2-f1), // ofs - Ra = f * (Rf2-Rf1)/(f2-f1) - Rb, + float *cal = gpx->ptu_calT1; + float Rb = (f1*gpx->ptu_Rf2-f2*gpx->ptu_Rf1)/(f2-f1), // ofs + Ra = f * (gpx->ptu_Rf2-gpx->ptu_Rf1)/(f2-f1) - Rb, raw = Ra/1000.0, g_r = 0.8024*cal[0] + 0.0176, // empirisch r_o = 0.0705*cal[1] + 0.0011, // empirisch @@ -510,11 +502,11 @@ float get_Tc0(ui32_t f, ui32_t f1, ui32_t f2) { // R/R0 = 1 + at + bt^2 + c(t-100)t^3 , R0 = 1000 Ohm, t/Celsius return t; } -float get_Tc(ui32_t f, ui32_t f1, ui32_t f2) { - float *p = co1; - float *c = calT1; - float g = (float)(f2-f1)/(Rf2-Rf1), // gain - Rb = (f1*Rf2-f2*Rf1)/(float)(f2-f1), // ofs +static float get_Tc(gpx_t *gpx, ui32_t f, ui32_t f1, ui32_t f2) { + float *p = gpx->ptu_co1; + float *c = gpx->ptu_calT1; + float g = (float)(f2-f1)/(gpx->ptu_Rf2-gpx->ptu_Rf1), // gain + Rb = (f1*gpx->ptu_Rf2-f2*gpx->ptu_Rf1)/(float)(f2-f1), // ofs Rc = f/g - Rb, //R = (Rc + c[1]) * c[0], //T = p[0] + p[1]*R + p[2]*R*R; @@ -523,7 +515,7 @@ float get_Tc(ui32_t f, ui32_t f1, ui32_t f2) { return T; } -int get_PTU() { +static int get_PTU(gpx_t *gpx) { int err=0, i; int bR, bc1, bT1, bc2, bT2; @@ -531,33 +523,33 @@ int get_PTU() { float Tc = -273.15; float Tc0 = -273.15; - get_CalData(); + get_CalData(gpx); - err = check_CRC(pos_PTU, pck_PTU); - if (err) gpx.crc |= crc_PTU; + err = check_CRC(gpx, pos_PTU, pck_PTU); + if (err) gpx->crc |= crc_PTU; if (err == 0) { for (i = 0; i < 12; i++) { - meas[i] = u3(frame+pos_PTU+2+3*i); + meas[i] = u3(gpx->frame+pos_PTU+2+3*i); } - bR = calfrchk[0x03] && calfrchk[0x04]; - bc1 = calfrchk[0x04] && calfrchk[0x05]; - bT1 = calfrchk[0x05] && calfrchk[0x06]; - bc2 = calfrchk[0x12] && calfrchk[0x13]; - bT2 = calfrchk[0x13]; + bR = gpx->calfrchk[0x03] && gpx->calfrchk[0x04]; + bc1 = gpx->calfrchk[0x04] && gpx->calfrchk[0x05]; + bT1 = gpx->calfrchk[0x05] && gpx->calfrchk[0x06]; + bc2 = gpx->calfrchk[0x12] && gpx->calfrchk[0x13]; + bT2 = gpx->calfrchk[0x13]; if (bR && bc1 && bT1) { - Tc = get_Tc(meas[0], meas[1], meas[2]); - Tc0 = get_Tc0(meas[0], meas[1], meas[2]); + Tc = get_Tc(gpx, meas[0], meas[1], meas[2]); + Tc0 = get_Tc0(gpx, meas[0], meas[1], meas[2]); } - gpx.T = Tc; + gpx->T = Tc; - if (option_verbose == 4) + if (gpx->option.vbs == 4) { - printf(" h: %8.2f # ", gpx.alt); // crc_GPS3 ? + printf(" h: %8.2f # ", gpx->alt); // crc_GPS3 ? printf("1: %8d %8d %8d", meas[0], meas[1], meas[2]); printf(" # "); @@ -570,11 +562,11 @@ int get_PTU() { } printf("\n"); - if (gpx.alt > -100.0) { - printf(" %9.2f ; %6.1f ; %6.1f ", gpx.alt, Rf1, Rf2); - printf("; %10.6f ; %10.6f ; %10.6f ;", calT1[0], calT1[1], calT1[2]); + if (gpx->alt > -100.0) { + printf(" %9.2f ; %6.1f ; %6.1f ", gpx->alt, gpx->ptu_Rf1, gpx->ptu_Rf2); + printf("; %10.6f ; %10.6f ; %10.6f ;", gpx->ptu_calT1[0], gpx->ptu_calT1[1], gpx->ptu_calT1[2]); printf(" %8d ; %8d ; %8d ", meas[0], meas[1], meas[2]); - printf("; %10.6f ; %10.6f ; %10.6f ;", calT2[0], calT2[1], calT2[2]); + printf("; %10.6f ; %10.6f ; %10.6f ;", gpx->ptu_calT2[0], gpx->ptu_calT2[1], gpx->ptu_calT2[2]); printf(" %8d ; %8d ; %8d" , meas[6], meas[7], meas[8]); printf("\n"); } @@ -585,27 +577,28 @@ int get_PTU() { return err; } -int get_GPSweek() { +static int get_GPSweek(gpx_t *gpx) { int i; unsigned byte; ui8_t gpsweek_bytes[2]; int gpsweek; for (i = 0; i < 2; i++) { - byte = framebyte(pos_GPSweek + i); + byte = gpx->frame[pos_GPSweek + i]; gpsweek_bytes[i] = byte; } gpsweek = gpsweek_bytes[0] + (gpsweek_bytes[1] << 8); - //if (gpsweek < 0) { gpx.week = -1; return -1; } // (short int) - gpx.week = gpsweek; + //if (gpsweek < 0) { gpx->week = -1; return -1; } // (short int) + gpx->week = gpsweek; return 0; } -char weekday[7][3] = { "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"}; +//char weekday[7][3] = { "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"}; +static char weekday[7][4] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; -int get_GPStime() { +static int get_GPStime(gpx_t *gpx) { int i; unsigned byte; ui8_t gpstime_bytes[4]; @@ -614,7 +607,7 @@ int get_GPStime() { int ms; for (i = 0; i < 4; i++) { - byte = framebyte(pos_GPSiTOW + i); + byte = gpx->frame[pos_GPSiTOW + i]; gpstime_bytes[i] = byte; } @@ -622,45 +615,44 @@ int get_GPStime() { ms = gpstime % 1000; gpstime /= 1000; - gpx.gpssec = gpstime; + gpx->gpssec = gpstime; day = (gpstime / (24 * 3600)) % 7; //if ((day < 0) || (day > 6)) return -1; // besser CRC-check gpstime %= (24*3600); - gpx.wday = day; - gpx.std = gpstime / 3600; - gpx.min = (gpstime % 3600) / 60; - gpx.sek = gpstime % 60 + ms/1000.0; + gpx->wday = day; + gpx->std = gpstime / 3600; + gpx->min = (gpstime % 3600) / 60; + gpx->sek = gpstime % 60 + ms/1000.0; return 0; } -int get_GPS1() { +static int get_GPS1(gpx_t *gpx) { int err=0; - // ((framebyte(pos_GPS1)<<8) | framebyte(pos_GPS1+1)) != pck_GPS1 ? - if ( framebyte(pos_GPS1) != ((pck_GPS1>>8) & 0xFF) ) { - gpx.crc |= crc_GPS1; + // ((gpx->frame[pos_GPS1]<<8) | gpx->frame[pos_GPS1+1]) != pck_GPS1 ? + if ( gpx->frame[pos_GPS1] != ((pck_GPS1>>8) & 0xFF) ) { + gpx->crc |= crc_GPS1; return -1; } - err = check_CRC(pos_GPS1, pck_GPS1); - if (err) gpx.crc |= crc_GPS1; + err = check_CRC(gpx, pos_GPS1, pck_GPS1); + if (err) gpx->crc |= crc_GPS1; - //err = 0; - err |= get_GPSweek(); - err |= get_GPStime(); + err |= get_GPSweek(gpx); // no plausibility-check + err |= get_GPStime(gpx); // no plausibility-check return err; } -int get_GPS2() { +static int get_GPS2(gpx_t *gpx) { int err=0; - err = check_CRC(pos_GPS2, pck_GPS2); - if (err) gpx.crc |= crc_GPS2; + err = check_CRC(gpx, pos_GPS2, pck_GPS2); + if (err) gpx->crc |= crc_GPS2; return err; } @@ -669,13 +661,14 @@ int get_GPS2() { #define EARTH_b 6356752.31424518 #define EARTH_a2_b2 (EARTH_a*EARTH_a - EARTH_b*EARTH_b) +const double a = EARTH_a, b = EARTH_b, a_b = EARTH_a2_b2, e2 = EARTH_a2_b2 / (EARTH_a*EARTH_a), ee2 = EARTH_a2_b2 / (EARTH_b*EARTH_b); -void ecef2elli(double X[], double *lat, double *lon, double *alt) { +static void ecef2elli(double X[], double *lat, double *lon, double *alt) { double phi, lam, R, p, t; lam = atan2( X[1] , X[0] ); @@ -693,7 +686,7 @@ void ecef2elli(double X[], double *lat, double *lon, double *alt) { *lon = lam*180/M_PI; } -int get_GPSkoord() { +static int get_GPSkoord(gpx_t *gpx) { int i, k; unsigned byte; ui8_t XYZ_bytes[4]; @@ -707,14 +700,14 @@ int get_GPSkoord() { for (k = 0; k < 3; k++) { for (i = 0; i < 4; i++) { - byte = frame[pos_GPSecefX + 4*k + i]; + byte = gpx->frame[pos_GPSecefX + 4*k + i]; XYZ_bytes[i] = byte; } memcpy(&XYZ, XYZ_bytes, 4); X[k] = XYZ / 100.0; for (i = 0; i < 2; i++) { - byte = frame[pos_GPSecefV + 2*k + i]; + byte = gpx->frame[pos_GPSecefV + 2*k + i]; gpsVel_bytes[i] = byte; } vel16 = gpsVel_bytes[0] | gpsVel_bytes[1] << 8; @@ -725,111 +718,123 @@ int get_GPSkoord() { // ECEF-Position ecef2elli(X, &lat, &lon, &alt); - gpx.lat = lat; - gpx.lon = lon; - gpx.alt = alt; - if ((alt < -1000) || (alt > 80000)) return -3; + gpx->lat = lat; + gpx->lon = lon; + gpx->alt = alt; + if ((alt < -1000) || (alt > 80000)) return -3; // plausibility-check: altitude, if ecef=(0,0,0) // ECEF-Velocities // ECEF-Vel -> NorthEastUp phi = lat*M_PI/180.0; lam = lon*M_PI/180.0; - gpx.vN = -V[0]*sin(phi)*cos(lam) - V[1]*sin(phi)*sin(lam) + V[2]*cos(phi); - gpx.vE = -V[0]*sin(lam) + V[1]*cos(lam); - gpx.vU = V[0]*cos(phi)*cos(lam) + V[1]*cos(phi)*sin(lam) + V[2]*sin(phi); + gpx->vN = -V[0]*sin(phi)*cos(lam) - V[1]*sin(phi)*sin(lam) + V[2]*cos(phi); + gpx->vE = -V[0]*sin(lam) + V[1]*cos(lam); + gpx->vU = V[0]*cos(phi)*cos(lam) + V[1]*cos(phi)*sin(lam) + V[2]*sin(phi); // NEU -> HorDirVer - gpx.vH = sqrt(gpx.vN*gpx.vN+gpx.vE*gpx.vE); + gpx->vH = sqrt(gpx->vN*gpx->vN+gpx->vE*gpx->vE); /* double alpha; - alpha = atan2(gpx.vN, gpx.vE)*180/M_PI; // ComplexPlane (von x-Achse nach links) - GeoMeteo (von y-Achse nach rechts) - dir = 90-alpha; // z=x+iy= -> i*conj(z)=y+ix=re(i(pi/2-t)), Achsen und Drehsinn vertauscht - if (dir < 0) dir += 360; // atan2(y,x)=atan(y/x)=pi/2-atan(x/y) , atan(1/t) = pi/2 - atan(t) - gpx.vD2 = dir; + alpha = atan2(gpx->vN, gpx->vE)*180/M_PI; // ComplexPlane (von x-Achse nach links) - GeoMeteo (von y-Achse nach rechts) + dir = 90-alpha; // z=x+iy= -> i*conj(z)=y+ix=re(i(pi/2-t)), Achsen und Drehsinn vertauscht + if (dir < 0) dir += 360; // atan2(y,x)=atan(y/x)=pi/2-atan(x/y) , atan(1/t) = pi/2 - atan(t) + gpx->vD2 = dir; */ - dir = atan2(gpx.vE, gpx.vN) * 180 / M_PI; + dir = atan2(gpx->vE, gpx->vN) * 180 / M_PI; if (dir < 0) dir += 360; - gpx.vD = dir; + gpx->vD = dir; + + gpx->numSV = gpx->frame[pos_numSats]; return 0; } -int get_GPS3() { +static int get_GPS3(gpx_t *gpx) { int err=0; - // ((framebyte(pos_GPS3)<<8) | framebyte(pos_GPS3+1)) != pck_GPS3 ? - if ( framebyte(pos_GPS3) != ((pck_GPS3>>8) & 0xFF) ) { - gpx.crc |= crc_GPS3; + // ((gpx->frame[pos_GPS3]<<8) | gpx->frame[pos_GPS3+1]) != pck_GPS3 ? + if ( gpx->frame[pos_GPS3] != ((pck_GPS3>>8) & 0xFF) ) { + gpx->crc |= crc_GPS3; return -1; } - err = check_CRC(pos_GPS3, pck_GPS3); - if (err) gpx.crc |= crc_GPS3; + err = check_CRC(gpx, pos_GPS3, pck_GPS3); + if (err) gpx->crc |= crc_GPS3; - err |= get_GPSkoord(); + err |= get_GPSkoord(gpx); // plausibility-check: altitude, if ecef=(0,0,0) return err; } -int get_Aux() { +static int get_Aux(gpx_t *gpx) { // // "Ozone Sounding with Vaisala Radiosonde RS41" user's guide // - int i, auxlen, auxcrc, count7E, pos7E; + int auxlen, auxcrc, count7E, pos7E; + int i, n; + n = 0; count7E = 0; pos7E = pos_AUX; + gpx->xdata[0] = '\0'; - // 7Exx: xdata - while ( pos7E < FRAME_LEN && framebyte(pos7E) == 0x7E ) { + if (frametype(gpx) <= 0) // pos7E == pos7611, 0x7E^0x76=0x08 ... + { + // 7Exx: xdata + while ( pos7E < FRAME_LEN && gpx->frame[pos7E] == 0x7E ) { - auxlen = framebyte(pos7E+1); - auxcrc = framebyte(pos7E+2+auxlen) | (framebyte(pos7E+2+auxlen+1)<<8); + auxlen = gpx->frame[pos7E+1]; + auxcrc = gpx->frame[pos7E+2+auxlen] | (gpx->frame[pos7E+2+auxlen+1]<<8); - if ( auxcrc == crc16(pos7E+2, auxlen) ) { - if (count7E == 0) fprintf(stdout, "\n # xdata = "); - else fprintf(stdout, " # "); + if ( auxcrc == crc16(gpx, pos7E+2, auxlen) ) { + if (count7E == 0) fprintf(stdout, "\n # xdata = "); + else { fprintf(stdout, " # "); gpx->xdata[n++] = '#'; } - //fprintf(stdout, " # %02x : ", framebyte(pos7E+2)); - for (i = 1; i < auxlen; i++) { - fprintf(stdout, "%c", framebyte(pos7E+2+i)); + //fprintf(stdout, " # %02x : ", gpx->frame[pos7E+2]); + for (i = 1; i < auxlen; i++) { + ui8_t c = gpx->frame[pos7E+2+i]; // (char) or better < 0x7F + if (c > 0x1E && c < 0x7F) { // ASCII-only + fprintf(stdout, "%c", c); + gpx->xdata[n++] = c; + } + } + count7E++; + pos7E += 2+auxlen+2; + } + else { + pos7E = FRAME_LEN; + gpx->crc |= crc_AUX; } - count7E++; - pos7E += 2+auxlen+2; - } - else { - pos7E = FRAME_LEN; - gpx.crc |= crc_AUX; } } + gpx->xdata[n] = '\0'; - i = check_CRC(pos7E, 0x7600); // 0x76xx: 00-padding block - if (i) gpx.crc |= crc_ZERO; + i = check_CRC(gpx, pos7E, 0x7600); // 0x76xx: 00-padding block + if (i) gpx->crc |= crc_ZERO; return count7E; } -int get_Calconf(int out) { +static int get_Calconf(gpx_t *gpx, int out) { int i; unsigned byte; ui8_t calfr = 0; - ui8_t burst = 0; ui16_t fw = 0; int freq = 0, f0 = 0, f1 = 0; char sondetyp[9]; int err = 0; - byte = framebyte(pos_CalData); + byte = gpx->frame[pos_CalData]; calfr = byte; - err = check_CRC(pos_FRAME, pck_FRAME); + err = check_CRC(gpx, pos_FRAME, pck_FRAME); - if (option_verbose == 3) { + if (gpx->option.vbs == 3) { fprintf(stdout, "\n"); // fflush(stdout); - fprintf(stdout, "[%5d] ", gpx.frnr); + fprintf(stdout, "[%5d] ", gpx->frnr); fprintf(stdout, " 0x%02x: ", calfr); for (i = 0; i < 16; i++) { - byte = framebyte(pos_CalData+1+i); + byte = gpx->frame[pos_CalData+1+i]; fprintf(stdout, "%02x ", byte); } if (err == 0) fprintf(stdout, "[OK]"); @@ -837,129 +842,112 @@ int get_Calconf(int out) { fprintf(stdout, " "); } - if (out && err == 0) + if (err == 0) { - if (calfr == 0x01 && option_verbose /*== 2*/) { - fw = framebyte(pos_CalData+6) | (framebyte(pos_CalData+7)<<8); - fprintf(stdout, ": fw 0x%04x ", fw); + if (calfr == 0x01) { + fw = gpx->frame[pos_CalData+6] | (gpx->frame[pos_CalData+7]<<8); + if (out && gpx->option.vbs) fprintf(stdout, ": fw 0x%04x ", fw); + gpx->conf_fw = fw; } - if (calfr == 0x02 && option_verbose /*== 2*/) { - byte = framebyte(pos_Calburst); - 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 == 0x02) { + ui8_t bk = gpx->frame[pos_Calburst]; // fw >= 0x4ef5, burst-killtimer in 0x31 relevant + ui16_t kt = gpx->frame[0x5A] + (gpx->frame[0x5B] << 8); // killtimer (short?) + if (out && gpx->option.vbs) fprintf(stdout, ": BK %02X ", bk); + if (out && gpx->option.vbs && kt != 0xFFFF ) fprintf(stdout, ": kt %.1fmin ", kt/60.0); + gpx->conf_bk = bk; + gpx->conf_kt = kt; } - if (calfr == 0x00 && option_verbose) { - byte = framebyte(pos_Calfreq) & 0xC0; // erstmal nur oberste beiden bits + if (calfr == 0x00) { + byte = gpx->frame[pos_Calfreq] & 0xC0; // erstmal nur oberste beiden bits f0 = (byte * 10) / 64; // 0x80 -> 1/2, 0x40 -> 1/4 ; dann mal 40 - byte = framebyte(pos_Calfreq+1); + byte = gpx->frame[pos_Calfreq+1]; f1 = 40 * byte; freq = 400000 + f1+f0; // kHz; - fprintf(stdout, ": fq %d ", freq); + if (out && gpx->option.vbs) fprintf(stdout, ": fq %d ", freq); + gpx->freq = freq; } - if (calfr == 0x31 && option_verbose == 3) { - int bt = frame[0x59] + (frame[0x5A] << 8); // short? + if (calfr == 0x31) { + ui16_t bt = gpx->frame[0x59] + (gpx->frame[0x5A] << 8); // burst timer (short?) // fw >= 0x4ef5: default=[88 77]=0x7788sec=510min - if ( bt != 0x0000 ) fprintf(stdout, ": bt 0x%04x = %dsec = %.1fmin ", bt, bt, bt/60.0); + if (out && gpx->option.vbs && bt != 0x0000 && gpx->conf_bk) fprintf(stdout, ": bt %.1fmin ", bt/60.0); + gpx->conf_bt = bt; } - if (calfr == 0x21 && option_verbose /*== 2*/) { // eventuell noch zwei bytes in 0x22 + if (calfr == 0x21) { // ... eventuell noch 2 bytes in 0x22 for (i = 0; i < 9; i++) sondetyp[i] = 0; for (i = 0; i < 8; i++) { - byte = framebyte(pos_CalRSTyp + i); + byte = gpx->frame[pos_CalRSTyp + i]; if ((byte >= 0x20) && (byte < 0x7F)) sondetyp[i] = byte; else if (byte == 0x00) sondetyp[i] = '\0'; } - fprintf(stdout, ": %s ", sondetyp); + if (out && gpx->option.vbs) fprintf(stdout, ": %s ", sondetyp); + strcpy(gpx->rstyp, sondetyp); } } return 0; } -/* - frame[pos_FRAME-1] == 0x0F: len == NDATA_LEN(320) - frame[pos_FRAME-1] == 0xF0: len == FRAME_LEN(518) -*/ -int frametype() { // -4..+4: 0xF0 -> -4 , 0x0F -> +4 - int i; - ui8_t b = frame[pos_FRAME-1]; - int ft = 0; - for (i = 0; i < 4; i++) { - ft += ((b>>i)&1) - ((b>>(i+4))&1); - } - return ft; -} - /* ------------------------------------------------------------------------------------ */ -/* - (uses fec-lib by KA9Q) - ka9q-fec: - gcc -c init_rs_char.c - gcc -c decode_rs_char.c - -#include "fec.h" // ka9q-fec - - -void *rs; -unsigned char codeword1[rs_N], codeword2[rs_N]; - - rs = init_rs_char( 8, 0x11d, 0, 1, rs_R, 0); - - // ka9q-fec301: p(x) = p[0]x^(N-1) + ... + p[N-2]x + p[N-1] - // -> cw[i] = codeword[RS.N-1-i] - -*/ #define rs_N 255 #define rs_R 24 #define rs_K (rs_N-rs_R) -ui8_t cw1[rs_N], cw2[rs_N]; - -int rs41_ecc(int frmlen) { +static int rs41_ecc(gpx_t *gpx, int frmlen) { // richtige framelen wichtig fuer 0-padding int i, leak, ret = 0; int errors1, errors2; + ui8_t cw1[rs_N], cw2[rs_N]; ui8_t err_pos1[rs_R], err_pos2[rs_R], err_val1[rs_R], err_val2[rs_R]; + memset(cw1, 0, rs_N); + memset(cw2, 0, rs_N); if (frmlen > FRAME_LEN) frmlen = FRAME_LEN; - cfg_rs41.frmlen = frmlen; - cfg_rs41.msglen = (frmlen-56)/2; // msgpos=56; + //cfg_rs41.frmlen = frmlen; + //cfg_rs41.msglen = (frmlen-56)/2; // msgpos=56; leak = frmlen % 2; - for (i = frmlen; i < FRAME_LEN; i++) frame[i] = 0; // FRAME_LEN-HDR = 510 = 2*255 + for (i = frmlen; i < FRAME_LEN; i++) gpx->frame[i] = 0; // FRAME_LEN-HDR = 510 = 2*255 - for (i = 0; i < rs_R; i++) cw1[i] = frame[cfg_rs41.parpos+i ]; - for (i = 0; i < rs_R; i++) cw2[i] = frame[cfg_rs41.parpos+i+rs_R]; - for (i = 0; i < rs_K; i++) cw1[rs_R+i] = frame[cfg_rs41.msgpos+2*i ]; - for (i = 0; i < rs_K; i++) cw2[rs_R+i] = frame[cfg_rs41.msgpos+2*i+1]; + for (i = 0; i < rs_R; i++) cw1[i] = gpx->frame[cfg_rs41.parpos+i ]; + for (i = 0; i < rs_R; i++) cw2[i] = gpx->frame[cfg_rs41.parpos+i+rs_R]; + for (i = 0; i < rs_K; i++) cw1[rs_R+i] = gpx->frame[cfg_rs41.msgpos+2*i ]; + for (i = 0; i < rs_K; i++) cw2[rs_R+i] = gpx->frame[cfg_rs41.msgpos+2*i+1]; errors1 = rs_decode(cw1, err_pos1, err_val1); errors2 = rs_decode(cw2, err_pos2, err_val2); - if (option_ecc == 2 && (errors1 < 0 || errors2 < 0)) { - frame[pos_FRAME] = (pck_FRAME>>8)&0xFF; frame[pos_FRAME+1] = pck_FRAME&0xFF; - frame[pos_PTU] = (pck_PTU >>8)&0xFF; frame[pos_PTU +1] = pck_PTU &0xFF; - frame[pos_GPS1] = (pck_GPS1 >>8)&0xFF; frame[pos_GPS1 +1] = pck_GPS1 &0xFF; - frame[pos_GPS2] = (pck_GPS2 >>8)&0xFF; frame[pos_GPS2 +1] = pck_GPS2 &0xFF; - frame[pos_GPS3] = (pck_GPS3 >>8)&0xFF; frame[pos_GPS3 +1] = pck_GPS3 &0xFF; - if (frametype() < -2) { - for (i = NDATA_LEN + 7; i < FRAME_LEN-2; i++) frame[i] = 0; + if (gpx->option.ecc == 2 && (errors1 < 0 || errors2 < 0)) + { // 2nd pass + gpx->frame[pos_FRAME] = (pck_FRAME>>8)&0xFF; gpx->frame[pos_FRAME+1] = pck_FRAME&0xFF; + gpx->frame[pos_PTU] = (pck_PTU >>8)&0xFF; gpx->frame[pos_PTU +1] = pck_PTU &0xFF; + gpx->frame[pos_GPS1] = (pck_GPS1 >>8)&0xFF; gpx->frame[pos_GPS1 +1] = pck_GPS1 &0xFF; + gpx->frame[pos_GPS2] = (pck_GPS2 >>8)&0xFF; gpx->frame[pos_GPS2 +1] = pck_GPS2 &0xFF; + gpx->frame[pos_GPS3] = (pck_GPS3 >>8)&0xFF; gpx->frame[pos_GPS3 +1] = pck_GPS3 &0xFF; + // AUX-frames mit vielen Fehlern besser mit 00 auffuellen + // std-O3-AUX-frame: NDATA+7 + if (frametype(gpx) < -2) { // ft >= 0: NDATA_LEN , ft < 0: FRAME_LEN + for (i = NDATA_LEN + 7; i < FRAME_LEN-2; i++) gpx->frame[i] = 0; } - for (i = 0; i < rs_K; i++) cw1[rs_R+i] = frame[cfg_rs41.msgpos+2*i ]; - for (i = 0; i < rs_K; i++) cw2[rs_R+i] = frame[cfg_rs41.msgpos+2*i+1]; + else { // std-frm (len=320): std_ZERO-frame (7611 00..00 ECC7) + for (i = NDATA_LEN; i < FRAME_LEN; i++) gpx->frame[i] = 0; + gpx->frame[pos_ZEROstd ] = 0x76; // pck_ZEROstd + gpx->frame[pos_ZEROstd+1] = 0x11; // pck_ZEROstd + for (i = pos_ZEROstd+2; i < NDATA_LEN-2; i++) gpx->frame[i] = 0; + gpx->frame[NDATA_LEN-2] = 0xEC; // crc(pck_ZEROstd) + gpx->frame[NDATA_LEN-1] = 0xC7; // crc(pck_ZEROstd) + } + for (i = 0; i < rs_K; i++) cw1[rs_R+i] = gpx->frame[cfg_rs41.msgpos+2*i ]; + for (i = 0; i < rs_K; i++) cw2[rs_R+i] = gpx->frame[cfg_rs41.msgpos+2*i+1]; errors1 = rs_decode(cw1, err_pos1, err_val1); errors2 = rs_decode(cw2, err_pos2, err_val2); } @@ -975,15 +963,15 @@ int rs41_ecc(int frmlen) { // CRC32 OK: //for (i = 0; i < cfg_rs41.hdrlen; i++) frame[i] = data[i]; for (i = 0; i < rs_R; i++) { - frame[cfg_rs41.parpos+ i] = cw1[i]; - frame[cfg_rs41.parpos+rs_R+i] = cw2[i]; + gpx->frame[cfg_rs41.parpos+ i] = cw1[i]; + gpx->frame[cfg_rs41.parpos+rs_R+i] = cw2[i]; } for (i = 0; i < rs_K; i++) { // cfg_rs41.msglen <= rs_K - frame[cfg_rs41.msgpos+ 2*i] = cw1[rs_R+i]; - frame[cfg_rs41.msgpos+1+2*i] = cw2[rs_R+i]; + gpx->frame[cfg_rs41.msgpos+ 2*i] = cw1[rs_R+i]; + gpx->frame[cfg_rs41.msgpos+1+2*i] = cw2[rs_R+i]; } if (leak) { - frame[cfg_rs41.msgpos+2*i] = cw1[rs_R+i]; + gpx->frame[cfg_rs41.msgpos+2*i] = cw1[rs_R+i]; } @@ -1001,92 +989,94 @@ int rs41_ecc(int frmlen) { /* ------------------------------------------------------------------------------------ */ -int print_position(int ec) { +static int print_position(gpx_t *gpx, int ec) { int i; int err, err0, err1, err2, err3; int output, out_mask; - err = get_FrameConf(); + gpx->out = 0; + gpx->aux = 0; - err1 = get_GPS1(); - err2 = get_GPS2(); - err3 = get_GPS3(); + err = get_FrameConf(gpx); - err0 = get_PTU(); + err1 = get_GPS1(gpx); + err2 = get_GPS2(gpx); + err3 = get_GPS3(gpx); + + err0 = get_PTU(gpx); out_mask = crc_FRAME|crc_GPS1|crc_GPS3; - output = ((gpx.crc & out_mask) != out_mask); // (!err || !err1 || !err3); + output = ((gpx->crc & out_mask) != out_mask); // (!err || !err1 || !err3); if (output) { + gpx->out = 1; // cf. gpx->crc + if (!err) { - fprintf(stdout, "[%5d] ", gpx.frnr); - fprintf(stdout, "(%s) ", gpx.id); + fprintf(stdout, "[%5d] ", gpx->frnr); + fprintf(stdout, "(%s) ", gpx->id); } if (!err1) { - Gps2Date(gpx.week, gpx.gpssec, &gpx.jahr, &gpx.monat, &gpx.tag); - fprintf(stdout, "%s ", weekday[gpx.wday]); + Gps2Date(gpx); + fprintf(stdout, "%s ", weekday[gpx->wday]); fprintf(stdout, "%04d-%02d-%02d %02d:%02d:%06.3f", - gpx.jahr, gpx.monat, gpx.tag, gpx.std, gpx.min, gpx.sek); - if (option_verbose == 3) fprintf(stdout, " (W %d)", gpx.week); + gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek); + if (gpx->option.vbs == 3) fprintf(stdout, " (W %d)", gpx->week); } if (!err3) { fprintf(stdout, " "); - fprintf(stdout, " lat: %.5f ", gpx.lat); - fprintf(stdout, " lon: %.5f ", gpx.lon); - fprintf(stdout, " alt: %.2f ", gpx.alt); - //if (option_verbose) + fprintf(stdout, " lat: %.5f ", gpx->lat); + fprintf(stdout, " lon: %.5f ", gpx->lon); + fprintf(stdout, " alt: %.2f ", gpx->alt); + //if (gpx->option.vbs) { - //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); + //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 (gpx->option.vbs == 3) fprintf(stdout," sats: %02d ", gpx->numSV); } } - if (option_ptu && !err0) { - if (gpx.T > -273.0) printf(" T=%.1fC ", gpx.T); + if (gpx->option.ptu && !err0) { + if (gpx->T > -273.0) printf(" T=%.1fC ", gpx->T); } - //if (output) - { - if (option_crc) { - 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; - } + if (gpx->option.crc) { + fprintf(stdout, " # "); + if (gpx->option.ecc && ec >= 0 && (gpx->crc & 0x1F) != 0) { + int pos, blk, len, crc; // unexpected blocks + int flen = NDATA_LEN; + if (frametype(gpx) < 0) flen += XDATA_LEN; + pos = pos_FRAME; + while (pos < flen-1) { + blk = gpx->frame[pos]; // 0x80XX: encrypted block + len = gpx->frame[pos+1]; // 0x76XX: 00-padding block + crc = check_CRC(gpx, pos, blk<<8); + fprintf(stdout, " %02X%02X", gpx->frame[pos], gpx->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, " (--)"); - } + } + else { + fprintf(stdout, "["); + for (i=0; i<5; i++) fprintf(stdout, "%d", (gpx->crc>>i)&1); + fprintf(stdout, "]"); + } + if (gpx->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, " (--)"); } } } - get_Calconf(output); + get_Calconf(gpx, output); + + if (gpx->option.vbs > 1) gpx->aux = get_Aux(gpx); + + fprintf(stdout, "\n"); // fflush(stdout); - //if (output) - { - if (option_verbose > 1) get_Aux(); - fprintf(stdout, "\n"); // fflush(stdout); - } } err |= err1 | err3; @@ -1094,88 +1084,88 @@ int print_position(int ec) { return err; } -void print_frame(int len) { +static void print_frame(gpx_t *gpx, int len) { int i, ec = 0, ft; - gpx.crc = 0; + gpx->crc = 0; + + // len < NDATA_LEN: EOF + if (len < pos_GPS1) { // else: try prev.frame + for (i = len; i < FRAME_LEN; i++) gpx->frame[i] = 0; + } //frame[pos_FRAME-1] == 0x0F: len == NDATA_LEN(320) //frame[pos_FRAME-1] == 0xF0: len == FRAME_LEN(518) - ft = frametype(); - if (ft > 2) len = NDATA_LEN; - // STD-frames mit 00 auffuellen fuer Fehlerkorrektur - if (len > NDATA_LEN && len < NDATA_LEN+XDATA_LEN-10) { - if (ft < -2) { - len = NDATA_LEN + 7; // std-O3-AUX-frame - } - } - // AUX-frames mit vielen Fehlern besser mit 00 auffuellen + ft = frametype(gpx); + if (ft >= 0) len = NDATA_LEN; // ft >= 0: NDATA_LEN (default) + else len = FRAME_LEN; // ft < 0: FRAME_LEN (aux) - for (i = len; i < FRAME_LEN-2; i++) { - frame[i] = 0; - } - if (ft > 2 || len == NDATA_LEN) { - frame[FRAME_LEN-2] = 0; - frame[FRAME_LEN-1] = 0; - } - if (len > NDATA_LEN) len = FRAME_LEN; - else len = NDATA_LEN; - - - if (option_ecc) { - ec = rs41_ecc(len); + if (gpx->option.ecc) { + ec = rs41_ecc(gpx, len); } - if (option_raw) { - if (option_ecc == 2 && ec >= 0) { - if (len < FRAME_LEN && frame[FRAME_LEN-1] != 0) len = FRAME_LEN; - } + if (gpx->option.raw) { for (i = 0; i < len; i++) { - fprintf(stdout, "%02x", frame[i]); + fprintf(stdout, "%02x", gpx->frame[i]); } - if (option_ecc) { + if (gpx->option.ecc) { if (ec >= 0) fprintf(stdout, " [OK]"); else fprintf(stdout, " [NO]"); - if (option_ecc == 2 && ec > 0) fprintf(stdout, " (%d)", ec); + if (gpx->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, " (--)"); + } + } } fprintf(stdout, "\n"); } - else if (option_sat) { - get_SatData(); + else if (gpx->option.sat) { + get_SatData(gpx); } else { - print_position(ec); + print_position(gpx, ec); } } int main(int argc, char *argv[]) { + int option_inv = 0; // invertiert Signal + int option_iq = 0; + int option_ofs = 0; + int wavloaded = 0; + int sel_wavch = 0; // audio channel: left + int rawhex = 0, xorhex = 0; + FILE *fp; char *fpname = NULL; - float spb = 0.0; char bitbuf[8]; int bit_count = 0, bitpos = 0, byte_count = FRAMESTART, - ft_len = FRAME_LEN, header_found = 0; int bit, byte; - int frmlen = FRAME_LEN; - int headerlen; - int herrs, herr1; - int bitQ, Qerror_count; + int herrs; + int bitQ; int k, K; float mv; - unsigned int mv_pos, mv0_pos; + ui32_t mv_pos, mv0_pos; int mp = 0; float thres = 0.7; - int bitofs = 0; int symlen = 1; - int shift = 2; + int bitofs = 2; + int shift = 0; + + pcm_t pcm = {0}; + dsp_t dsp = {0}; + + gpx_t gpx = {0}; #ifdef CYGWIN @@ -1183,6 +1173,11 @@ int main(int argc, char *argv[]) { #endif setbuf(stdout, NULL); + + // init gpx + memcpy(gpx.frame, header_bytes, sizeof(header_bytes)); // 8 header bytes + + fpname = argv[0]; ++argv; while ((*argv) && (!wavloaded)) { @@ -1193,33 +1188,29 @@ int main(int argc, char *argv[]) { fprintf(stderr, " -r, --raw\n"); fprintf(stderr, " -i, --invert\n"); fprintf(stderr, " --crc (check CRC)\n"); - fprintf(stderr, " --ecc (Reed-Solomon)\n"); - fprintf(stderr, " --std (std framelen)\n"); + fprintf(stderr, " --ecc2 (Reed-Solomon 2-pass)\n"); fprintf(stderr, " --ths (peak threshold; default=%.1f)\n", thres); fprintf(stderr, " --iq0,2,3 (IQ data)\n"); return 0; } else if ( (strcmp(*argv, "-v") == 0) || (strcmp(*argv, "--verbose") == 0) ) { - option_verbose = 1; + gpx.option.vbs = 1; } - else if (strcmp(*argv, "-vx") == 0) { option_verbose = 2; } - else if (strcmp(*argv, "-vv") == 0) { option_verbose = 3; } - else if (strcmp(*argv, "-vvv") == 0) { option_verbose = 4; } - else if (strcmp(*argv, "--crc") == 0) { option_crc = 1; } - else if (strcmp(*argv, "--res") == 0) { option_res = 1; } + else if (strcmp(*argv, "-vx") == 0) { gpx.option.vbs = 2; } + else if (strcmp(*argv, "-vv") == 0) { gpx.option.vbs = 3; } + else if (strcmp(*argv, "-vvv") == 0) { gpx.option.vbs = 4; } + else if (strcmp(*argv, "--crc") == 0) { gpx.option.crc = 1; } else if ( (strcmp(*argv, "-r") == 0) || (strcmp(*argv, "--raw") == 0) ) { - option_raw = 1; + gpx.option.raw = 1; } else if ( (strcmp(*argv, "-i") == 0) || (strcmp(*argv, "--invert") == 0) ) { option_inv = 1; } - else if (strcmp(*argv, "--ecc" ) == 0) { option_ecc = 1; } - else if (strcmp(*argv, "--ecc2") == 0) { option_ecc = 2; } - else if (strcmp(*argv, "--std" ) == 0) { frmlen = 320; } // NDATA_LEN - 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, "--ch2") == 0) { wav_channel = 1; } // right channel (default: 0=left) + else if (strcmp(*argv, "--ecc" ) == 0) { gpx.option.ecc = 1; } + else if (strcmp(*argv, "--ecc2") == 0) { gpx.option.ecc = 2; } + else if (strcmp(*argv, "--sat") == 0) { gpx.option.sat = 1; } + else if (strcmp(*argv, "--ptu") == 0) { gpx.option.ptu = 1; } + else if (strcmp(*argv, "--ch2") == 0) { sel_wavch = 1; } // right channel (default: 0=left) else if (strcmp(*argv, "--ths") == 0) { ++argv; if (*argv) { @@ -1231,16 +1222,17 @@ int main(int argc, char *argv[]) { ++argv; if (*argv) { shift = atoi(*argv); - if (shift > 6) shift = 6; - if (shift < -2) shift = -2; + if (shift > 4) shift = 4; + if (shift < -4) shift = -4; } else return -1; } else if (strcmp(*argv, "--iq0") == 0) { option_iq = 1; } // differential/FM-demod else if (strcmp(*argv, "--iq2") == 0) { option_iq = 2; } - else if (strcmp(*argv, "--iq3") == 0) { option_iq = 3; } // iq2==iq3 + else if (strcmp(*argv, "--iq3") == 0) { option_iq = 3; } // iq2==iq3 else if (strcmp(*argv, "--ofs") == 0) { option_ofs = 1; } - else if (strcmp(*argv, "--dbg") == 0) { option_dbg = 1; } + else if (strcmp(*argv, "--rawhex") == 0) { rawhex = 2; } // raw hex input + else if (strcmp(*argv, "--xorhex") == 0) { rawhex = 2; xorhex = 1; } // raw xor input else { fp = fopen(*argv, "rb"); if (fp == NULL) { @@ -1254,135 +1246,158 @@ int main(int argc, char *argv[]) { if (!wavloaded) fp = stdin; - if (option_iq) wav_channel = 0; + if (gpx.option.ecc < 2) gpx.option.ecc = 1; - - spb = read_wav_header(fp, (float)BAUD_RATE, wav_channel); - if ( spb < 0 ) { - fclose(fp); - fprintf(stderr, "error: wav header\n"); - return -1; - } - if ( spb < 8 ) { - fprintf(stderr, "note: sample rate low\n"); + if (gpx.option.ecc) { + rs_init_RS255(); // ... rs_init_RS255(&RS); } - if (option_ecc) { - rs_init_RS255(); - } - // rs41: BT=0.5, h=0.8,1.0 ? - symlen = 1; - headerlen = strlen(header); - bitofs = shift; // +0 .. +3 // FM: +1 , IQ: +2 - K = init_buffers(header, headerlen, 0.5, option_iq); // BT=0.5 (IQ-Int: BT > 0.5 ?) - if ( K < 0 ) { - fprintf(stderr, "error: init buffers\n"); - return -1; - }; + if (!rawhex) { + if (option_iq) sel_wavch = 0; - k = 0; - mv = -1; mv_pos = 0; - - while ( f32buf_sample(fp, option_inv, 1) != EOF ) { - - k += 1; - if (k >= K-4) { - mv0_pos = mv_pos; - mp = getCorrDFT(0, K, 0, &mv, &mv_pos); - k = 0; - } - else { - mv = 0.0; - continue; + pcm.sel_ch = sel_wavch; + k = read_wav_header(&pcm, fp); + if ( k < 0 ) { + fclose(fp); + fprintf(stderr, "error: wav header\n"); + return -1; } - if (mv > thres && mp > 0) { - if (mv_pos > mv0_pos) { + // rs41: BT=0.5, h=0.8,1.0 ? + symlen = 1; - header_found = 0; - herrs = headcmp(symlen, header, headerlen, mv_pos, mv<0, 0); // symlen=1 - herr1 = 0; - if (herrs <= 3 && herrs > 0) { - herr1 = headcmp(symlen, header, headerlen, mv_pos+1, mv<0, 0); - if (herr1 < herrs) { - herrs = herr1; - herr1 = 1; - } - } - if (herrs <= 2) header_found = 1; // herrs <= 2 bitfehler in header + // init dsp + // + //memset(&dsp, 0, sizeof(dsp)); + dsp.fp = fp; + dsp.sr = pcm.sr; + dsp.bps = pcm.bps; + dsp.nch = pcm.nch; + dsp.ch = pcm.sel_ch; + dsp.br = (float)BAUD_RATE; + dsp.sps = (float)dsp.sr/dsp.br; + dsp.symlen = symlen; + dsp._spb = dsp.sps*symlen; + dsp.hdr = header; + dsp.hdrlen = strlen(header); + dsp.BT = 0.5; // bw/time (ISI) // 0.3..0.5 + dsp.h = 1.0; // 0.8..0.9? modulation index + dsp.opt_iq = option_iq; - if (header_found) { + if ( dsp.sps < 8 ) { + fprintf(stderr, "note: sample rate low (%.1f sps)\n", dsp.sps); + } - if (/*preamble &&*/ option_ofs) - { - float freq = 0.0; - float snr = 0.0; - get_fqofs(headerlen, mv_pos, &freq, &snr); - if (option_dbg) { - fprintf(stderr, "fq-ofs: %+.2f Hz snr: %.2f dB\n", freq, snr); - } - } - byte_count = FRAMESTART; - bit_count = 0; // byte_count*8-HEADLEN - bitpos = 0; + K = init_buffers(&dsp); // BT=0.5 (IQ-Int: BT > 0.5 ?) + if ( K < 0 ) { + fprintf(stderr, "error: init buffers\n"); + return -1; + }; - Qerror_count = 0; - ft_len = frmlen; + //if (option_iq >= 2) bitofs += 1; + bitofs += shift; // +0 .. +3 // FM: +1 , IQ: +2 - while ( byte_count < frmlen ) { - if (option_iq) { - bitQ = read_IDsbit(fp, symlen, &bit, option_inv, bitofs, bit_count==0, 0); // symlen=1, return: zeroX/bit - } - else { - bitQ = read_sbit(fp, symlen, &bit, option_inv, bitofs, bit_count==0, 0); // symlen=1, return: zeroX/bit - } - if ( bitQ == EOF) break; - bit_count += 1; - bitbuf[bitpos] = bit; - bitpos++; - if (bitpos == BITS) { - bitpos = 0; - byte = bits2byte(bitbuf); - frame[byte_count] = byte ^ mask[byte_count % MASK_LEN]; + k = 0; + mv = 0.0; + mv_pos = 0; - byteQ[byte_count] = get_bufvar(0); + while ( f32buf_sample(&dsp, option_inv) != EOF ) { - if (byte_count > NDATA_LEN) { // Fehler erst ab minimaler framelen Zaehlen - if (byteQ[byte_count]*2 > byteQ[byte_count-300]*3) { // Var(frame)/Var(noise) ca. 1:2 - Qerror_count += 1; - } - } + k += 1; + if (k >= dsp.K-4) { + mv0_pos = mv_pos; + mp = getCorrDFT(&dsp, 0, 0, &mv, &mv_pos); + k = 0; + } + else { + mv = 0.0; + continue; + } + + if (mv > thres && mp > 0) { + if (mv_pos > mv0_pos) { - byte_count++; - } - if (Qerror_count == 4) { // framelen = 320 oder 518 - ft_len = byte_count; - Qerror_count += 1; - } - } header_found = 0; - print_frame(ft_len); + herrs = headcmp(&dsp, symlen, mv_pos, mv<0, 0); // symlen=1 + if (herrs <= 3) header_found = 1; // herrs <= 3 bitfehler in header - while ( bit_count < BITS*(FRAME_LEN-8+24) ) { - bitQ = read_sbit(fp, symlen, &bit, option_inv, bitofs, bit_count==0, 0); // symlen=1, return: zeroX/bit - if ( bitQ == EOF) break; - bit_count++; + if (header_found) { + + if (/*preamble &&*/ option_ofs /*option_iq*/) + { + float freq = 0.0; + float snr = 0.0; + int er = get_fqofs_rs41(&dsp, mv_pos, &freq, &snr); + } + + byte_count = FRAMESTART; + bit_count = 0; // byte_count*8-HEADLEN + bitpos = 0; + + while ( byte_count < FRAME_LEN ) { + if (option_iq >= 2) { + bitQ = read_slbit(&dsp, symlen, &bit, option_inv, bitofs, bit_count, 1.0); + } + else { + bitQ = read_slbit(&dsp, symlen, &bit, option_inv, bitofs, bit_count, -1); + } + if ( bitQ == EOF) break; + bit_count += 1; + bitbuf[bitpos] = bit; + bitpos++; + if (bitpos == BITS) { + bitpos = 0; + byte = bits2byte(bitbuf); + gpx.frame[byte_count] = byte ^ mask[byte_count % MASK_LEN]; + byte_count++; + } + } + + print_frame(&gpx, byte_count); + byte_count = FRAMESTART; + header_found = 0; } - - byte_count = FRAMESTART; } } + } + free_buffers(&dsp); + } + else //if (rawhex) + { + char buffer_rawhex[2*FRAME_LEN+12]; + char *pbuf = NULL, *buf_sp = NULL; + ui8_t frmbyte; + int frameofs = 0, len, i; + + while (1 > 0) { + + pbuf = fgets(buffer_rawhex, 2*FRAME_LEN+12, fp); + if (pbuf == NULL) break; + buffer_rawhex[2*FRAME_LEN] = '\0'; + buf_sp = strchr(buffer_rawhex, ' '); + if (buf_sp != NULL && buf_sp-buffer_rawhex < 2*FRAME_LEN) { + buffer_rawhex[buf_sp-buffer_rawhex] = '\0'; + } + len = strlen(buffer_rawhex) / 2; + if (len > pos_SondeID+10) { + for (i = 0; i < len; i++) { //%2x SCNx8=%hhx(inttypes.h) + sscanf(buffer_rawhex+2*i, "%2hhx", &frmbyte); + // wenn ohne %hhx: sscanf(buffer_rawhex+rawhex*i, "%2x", &byte); frame[frameofs+i] = (ui8_t)byte; + if (xorhex) frmbyte ^= mask[(frameofs+i) % MASK_LEN]; + gpx.frame[frameofs+i] = frmbyte; + } + print_frame(&gpx, frameofs+len); + } + } } - free_buffers(); - fclose(fp); return 0; diff --git a/scan/dft_detect.c b/scan/dft_detect.c index 5c681ba..7ab4a52 100644 --- a/scan/dft_detect.c +++ b/scan/dft_detect.c @@ -22,8 +22,8 @@ static int wav_channel = 0; // audio channel: left //int dfm_bps = 2500; -static char dfm_header[] = "01100101011001101010010110101010"; - +static char dfm_header[] = "10011010100110010101101001010101"; // DFM-09 + // "01100101011001101010010110101010"; // DFM-06 //int vai_bps = 4800; static char rs41_header[] = "00001000011011010101001110001000" "01000100011010010100100000011111"; @@ -54,7 +54,7 @@ static char imet_preamble[] = "11110000111100001111000011110000" //int imet1ab_bps = 9600; // 1200 bits/sec static char imet1ab_header[] = "11110000111100001111000011110000" - // "11110000""10101100110010101100101010101100" + // "11110000""10101100110010101100101010101100" "11110000""10101100110010101100101010101100"; @@ -83,14 +83,14 @@ typedef struct { float thres; float complex *Fm; char *type; - unsigned char tn; + ui8_t tn; // signed? } rsheader_t; #define Nrs 9 #define idxAB 7 #define idxRS 8 static rsheader_t rs_hdr[Nrs] = { - { 2500, 0, 0, dfm_header, 1.0, 0.0, 0.65, NULL, "DFM", 2}, + { 2500, 0, 0, dfm_header, 1.0, 0.0, 0.65, NULL, "DFM9", 2}, // DFM6: -2 (unsigned) { 4800, 0, 0, rs41_header, 0.5, 0.0, 0.70, NULL, "RS41", 3}, { 4800, 0, 0, rs92_header, 0.5, 0.0, 0.70, NULL, "RS92", 4}, { 4800, 0, 0, lms6_header, 1.0, 0.0, 0.70, NULL, "LMS6", 8}, @@ -594,7 +594,7 @@ static int init_buffers() { b += b0*pulse(t+1, sigma); } - if (pos < hLen) { + if (pos < hLen-1) { b2 = ((bits[pos+1] & 0x1) - 0.5)*2.0; b += b2*pulse(t-1, sigma); } @@ -661,6 +661,7 @@ int main(int argc, char **argv) { int header_found = 0; int herrs; float thres = 0.76; + float tl = -1.0; int j_max; float mv_max; @@ -682,12 +683,15 @@ int main(int argc, char **argv) { else if ( (strcmp(*argv, "-v") == 0) || (strcmp(*argv, "--verbose") == 0) ) { option_verbose = 1; } - else if ( (strcmp(*argv, "--dc") == 0) ) { - option_dc = 1; - } + //else if ( (strcmp(*argv, "--dc") == 0) ) { option_dc = 1; } else if ( (strcmp(*argv, "-s") == 0) || (strcmp(*argv, "--silent") == 0) ) { option_silent = 1; } + else if ( (strcmp(*argv, "-t") == 0) || (strcmp(*argv, "--time") == 0) ) { + ++argv; + if (*argv) tl = atof(*argv); + else return -50; + } else if ( (strcmp(*argv, "--ch2") == 0) ) { wav_channel = 1; } // right channel (default: 0=left) else if ( (strcmp(*argv, "--ths") == 0) ) { ++argv; @@ -695,13 +699,13 @@ int main(int argc, char **argv) { thres = atof(*argv); for (j = 0; j < Nrs; j++) rs_hdr[j].thres = thres; } - else return -1; + else return -50; } else { fp = fopen(*argv, "rb"); if (fp == NULL) { fprintf(stderr, "%s konnte nicht geoeffnet werden\n", *argv); - return -1; + return -50; } wavloaded = 1; } @@ -714,14 +718,14 @@ int main(int argc, char **argv) { if ( j < 0 ) { fclose(fp); fprintf(stderr, "error: wav header\n"); - return -1; + return -50; } K = init_buffers(); if ( K < 0 ) { fprintf(stderr, "error: init buffers\n"); - return -1; + return -50; }; for (j = 0; j < Nrs; j++) { @@ -734,6 +738,8 @@ int main(int argc, char **argv) { while ( f32buf_sample(fp, option_inv, 1) != EOF ) { + if (tl > 0 && sample_in > (tl+1)*sample_rate) break; // (int)sample_out < 0 + k += 1; if (k >= K-4) { @@ -754,7 +760,7 @@ int main(int argc, char **argv) { if (mp[j] > 0 && (mv[j] > rs_hdr[j].thres || mv[j] < -rs_hdr[j].thres)) { if (mv_pos[j] > mv0_pos[j]) { - herrs = headcmp(1, rs_hdr[j].header, rs_hdr[j].hLen, mv_pos[j], mv[j]<0, option_dc, rs_hdr[j].spb); + herrs = headcmp(1, rs_hdr[j].header, rs_hdr[j].hLen, mv_pos[j], mv[j]<0, 0, rs_hdr[j].spb); if (herrs < 2) { // max 1 bitfehler in header if ( strncmp(rs_hdr[j].type, "IMET", 4) == 0 ) @@ -843,7 +849,7 @@ int main(int argc, char **argv) { if (header_found) { if (!option_silent) { - fprintf(stdout, "sample: %d\n", mv_pos[j]); + if (option_verbose) fprintf(stdout, "sample: %d\n", mv_pos[j]); fprintf(stdout, "%s: %.4f\n", rs_hdr[j].type, mv[j]); } if ((j < 3) && mv[j] < 0) header_found = -1;