Pass around ss_iq and ss_power paths. Update DFM decoder

pull/638/head
Mark Jessop 2022-05-14 17:29:15 +09:30
rodzic 258d48b3cb
commit 7e04b212f9
9 zmienionych plików z 307 dodań i 89 usunięć

Wyświetl plik

@ -166,6 +166,8 @@ def start_scanner():
# Network SDR Options
sdr_hostname=config["sdr_hostname"],
sdr_port=config["sdr_port"],
ss_iq_path=config["ss_iq_path"],
ss_power_path=config["ss_power_path"],
rtl_power_path=config["sdr_power"],
rtl_fm_path=config["sdr_fm"],
rtl_device_idx=_device_idx,
@ -242,6 +244,7 @@ def start_decoder(freq, sonde_type):
# Network SDR Options
sdr_hostname=config["sdr_hostname"],
sdr_port=config["sdr_port"],
ss_iq_path=config["ss_iq_path"],
# RTLSDR Options
rtl_fm_path=config["sdr_fm"],
rtl_device_idx=_device_idx,

Wyświetl plik

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

Wyświetl plik

@ -76,6 +76,8 @@ def read_auto_rx_config(filename, no_sdr_test=False):
"sdr_port": 5555,
"sdr_fm": "rtl_fm",
"sdr_power": "rtl_power",
"ss_iq_path": "./ss_iq",
"ss_power_path": "./ss_power",
"sdr_quantity": 1,
# Search Parameters
"min_freq": 400.4,
@ -693,11 +695,14 @@ def read_auto_rx_config(filename, no_sdr_test=False):
auto_rx_config["sdr_type"] = config.get("sdr", "sdr_type")
auto_rx_config["sdr_hostname"] = config.get("sdr", "sdr_hostname")
auto_rx_config["sdr_port"] = config.getint("sdr", "sdr_port")
auto_rx_config["ss_iq_path"] = config.get("advanced", "ss_iq_path")
auto_rx_config["ss_power_path"] = config.get("advanced", "ss_power_path")
except:
# Switch this to warning on release...
logging.debug(
"Config - Did not find sdr_type option, using defaults."
"Config - Did not find new sdr_type and associated options, defaulting to RTLSDR operation."
)
auto_rx_config["sdr_type"] = "RTLSDR"
# If we are being called as part of a unit test, just return the config now.
@ -747,7 +752,9 @@ def read_auto_rx_config(filename, no_sdr_test=False):
_sdr_ok = test_sdr(
sdr_type=auto_rx_config["sdr_type"],
sdr_hostname=auto_rx_config["sdr_hostname"],
sdr_port=auto_rx_config["sdr_port"]
sdr_port=auto_rx_config["sdr_port"],
ss_iq_path=auto_rx_config["ss_iq_path"],
ss_power_path=auto_rx_config["ss_power_path"],
)
if not _sdr_ok:

Wyświetl plik

