kopia lustrzana https://github.com/projecthorus/radiosonde_auto_rx
commit
c902974aa9
|
@ -475,7 +475,7 @@ def telemetry_filter(telemetry):
|
|||
|
||||
# Check Meisei sonde callsigns for validity.
|
||||
# meisei_ims returns a callsign of IMS100-xxxxxx until it receives the serial number, so we filter based on the x's being present or not.
|
||||
if 'IMS100' in telemetry['type']:
|
||||
if 'MEISEI' in telemetry['type']:
|
||||
meisei_callsign_valid = 'x' not in _serial.split('-')[1]
|
||||
else:
|
||||
meisei_callsign_valid = False
|
||||
|
|
|
@ -3,7 +3,7 @@ Description=auto_rx
|
|||
After=syslog.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/python /home/pi/radiosonde_auto_rx/auto_rx/auto_rx.py -t 0
|
||||
ExecStart=/usr/bin/python3 /home/pi/radiosonde_auto_rx/auto_rx/auto_rx.py -t 0
|
||||
Restart=always
|
||||
RestartSec=120
|
||||
WorkingDirectory=/home/pi/radiosonde_auto_rx/auto_rx/
|
||||
|
|
|
@ -16,4 +16,6 @@ cd $(dirname $0)
|
|||
rm log_power*.csv
|
||||
|
||||
# Start auto_rx process with a 3 hour timeout.
|
||||
python auto_rx.py -t 180
|
||||
# auto_rx will exit after this time.
|
||||
|
||||
python3 auto_rx.py -t 180
|
||||
|
|
|
@ -17,7 +17,7 @@ except ImportError:
|
|||
# MINOR - New sonde type support, other fairly big changes that may result in telemetry or config file incompatability issus.
|
||||
# PATCH - Small changes, or minor feature additions.
|
||||
|
||||
__version__ = "1.3.3-beta3"
|
||||
__version__ = "1.3.3-beta4"
|
||||
|
||||
|
||||
# Global Variables
|
||||
|
|
|
@ -283,7 +283,7 @@ class SondeDecoder(object):
|
|||
if self.save_decode_audio:
|
||||
decode_cmd += " tee decode_%s.wav |" % str(self.device_idx)
|
||||
|
||||
decode_cmd += "./rs41mod --ptu --json 2>/dev/null"
|
||||
decode_cmd += "./rs41mod --ptu2 --json 2>/dev/null"
|
||||
|
||||
elif self.sonde_type == "RS92":
|
||||
# Decoding a RS92 requires either an ephemeris or an almanac file.
|
||||
|
@ -480,7 +480,7 @@ class SondeDecoder(object):
|
|||
|
||||
demod_cmd += "./fsk_demod --cs16 -b %d -u %d -s --stats=%d 2 %d %d - -" % (_lower, _upper, _stats_rate, _sdr_rate, _baud_rate)
|
||||
|
||||
decode_cmd = "./rs41mod --ptu --json --softin -i 2>/dev/null"
|
||||
decode_cmd = "./rs41mod --ptu2 --json --softin -i 2>/dev/null"
|
||||
|
||||
# RS41s transmit pulsed beacons - average over the last 2 frames, and use a peak-hold
|
||||
demod_stats = FSKDemodStats(averaging_time=2.0, peak_hold=True)
|
||||
|
|
|
@ -54,6 +54,7 @@ bias = False
|
|||
[search_params]
|
||||
# Minimum and maximum search frequencies, in MHz.
|
||||
# Australia: Use 400.05 - 403 MHz
|
||||
# New Zealand: Use 400.05 - 404 MHz
|
||||
# Europe: Use 400.05 - 406 MHz
|
||||
# US:
|
||||
# Some areas have transitioned to the 400.05 - 406 MHz band.
|
||||
|
@ -65,7 +66,7 @@ bias = False
|
|||
min_freq = 400.05
|
||||
max_freq = 403.0
|
||||
|
||||
# Have the decoder timeout after X seconds of no valid data.
|
||||
# After rx_timeout seconds of no valid data from a decoder, stop the decoder and go back to scanning (if a SDR is available)
|
||||
rx_timeout = 180
|
||||
|
||||
# Frequency Lists - These must be provided as JSON-compatible lists of floats (in MHz), i.e. [400.50, 401.520, 403.200]
|
||||
|
@ -147,6 +148,7 @@ aprs_enabled = False
|
|||
# APRS-IS Login Information
|
||||
# The aprs_user field can have an SSID on the end if desired, i.e. N0CALL-4
|
||||
aprs_user = N0CALL
|
||||
# APRS-IS Passcode. You can generate one for your callsign here: https://apps.magicbug.co.uk/passcode/
|
||||
aprs_pass = 00000
|
||||
|
||||
# APRS Upload Rate - Upload a packet every X seconds.
|
||||
|
|
|
@ -304,6 +304,7 @@ float read_wav_header(pcm_t *pcm, FILE *fp) {
|
|||
|
||||
if (bits_sample != 8 && bits_sample != 16 && bits_sample != 32) return -1;
|
||||
|
||||
if (sample_rate == 900001) sample_rate -= 1;
|
||||
|
||||
pcm->sr = sample_rate;
|
||||
pcm->bps = bits_sample;
|
||||
|
@ -346,6 +347,7 @@ typedef struct {
|
|||
double sumIQy;
|
||||
float avgIQx;
|
||||
float avgIQy;
|
||||
float complex avgIQ;
|
||||
ui32_t cnt;
|
||||
ui32_t maxcnt;
|
||||
ui32_t maxlim;
|
||||
|
@ -375,16 +377,22 @@ static int f32read_csample(dsp_t *dsp, float complex *z) {
|
|||
y = (u[1]-128)/128.0;
|
||||
}
|
||||
|
||||
*z = (x - IQdc.avgIQx) + I*(y - IQdc.avgIQy);
|
||||
*z = x + I*y;
|
||||
|
||||
IQdc.sumIQx += x;
|
||||
IQdc.sumIQy += y;
|
||||
IQdc.cnt += 1;
|
||||
if (IQdc.cnt == IQdc.maxcnt) {
|
||||
IQdc.avgIQx = IQdc.sumIQx/(float)IQdc.maxcnt;
|
||||
IQdc.avgIQy = IQdc.sumIQy/(float)IQdc.maxcnt;
|
||||
IQdc.sumIQx = 0; IQdc.sumIQy = 0; IQdc.cnt = 0;
|
||||
if (IQdc.maxcnt < IQdc.maxlim) IQdc.maxcnt *= 2;
|
||||
// IQ-dc removal optional
|
||||
if (dsp->opt_iqdc) {
|
||||
*z -= IQdc.avgIQ;
|
||||
|
||||
IQdc.sumIQx += x;
|
||||
IQdc.sumIQy += y;
|
||||
IQdc.cnt += 1;
|
||||
if (IQdc.cnt == IQdc.maxcnt) {
|
||||
IQdc.avgIQx = IQdc.sumIQx/(float)IQdc.maxcnt;
|
||||
IQdc.avgIQy = IQdc.sumIQy/(float)IQdc.maxcnt;
|
||||
IQdc.avgIQ = IQdc.avgIQx + I*IQdc.avgIQy;
|
||||
IQdc.sumIQx = 0; IQdc.sumIQy = 0; IQdc.cnt = 0;
|
||||
if (IQdc.maxcnt < IQdc.maxlim) IQdc.maxcnt *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -395,63 +403,42 @@ static int f32read_cblock(dsp_t *dsp) {
|
|||
int n;
|
||||
int len;
|
||||
float x, y;
|
||||
ui8_t s[4*2*dsp->decM]; //uin8,int16,flot32
|
||||
ui8_t *u = (ui8_t*)s;
|
||||
short *b = (short*)s;
|
||||
float *f = (float*)s;
|
||||
|
||||
len = dsp->decM;
|
||||
|
||||
if (dsp->bps == 8) { //uint8
|
||||
ui8_t u[2*dsp->decM];
|
||||
len = fread( u, dsp->bps/8, 2*dsp->decM, dsp->fp) / 2;
|
||||
//for (n = 0; n < len; n++) dsp->decMbuf[n] = (u[2*n]-128)/128.0 + I*(u[2*n+1]-128)/128.0;
|
||||
// u8: 0..255, 128 -> 0V
|
||||
for (n = 0; n < len; n++) {
|
||||
len = fread( s, dsp->bps/8, 2*dsp->decM, dsp->fp) / 2;
|
||||
|
||||
//for (n = 0; n < len; n++) dsp->decMbuf[n] = (u[2*n]-128)/128.0 + I*(u[2*n+1]-128)/128.0;
|
||||
// u8: 0..255, 128 -> 0V
|
||||
for (n = 0; n < len; n++) {
|
||||
if (dsp->bps == 8) { //uint8
|
||||
x = (u[2*n ]-128)/128.0;
|
||||
y = (u[2*n+1]-128)/128.0;
|
||||
dsp->decMbuf[n] = (x-IQdc.avgIQx) + I*(y-IQdc.avgIQy);
|
||||
IQdc.sumIQx += x;
|
||||
IQdc.sumIQy += y;
|
||||
IQdc.cnt += 1;
|
||||
if (IQdc.cnt == IQdc.maxcnt) {
|
||||
IQdc.avgIQx = IQdc.sumIQx/(float)IQdc.maxcnt;
|
||||
IQdc.avgIQy = IQdc.sumIQy/(float)IQdc.maxcnt;
|
||||
IQdc.sumIQx = 0; IQdc.sumIQy = 0; IQdc.cnt = 0;
|
||||
if (IQdc.maxcnt < IQdc.maxlim) IQdc.maxcnt *= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (dsp->bps == 16) { //int16
|
||||
short b[2*dsp->decM];
|
||||
len = fread( b, dsp->bps/8, 2*dsp->decM, dsp->fp) / 2;
|
||||
for (n = 0; n < len; n++) {
|
||||
else if (dsp->bps == 16) { //int16
|
||||
x = b[2*n ]/32768.0;
|
||||
y = b[2*n+1]/32768.0;
|
||||
dsp->decMbuf[n] = (x-IQdc.avgIQx) + I*(y-IQdc.avgIQy);
|
||||
IQdc.sumIQx += x;
|
||||
IQdc.sumIQy += y;
|
||||
IQdc.cnt += 1;
|
||||
if (IQdc.cnt == IQdc.maxcnt) {
|
||||
IQdc.avgIQx = IQdc.sumIQx/(float)IQdc.maxcnt;
|
||||
IQdc.avgIQy = IQdc.sumIQy/(float)IQdc.maxcnt;
|
||||
IQdc.sumIQx = 0; IQdc.sumIQy = 0; IQdc.cnt = 0;
|
||||
if (IQdc.maxcnt < IQdc.maxlim) IQdc.maxcnt *= 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // dsp->bps == 32 //float32
|
||||
float f[2*dsp->decM];
|
||||
len = fread( f, dsp->bps/8, 2*dsp->decM, dsp->fp) / 2;
|
||||
for (n = 0; n < len; n++) {
|
||||
else { // dsp->bps == 32 //float32
|
||||
x = f[2*n];
|
||||
y = f[2*n+1];
|
||||
dsp->decMbuf[n] = (x-IQdc.avgIQx) + I*(y-IQdc.avgIQy);
|
||||
IQdc.sumIQx += x;
|
||||
IQdc.sumIQy += y;
|
||||
IQdc.cnt += 1;
|
||||
if (IQdc.cnt == IQdc.maxcnt) {
|
||||
IQdc.avgIQx = IQdc.sumIQx/(float)IQdc.maxcnt;
|
||||
IQdc.avgIQy = IQdc.sumIQy/(float)IQdc.maxcnt;
|
||||
IQdc.sumIQx = 0; IQdc.sumIQy = 0; IQdc.cnt = 0;
|
||||
if (IQdc.maxcnt < IQdc.maxlim) IQdc.maxcnt *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
// baseband: IQ-dc removal mandatory
|
||||
dsp->decMbuf[n] = (x-IQdc.avgIQx) + I*(y-IQdc.avgIQy);
|
||||
|
||||
IQdc.sumIQx += x;
|
||||
IQdc.sumIQy += y;
|
||||
IQdc.cnt += 1;
|
||||
if (IQdc.cnt == IQdc.maxcnt) {
|
||||
IQdc.avgIQx = IQdc.sumIQx/(float)IQdc.maxcnt;
|
||||
IQdc.avgIQy = IQdc.sumIQy/(float)IQdc.maxcnt;
|
||||
IQdc.avgIQ = IQdc.avgIQx + I*IQdc.avgIQy;
|
||||
IQdc.sumIQx = 0; IQdc.sumIQy = 0; IQdc.cnt = 0;
|
||||
if (IQdc.maxcnt < IQdc.maxlim) IQdc.maxcnt *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ typedef struct {
|
|||
|
||||
// IQ-data
|
||||
int opt_iq;
|
||||
int opt_iqdc;
|
||||
int N_IQBUF;
|
||||
float complex *rot_iqbuf;
|
||||
float complex F1sum;
|
||||
|
|
|
@ -148,6 +148,7 @@ typedef struct {
|
|||
int sf6;
|
||||
int sfX;
|
||||
int typ;
|
||||
int jsn_freq; // freq/kHz (SDR)
|
||||
float frm_rate;
|
||||
int auto_detect;
|
||||
int reset_dsp;
|
||||
|
@ -760,6 +761,9 @@ static void print_frame(gpx_t *gpx, int crc_err, int len) {
|
|||
gpx->std, gpx->min, gpx->sek, gpx->lat, gpx->lon, gpx->alt, gpx->vH, gpx->vD, gpx->vV );
|
||||
printf(", \"gpstow\": %d", gpx->gpstow );
|
||||
printf(", \"subtype\": \"%c\"", sntyp[3]); // "6":LMS6-403, "X":lms6X, "MK2A":LMS6-1680/Mk2a
|
||||
if (gpx->jsn_freq > 0) {
|
||||
printf(", \"freq\": %d", gpx->jsn_freq);
|
||||
}
|
||||
printf(" }\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
@ -949,6 +953,7 @@ int main(int argc, char **argv) {
|
|||
int option_inv = 0; // invertiert Signal
|
||||
int option_min = 0;
|
||||
int option_iq = 0;
|
||||
int option_iqdc = 0;
|
||||
int option_lp = 0;
|
||||
int option_dc = 0;
|
||||
int option_softin = 0;
|
||||
|
@ -956,6 +961,7 @@ int main(int argc, char **argv) {
|
|||
int wavloaded = 0;
|
||||
int sel_wavch = 0; // audio channel: left
|
||||
int gpsweek = 0;
|
||||
int cfreq = -1;
|
||||
|
||||
FILE *fp = NULL;
|
||||
char *fpname = NULL;
|
||||
|
@ -1073,6 +1079,7 @@ int main(int argc, char **argv) {
|
|||
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, "--iqdc") == 0) { option_iqdc = 1; } // iq-dc removal (iq0,2,3)
|
||||
else if (strcmp(*argv, "--IQ") == 0) { // fq baseband -> IF (rotate from and decimate)
|
||||
double fq = 0.0; // --IQ <fq> , -0.5 < fq < 0.5
|
||||
++argv;
|
||||
|
@ -1101,6 +1108,13 @@ int main(int argc, char **argv) {
|
|||
gpx->option.ecc = 1;
|
||||
gpx->option.vit = 1;
|
||||
}
|
||||
else if (strcmp(*argv, "--jsn_cfq") == 0) {
|
||||
int frq = -1; // center frequency / Hz
|
||||
++argv;
|
||||
if (*argv) frq = atoi(*argv); else return -1;
|
||||
if (frq < 300000000) frq = -1;
|
||||
cfreq = frq;
|
||||
}
|
||||
else if (strcmp(*argv, "-") == 0) {
|
||||
int sample_rate = 0, bits_sample = 0, channels = 0;
|
||||
++argv;
|
||||
|
@ -1149,6 +1163,8 @@ int main(int argc, char **argv) {
|
|||
|
||||
gpx->week = gpsweek;
|
||||
|
||||
if (cfreq > 0) gpx->jsn_freq = (cfreq+500)/1000;
|
||||
|
||||
|
||||
#ifdef EXT_FSK
|
||||
if (!option_softin) {
|
||||
|
@ -1180,6 +1196,11 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
if (cfreq > 0) {
|
||||
int fq_kHz = (cfreq - dsp.xlt_fq*pcm.sr + 500)/1e3;
|
||||
gpx->jsn_freq = fq_kHz;
|
||||
}
|
||||
|
||||
symlen = 1;
|
||||
|
||||
// init dsp
|
||||
|
@ -1199,6 +1220,7 @@ int main(int argc, char **argv) {
|
|||
dsp.BT = 1.2; // bw/time (ISI) // 1.0..2.0 // BT(lmsX) < BT(lms6) ? -> init_buffers()
|
||||
dsp.h = 0.9; // 0.95 modulation index
|
||||
dsp.opt_iq = option_iq;
|
||||
dsp.opt_iqdc = option_iqdc;
|
||||
dsp.opt_lp = option_lp;
|
||||
dsp.lpIQ_bw = lpIQ_bw; // 16e3; // IF lowpass bandwidth // soft decoding?
|
||||
dsp.lpFM_bw = 6e3; // FM audio lowpass
|
||||
|
|
|
@ -93,6 +93,7 @@ typedef struct {
|
|||
ui8_t frame_bytes[FRAME_LEN+AUX_LEN+4];
|
||||
char frame_bits[BITFRAME_LEN+BITAUX_LEN+8];
|
||||
int auxlen; // 0 .. 0x76-0x64
|
||||
int jsn_freq; // freq/kHz (SDR)
|
||||
option_t option;
|
||||
ui8_t type;
|
||||
} gpx_t;
|
||||
|
@ -1004,6 +1005,9 @@ static int print_pos(gpx_t *gpx, int csOK) {
|
|||
fprintf(stdout, ", \"rawid\": \"M10_%02X%02X%02X%02X%02X\"", gpx->frame_bytes[pos_SN], gpx->frame_bytes[pos_SN+1],
|
||||
gpx->frame_bytes[pos_SN+2], gpx->frame_bytes[pos_SN+3], gpx->frame_bytes[pos_SN+4]); // gpx->type
|
||||
fprintf(stdout, ", \"subtype\": \"0x%02X\"", gpx->type);
|
||||
if (gpx->jsn_freq > 0) {
|
||||
fprintf(stdout, ", \"freq\": %d", gpx->jsn_freq);
|
||||
}
|
||||
fprintf(stdout, " }\n");
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
@ -1115,6 +1119,7 @@ int main(int argc, char **argv) {
|
|||
int option_ptu = 0;
|
||||
int option_min = 0;
|
||||
int option_iq = 0;
|
||||
int option_iqdc = 0;
|
||||
int option_lp = 0;
|
||||
int option_dc = 0;
|
||||
int option_chk = 0;
|
||||
|
@ -1123,6 +1128,7 @@ int main(int argc, char **argv) {
|
|||
int wavloaded = 0;
|
||||
int sel_wavch = 0; // audio channel: left
|
||||
int spike = 0;
|
||||
int cfreq = -1;
|
||||
|
||||
FILE *fp = NULL;
|
||||
char *fpname = NULL;
|
||||
|
@ -1214,6 +1220,7 @@ int main(int argc, char **argv) {
|
|||
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, "--iqdc") == 0) { option_iqdc = 1; } // iq-dc removal (iq0,2,3)
|
||||
else if (strcmp(*argv, "--IQ") == 0) { // fq baseband -> IF (rotate from and decimate)
|
||||
double fq = 0.0; // --IQ <fq> , -0.5 < fq < 0.5
|
||||
++argv;
|
||||
|
@ -1230,6 +1237,13 @@ int main(int argc, char **argv) {
|
|||
option_min = 1;
|
||||
}
|
||||
else if (strcmp(*argv, "--json") == 0) { gpx.option.jsn = 1; }
|
||||
else if (strcmp(*argv, "--jsn_cfq") == 0) {
|
||||
int frq = -1; // center frequency / Hz
|
||||
++argv;
|
||||
if (*argv) frq = atoi(*argv); else return -1;
|
||||
if (frq < 300000000) frq = -1;
|
||||
cfreq = frq;
|
||||
}
|
||||
else if (strcmp(*argv, "-") == 0) {
|
||||
int sample_rate = 0, bits_sample = 0, channels = 0;
|
||||
++argv;
|
||||
|
@ -1266,6 +1280,8 @@ int main(int argc, char **argv) {
|
|||
gpx.option.ptu = option_ptu;
|
||||
gpx.option.col = option_color;
|
||||
|
||||
if (cfreq > 0) gpx.jsn_freq = (cfreq+500)/1000;
|
||||
|
||||
|
||||
#ifdef EXT_FSK
|
||||
if (!option_softin) {
|
||||
|
@ -1293,6 +1309,11 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
if (cfreq > 0) {
|
||||
int fq_kHz = (cfreq - dsp.xlt_fq*pcm.sr + 500)/1e3;
|
||||
gpx.jsn_freq = fq_kHz;
|
||||
}
|
||||
|
||||
// m10: BT>1?, h=1.2 ?
|
||||
symlen = 2;
|
||||
|
||||
|
@ -1313,6 +1334,7 @@ int main(int argc, char **argv) {
|
|||
dsp.BT = 1.8; // bw/time (ISI) // 1.0..2.0
|
||||
dsp.h = 0.9; // 1.2 modulation index
|
||||
dsp.opt_iq = option_iq;
|
||||
dsp.opt_iqdc = option_iqdc;
|
||||
dsp.opt_lp = option_lp;
|
||||
dsp.lpIQ_bw = 24e3; // IF lowpass bandwidth
|
||||
dsp.lpFM_bw = 10e3; // FM audio lowpass
|
||||
|
|
|
@ -95,6 +95,7 @@ typedef struct {
|
|||
ui8_t frame_bytes[FRAME_LEN+AUX_LEN+4];
|
||||
char frame_bits[BITFRAME_LEN+BITAUX_LEN+8];
|
||||
int auxlen; // ? 0 .. 0x57-0x45
|
||||
int jsn_freq; // freq/kHz (SDR)
|
||||
option_t option;
|
||||
ui8_t type;
|
||||
} gpx_t;
|
||||
|
@ -642,6 +643,9 @@ static int print_pos(gpx_t *gpx, int bcOK, int csOK) {
|
|||
sn_id, gpx->jahr, gpx->monat, gpx->tag, gpx->std, gpx->min, gpx->sek, gpx->lat, gpx->lon, gpx->alt, gpx->vH, gpx->vD, gpx->vV);
|
||||
fprintf(stdout, ", \"rawid\": \"M20_%02X%02X%02X\"", gpx->frame_bytes[pos_SN], gpx->frame_bytes[pos_SN+1], gpx->frame_bytes[pos_SN+2]); // gpx->type
|
||||
fprintf(stdout, ", \"subtype\": \"0x%02X\"", gpx->type);
|
||||
if (gpx->jsn_freq > 0) {
|
||||
fprintf(stdout, ", \"freq\": %d", gpx->jsn_freq);
|
||||
}
|
||||
fprintf(stdout, " }\n");
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
@ -755,6 +759,7 @@ int main(int argc, char **argv) {
|
|||
int option_ptu = 0;
|
||||
int option_min = 0;
|
||||
int option_iq = 0;
|
||||
int option_iqdc = 0;
|
||||
int option_lp = 0;
|
||||
int option_dc = 0;
|
||||
int option_softin = 0;
|
||||
|
@ -762,6 +767,7 @@ int main(int argc, char **argv) {
|
|||
int wavloaded = 0;
|
||||
int sel_wavch = 0; // audio channel: left
|
||||
int spike = 0;
|
||||
int cfreq = -1;
|
||||
|
||||
float baudrate = -1;
|
||||
|
||||
|
@ -862,6 +868,7 @@ int main(int argc, char **argv) {
|
|||
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, "--iqdc") == 0) { option_iqdc = 1; } // iq-dc removal (iq0,2,3)
|
||||
else if (strcmp(*argv, "--IQ") == 0) { // fq baseband -> IF (rotate from and decimate)
|
||||
double fq = 0.0; // --IQ <fq> , -0.5 < fq < 0.5
|
||||
++argv;
|
||||
|
@ -878,6 +885,13 @@ int main(int argc, char **argv) {
|
|||
option_min = 1;
|
||||
}
|
||||
else if (strcmp(*argv, "--json") == 0) { gpx.option.jsn = 1; }
|
||||
else if (strcmp(*argv, "--jsn_cfq") == 0) {
|
||||
int frq = -1; // center frequency / Hz
|
||||
++argv;
|
||||
if (*argv) frq = atoi(*argv); else return -1;
|
||||
if (frq < 300000000) frq = -1;
|
||||
cfreq = frq;
|
||||
}
|
||||
else if (strcmp(*argv, "-") == 0) {
|
||||
int sample_rate = 0, bits_sample = 0, channels = 0;
|
||||
++argv;
|
||||
|
@ -914,6 +928,8 @@ int main(int argc, char **argv) {
|
|||
gpx.option.ptu = option_ptu;
|
||||
gpx.option.col = option_color;
|
||||
|
||||
if (cfreq > 0) gpx.jsn_freq = (cfreq+500)/1000;
|
||||
|
||||
|
||||
#ifdef EXT_FSK
|
||||
if (!option_softin) {
|
||||
|
@ -941,6 +957,11 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
if (cfreq > 0) {
|
||||
int fq_kHz = (cfreq - dsp.xlt_fq*pcm.sr + 500)/1e3;
|
||||
gpx.jsn_freq = fq_kHz;
|
||||
}
|
||||
|
||||
// m10: BT>1?, h=1.2 ?
|
||||
symlen = 2;
|
||||
|
||||
|
@ -961,6 +982,7 @@ int main(int argc, char **argv) {
|
|||
dsp.BT = 1.8; // bw/time (ISI) // 1.0..2.0 // M20 ?
|
||||
dsp.h = 0.9; // 1.2 modulation index // M20 ?
|
||||
dsp.opt_iq = option_iq;
|
||||
dsp.opt_iqdc = option_iqdc;
|
||||
dsp.opt_lp = option_lp;
|
||||
dsp.lpIQ_bw = 24e3; // IF lowpass bandwidth
|
||||
dsp.lpFM_bw = 10e3; // FM audio lowpass
|
||||
|
|
|
@ -122,7 +122,7 @@ typedef short i16_t;
|
|||
#define RAWBITFRAME_LEN (BITFRAME_LEN*2)
|
||||
|
||||
typedef struct {
|
||||
int frnr;
|
||||
int frnr; int frnr1;
|
||||
int jahr; int monat; int tag;
|
||||
int std; int min; float sek;
|
||||
double lat; double lon; double alt;
|
||||
|
@ -134,6 +134,7 @@ typedef struct {
|
|||
ui32_t _sn;
|
||||
float sn; // 0 mod 16
|
||||
float fq; // 15 mod 64
|
||||
int jsn_freq; // freq/kHz (SDR)
|
||||
RS_t RS;
|
||||
} gpx_t;
|
||||
|
||||
|
@ -210,12 +211,14 @@ int main(int argc, char **argv) {
|
|||
option_jsn = 0; // JSON output (auto_rx)
|
||||
int option_min = 0;
|
||||
int option_iq = 0;
|
||||
int option_iqdc = 0;
|
||||
int option_lp = 0;
|
||||
int option_dc = 0;
|
||||
int option_softin = 0;
|
||||
int option_pcmraw = 0;
|
||||
int sel_wavch = 0;
|
||||
int wavloaded = 0;
|
||||
int cfreq = -1;
|
||||
|
||||
int option1 = 0,
|
||||
option2 = 0;
|
||||
|
@ -229,6 +232,7 @@ int main(int argc, char **argv) {
|
|||
int err_frm = 0;
|
||||
int gps_chk_sum = 0;
|
||||
int gps_err = 0;
|
||||
int err_blks = 0;
|
||||
|
||||
ui8_t block_err[6];
|
||||
int block;
|
||||
|
@ -265,6 +269,8 @@ int main(int argc, char **argv) {
|
|||
int bitofs = 0; // 0..+1
|
||||
int shift = 0;
|
||||
|
||||
int reset_gpx = 0;
|
||||
|
||||
pcm_t pcm = {0};
|
||||
dsp_t dsp = {0}; //memset(&dsp, 0, sizeof(dsp));
|
||||
|
||||
|
@ -332,6 +338,7 @@ int main(int argc, char **argv) {
|
|||
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, "--iqdc") == 0) { option_iqdc = 1; } // iq-dc removal (iq0,2,3)
|
||||
else if (strcmp(*argv, "--IQ") == 0) { // fq baseband -> IF (rotate from and decimate)
|
||||
double fq = 0.0; // --IQ <fq> , -0.5 < fq < 0.5
|
||||
++argv;
|
||||
|
@ -351,6 +358,13 @@ int main(int argc, char **argv) {
|
|||
option_jsn = 1;
|
||||
option_ecc = 1;
|
||||
}
|
||||
else if (strcmp(*argv, "--jsn_cfq") == 0) {
|
||||
int frq = -1; // center frequency / Hz
|
||||
++argv;
|
||||
if (*argv) frq = atoi(*argv); else return -1;
|
||||
if (frq < 300000000) frq = -1;
|
||||
cfreq = frq;
|
||||
}
|
||||
else if (strcmp(*argv, "-") == 0) {
|
||||
int sample_rate = 0, bits_sample = 0, channels = 0;
|
||||
++argv;
|
||||
|
@ -381,6 +395,8 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
if (!wavloaded) fp = stdin;
|
||||
|
||||
if (cfreq > 0) gpx.jsn_freq = (cfreq+500)/1000;
|
||||
|
||||
|
||||
#ifdef EXT_FSK
|
||||
if (!option_softin) {
|
||||
|
@ -408,6 +424,11 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
if (cfreq > 0) {
|
||||
int fq_kHz = (cfreq - dsp.xlt_fq*pcm.sr + 500)/1e3;
|
||||
gpx.jsn_freq = fq_kHz;
|
||||
}
|
||||
|
||||
symlen = 1;
|
||||
|
||||
// init dsp
|
||||
|
@ -427,6 +448,7 @@ int main(int argc, char **argv) {
|
|||
dsp.BT = 1.2; // bw/time (ISI) // 1.0..2.0
|
||||
dsp.h = 2.4; // 2.8
|
||||
dsp.opt_iq = option_iq;
|
||||
dsp.opt_iqdc = option_iqdc;
|
||||
dsp.opt_lp = option_lp;
|
||||
dsp.lpIQ_bw = 16e3; // IF lowpass bandwidth
|
||||
dsp.lpFM_bw = 4e3; // FM audio lowpass
|
||||
|
@ -525,10 +547,11 @@ int main(int argc, char **argv) {
|
|||
gps_chk_sum = 0;
|
||||
gps_err = 0;
|
||||
err_frm = 0;
|
||||
err_blks = 0;
|
||||
|
||||
for (subframe = 0; subframe < 2; subframe++)
|
||||
{ // option2:
|
||||
subframe_bits = gpx.frame_bits; // subframe 0: 049DCE
|
||||
subframe_bits = gpx.frame_bits; // subframe 0: 049DCE
|
||||
if (subframe > 0) subframe_bits += BITFRAME_LEN/4; // subframe 1: FB6230
|
||||
|
||||
if (option_ecc) {
|
||||
|
@ -571,13 +594,23 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
else block_err[block] = errors;
|
||||
|
||||
err_blks += (errors != 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (!option2 && !option_raw) {
|
||||
jmpRS11:
|
||||
if (reset_gpx) {
|
||||
memset(&gpx, sizeof(gpx), 0);
|
||||
sn = 0;
|
||||
reset_gpx = 0;
|
||||
}
|
||||
if (header_found % 2 == 1)
|
||||
{
|
||||
ui16_t w16[2];
|
||||
ui32_t w32;
|
||||
float *fcfg = (float *)&w32;
|
||||
|
||||
val = bits2val(subframe_bits+HEADLEN, 16);
|
||||
counter = val & 0xFFFF;
|
||||
printf("[%d] ", counter);
|
||||
|
@ -587,24 +620,60 @@ int main(int argc, char **argv) {
|
|||
if ( (val & 0xFF) >= 0xC0 && err_frm == 0) {
|
||||
option2 = 1;
|
||||
printf("\n");
|
||||
reset_gpx = 1;
|
||||
goto jmpIMS;
|
||||
}
|
||||
|
||||
w16[0] = bits2val(subframe_bits+HEADLEN+46*1 , 16);
|
||||
w16[1] = bits2val(subframe_bits+HEADLEN+46*1+17, 16);
|
||||
w32 = (w16[1]<<16) | w16[0];
|
||||
|
||||
if (err_blks == 0) // err_frm zu schwach
|
||||
{
|
||||
if (counter % 0x10 == 0) { sn = w32; gpx.sn = sn; gpx._sn = w32; }
|
||||
}
|
||||
|
||||
if (counter % 2 == 1) {
|
||||
t2 = bits2val(subframe_bits+HEADLEN+5*46 , 8); // LSB
|
||||
t1 = bits2val(subframe_bits+HEADLEN+5*46+8, 8);
|
||||
ms = (t1 << 8) | t2;
|
||||
std = bits2val(subframe_bits+HEADLEN+5*46+17, 8);
|
||||
min = bits2val(subframe_bits+HEADLEN+5*46+25, 8);
|
||||
printf(" ");
|
||||
printf("%02d:%02d:%06.3f ", std, min, (double)ms/1000.0);
|
||||
if (std < 24 && min < 60 && ms < 60000) { // ui32_t ms, min, std
|
||||
printf(" ");
|
||||
printf("%02d:%02d:%06.3f ", std, min, (double)ms/1000.0);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
if (err_blks == 0) {
|
||||
gpx.frnr1 = counter;
|
||||
gpx.std = std;
|
||||
gpx.min = min;
|
||||
gpx.sek = (double)ms/1000.0;
|
||||
|
||||
if (0 && option_jsn && err_blks==0 && gpx.frnr1-gpx.frnr==1) {
|
||||
char id_str[] = "xxxxxx\0\0\0\0\0\0";
|
||||
if (gpx._sn > 0) {
|
||||
sprintf(id_str, "__%05d", gpx._sn & 0xFFFF); // last 5 digits?
|
||||
}
|
||||
printf("{ \"type\": \"%s\"", "MEISEI");
|
||||
printf(", \"frame\": %d, \"id\": \"RS11G-%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f, \"vel_v\": %.5f",
|
||||
gpx.frnr, id_str, gpx.jahr, gpx.monat, gpx.tag, gpx.std, gpx.min, gpx.sek, gpx.lat, gpx.lon, gpx.alt, gpx.vH, gpx.vD, gpx.vV );
|
||||
printf(", \"subtype\": \"RS11G\"");
|
||||
if (gpx.jsn_freq > 0) {
|
||||
printf(", \"freq\": %d", gpx.jsn_freq);
|
||||
}
|
||||
printf(" }\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (header_found % 2 == 0)
|
||||
{
|
||||
if ((counter % 2 == 0)) {
|
||||
if (counter % 2 == 0) {
|
||||
//offset=24+16+1;
|
||||
|
||||
lat1 = bits2val(subframe_bits+HEADLEN+46*0+17, 16);
|
||||
|
@ -634,7 +703,26 @@ int main(int argc, char **argv) {
|
|||
jj = bits2val(subframe_bits+HEADLEN+5*46+ 8, 8) + 0x0700;
|
||||
mm = bits2val(subframe_bits+HEADLEN+5*46+17, 8);
|
||||
tt = bits2val(subframe_bits+HEADLEN+5*46+25, 8);
|
||||
printf(" %4d-%02d-%02d ", jj, mm, tt);
|
||||
if (jj > 1980 && mm > 0 && mm < 13 && tt > 0 && tt < 32) { // ui32_t tt, mm, jj
|
||||
printf(" %4d-%02d-%02d ", jj, mm, tt);
|
||||
}
|
||||
|
||||
if (err_blks == 0) { // err_frm zu schwach
|
||||
gpx.frnr = counter;
|
||||
gpx.tag = tt;
|
||||
gpx.monat = mm;
|
||||
gpx.jahr = jj;
|
||||
gpx.lat = (double)lat/1e7;
|
||||
gpx.lon = (double)lon/1e7;
|
||||
gpx.alt = (double)alt/1e2;
|
||||
gpx.vH = velH;
|
||||
gpx.vD = velD;
|
||||
gpx.vV = velU;
|
||||
}
|
||||
if (err_blks == 0 && counter%0x10==0 && gpx._sn > 0) { // gpx._sn>>16 = 0x5697 , 0x7297
|
||||
//fprintf(stdout, " : sn 0x%08x = %05d %d", gpx._sn, gpx._sn & 0xFFFF, (gpx._sn>>16) & 0xFFFF);
|
||||
fprintf(stdout, " : _sn %05d", gpx._sn & 0xFFFF);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
@ -642,6 +730,11 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
else if (option2 && !option_raw) { // iMS-100
|
||||
jmpIMS:
|
||||
if (reset_gpx) {
|
||||
memset(&gpx, sizeof(gpx), 0);
|
||||
sn = 0;
|
||||
reset_gpx = 0;
|
||||
}
|
||||
if (header_found % 2 == 1) { // 049DCE
|
||||
ui16_t w16[2];
|
||||
ui32_t w32;
|
||||
|
@ -655,6 +748,7 @@ int main(int argc, char **argv) {
|
|||
if ( (val & 0xFF) < 0xC0 && err_frm == 0) {
|
||||
option2 = 0;
|
||||
printf("\n");
|
||||
reset_gpx = 1;
|
||||
goto jmpRS11;
|
||||
}
|
||||
|
||||
|
@ -666,8 +760,8 @@ int main(int argc, char **argv) {
|
|||
w16[0] = bits2val(subframe_bits+HEADLEN+46*1 , 16);
|
||||
w16[1] = bits2val(subframe_bits+HEADLEN+46*1+17, 16);
|
||||
w32 = (w16[1]<<16) | w16[0];
|
||||
|
||||
if (err_frm == 0) // oder kleineren subblock pruefen
|
||||
// counter ok and w16[] ok (max 1 error)
|
||||
if (err_frm == 0 && block_err[0] < 2 && block_err[1] < 2)
|
||||
{
|
||||
gpx.cfg[counter%64] = *fcfg;
|
||||
|
||||
|
@ -699,13 +793,16 @@ int main(int argc, char **argv) {
|
|||
for (j = 0; j < 11; j++) gps_chk_sum += get_w16(subframe_bits, j);
|
||||
gps_err = (gps_chk_sum & 0xFFFF) != get_w16(subframe_bits, 11); // 1st+2nd subframe
|
||||
|
||||
if ((counter % 2 == 0)) {
|
||||
if (counter % 2 == 0) {
|
||||
//offset=24+16+1;
|
||||
int _y = 0;
|
||||
|
||||
dat2 = bits2val(subframe_bits+HEADLEN, 16);
|
||||
gpx.tag = dat2/1000;
|
||||
gpx.monat = (dat2/10)%100;
|
||||
gpx.jahr = 2000 + (dat2%10)+10;
|
||||
_y = (dat2%10)+10;
|
||||
if (_y < 14) _y += 10; // 2020
|
||||
gpx.jahr = 2000 + _y;
|
||||
//if (option_verbose) printf("%05u ", dat2);
|
||||
//printf("(%02d-%02d-%02d) ", gpx.tag, gpx.monat, gpx.jahr%100); // 2020: +20 ?
|
||||
printf("(%04d-%02d-%02d) ", gpx.jahr, gpx.monat, gpx.tag); // 2020: +20 ?
|
||||
|
@ -766,9 +863,14 @@ int main(int argc, char **argv) {
|
|||
if (gpx.sn > 0 && gpx.sn < 1e9) {
|
||||
sprintf(id_str, "%.0f", gpx.sn);
|
||||
}
|
||||
printf("{ \"type\": \"%s\"", "IMS100");
|
||||
printf(", \"frame\": %d, \"id\": \"IMS100-%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f }\n",
|
||||
printf("{ \"type\": \"%s\"", "MEISEI"); // alt: "IMS100"
|
||||
printf(", \"frame\": %d, \"id\": \"IMS100-%s\", \"datetime\": \"%04d-%02d-%02dT%02d:%02d:%06.3fZ\", \"lat\": %.5f, \"lon\": %.5f, \"alt\": %.5f, \"vel_h\": %.5f, \"heading\": %.5f",
|
||||
gpx.frnr, id_str, gpx.jahr, gpx.monat, gpx.tag, gpx.std, gpx.min, gpx.sek, gpx.lat, gpx.lon, gpx.alt, gpx.vH, gpx.vD );
|
||||
printf(", \"subtype\": \"IMS100\"");
|
||||
if (gpx.jsn_freq > 0) { // not gpx.fq, because gpx.sn not in every frame
|
||||
printf(", \"freq\": %d", gpx.jsn_freq);
|
||||
}
|
||||
printf(" }\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,18 @@ static rscfg_t cfg_rs41 = { 41, (320-56)/2, 56, 8, 8, 320}; // const: msgpos, pa
|
|||
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 {
|
||||
float frm_bytescore[FRAME_LEN+8];
|
||||
float ts;
|
||||
float last_frnb_ts;
|
||||
float last_calfrm_ts;
|
||||
ui16_t last_frnb;
|
||||
ui8_t last_calfrm;
|
||||
int sort_idx1[FRAME_LEN]; // ui8_t[] sort_cw1_idx
|
||||
int sort_idx2[FRAME_LEN]; // ui8_t[] sort_cw2_idx
|
||||
} ecdat_t;
|
||||
|
||||
typedef struct {
|
||||
int out;
|
||||
int frnr;
|
||||
|
@ -84,10 +96,12 @@ typedef struct {
|
|||
int std; int min; float sek;
|
||||
double lat; double lon; double alt;
|
||||
double vH; double vD; double vV;
|
||||
float T; float RH;
|
||||
float T; float RH; float TH;
|
||||
float P; float RH2;
|
||||
ui32_t crc;
|
||||
ui8_t frame[FRAME_LEN];
|
||||
ui8_t dfrm[FRAME_LEN];
|
||||
//ui8_t dfrm_shiftsgn[FRAME_LEN];
|
||||
ui8_t dfrm_bitscore[FRAME_LEN];
|
||||
ui8_t calibytes[51*16];
|
||||
ui8_t calfrchk[51];
|
||||
float ptu_Rf1; // ref-resistor f1 (750 Ohm)
|
||||
|
@ -97,7 +111,12 @@ typedef struct {
|
|||
float ptu_co2[3]; // { -243.911 , 0.187654 , 8.2e-06 }
|
||||
float ptu_calT2[3]; // calibration T2-Hum
|
||||
float ptu_calH[2]; // calibration Hum
|
||||
ui32_t freq; // freq/kHz
|
||||
float ptu_mtxH[42];
|
||||
float ptu_Cf1;
|
||||
float ptu_Cf2;
|
||||
float ptu_calP[25];
|
||||
ui32_t freq; // freq/kHz (RS41)
|
||||
int jsn_freq; // freq/kHz (SDR)
|
||||
float batt; // battery voltage (V)
|
||||
ui16_t conf_fw; // firmware
|
||||
ui16_t conf_kt; // kill timer (sec)
|
||||
|
@ -109,6 +128,7 @@ typedef struct {
|
|||
char xdata[XDATA_LEN+16]; // xdata: aux_str1#aux_str2 ...
|
||||
option_t option;
|
||||
RS_t RS;
|
||||
ecdat_t ecdat;
|
||||
} gpx_t;
|
||||
|
||||
|
||||
|
@ -210,6 +230,13 @@ static ui32_t u2(ui8_t *bytes) { // 16bit unsigned int
|
|||
return bytes[0] | (bytes[1]<<8);
|
||||
}
|
||||
|
||||
static int i2(ui8_t *bytes) { // 16bit signed int
|
||||
//return (i16_t)u2(bytes);
|
||||
int val = bytes[0] | (bytes[1]<<8);
|
||||
if (val & 0x8000) val -= 0x10000;
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
double r8(ui8_t *bytes) {
|
||||
double val = 0;
|
||||
|
@ -349,7 +376,7 @@ static int frametype(gpx_t *gpx) { // -4..+4: 0xF0 -> -4 , 0x0F -> +4
|
|||
return ft;
|
||||
}
|
||||
|
||||
static int get_FrameNb(gpx_t *gpx, int ofs) {
|
||||
static int get_FrameNb(gpx_t *gpx, int crc, int ofs) {
|
||||
int i;
|
||||
unsigned byte;
|
||||
ui8_t frnr_bytes[2];
|
||||
|
@ -363,6 +390,12 @@ static int get_FrameNb(gpx_t *gpx, int ofs) {
|
|||
frnr = frnr_bytes[0] + (frnr_bytes[1] << 8);
|
||||
gpx->frnr = frnr;
|
||||
|
||||
// crc check
|
||||
if (crc == 0) {
|
||||
gpx->ecdat.last_frnb = frnr;
|
||||
gpx->ecdat.last_frnb_ts = gpx->ecdat.ts;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -409,9 +442,13 @@ static int get_SondeID(gpx_t *gpx, int crc, int ofs) {
|
|||
// don't reset gpx->frame[] !
|
||||
gpx->T = -273.15;
|
||||
gpx->RH = -1.0;
|
||||
gpx->P = -1.0;
|
||||
gpx->RH2 = -1.0;
|
||||
// new ID:
|
||||
memcpy(gpx->id, sondeid_bytes, 8);
|
||||
gpx->id[8] = '\0';
|
||||
|
||||
gpx->ecdat.last_frnb = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -428,7 +465,7 @@ static int get_FrameConf(gpx_t *gpx, int ofs) {
|
|||
|
||||
err = crc;
|
||||
err |= get_SondeID(gpx, crc, ofs);
|
||||
err |= get_FrameNb(gpx, ofs);
|
||||
err |= get_FrameNb(gpx, crc, ofs);
|
||||
err |= get_BattVolts(gpx, ofs);
|
||||
|
||||
if (crc == 0) {
|
||||
|
@ -440,6 +477,9 @@ static int get_FrameConf(gpx_t *gpx, int ofs) {
|
|||
}
|
||||
gpx->calfrchk[calfr] = 1;
|
||||
}
|
||||
|
||||
gpx->ecdat.last_calfrm = calfr;
|
||||
gpx->ecdat.last_calfrm_ts = gpx->ecdat.ts;
|
||||
}
|
||||
|
||||
return err;
|
||||
|
@ -447,6 +487,8 @@ static int get_FrameConf(gpx_t *gpx, int ofs) {
|
|||
|
||||
static int get_CalData(gpx_t *gpx) {
|
||||
|
||||
int j;
|
||||
|
||||
memcpy(&(gpx->ptu_Rf1), gpx->calibytes+61, 4); // 0x03*0x10+13
|
||||
memcpy(&(gpx->ptu_Rf2), gpx->calibytes+65, 4); // 0x04*0x10+ 1
|
||||
|
||||
|
@ -457,6 +499,7 @@ static int get_CalData(gpx_t *gpx) {
|
|||
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
|
||||
// ptu_calT1[3..6]
|
||||
|
||||
memcpy(gpx->ptu_calH+0, gpx->calibytes+117, 4); // 0x07*0x10+ 5
|
||||
memcpy(gpx->ptu_calH+1, gpx->calibytes+121, 4); // 0x07*0x10+ 9
|
||||
|
@ -468,82 +511,168 @@ static int get_CalData(gpx_t *gpx) {
|
|||
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
|
||||
// ptu_calT2[3..6]
|
||||
|
||||
|
||||
// cf. DF9DQ
|
||||
memcpy(&(gpx->ptu_Cf1), gpx->calibytes+69, 4); // 0x04*0x10+ 5
|
||||
memcpy(&(gpx->ptu_Cf2), gpx->calibytes+73, 4); // 0x04*0x10+ 9
|
||||
for (j = 0; j < 42; j++) { // 0x07*0x10+13 = 0x07D = 125
|
||||
memcpy(gpx->ptu_mtxH+j, gpx->calibytes+125+4*j, 4);
|
||||
}
|
||||
// cf. DF9DQ or stsst/RS-fork
|
||||
memcpy(gpx->ptu_calP+0, gpx->calibytes+606, 4); // 0x25*0x10+14 = 0x25E
|
||||
memcpy(gpx->ptu_calP+4, gpx->calibytes+610, 4); // ..
|
||||
memcpy(gpx->ptu_calP+8, gpx->calibytes+614, 4);
|
||||
memcpy(gpx->ptu_calP+12, gpx->calibytes+618, 4);
|
||||
memcpy(gpx->ptu_calP+16, gpx->calibytes+622, 4);
|
||||
memcpy(gpx->ptu_calP+20, gpx->calibytes+626, 4);
|
||||
memcpy(gpx->ptu_calP+24, gpx->calibytes+630, 4);
|
||||
memcpy(gpx->ptu_calP+1, gpx->calibytes+634, 4);
|
||||
memcpy(gpx->ptu_calP+5, gpx->calibytes+638, 4);
|
||||
memcpy(gpx->ptu_calP+9, gpx->calibytes+642, 4);
|
||||
memcpy(gpx->ptu_calP+13, gpx->calibytes+646, 4);
|
||||
memcpy(gpx->ptu_calP+2, gpx->calibytes+650, 4);
|
||||
memcpy(gpx->ptu_calP+6, gpx->calibytes+654, 4);
|
||||
memcpy(gpx->ptu_calP+10, gpx->calibytes+658, 4);
|
||||
memcpy(gpx->ptu_calP+14, gpx->calibytes+662, 4);
|
||||
memcpy(gpx->ptu_calP+3, gpx->calibytes+666, 4);
|
||||
memcpy(gpx->ptu_calP+7, gpx->calibytes+670, 4); // ..
|
||||
memcpy(gpx->ptu_calP+11, gpx->calibytes+674, 4); // 0x2A*0x10+ 2
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
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 = 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
|
||||
r = raw * g_r + r_o,
|
||||
t = (-a + sqrt(a*a + 4*b*(r-1)))/(2*b); // t>0: c=0
|
||||
// R/R0 = 1 + at + bt^2 + c(t-100)t^3 , R0 = 1000 Ohm, t/Celsius
|
||||
return t;
|
||||
}
|
||||
*/
|
||||
// T_RH-sensor
|
||||
static float get_TH(gpx_t *gpx, ui32_t f, ui32_t f1, ui32_t f2) {
|
||||
float *p = gpx->ptu_co2;
|
||||
float *c = gpx->ptu_calT2;
|
||||
// temperature, platinum resistor
|
||||
// T-sensor: gpx->ptu_co1 , gpx->ptu_calT1
|
||||
// T_RH-sensor: gpx->ptu_co2 , gpx->ptu_calT2
|
||||
static float get_T(gpx_t *gpx, ui32_t f, ui32_t f1, ui32_t f2, float *ptu_co, float *ptu_calT) {
|
||||
float *p = ptu_co;
|
||||
float *c = ptu_calT;
|
||||
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;
|
||||
R = Rc * c[0],
|
||||
T = (p[0] + p[1]*R + p[2]*R*R + c[1])*(1.0 + c[2]);
|
||||
return T;
|
||||
}
|
||||
// T-sensor, platinum resistor
|
||||
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;
|
||||
R = Rc * c[0],
|
||||
T = (p[0] + p[1]*R + p[2]*R*R + c[1])*(1.0 + c[2]);
|
||||
return T;
|
||||
return T; // [Celsius]
|
||||
}
|
||||
|
||||
// rel.hum., capacitor
|
||||
// (data:) ftp://ftp-cdc.dwd.de/climate_environment/CDC/observations_germany/radiosondes/
|
||||
// (diffAlt: Ellipsoid-Geoid)
|
||||
// (note: humidity sensor significant has time lag at low temperatures)
|
||||
static float get_RH(gpx_t *gpx, ui32_t f, ui32_t f1, ui32_t f2, float T) {
|
||||
float a0 = 7.5; // empirical
|
||||
float a1 = 350.0/gpx->ptu_calH[0]; // empirical
|
||||
float fh = (f-f1)/(float)(f2-f1);
|
||||
float rh = 100.0 * ( a1*fh - a0 );
|
||||
float T0 = 0.0, T1 = -25.0; // T/C
|
||||
rh += T0 - T/5.5; // empir. temperature compensation
|
||||
if (T < T1) rh *= 1.0 + (T1-T)/90.0; // empir. temperature compensation
|
||||
float T0 = 0.0, T1 = -20.0, T2 = -40.0; // T/C v0.4
|
||||
rh += T0 - T/5.5; // empir. temperature compensation
|
||||
if (T < T1) rh *= 1.0 + (T1-T)/100.0; // empir. temperature compensation
|
||||
if (T < T2) rh *= 1.0 + (T2-T)/120.0; // empir. temperature compensation
|
||||
if (rh < 0.0) rh = 0.0;
|
||||
if (rh > 100.0) rh = 100.0;
|
||||
if (T < -273.0) rh = -1.0;
|
||||
return rh;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
//
|
||||
// cf. github DF9DQ
|
||||
// water vapor saturation pressure (Hyland and Wexler)
|
||||
static float vaporSatP(float Tc) {
|
||||
double T = Tc + 273.15;
|
||||
|
||||
// Apply some correction magic
|
||||
// T = -0.4931358 + (1.0 + 4.61e-3) * T - 1.3746454e-5 * T*T + 1.2743214e-8 * T*T*T;
|
||||
|
||||
// H+W equation
|
||||
double p = expf(-5800.2206 / T
|
||||
+1.3914993
|
||||
+6.5459673 * log(T)
|
||||
-4.8640239e-2 * T
|
||||
+4.1764768e-5 * T*T
|
||||
-1.4452093e-8 * T*T*T
|
||||
);
|
||||
|
||||
return (float)p; // [Pa]
|
||||
}
|
||||
// cf. github DF9DQ // offset stratosphere RH2(-60C)=+5% , RH2(-40C)=+1% ?
|
||||
static float get_RH2adv(gpx_t *gpx, ui32_t f, ui32_t f1, ui32_t f2, float T, float TH) {
|
||||
float rh = 0.0;
|
||||
float cfh = (f-f1)/(float)(f2-f1);
|
||||
float cap = gpx->ptu_Cf1+(gpx->ptu_Cf2-gpx->ptu_Cf1)*cfh;
|
||||
double Cp = (cap / gpx->ptu_calH[0] - 1.0) * gpx->ptu_calH[1];
|
||||
double Trh_20_180 = (TH - 20.0) / 180.0;
|
||||
double _rh = 0.0;
|
||||
double aj = 1.0;
|
||||
double bk = 1.0, b[6];
|
||||
int j, k;
|
||||
|
||||
bk = 1.0;
|
||||
for (k = 0; k < 6; k++) {
|
||||
b[k] = bk;
|
||||
bk *= Trh_20_180;
|
||||
}
|
||||
|
||||
aj = 1.0;
|
||||
for (j = 0; j < 7; j++) {
|
||||
for (k = 0; k < 6; k++) {
|
||||
_rh += aj * b[k] * gpx->ptu_mtxH[6*j+k];
|
||||
}
|
||||
aj *= Cp;
|
||||
}
|
||||
|
||||
if ( 1 ) { // empirical correction
|
||||
float T2 = -40;
|
||||
if (T < T2) { _rh += (T-T2)/12.0; }
|
||||
}
|
||||
|
||||
rh = _rh * vaporSatP(TH)/vaporSatP(T);
|
||||
|
||||
if (rh < 0.0) rh = 0.0;
|
||||
if (rh > 100.0) rh = 100.0;
|
||||
return rh;
|
||||
}
|
||||
//
|
||||
// cf. github DF9DQ or stsst/RS-fork
|
||||
static float get_P(gpx_t *gpx, ui32_t f, ui32_t f1, ui32_t f2, int fx)
|
||||
{
|
||||
double p = 0.0;
|
||||
double a0, a1, a0j, a1k;
|
||||
int j, k;
|
||||
if (f1 == f2 || f1 == f) return 0.0;
|
||||
a0 = gpx->ptu_calP[24] / ((float)(f - f1) / (float)(f2 - f1));
|
||||
a1 = fx * 0.01;
|
||||
|
||||
a0j = 1.0;
|
||||
for (j = 0; j < 6; j++) {
|
||||
a1k = 1.0;
|
||||
for (k = 0; k < 4; k++) {
|
||||
p += a0j * a1k * gpx->ptu_calP[j*4+k];
|
||||
a1k *= a1;
|
||||
}
|
||||
a0j *= a0;
|
||||
}
|
||||
|
||||
return (float)p;
|
||||
}
|
||||
// ---------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
static int get_PTU(gpx_t *gpx, int ofs, int pck) {
|
||||
int err=0, i;
|
||||
int bR, bc1, bT1,
|
||||
bc2, bT2;
|
||||
int bH;
|
||||
int bH2;
|
||||
int bP;
|
||||
ui32_t meas[12];
|
||||
float Tc = -273.15;
|
||||
float TH = -273.15;
|
||||
float RH = -1.0;
|
||||
float RH2 = -1.0;
|
||||
float P = -1.0;
|
||||
|
||||
get_CalData(gpx);
|
||||
|
||||
|
@ -565,21 +694,42 @@ static int get_PTU(gpx_t *gpx, int ofs, int pck) {
|
|||
bT2 = gpx->calfrchk[0x13];
|
||||
bH = gpx->calfrchk[0x07];
|
||||
|
||||
bH2 = gpx->calfrchk[0x08] && gpx->calfrchk[0x09]
|
||||
&& gpx->calfrchk[0x10] && gpx->calfrchk[0x11]
|
||||
&& gpx->calfrchk[0x12] && gpx->calfrchk[0x13];
|
||||
|
||||
bP = gpx->calfrchk[0x21] && gpx->calibytes[0x21F] == 'P'
|
||||
&& gpx->calfrchk[0x25] && gpx->calfrchk[0x26]
|
||||
&& gpx->calfrchk[0x27] && gpx->calfrchk[0x28]
|
||||
&& gpx->calfrchk[0x29] && gpx->calfrchk[0x2A];
|
||||
|
||||
if (bR && bc1 && bT1) {
|
||||
Tc = get_Tc(gpx, meas[0], meas[1], meas[2]);
|
||||
//Tc0 = get_Tc0(gpx, meas[0], meas[1], meas[2]);
|
||||
Tc = get_T(gpx, meas[0], meas[1], meas[2], gpx->ptu_co1, gpx->ptu_calT1);
|
||||
}
|
||||
gpx->T = Tc;
|
||||
|
||||
if (bR && bc2 && bT2) {
|
||||
TH = get_TH(gpx, meas[6], meas[7], meas[8]);
|
||||
TH = get_T(gpx, meas[6], meas[7], meas[8], gpx->ptu_co2, gpx->ptu_calT2);
|
||||
}
|
||||
gpx->TH = TH;
|
||||
|
||||
if (bH) {
|
||||
if (bH && Tc > -273.0) {
|
||||
RH = get_RH(gpx, meas[3], meas[4], meas[5], Tc); // TH, TH-Tc (sensorT - T)
|
||||
}
|
||||
gpx->RH = RH;
|
||||
|
||||
// cf. DF9DQ, stsst/RS-fork
|
||||
if (gpx->option.ptu == 2) {
|
||||
if (bH && bH2 && Tc > -273.0 && TH > -273.0) {
|
||||
RH2 = get_RH2adv(gpx, meas[3], meas[4], meas[5], Tc, TH);
|
||||
}
|
||||
}
|
||||
gpx->RH2 = RH2;
|
||||
if (bP) {
|
||||
P = get_P(gpx, meas[9], meas[10], meas[11], i2(gpx->frame+pos_PTU+ofs+2+38));
|
||||
}
|
||||
gpx->P = P;
|
||||
|
||||
|
||||
if (gpx->option.vbs == 4 && (gpx->crc & (crc_PTU | crc_GPS3))==0)
|
||||
{
|
||||
|
@ -592,7 +742,7 @@ static int get_PTU(gpx_t *gpx, int ofs, int pck) {
|
|||
printf("3: %8d %8d %8d", meas[6], meas[7], meas[8]);
|
||||
printf(" # ");
|
||||
|
||||
//if (Tc > -273.0 && RH > -0.5)
|
||||
if (0 && Tc > -273.0 && RH > -0.5)
|
||||
{
|
||||
printf(" ");
|
||||
printf(" Tc:%.2f ", Tc);
|
||||
|
@ -703,6 +853,7 @@ static int get_GPS2(gpx_t *gpx, int ofs) {
|
|||
return err;
|
||||
}
|
||||
|
||||
// WGS84/GRS80 Ellipsoid
|
||||
#define EARTH_a 6378137.0
|
||||
#define EARTH_b 6356752.31424518
|
||||
#define EARTH_a2_b2 (EARTH_a*EARTH_a - EARTH_b*EARTH_b)
|
||||
|
@ -974,6 +1125,37 @@ static int get_Calconf(gpx_t *gpx, int out, int ofs) {
|
|||
|
||||
/* ------------------------------------------------------------------------------------ */
|
||||
|
||||
static int set_bytes(gpx_t *gpx, int pos, ui8_t *src, int len, int subcw, int *pset) {
|
||||
int rem = 0; // cw1: rem=0 , cw2: rem=1 ( pos >= msgpos)
|
||||
int i;
|
||||
if (subcw == 2) rem = 1; else rem = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if ( (pos+i) % 2 == rem) {
|
||||
gpx->frame[pos+i] = src[i];
|
||||
*pset = pos+i;
|
||||
pset++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define N_idx_fixed 5
|
||||
static int idx_fixed[N_idx_fixed] = { pos_FRAME, pos_PTU, pos_GPS1, pos_GPS2, pos_GPS3 };
|
||||
|
||||
static int inFixed(gpx_t *gpx, int idx, int *frmset, int setcnt) {
|
||||
int j;
|
||||
for (j = 0; j < N_idx_fixed; j++) {
|
||||
if (idx == idx_fixed[j] || idx == idx_fixed[j]+1) return 1;
|
||||
}
|
||||
if (frametype(gpx) >= -2) {
|
||||
if (idx >= pos_ZEROstd && idx < NDATA_LEN) return 1;
|
||||
}
|
||||
for (j = 0; j < setcnt; j++) {
|
||||
if (idx == frmset[j]) return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define rs_N 255
|
||||
#define rs_R 24
|
||||
#define rs_K (rs_N-rs_R)
|
||||
|
@ -981,11 +1163,17 @@ static int get_Calconf(gpx_t *gpx, int out, int ofs) {
|
|||
static int rs41_ecc(gpx_t *gpx, int frmlen) {
|
||||
// richtige framelen wichtig fuer 0-padding
|
||||
|
||||
int i, leak, ret = 0;
|
||||
int i, j, k, 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];
|
||||
ui8_t era_pos[rs_R];
|
||||
ui8_t Era_max = 12; // iteration depth 2..255 (2 erasures for 1 error)
|
||||
|
||||
int frmset[FRAME_LEN];
|
||||
int setcnt = 0;
|
||||
|
||||
|
||||
memset(cw1, 0, rs_N);
|
||||
memset(cw2, 0, rs_N);
|
||||
|
@ -1007,28 +1195,8 @@ static int rs41_ecc(gpx_t *gpx, int frmlen) {
|
|||
errors2 = rs_decode(&gpx->RS, cw2, err_pos2, err_val2);
|
||||
|
||||
|
||||
if (gpx->option.ecc >= 2) // option_softin: mark weak dfrm[]
|
||||
{ // 2nd pass
|
||||
if (errors1 < 0) {
|
||||
for (i = 0; i < frmlen/2; i++) gpx->frame[2*i] ^= gpx->dfrm[2*i];
|
||||
for (i = 0; i < rs_K; i++) cw1[rs_R+i] = gpx->frame[cfg_rs41.msgpos+2*i ];
|
||||
errors1 = rs_decode(&gpx->RS, cw1, err_pos1, err_val1);
|
||||
if (errors1 < 0) {
|
||||
for (i = 0; i < frmlen/2; i++) gpx->frame[2*i] ^= gpx->dfrm[2*i];
|
||||
}
|
||||
}
|
||||
if (errors2 < 0) {
|
||||
for (i = 0; i < frmlen/2; i++) gpx->frame[2*i+1] ^= gpx->dfrm[2*i+1];
|
||||
for (i = 0; i < rs_K; i++) cw2[rs_R+i] = gpx->frame[cfg_rs41.msgpos+2*i+1];
|
||||
errors2 = rs_decode(&gpx->RS, cw2, err_pos2, err_val2);
|
||||
if (errors2 < 0) {
|
||||
for (i = 0; i < frmlen/2; i++) gpx->frame[2*i+1] ^= gpx->dfrm[2*i+1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gpx->option.ecc >= 2 && (errors1 < 0 || errors2 < 0))
|
||||
{ // 2nd pass
|
||||
{ // 2nd pass: set packet-IDs
|
||||
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;
|
||||
|
@ -1053,11 +1221,181 @@ static int rs41_ecc(gpx_t *gpx, int frmlen) {
|
|||
errors2 = rs_decode(&gpx->RS, cw2, err_pos2, err_val2);
|
||||
}
|
||||
|
||||
if (gpx->option.ecc >= 3)
|
||||
{ // 3nd pass: erasures ...
|
||||
if (gpx->option.ecc == 4) // set (probably) known bytes (if same rs41)
|
||||
{
|
||||
int crc = 0;
|
||||
float frnb_ts = gpx->ecdat.ts - gpx->ecdat.last_frnb_ts + 0.5f;
|
||||
int frnb = gpx->ecdat.last_frnb + (unsigned)frnb_ts;
|
||||
float calfr_ts = gpx->ecdat.ts - gpx->ecdat.last_calfrm_ts + 0.5f;
|
||||
int calfr = (gpx->ecdat.last_calfrm + (unsigned)calfr_ts) % 51;
|
||||
|
||||
if (errors1 < 0) {
|
||||
// chkCRC
|
||||
crc = check_CRC(gpx, pos_FRAME, pck_FRAME);
|
||||
if (crc)
|
||||
{
|
||||
if ( gpx->id[0] && strncmp(gpx->frame+pos_SondeID, gpx->id, 8) != 0 )
|
||||
{ // raw: gpx->id[0]==0
|
||||
// check gpx->frame+pos_SondeID[1..7] in 0x30..0x39
|
||||
set_bytes(gpx, pos_SondeID, gpx->id, 8, 1, frmset+setcnt);
|
||||
setcnt += 8/2;
|
||||
}
|
||||
|
||||
crc = check_CRC(gpx, pos_FRAME, pck_FRAME);
|
||||
if (crc && gpx->calfrchk[calfr])
|
||||
{
|
||||
// pos_CalData: 0x052
|
||||
// gpx->frame[pos_CalData] == calfr ?
|
||||
if (gpx->frame[pos_CalData] != calfr) {
|
||||
}
|
||||
else { // probably same SondeID
|
||||
//gpx->frame[pos_CalData] = calfr;
|
||||
set_bytes(gpx, pos_CalData+1, gpx->calibytes+calfr*16, 16, 1, frmset+setcnt);
|
||||
setcnt += 16/2;
|
||||
}
|
||||
}
|
||||
|
||||
crc = check_CRC(gpx, pos_FRAME, pck_FRAME);
|
||||
//pos_FrameNb: 0x03B=59
|
||||
if (crc && ((frnb>>8)&0xFF) != gpx->frame[pos_FrameNb+1]) {
|
||||
// last valid check, last_frnb>0 ...
|
||||
if (gpx->ecdat.last_frnb > 0) {
|
||||
gpx->frame[pos_FrameNb+1] = (frnb>>8)&0xFF;
|
||||
frmset[setcnt++] = pos_FrameNb+1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < rs_K; i++) cw1[rs_R+i] = gpx->frame[cfg_rs41.msgpos+2*i ];
|
||||
errors1 = rs_decode(&gpx->RS, cw1, err_pos1, err_val1);
|
||||
}
|
||||
if (errors2 < 0) {
|
||||
// chkCRC
|
||||
crc = check_CRC(gpx, pos_FRAME, pck_FRAME);
|
||||
if (crc)
|
||||
{ // check gpx->frame+pos_SondeID[1..7] in 0x30..0x39
|
||||
if ( gpx->id[0] && strncmp(gpx->frame+pos_SondeID, gpx->id, 8) != 0 )
|
||||
{
|
||||
set_bytes(gpx, pos_SondeID, gpx->id, 8, 2, frmset+setcnt);
|
||||
setcnt += 8/2;
|
||||
}
|
||||
|
||||
crc = check_CRC(gpx, pos_FRAME, pck_FRAME);
|
||||
if (crc && gpx->calfrchk[calfr]) {
|
||||
if (gpx->frame[pos_CalData] == calfr) {
|
||||
set_bytes(gpx, pos_CalData+1, gpx->calibytes+calfr*16, 16, 2, frmset+setcnt);
|
||||
setcnt += 16/2;
|
||||
}
|
||||
}
|
||||
|
||||
crc = check_CRC(gpx, pos_FRAME, pck_FRAME);
|
||||
//pos_FrameNb: 0x03B=59
|
||||
if (crc && (frnb&0xFF) != gpx->frame[pos_FrameNb]) {
|
||||
// last valid check, last_frnb>0 ...
|
||||
if (gpx->ecdat.last_frnb > 0) {
|
||||
gpx->frame[pos_FrameNb] = frnb&0xFF;
|
||||
frmset[setcnt++] = pos_FrameNb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < rs_K; i++) cw2[rs_R+i] = gpx->frame[cfg_rs41.msgpos+2*i+1];
|
||||
errors2 = rs_decode(&gpx->RS, cw2, err_pos2, err_val2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 3rd pass:
|
||||
// 2 RS codewords interleaved: 2x12 errors can be corrected;
|
||||
// CRC is good for list decoding, high rate is not;
|
||||
// burst errors could affect neighboring bytes, however
|
||||
// if AWGN and 24 bit-errors per frame, probability for 2 bit-errors in 1 byte is low;
|
||||
// low byte-score -> erasure , low bit-score -> bit-toggle:
|
||||
// - erasures: 11 + 2/2 = 12 (11 errors and 2 erasures per codeword can be corrected)
|
||||
// 11 + 2 = 13: try combinations of 2 erasures with low byte-scores
|
||||
// - toggle low-score bits
|
||||
|
||||
if (gpx->option.ecc > 2)
|
||||
{
|
||||
int pos_cw = 0;
|
||||
int pos_frm = 0;
|
||||
|
||||
if (errors1 < 0)
|
||||
{
|
||||
for (i = 1; i < Era_max; i++) {
|
||||
pos_frm = gpx->ecdat.sort_idx1[i];
|
||||
if (inFixed(gpx, pos_frm, frmset, setcnt)) continue;
|
||||
if (pos_frm < cfg_rs41.msgpos) pos_cw = pos_frm - cfg_rs41.parpos;
|
||||
else pos_cw = rs_R + (pos_frm - cfg_rs41.msgpos)/2;
|
||||
if (pos_cw < 0 || pos_cw > 254) continue;
|
||||
era_pos[0] = pos_cw;
|
||||
for (j = 0; j < i; j++) {
|
||||
pos_frm = gpx->ecdat.sort_idx1[j];
|
||||
if (inFixed(gpx, pos_frm, frmset, setcnt)) continue;
|
||||
if (pos_frm < cfg_rs41.msgpos) pos_cw = pos_frm - cfg_rs41.parpos;
|
||||
else pos_cw = rs_R + (pos_frm - cfg_rs41.msgpos)/2;
|
||||
if (pos_cw < 0 || pos_cw > 254) continue;
|
||||
era_pos[1] = pos_cw;
|
||||
|
||||
//k = -1;
|
||||
for (k = -1; k < j; k++) // toggle low-score bits
|
||||
{
|
||||
if (k >= 0) {
|
||||
pos_frm = gpx->ecdat.sort_idx1[k];
|
||||
if (inFixed(gpx, pos_frm, frmset, setcnt)) continue;
|
||||
else {
|
||||
if (pos_frm < cfg_rs41.msgpos) pos_cw = pos_frm - cfg_rs41.parpos;
|
||||
else pos_cw = rs_R + (pos_frm - cfg_rs41.msgpos)/2;
|
||||
if (pos_cw < 0 || pos_cw > 254) continue;
|
||||
cw1[pos_cw] ^= gpx->dfrm_bitscore[pos_frm];
|
||||
}
|
||||
}
|
||||
|
||||
errors1 = rs_decode_ErrEra(&gpx->RS, cw1, 2, era_pos, err_pos1, err_val1);
|
||||
if (errors1 >= 0) { j = 256; i = 256; k = 256; } //break;
|
||||
//else if (k >= 0) { cw1[pos_cw] ^= gpx->dfrm_bitscore[pos_frm]; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (errors2 < 0)
|
||||
{
|
||||
for (i = 1; i < Era_max; i++) {
|
||||
pos_frm = gpx->ecdat.sort_idx2[i];
|
||||
if (inFixed(gpx, pos_frm, frmset, setcnt)) continue;
|
||||
if (pos_frm < cfg_rs41.msgpos) pos_cw = pos_frm - cfg_rs41.parpos - rs_R;
|
||||
else pos_cw = rs_R + (pos_frm - cfg_rs41.msgpos)/2;
|
||||
if (pos_cw < 0 || pos_cw > 254) continue;
|
||||
era_pos[0] = pos_cw;
|
||||
for (j = 0; j < i; j++) {
|
||||
pos_frm = gpx->ecdat.sort_idx2[j];
|
||||
if (inFixed(gpx, pos_frm, frmset, setcnt)) continue;
|
||||
if (pos_frm < cfg_rs41.msgpos) pos_cw = pos_frm - cfg_rs41.parpos - rs_R;
|
||||
else pos_cw = rs_R + (pos_frm - cfg_rs41.msgpos)/2;
|
||||
if (pos_cw < 0 || pos_cw > 254) continue;
|
||||
era_pos[1] = pos_cw;
|
||||
|
||||
//k = -1;
|
||||
for (k = -1; k < j; k++) // toggle low-score bits
|
||||
{
|
||||
if (k >= 0) {
|
||||
pos_frm = gpx->ecdat.sort_idx2[k];
|
||||
if (inFixed(gpx, pos_frm, frmset, setcnt)) continue;
|
||||
else {
|
||||
if (pos_frm < cfg_rs41.msgpos) pos_cw = pos_frm - cfg_rs41.parpos - rs_R;
|
||||
else pos_cw = rs_R + (pos_frm - cfg_rs41.msgpos)/2;
|
||||
if (pos_cw < 0 || pos_cw > 254) continue;
|
||||
cw2[pos_cw] ^= gpx->dfrm_bitscore[pos_frm];
|
||||
}
|
||||
}
|
||||
|
||||
errors2 = rs_decode_ErrEra(&gpx->RS, cw2, 2, era_pos, err_pos2, err_val2);
|
||||
if (errors2 >= 0) { j = 256; i = 256; k = 256; } //break;
|
||||
//else if (k >= 0) { cw2[pos_cw] ^= gpx->dfrm_bitscore[pos_frm]; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1109,6 +1447,13 @@ static int prn_ptu(gpx_t *gpx) {
|
|||
fprintf(stdout, " ");
|
||||
if (gpx->T > -273.0) fprintf(stdout, " T=%.1fC ", gpx->T);
|
||||
if (gpx->RH > -0.5) fprintf(stdout, " RH=%.0f%% ", gpx->RH);
|
||||
if (gpx->P > 0.0) {
|
||||
if (gpx->P < 100.0) fprintf(stdout, " P=%.2fhPa ", gpx->P);
|
||||
else fprintf(stdout, " P=%.1fhPa ", gpx->P);
|
||||
}
|
||||
if (gpx->option.ptu == 2) {
|
||||
if (gpx->RH2 > -0.5) fprintf(stdout, " RH2=%.0f%% ", gpx->RH2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1207,7 +1552,7 @@ static int prn_sat3(gpx_t *gpx, int ofs) {
|
|||
}
|
||||
|
||||
static int print_position(gpx_t *gpx, int ec) {
|
||||
int i, j;
|
||||
int i;
|
||||
int err, err0, err1, err2, err3;
|
||||
//int output, out_mask;
|
||||
int encrypted = 0;
|
||||
|
@ -1359,11 +1704,18 @@ static int print_position(gpx_t *gpx, int ec) {
|
|||
fprintf(stdout, "{ \"type\": \"%s\"", "RS41");
|
||||
fprintf(stdout, ", \"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, \"bt\": %d, \"batt\": %.2f",
|
||||
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->vV, gpx->numSV, gpx->conf_cd, gpx->batt );
|
||||
if (gpx->option.ptu && !err0 && gpx->T > -273.0) {
|
||||
fprintf(stdout, ", \"temp\": %.1f", gpx->T );
|
||||
}
|
||||
if (gpx->option.ptu && !err0 && gpx->RH > -0.5) {
|
||||
fprintf(stdout, ", \"humidity\": %.1f", gpx->RH );
|
||||
if (gpx->option.ptu && !err0) {
|
||||
float _RH = gpx->RH;
|
||||
if (gpx->option.ptu == 2) _RH = gpx->RH2;
|
||||
if (gpx->T > -273.0) {
|
||||
fprintf(stdout, ", \"temp\": %.1f", gpx->T );
|
||||
}
|
||||
if (_RH > -0.5) {
|
||||
fprintf(stdout, ", \"humidity\": %.1f", _RH );
|
||||
}
|
||||
if (gpx->P > 0.0) {
|
||||
fprintf(stdout, ", \"pressure\": %.2f", gpx->P );
|
||||
}
|
||||
}
|
||||
if (gpx->aux) { // <=> gpx->xdata[0]!='\0'
|
||||
fprintf(stdout, ", \"aux\": \"%s\"", gpx->xdata );
|
||||
|
@ -1376,6 +1728,11 @@ static int print_position(gpx_t *gpx, int ec) {
|
|||
fprintf(stdout, ", \"encrypted\": false");
|
||||
}
|
||||
}
|
||||
if (gpx->jsn_freq > 0) { // rs41-frequency: gpx->freq
|
||||
int fq_kHz = gpx->jsn_freq;
|
||||
if (gpx->freq > 0) fq_kHz = gpx->freq;
|
||||
fprintf(stdout, ", \"freq\": %d", fq_kHz);
|
||||
}
|
||||
fprintf(stdout, " }\n");
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
|
@ -1450,7 +1807,11 @@ static int print_position(gpx_t *gpx, int ec) {
|
|||
}
|
||||
|
||||
static void print_frame(gpx_t *gpx, int len) {
|
||||
int i, ec = 0, ft;
|
||||
int i, j, ec = 0, ft;
|
||||
int j1 = 0;
|
||||
int j2 = 0;
|
||||
int sort_score_idx[FRAME_LEN];
|
||||
float max_minscore = 0.0;
|
||||
|
||||
gpx->crc = 0;
|
||||
|
||||
|
@ -1466,6 +1827,38 @@ static void print_frame(gpx_t *gpx, int len) {
|
|||
else len = FRAME_LEN; // ft < 0: FRAME_LEN (aux)
|
||||
|
||||
|
||||
for (i = FRAMESTART; i < len; i++) {
|
||||
if (fabs(gpx->ecdat.frm_bytescore[i]) > max_minscore) max_minscore = fabs(gpx->ecdat.frm_bytescore[i]);
|
||||
}
|
||||
max_minscore = floor(max_minscore+1.5);
|
||||
if (gpx->option.ecc > 2) {
|
||||
for (i = 0; i < FRAMESTART; i++) gpx->ecdat.frm_bytescore[i] = max_minscore*2.0; //*sign
|
||||
for (i = len; i < FRAME_LEN; i++) gpx->ecdat.frm_bytescore[i] = max_minscore;
|
||||
}
|
||||
for (i = 0; i < FRAME_LEN; i++) sort_score_idx[i] = i;
|
||||
if (gpx->option.ecc > 2) {
|
||||
for (i = 0; i < FRAME_LEN; i++) {
|
||||
for (j = 0; j < FRAME_LEN-1; j++) {
|
||||
if (fabs(gpx->ecdat.frm_bytescore[sort_score_idx[j+1]]) < fabs(gpx->ecdat.frm_bytescore[sort_score_idx[j]])) {
|
||||
int tmp = sort_score_idx[j+1];
|
||||
sort_score_idx[j+1] = sort_score_idx[j];
|
||||
sort_score_idx[j] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < FRAME_LEN; i++) gpx->ecdat.sort_idx1[i] = i;
|
||||
for (i = 0; i < FRAME_LEN; i++) gpx->ecdat.sort_idx2[i] = i;
|
||||
j1 = 0;
|
||||
j2 = 0;
|
||||
for (i = 0; i < FRAME_LEN; i++) {
|
||||
if (sort_score_idx[i] >= cfg_rs41.parpos && sort_score_idx[i] < cfg_rs41.parpos+ rs_R) gpx->ecdat.sort_idx1[j1++] = sort_score_idx[i];
|
||||
else if (sort_score_idx[i] >= cfg_rs41.parpos+rs_R && sort_score_idx[i] < cfg_rs41.parpos+2*rs_R) gpx->ecdat.sort_idx2[j2++] = sort_score_idx[i];
|
||||
else if (sort_score_idx[i] >= cfg_rs41.msgpos && sort_score_idx[i] % 2 == 0) gpx->ecdat.sort_idx1[j1++] = sort_score_idx[i];
|
||||
else if (sort_score_idx[i] >= cfg_rs41.msgpos && sort_score_idx[i] % 2 == 1) gpx->ecdat.sort_idx2[j2++] = sort_score_idx[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (gpx->option.ecc) {
|
||||
ec = rs41_ecc(gpx, len);
|
||||
}
|
||||
|
@ -1501,6 +1894,7 @@ int main(int argc, char *argv[]) {
|
|||
//int option_inv = 0; // invertiert Signal
|
||||
int option_min = 0;
|
||||
int option_iq = 0;
|
||||
int option_iqdc = 0;
|
||||
int option_lp = 0;
|
||||
int option_dc = 0;
|
||||
int option_bin = 0;
|
||||
|
@ -1509,6 +1903,7 @@ int main(int argc, char *argv[]) {
|
|||
int wavloaded = 0;
|
||||
int sel_wavch = 0; // audio channel: left
|
||||
int rawhex = 0, xorhex = 0;
|
||||
int cfreq = -1;
|
||||
|
||||
FILE *fp;
|
||||
char *fpname = NULL;
|
||||
|
@ -1541,6 +1936,7 @@ int main(int argc, char *argv[]) {
|
|||
gpx_t gpx = {0};
|
||||
|
||||
hdb_t hdb = {0};
|
||||
float softbits[BITS];
|
||||
|
||||
|
||||
#ifdef CYGWIN
|
||||
|
@ -1580,8 +1976,10 @@ int main(int argc, char *argv[]) {
|
|||
else if (strcmp(*argv, "--ecc" ) == 0) { gpx.option.ecc = 1; }
|
||||
else if (strcmp(*argv, "--ecc2") == 0) { gpx.option.ecc = 2; }
|
||||
else if (strcmp(*argv, "--ecc3") == 0) { gpx.option.ecc = 3; }
|
||||
else if (strcmp(*argv, "--ecc4") == 0) { gpx.option.ecc = 4; }
|
||||
else if (strcmp(*argv, "--sat") == 0) { gpx.option.sat = 1; }
|
||||
else if (strcmp(*argv, "--ptu") == 0) { gpx.option.ptu = 1; }
|
||||
else if (strcmp(*argv, "--ptu" ) == 0) { gpx.option.ptu = 1; }
|
||||
else if (strcmp(*argv, "--ptu2") == 0) { gpx.option.ptu = 2; }
|
||||
else if (strcmp(*argv, "--silent") == 0) { gpx.option.slt = 1; }
|
||||
else if (strcmp(*argv, "--ch2") == 0) { sel_wavch = 1; } // right channel (default: 0=left)
|
||||
else if (strcmp(*argv, "--auto") == 0) { gpx.option.aut = 1; }
|
||||
|
@ -1606,6 +2004,7 @@ int main(int argc, char *argv[]) {
|
|||
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, "--iqdc") == 0) { option_iqdc = 1; } // iq-dc removal (iq0,2,3)
|
||||
else if (strcmp(*argv, "--IQ") == 0) { // fq baseband -> IF (rotate from and decimate)
|
||||
double fq = 0.0; // --IQ <fq> , -0.5 < fq < 0.5
|
||||
++argv;
|
||||
|
@ -1634,6 +2033,13 @@ int main(int argc, char *argv[]) {
|
|||
gpx.option.ecc = 2;
|
||||
gpx.option.crc = 1;
|
||||
}
|
||||
else if (strcmp(*argv, "--jsn_cfq") == 0) {
|
||||
int frq = -1; // center frequency / Hz
|
||||
++argv;
|
||||
if (*argv) frq = atoi(*argv); else return -1;
|
||||
if (frq < 300000000) frq = -1;
|
||||
cfreq = frq;
|
||||
}
|
||||
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 if (strcmp(*argv, "-") == 0) {
|
||||
|
@ -1674,6 +2080,8 @@ int main(int argc, char *argv[]) {
|
|||
// init gpx
|
||||
memcpy(gpx.frame, rs41_header_bytes, sizeof(rs41_header_bytes)); // 8 header bytes
|
||||
|
||||
if (cfreq > 0) gpx.jsn_freq = (cfreq+500)/1000;
|
||||
|
||||
|
||||
#ifdef EXT_FSK
|
||||
if (!option_bin && !option_softin) {
|
||||
|
@ -1703,6 +2111,11 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
if (cfreq > 0) {
|
||||
int fq_kHz = (cfreq - dsp.xlt_fq*pcm.sr + 500)/1e3;
|
||||
gpx.jsn_freq = fq_kHz;
|
||||
}
|
||||
|
||||
// rs41: BT=0.5, h=0.8,1.0 ?
|
||||
symlen = 1;
|
||||
|
||||
|
@ -1723,6 +2136,7 @@ int main(int argc, char *argv[]) {
|
|||
dsp.BT = 0.5; // bw/time (ISI) // 0.3..0.5
|
||||
dsp.h = 0.6; //0.7; // 0.7..0.8? modulation index abzgl. BT
|
||||
dsp.opt_iq = option_iq;
|
||||
dsp.opt_iqdc = option_iqdc;
|
||||
dsp.opt_lp = option_lp;
|
||||
dsp.lpIQ_bw = lpIQ_bw; // 7.4e3 (6e3..8e3) // IF lowpass bandwidth
|
||||
dsp.lpFM_bw = 6e3; // FM audio lowpass
|
||||
|
@ -1795,12 +2209,20 @@ int main(int argc, char *argv[]) {
|
|||
{
|
||||
if (option_bin) {
|
||||
bitQ = fgetc(fp);
|
||||
if (bitQ != EOF) bit = bitQ & 0x1;
|
||||
if (bitQ != EOF) {
|
||||
bit = bitQ & 0x1;
|
||||
hsbit.hb = bit;
|
||||
hsbit.sb = 2*bit-1;
|
||||
}
|
||||
}
|
||||
else if (option_softin) {
|
||||
float s = 0.0;
|
||||
bitQ = f32soft_read(fp, &s);
|
||||
if (bitQ != EOF) bit = (s>=0.0); // no soft decoding
|
||||
if (bitQ != EOF) {
|
||||
bit = (s>=0.0);
|
||||
hsbit.hb = bit;
|
||||
hsbit.sb = s;
|
||||
}
|
||||
}
|
||||
else {
|
||||
float bl = -1;
|
||||
|
@ -1808,7 +2230,7 @@ int main(int argc, char *argv[]) {
|
|||
//bitQ = read_slbit(&dsp, &bit, 0, bitofs, bitpos, bl, 0); // symlen=1
|
||||
bitQ = read_softbit2p(&dsp, &hsbit, 0, bitofs, bitpos, bl, 0, &hsbit1); // symlen=1
|
||||
bit = hsbit.hb;
|
||||
if (gpx.option.ecc == 3) bit = (hsbit.sb+hsbit1.sb)>=0;
|
||||
if (gpx.option.ecc >= 3) bit = (hsbit.sb+hsbit1.sb)>=0;
|
||||
|
||||
if (bitpos < FRAME_LEN*BITS && hsbit.sb*hsbit1.sb < 0) {
|
||||
difbyte |= 1<<b8pos;
|
||||
|
@ -1816,20 +2238,33 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
if ( bitQ == EOF ) break; // liest 2x EOF
|
||||
|
||||
softbits[b8pos] = hsbit.sb;
|
||||
|
||||
if (gpx.option.inv) bit ^= 1;
|
||||
|
||||
bitpos += 1;
|
||||
bitbuf[b8pos] = bit;
|
||||
b8pos++;
|
||||
if (b8pos == BITS) {
|
||||
int j, j0 = 0;
|
||||
float min_score_byte = softbits[0];
|
||||
for (j = 1; j < BITS; j++) {
|
||||
if (fabs(softbits[j]) < fabs(min_score_byte)) {
|
||||
min_score_byte = softbits[j];
|
||||
j0 = j;
|
||||
}
|
||||
}
|
||||
gpx.ecdat.frm_bytescore[byte_count] = min_score_byte;
|
||||
b8pos = 0;
|
||||
byte = bits2byte(bitbuf);
|
||||
gpx.frame[byte_count] = byte ^ mask[byte_count % MASK_LEN];
|
||||
gpx.dfrm[byte_count] = difbyte;
|
||||
//gpx.dfrm_shiftsgn[byte_count] = difbyte;
|
||||
gpx.dfrm_bitscore[byte_count] = (1<<j0);
|
||||
difbyte = 0;
|
||||
byte_count++;
|
||||
}
|
||||
}
|
||||
gpx.ecdat.ts = dsp.mv_pos/(float)dsp.sr;
|
||||
|
||||
print_frame(&gpx, byte_count);
|
||||
byte_count = FRAMESTART;
|
||||
|
|
|
@ -117,7 +117,8 @@ typedef struct {
|
|||
int sats[4];
|
||||
double dop;
|
||||
ui16_t conf_kt; // kill timer (sec)
|
||||
int freq;
|
||||
int freq; // freq/kHz (RS92)
|
||||
int jsn_freq; // freq/kHz (SDR)
|
||||
ui32_t crc;
|
||||
ui8_t frame[FRAME_LEN]; // { 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x10}
|
||||
unsigned short aux[4];
|
||||
|
@ -1184,6 +1185,11 @@ static int print_position(gpx_t *gpx, int ec) { // GPS-Hoehe ueber Ellipsoid
|
|||
if ((gpx->crc & crc_AUX)==0 && (gpx->aux[0] != 0 || gpx->aux[1] != 0 || gpx->aux[2] != 0 || gpx->aux[3] != 0)) {
|
||||
fprintf(stdout, ", \"aux\": \"%04x%04x%04x%04x\"", gpx->aux[0], gpx->aux[1], gpx->aux[2], gpx->aux[3]);
|
||||
}
|
||||
if (gpx->jsn_freq > 0) { // rs92-frequency: gpx->freq
|
||||
int fq_kHz = gpx->jsn_freq;
|
||||
//if (gpx->freq > 0) fq_kHz = gpx->freq; // L-band: option.ngp ?
|
||||
fprintf(stdout, ", \"freq\": %d", fq_kHz);
|
||||
}
|
||||
fprintf(stdout, " }\n");
|
||||
}
|
||||
}
|
||||
|
@ -1237,6 +1243,7 @@ int main(int argc, char *argv[]) {
|
|||
int option_der = 0; // linErr
|
||||
int option_min = 0;
|
||||
int option_iq = 0;
|
||||
int option_iqdc = 0;
|
||||
int option_lp = 0;
|
||||
int option_dc = 0;
|
||||
int option_softin = 0;
|
||||
|
@ -1244,6 +1251,7 @@ int main(int argc, char *argv[]) {
|
|||
int sel_wavch = 0; // audio channel: left
|
||||
int spike = 0;
|
||||
int fileloaded = 0;
|
||||
int cfreq = -1;
|
||||
|
||||
char bitbuf[BITS];
|
||||
int bitpos = 0,
|
||||
|
@ -1389,6 +1397,13 @@ int main(int argc, char *argv[]) {
|
|||
gpx.option.crc = 1;
|
||||
gpx.gps.opt_vel = 4;
|
||||
}
|
||||
else if (strcmp(*argv, "--jsn_cfq") == 0) {
|
||||
int frq = -1; // center frequency / Hz
|
||||
++argv;
|
||||
if (*argv) frq = atoi(*argv); else return -1;
|
||||
if (frq < 300000000) frq = -1;
|
||||
cfreq = frq;
|
||||
}
|
||||
else if (strcmp(*argv, "--spike") == 0) { spike = 1; }
|
||||
else if (strcmp(*argv, "--ch2") == 0) { sel_wavch = 1; } // right channel (default: 0=left)
|
||||
else if (strcmp(*argv, "--softin") == 0) { option_softin = 1; } // float32 soft input
|
||||
|
@ -1411,6 +1426,7 @@ int main(int argc, char *argv[]) {
|
|||
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, "--iqdc") == 0) { option_iqdc = 1; } // iq-dc removal (iq0,2,3)
|
||||
else if (strcmp(*argv, "--IQ") == 0) { // fq baseband -> IF (rotate from and decimate)
|
||||
double fq = 0.0; // --IQ <fq> , -0.5 < fq < 0.5
|
||||
++argv;
|
||||
|
@ -1486,6 +1502,8 @@ int main(int argc, char *argv[]) {
|
|||
// init gpx
|
||||
memcpy(gpx.frame, rs92_header_bytes, sizeof(rs92_header_bytes)); // 6 header bytes
|
||||
|
||||
if (cfreq > 0) gpx.jsn_freq = (cfreq+500)/1000;
|
||||
|
||||
|
||||
#ifdef EXT_FSK
|
||||
if (!option_softin) {
|
||||
|
@ -1513,6 +1531,11 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
}
|
||||
|
||||
if (cfreq > 0) {
|
||||
int fq_kHz = (cfreq - dsp.xlt_fq*pcm.sr + 500)/1e3;
|
||||
gpx.jsn_freq = fq_kHz;
|
||||
}
|
||||
|
||||
// rs92-sgp: BT=0.5, h=1.0 ?
|
||||
symlen = 2;
|
||||
|
||||
|
@ -1533,6 +1556,7 @@ int main(int argc, char *argv[]) {
|
|||
dsp.BT = 0.5; // bw/time (ISI) // 0.3..0.5
|
||||
dsp.h = 0.8; // 1.0 modulation index abzgl. BT
|
||||
dsp.opt_iq = option_iq;
|
||||
dsp.opt_iqdc = option_iqdc;
|
||||
dsp.opt_lp = option_lp;
|
||||
dsp.lpIQ_bw = 8e3; // IF lowpass bandwidth
|
||||
dsp.lpFM_bw = 6e3; // FM audio lowpass
|
||||
|
|
Ładowanie…
Reference in New Issue