@ -125,6 +125,7 @@ class SondeDecoder(object):
sdr_type="RTLSDR",
sdr_hostname="localhost",
sdr_port=12345,
ss_iq_path="./ss_iq",
rs_path="./",
rtl_fm_path="rtl_fm",
rtl_device_idx=0,
@ -190,6 +191,7 @@ class SondeDecoder(object):
self.sdr_hostname = sdr_hostname
self.sdr_port = sdr_port
self.ss_iq_path = ss_iq_path
self.rs_path = rs_path
self.rtl_fm_path = rtl_fm_path
@ -260,7 +262,8 @@ class SondeDecoder(object):
self.sdr_type,
rtl_device_idx = self.rtl_device_idx,
sdr_hostname = self.sdr_hostname,
sdr_port = self.sdr_port
sdr_port = self.sdr_port,
ss_iq_path = self.ss_iq_path
)
if not _sdr_ok:
@ -519,6 +522,7 @@ class SondeDecoder(object):
sample_rate = _sample_rate,
sdr_hostname = self.sdr_hostname,
sdr_port = self.sdr_port,
ss_iq_path = self.ss_iq_path,
rtl_device_idx = self.rtl_device_idx,
ppm = self.ppm,
gain = self.gain,
@ -543,6 +547,7 @@ class SondeDecoder(object):
sample_rate = _sample_rate,
sdr_hostname = self.sdr_hostname,
sdr_port = self.sdr_port,
ss_iq_path = self.ss_iq_path,
rtl_device_idx = self.rtl_device_idx,
ppm = self.ppm,
gain = self.gain,
@ -569,6 +574,7 @@ class SondeDecoder(object):
sample_rate = _sample_rate,
sdr_hostname = self.sdr_hostname,
sdr_port = self.sdr_port,
ss_iq_path = self.ss_iq_path,
rtl_device_idx = self.rtl_device_idx,
ppm = self.ppm,
gain = self.gain,
@ -604,6 +610,7 @@ class SondeDecoder(object):
sample_rate = _sample_rate,
sdr_hostname = self.sdr_hostname,
sdr_port = self.sdr_port,
ss_iq_path = self.ss_iq_path,
rtl_device_idx = self.rtl_device_idx,
ppm = self.ppm,
gain = self.gain,
@ -731,6 +738,7 @@ class SondeDecoder(object):
sample_rate = _sample_rate,
sdr_hostname = self.sdr_hostname,
sdr_port = self.sdr_port,
ss_iq_path = self.ss_iq_path,
rtl_device_idx = self.rtl_device_idx,
ppm = self.ppm,
gain = self.gain,
@ -804,6 +812,7 @@ class SondeDecoder(object):
sample_rate = _sample_rate,
sdr_hostname = self.sdr_hostname,
sdr_port = self.sdr_port,
ss_iq_path = self.ss_iq_path,
rtl_device_idx = self.rtl_device_idx,
ppm = self.ppm,
gain = self.gain,
@ -853,6 +862,7 @@ class SondeDecoder(object):
sample_rate = _sample_rate,
sdr_hostname = self.sdr_hostname,
sdr_port = self.sdr_port,
ss_iq_path = self.ss_iq_path,
rtl_device_idx = self.rtl_device_idx,
ppm = self.ppm,
gain = self.gain,
@ -903,6 +913,7 @@ class SondeDecoder(object):
sample_rate = _sample_rate,
sdr_hostname = self.sdr_hostname,
sdr_port = self.sdr_port,
ss_iq_path = self.ss_iq_path,
rtl_device_idx = self.rtl_device_idx,
ppm = self.ppm,
gain = self.gain,
@ -943,6 +954,7 @@ class SondeDecoder(object):
sample_rate = _sample_rate,
sdr_hostname = self.sdr_hostname,
sdr_port = self.sdr_port,
ss_iq_path = self.ss_iq_path,
rtl_device_idx = self.rtl_device_idx,
ppm = self.ppm,
gain = self.gain,
@ -981,6 +993,7 @@ class SondeDecoder(object):
sample_rate = _sample_rate,
sdr_hostname = self.sdr_hostname,
sdr_port = self.sdr_port,
ss_iq_path = self.ss_iq_path,
rtl_device_idx = self.rtl_device_idx,
ppm = self.ppm,
gain = self.gain,
@ -1021,6 +1034,7 @@ class SondeDecoder(object):
sample_rate = _sample_rate,
sdr_hostname = self.sdr_hostname,
sdr_port = self.sdr_port,
ss_iq_path = self.ss_iq_path,
rtl_device_idx = self.rtl_device_idx,
ppm = self.ppm,
gain = self.gain,
@ -1060,6 +1074,7 @@ class SondeDecoder(object):
sample_rate = _sample_rate,
sdr_hostname = self.sdr_hostname,
sdr_port = self.sdr_port,
ss_iq_path = self.ss_iq_path,
rtl_device_idx = self.rtl_device_idx,
ppm = self.ppm,
gain = self.gain,
@ -1104,6 +1119,7 @@ class SondeDecoder(object):
sample_rate = _sample_rate,
sdr_hostname = self.sdr_hostname,
sdr_port = self.sdr_port,
ss_iq_path = self.ss_iq_path,
rtl_device_idx = self.rtl_device_idx,
ppm = self.ppm,
gain = self.gain,

Wyświetl plik

@ -236,6 +236,7 @@ def detect_sonde(
sdr_type="RTLSDR",
sdr_hostname="localhost",
sdr_port=5555,
ss_iq_path = "./ss_iq",
rtl_fm_path="rtl_fm",
rtl_device_idx=0,
ppm=0,
@ -330,7 +331,8 @@ def detect_sonde(
gain = gain,
bias = bias,
sdr_hostname = sdr_hostname,
sdr_port = sdr_port
sdr_port = sdr_port,
ss_iq_path = ss_iq_path
)
# rx_test_command = (
@ -626,6 +628,8 @@ class SondeScanner(object):
sdr_type="RTLSDR",
sdr_hostname="localhost",
sdr_port=5555,
ss_iq_path = "./ss_iq",
ss_power_path = "./ss_power",
rtl_power_path="rtl_power",
rtl_fm_path="rtl_fm",
@ -713,6 +717,8 @@ class SondeScanner(object):
self.sdr_hostname = sdr_hostname
self.sdr_port = sdr_port
self.ss_iq_path = ss_iq_path
self.ss_power_path = ss_power_path
self.rtl_power_path = rtl_power_path
self.rtl_fm_path = rtl_fm_path
@ -752,7 +758,8 @@ class SondeScanner(object):
self.sdr_type,
rtl_device_idx = self.rtl_device_idx,
sdr_hostname = self.sdr_hostname,
sdr_port = self.sdr_port
sdr_port = self.sdr_port,
ss_iq_path = self.ss_iq_path
)
if not _sdr_ok:
@ -813,7 +820,8 @@ class SondeScanner(object):
self.sdr_type,
rtl_device_idx = self.rtl_device_idx,
sdr_hostname = self.sdr_hostname,
sdr_port = self.sdr_port
sdr_port = self.sdr_port,
ss_iq_path = self.ss_iq_path
)
if not _sdr_ok:
@ -892,7 +900,8 @@ class SondeScanner(object):
gain=self.gain,
bias=self.bias,
sdr_hostname=self.sdr_hostname,
sdr_port=self.sdr_port
sdr_port=self.sdr_port,
ss_power_path = self.ss_power_path
)
# Exit opportunity.
@ -1058,6 +1067,7 @@ class SondeScanner(object):
sdr_type=self.sdr_type,
sdr_hostname=self.sdr_hostname,
sdr_port=self.sdr_port,
ss_iq_path = self.ss_iq_path,
rtl_fm_path=self.rtl_fm_path,
rtl_device_idx=self.rtl_device_idx,
ppm=self.ppm,

Wyświetl plik

@ -19,7 +19,9 @@ def test_sdr(
sdr_type: str,
rtl_device_idx = "0",
sdr_hostname = "",
sdr_port = 5555
sdr_port = 5555,
ss_iq_path = "./ss_iq",
ss_power_path = "./ss_power"
):
"""
Test the prescence / functionality of a SDR.
@ -33,6 +35,9 @@ def test_sdr(
sdr_hostname (str): Hostname of KA9Q Server
sdr_port (int): Port number of KA9Q Server
Arguments for SpyServer Client:
ss_iq_path (str): Path to spyserver IQ client utility.
ss_power_path (str): Path to spyserver power utility.
"""
if sdr_type == "RTLSDR":
@ -57,14 +62,13 @@ def test_sdr(
elif sdr_type == "SpyServer":
# Test connectivity to a SpyServer by trying to grab some samples.
if not os.path.isfile('ss_iq'):
if not os.path.isfile(ss_iq_path):
logging.critical("Could not find ss_iq binary! This may need to be compiled.")
return False
_cmd = (
f"timeout 10 " # Add a timeout, because connections to non-existing IPs seem to block.
f"./ss_iq "
f"{ss_iq_path} "
f"-f 401500000 "
f"-s 48000 "
f"-r {sdr_hostname} -q {sdr_port} -n 48000 - > /dev/null 2> /dev/null"
@ -155,7 +159,8 @@ def get_sdr_iq_cmd(
gain = None,
bias = False,
sdr_hostname = "",
sdr_port = 5555
sdr_port = 5555,
ss_iq_path = "./ss_iq"
):
"""
Get a command-line argument to get IQ (signed 16-bit) from a SDR
@ -177,6 +182,9 @@ def get_sdr_iq_cmd(
sdr_hostname (str): Hostname of KA9Q Server
sdr_port (int): Port number of KA9Q Server
Arguments for SpyServer Client:
ss_iq_path (str): Path to spyserver IQ client utility.
"""
if sdr_type == "RTLSDR":
@ -201,7 +209,7 @@ def get_sdr_iq_cmd(
if sdr_type == "SpyServer":
_cmd = (
f"./ss_iq "
f"{ss_iq_path} "
f"-f {frequency} "
f"-s {int(sample_rate)} "
f"-r {sdr_hostname} -q {sdr_port} - 2>/dev/null|"
@ -361,7 +369,8 @@ def get_power_spectrum(
gain = None,
bias = False,
sdr_hostname = "",
sdr_port = 5555
sdr_port = 5555,
ss_power_path = "./ss_power"
):
"""
Get power spectral density data from a SDR.
@ -376,8 +385,8 @@ def get_power_spectrum(
integration_time (int): Integration time in seconds.
Arguments for RTLSDRs:
rtl_device_idx (str) - Device ID for a RTLSDR
rtl_power_path (str) - Path to rtl_power. Defaults to just "rtl_power"
rtl_device_idx (str): Device ID for a RTLSDR
rtl_power_path (str): Path to rtl_power. Defaults to just "rtl_power"
ppm (int): SDR Frequency accuracy correction, in ppm.
gain (int): SDR Gain setting, in dB. A gain setting of -1 enables the RTLSDR AGC.
bias (bool): If True, enable the bias tee on the SDR.
@ -386,6 +395,10 @@ def get_power_spectrum(
sdr_hostname (str): Hostname of KA9Q Server
sdr_port (int): Port number of KA9Q Server
Arguments for SpyServer Client:
ss_power_path (str): Path to spyserver power utility.
ss_iq_path (str): Path to spyserver IQ client utility.
Returns:
(freq, power, step) Tuple
@ -511,7 +524,7 @@ def get_power_spectrum(
_frequency_centre = int(frequency_start + (frequency_stop-frequency_start)/2.0)
_ss_power_cmd = (
f"{_timeout_cmd} ./ss_power "
f"{_timeout_cmd} {ss_power_path} "
f"-f {_frequency_centre} "
f"-i {integration_time} -1 "
f"-r {sdr_hostname} -q {sdr_port} "

Wyświetl plik

@ -61,6 +61,7 @@ class SondehubUploader(object):
"""
self.upload_rate = upload_rate
self.actual_upload_rate = upload_rate # Allow for the upload rate to be tweaked...
self.upload_timeout = upload_timeout
self.upload_retries = upload_retries
self.user_callsign = user_callsign
@ -69,6 +70,8 @@ class SondehubUploader(object):
self.contact_email = contact_email
self.user_position_update_rate = user_position_update_rate
self.slower_uploads = False
if self.user_position is None:
self.inhibit_upload = True
else:
@ -175,6 +178,10 @@ class SondehubUploader(object):
if "dfmcode" in telemetry:
_output["dfmcode"] = telemetry["dfmcode"]
# We are handling DFM packets. We need a few more of these in an upload
# for our packets to pass the Sondehub z-check.
self.slower_uploads = True
elif telemetry["type"].startswith("M10") or telemetry["type"].startswith("M20"):
_output["manufacturer"] = "Meteomodem"
_output["type"] = telemetry["type"]
@ -310,8 +317,13 @@ class SondehubUploader(object):
) > self.user_position_update_rate * 3600:
self.station_position_upload()
# If we are encounting DFM packets we need to upload at a slower rate so
# that we have enough uploaded packets to pass z-check.
if self.slower_uploads:
self.actual_upload_rate = min(30,int(self.upload_rate*1.5))
# Sleep while waiting for some new data.
for i in range(self.upload_rate):
for i in range(self.actual_upload_rate):
time.sleep(1)
if self.input_processing_running == False:
break

Wyświetl plik

@ -14,39 +14,10 @@
################
[sdr]
#
# SDR Type
#
# RTLSDR - Use one or more RTLSDRs
#
# EXPERIMENTAL / NOT IMPLEMENTED options:
# KA9Q - Use a KA9Q SDR Server
# SpyServer - Use a SpyServer
#
sdr_type = RTLSDR
#
# Number of SDRs or SDR Connection Threads to use
#
# If SDR type is either KA9Q or SpyServer, this defines the maximum number of parallel
# decoding/scan tasks.
# If SDR type is set to RTLSDR above, then this number is the number of individual RTLSDRs
# that will be used, eith each RTLSDR allocated a scan or decode task.
# Number of RTLSDRs to use.
# If more than one RTLSDR is in use, multiple [sdr_X] sections must be populated below
#
sdr_quantity = 1
#
# Network SDR Connection Details
#
# If using either a KA9Q or SpyServer network server, the hostname and port
# of the server needs to be defined below. Usually this will be running on the
# same machine as auto_rx, so the defaults are usually fine.
#
sdr_hostname = localhost
sdr_port = 5555
#
# Individual RTLSDR Settings
#
@ -511,6 +482,11 @@ payload_id_valid = 3
sdr_fm_path = rtl_fm
sdr_power_path = rtl_power
# Paths to SpyServer client (https://github.com/miweber67/spyserver_client) utilities, for experimental SpyServer Client support
# At the moment we assume these are in the auto_rx directory.
ss_iq_path = ./ss_iq
ss_power_path = ./ss_power
################################
# DEMODULATOR / DECODER TWEAKS #

Wyświetl plik

@ -63,6 +63,7 @@ typedef struct {
i8_t ecc; // Hamming ECC
i8_t sat; // GPS sat data
i8_t ptu; // PTU: temperature
i8_t aux; // decode xdata
i8_t inv;
i8_t aut;
i8_t jsn; // JSON output (auto_rx)
@ -91,6 +92,7 @@ typedef struct {
} gpsdat_t;
#define BITFRAME_LEN 280
#define XDATA_LEN 26 // (2+4*6)
typedef struct {
int frnr;
@ -102,13 +104,17 @@ typedef struct {
int std; int min; float sek;
double lat; double lon; double alt;
double dir; double horiV; double vertV;
double lat2; double lon2; double alt2;
double dir2; double horiV2; double vertV2;
//float T;
float Rf;
float _frmcnt;
float meas24[9];
float status[2];
float status[3];
ui32_t val24[9];
ui8_t cfgchk24[9];
i8_t posmode;
ui8_t xdata[XDATA_LEN]; // 2+4*6
int cfgchk;
char sonde_id[16]; // "ID__:xxxxxxxx\0\0"
hsbit_t frame[BITFRAME_LEN+4]; // char frame_bits[BITFRAME_LEN+4];
@ -341,6 +347,7 @@ static int dat_out(gpx_t *gpx, ui8_t *dat_bits, int ec) {
int frnr = 0;
int msek = 0;
int lat = 0, lon = 0, alt = 0;
int mode = 2;
int nib;
int dvv; // signed/unsigned 16bit
@ -369,47 +376,135 @@ static int dat_out(gpx_t *gpx, ui8_t *dat_bits, int ec) {
if (fr_id == 0) {
//start = 0x1000;
mode = bits2val(dat_bits+16, 8);
if (mode > 1 && mode < 5) gpx->posmode = mode;
else gpx->posmode = -1;//2
frnr = bits2val(dat_bits+24, 8);
gpx->frnr = frnr;
}
if (fr_id == 1) {
// 00..31: GPS-Sats in solution (bitmap)
gpx->gps.prn = bits2val(dat_bits, 32); // SV/PRN used
msek = bits2val(dat_bits+32, 16); // UTC (= GPS - 18sec ab 1.1.2017)
gpx->sek = msek/1000.0;
}
if (gpx->posmode <= 2)
{
if (fr_id == 0) {
}
if (fr_id == 1) {
// 00..31: GPS-Sats in solution (bitmap)
gpx->gps.prn = bits2val(dat_bits, 32); // SV/PRN used
msek = bits2val(dat_bits+32, 16); // UTC (= GPS - 18sec ab 1.1.2017)
gpx->sek = msek/1000.0;
}
if (fr_id == 2) {
lat = bits2val(dat_bits, 32);
gpx->lat = lat/1e7;
dvv = (short)bits2val(dat_bits+32, 16); // (short)? zusammen mit dir sollte unsigned sein
gpx->horiV = dvv/1e2;
}
if (fr_id == 2) {
lat = bits2val(dat_bits, 32);
gpx->lat = lat/1e7;
dvv = (short)bits2val(dat_bits+32, 16); // (short)? zusammen mit dir sollte unsigned sein
gpx->horiV = dvv/1e2;
}
if (fr_id == 3) {
lon = bits2val(dat_bits, 32);
gpx->lon = lon/1e7;
dvv = bits2val(dat_bits+32, 16) & 0xFFFF; // unsigned
gpx->dir = dvv/1e2;
}
if (fr_id == 3) {
lon = bits2val(dat_bits, 32);
gpx->lon = lon/1e7;
dvv = bits2val(dat_bits+32, 16) & 0xFFFF; // unsigned
gpx->dir = dvv/1e2;
}
if (fr_id == 4) {
alt = bits2val(dat_bits, 32);
gpx->alt = alt/1e2;
dvv = (short)bits2val(dat_bits+32, 16); // signed
gpx->vertV = dvv/1e2;
}
if (fr_id == 4) {
alt = bits2val(dat_bits, 32);
gpx->alt = alt/1e2; // GPS/Ellipsoid
dvv = (short)bits2val(dat_bits+32, 16); // signed
gpx->vertV = dvv/1e2;
}
if (fr_id == 5) {
short dMSL = bits2val(dat_bits, 16);
gpx->gps.dMSL = dMSL/1e2;
}
if (fr_id == 5) {
short dMSL = bits2val(dat_bits, 16);
gpx->gps.dMSL = dMSL/1e2;
}
if (fr_id == 6) { // sat data
}
if (fr_id == 6) { // sat data
}
if (fr_id == 7) { // sat data
if (fr_id == 7) { // sat data
}
}
else if (gpx->posmode == 3) // cf. dfm-ts20170801.c
{
if (fr_id == 0) {
msek = bits2val(dat_bits, 16);
gpx->sek = msek/1000.0;
dvv = (short)bits2val(dat_bits+32, 16);
gpx->horiV = dvv/1e2;
}
if (fr_id == 1) {
lat = bits2val(dat_bits, 32);
gpx->lat = lat/1e7;
dvv = bits2val(dat_bits+32, 16) & 0xFFFF; // unsigned
gpx->dir = dvv/1e2;
}
if (fr_id == 2) {
lon = bits2val(dat_bits, 32);
gpx->lon = lon/1e7;
dvv = (short)bits2val(dat_bits+32, 16); // signed
gpx->vertV = dvv/1e2;
}
if (fr_id == 3) {
alt = bits2val(dat_bits, 32);
gpx->alt = alt/1e2; // mode>2: alt/MSL
}
if (fr_id == 5) {
lat = bits2val(dat_bits, 32);
gpx->lat2 = lat/1e7;
dvv = (short)bits2val(dat_bits+32, 16); // (short)? zusammen mit dir sollte unsigned sein
gpx->horiV2 = dvv/1e2;
}
if (fr_id == 6) {
lon = bits2val(dat_bits, 32);
gpx->lon2 = lon/1e7;
dvv = bits2val(dat_bits+32, 16) & 0xFFFF; // unsigned
gpx->dir2 = dvv/1e2;
}
if (fr_id == 7) {
alt = bits2val(dat_bits, 32);
gpx->alt2 = alt/1e2;
dvv = (short)bits2val(dat_bits+32, 16); // signed
gpx->vertV2 = dvv/1e2;
}
}
else if (gpx->posmode == 4) // XDATA: cf. DF9DQ https://github.com/einergehtnochrein/ra-firmware/tree/master/src/dfm
{
if (fr_id == 0) {
msek = bits2val(dat_bits, 16);
gpx->sek = msek/1000.0;
dvv = (short)bits2val(dat_bits+32, 16);
gpx->horiV = dvv/1e2;
}
if (fr_id == 1) {
lat = bits2val(dat_bits, 32);
gpx->lat = lat/1e7;
dvv = bits2val(dat_bits+32, 16) & 0xFFFF; // unsigned
gpx->dir = dvv/1e2;
}
if (fr_id == 2) {
lon = bits2val(dat_bits, 32);
gpx->lon = lon/1e7;
dvv = (short)bits2val(dat_bits+32, 16); // signed
gpx->vertV = dvv/1e2;
}
if (fr_id == 3) {
alt = bits2val(dat_bits, 32);
gpx->alt = alt/1e2; // mode>2: alt/MSL
for (int j = 0; j < 2; j++) gpx->xdata[j] = bits2val(dat_bits+32+8*j, 8);
}
if (fr_id > 3 && fr_id < 8) {
int ofs = fr_id - 4;
for (int j = 0; j < 6; j++) gpx->xdata[2+6*ofs+j] = bits2val(dat_bits+8*j, 8);
}
}
if (fr_id == 8) {
@ -557,7 +652,7 @@ static float get_Temp4(gpx_t *gpx) { // meas[0..4]
// [ 30.0 , 0.82845 , 3.7 ]
// [ 35.0 , 0.68991 , 3.6 ]
// [ 40.0 , 0.57742 , 3.5 ]
// -> SteinhartHart coefficients (polyfit):
// -> Steinhart-Hart coefficients (polyfit):
float p0 = 1.09698417e-03,
p1 = 2.39564629e-04,
p2 = 2.48821437e-06,
@ -588,6 +683,7 @@ static int reset_cfgchk(gpx_t *gpx) {
for (j = 0; j < 9; j++) gpx->cfgchk24[j] = 0;
gpx->cfgchk = 0;
gpx->ptu_out = 0;
//gpx->gps.dMSL = 0;
return 0;
}
@ -725,6 +821,7 @@ static int conf_out(gpx_t *gpx, ui8_t *conf_bits, int ec) {
ui8_t ofs = 0;
if (gpx->sensortyp0xC == 'P') ofs = 2;
//
// c0xxxx0 inner 16 bit
if (conf_id == 0x5+ofs) { // voltage
val = bits2val(conf_bits+8, 4*4);
gpx->status[0] = val/1000.0;
@ -733,10 +830,15 @@ static int conf_out(gpx_t *gpx, ui8_t *conf_bits, int ec) {
val = bits2val(conf_bits+8, 4*4);
gpx->status[1] = val/100.0;
}
if (conf_id == 0x7+ofs && gpx->Rf > 300e3) { // DFM17 counter
val = bits2val(conf_bits+8, 4*4);
gpx->status[2] = val/1.0; // sec counter
}
}
else {
gpx->status[0] = 0;
gpx->status[1] = 0;
gpx->status[2] = 0;
}
}
@ -774,9 +876,11 @@ static int conf_out(gpx_t *gpx, ui8_t *conf_bits, int ec) {
static void print_gpx(gpx_t *gpx) {
int i, j;
int contgps = 0;
int contaux = 0;
int output = 0;
int jsonout = 0;
int start = 0;
int repeat_gps = 0;
if (gpx->frnr > 0) start = 0x1000;
@ -793,7 +897,10 @@ static void print_gpx(gpx_t *gpx) {
jsonout = output;
contgps = ((output & 0x11F) == 0x11F); // 0,1,2,3,8
contgps = ((output & 0x11F) == 0x11F); // 0,1,2,3,4,8 (incl. xdata ID=0x01)
if (gpx->posmode == 4) { // xdata
contaux = ((output & 0xF8) == 0xF8); // 3,4,5,6,7
}
if (gpx->option.dst && !contgps) {
output = 0;
@ -869,6 +976,7 @@ static void print_gpx(gpx_t *gpx) {
if (gpx->option.vbs == 3 && gpx->ptu_out >= 0xA) {
if (gpx->status[0]> 0.0) printf(" U: %.2fV ", gpx->status[0]);
if (gpx->status[1]> 0.0) printf(" Ti: %.1fK ", gpx->status[1]);
if (gpx->status[2]> 0.0) printf(" sec: %.0f ", gpx->status[2]);
}
}
if (gpx->option.dbg) {
@ -894,7 +1002,46 @@ static void print_gpx(gpx_t *gpx) {
}
printf("\n");
if (gpx->option.sat) {
if (gpx->posmode > 2) {
//printf(" ");
//printf("(mode:%d) ", gpx->posmode);
if (gpx->posmode == 3 && repeat_gps) {
printf(" ");
printf("(mode:%d) ", gpx->posmode);
printf(" lat: %.5f ", gpx->lat2);
printf(" lon: %.5f ", gpx->lon2);
printf(" alt: %.1f ", gpx->alt2);
printf(" vH: %5.2f ", gpx->horiV2);
printf(" D: %5.1f ", gpx->dir2);
printf(" vV: %5.2f ", gpx->vertV2);
printf("\n");
}
if (gpx->posmode == 4 && gpx->option.aux) {
printf(" ");
//printf("(mode:%d) ", gpx->posmode);
printf("XDATA:");
for (j = 0; j < 2; j++) printf(" %02X", gpx->xdata[j]);
for (j = 2; j < XDATA_LEN; j++) printf(" %02X", gpx->xdata[j]);
printf("\n");
if (gpx->xdata[0] == 0x01)
{ // ECC Ozonesonde 01 .. .. (MSB)
ui8_t InstrumentNum = gpx->xdata[1];
ui16_t Icell = gpx->xdata[2+1] | (gpx->xdata[2]<<8); // MSB
i16_t Tpump = gpx->xdata[4+1] | (gpx->xdata[4]<<8); // MSB
ui8_t Ipump = gpx->xdata[6];
ui8_t Vbat = gpx->xdata[7];
printf(" ");
printf(" ID=0x01 ECC ");
printf(" Icell:%.3fuA ", Icell/1000.0);
printf(" Tpump:%.2fC ", Tpump/100.0);
printf(" Ipump:%dmA ", Ipump);
printf(" Vbat:%.1fV ", Vbat/10.0);
printf("\n");
}
}
}
if (gpx->option.sat && gpx->posmode <= 2) {
printf(" ");
printf(" dMSL: %+.2f", gpx->gps.dMSL); // MSL = alt + gps.dMSL
printf(" sats: %d", gpx->gps.nSV);
@ -932,6 +1079,14 @@ static void print_gpx(gpx_t *gpx) {
float t = get_Temp(gpx); // ecc-valid temperature?
if (t > -270.0) printf(", \"temp\": %.1f", t);
}
if (gpx->posmode == 4 && contaux && gpx->xdata[0]) {
char xdata_str[2*XDATA_LEN+1];
memset(xdata_str, 0, 2*XDATA_LEN+1);
for (j = 0; j < XDATA_LEN; j++) {
sprintf(xdata_str+2*j, "%02X", gpx->xdata[j]);
}
printf(", \"aux\": \"%s\"", xdata_str);
}
//if (dfmXtyp > 0) printf(", \"subtype\": \"0x%1X\"", dfmXtyp);
if (dfmXtyp > 0) {
printf(", \"subtype\": \"0x%1X", dfmXtyp);
@ -941,6 +1096,15 @@ static void print_gpx(gpx_t *gpx) {
if (gpx->jsn_freq > 0) {
printf(", \"freq\": %d", gpx->jsn_freq);
}
// Reference time/position
printf(", \"ref_datetime\": \"%s\"", "UTC" ); // {"GPS", "UTC"} GPS-UTC=leap_sec
if (gpx->posmode <= 2) { // mode 2
printf(", \"ref_position\": \"%s\"", "GPS" ); // {"GPS", "MSL"} GPS=ellipsoid , MSL=geoid
printf(", \"diff_GPS_MSL\": %+.2f", -gpx->gps.dMSL ); // MSL = GPS + gps.dMSL
}
else printf(", \"ref_position\": \"%s\"", "MSL" ); // mode 3,4
#ifdef VER_JSN_STR
ver_jsn = VER_JSN_STR;
#endif
@ -1034,6 +1198,7 @@ static int print_frame(gpx_t *gpx) {
if (gpx->option.ecc && gpx->option.vbs) {
if (gpx->option.vbs > 1) printf(" (%1X,%1X,%1X) ", cnt_biterr(ret0), cnt_biterr(ret1), cnt_biterr(ret2));
printf(" (%d) ", cnt_biterr(ret0)+cnt_biterr(ret1)+cnt_biterr(ret2));
if (gpx->option.vbs > 1) printf(" <%.1f>", gpx->_frmcnt);
}
printf("\n");
@ -1075,7 +1240,6 @@ static int print_frame(gpx_t *gpx) {
int main(int argc, char **argv) {
int option_verbose = 0; // ausfuehrliche Anzeige
int option_raw = 0; // rohe Frames
int option_inv = 0; // invertiert Signal
int option_ecc = 0;
@ -1098,6 +1262,8 @@ int main(int argc, char **argv) {
int rawhex = 0;
int cfreq = -1;
float baudrate = -1;
FILE *fp = NULL;
char *fpname = NULL;
@ -1153,10 +1319,11 @@ int main(int argc, char **argv) {
return 0;
}
else if ( (strcmp(*argv, "-v") == 0) || (strcmp(*argv, "--verbose") == 0) ) {
option_verbose = 1;
gpx.option.vbs = 1;
}
else if ( (strcmp(*argv, "-vv" ) == 0) ) { option_verbose = 2; }
else if ( (strcmp(*argv, "-vvv") == 0) ) { option_verbose = 3; }
else if (strcmp(*argv, "-vv" ) == 0) { gpx.option.vbs = 2; }
else if (strcmp(*argv, "-vvv") == 0) { gpx.option.vbs = 3; }
else if (strcmp(*argv, "-vx" ) == 0) { gpx.option.aux = 1; }
else if ( (strcmp(*argv, "-r") == 0) || (strcmp(*argv, "--raw") == 0) ) {
option_raw = 1;
}
@ -1236,6 +1403,14 @@ int main(int argc, char **argv) {
else if (strcmp(*argv, "--min") == 0) {
option_min = 1;
}
else if ( (strcmp(*argv, "--br") == 0) ) {
++argv;
if (*argv) {
baudrate = atof(*argv);
if (baudrate < 2200 || baudrate > 2800) baudrate = BAUD_RATE; // default: 2500
}
else return -1;
}
else if (strcmp(*argv, "--dbg") == 0) { gpx.option.dbg = 1; }
else if (strcmp(*argv, "--sat") == 0) { gpx.option.sat = 1; }
else if (strcmp(*argv, "--rawhex") == 0) { rawhex = 1; } // raw hex input
@ -1303,7 +1478,6 @@ int main(int argc, char **argv) {
for (k = 0; k < 9; k++) gpx.pck[k].ec = -1; // init ecc-status
gpx.option.inv = option_inv;
gpx.option.vbs = option_verbose;
gpx.option.raw = option_raw;
gpx.option.ptu = option_ptu;
gpx.option.ecc = option_ecc;
@ -1311,6 +1485,8 @@ int main(int argc, char **argv) {
gpx.option.dst = option_dist;
gpx.option.jsn = option_json;
if (gpx.option.aux && gpx.option.vbs < 1) gpx.option.vbs = 1;
if (cfreq > 0) gpx.jsn_freq = (cfreq+500)/1000;
headerlen = strlen(dfm_rawheader);
@ -1381,6 +1557,11 @@ int main(int argc, char **argv) {
fprintf(stderr, "note: sample rate low\n");
}
if (baudrate > 0) {
dsp.br = (float)baudrate;
dsp.sps = (float)dsp.sr/dsp.br;
fprintf(stderr, "sps corr: %.4f\n", dsp.sps);
}
k = init_buffers(&dsp);
if ( k < 0 ) {