Skip to content

Commit

Permalink
Merge pull request #806 from darksidelemm/testing
Browse files Browse the repository at this point in the history
Further updates to make WxR-301D decoding work.
  • Loading branch information
darksidelemm authored Sep 13, 2023
2 parents 6efc17e + 243a89b commit 0877ecc
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 27 deletions.
1 change: 1 addition & 0 deletions auto_rx/auto_rx.py
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,7 @@ def telemetry_filter(telemetry):
or ("LMS" in telemetry["type"])
or ("IMET" in telemetry["type"])
or ("MTS01" in telemetry["type"])
or ("WXR" in telemetry["type"])
):
return "OK"
else:
Expand Down
2 changes: 1 addition & 1 deletion auto_rx/autorx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
# 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.6.3-beta4"
__version__ = "1.6.3-beta5"


# Global Variables
Expand Down
2 changes: 1 addition & 1 deletion auto_rx/autorx/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ def read_auto_rx_config(filename, no_sdr_test=False):
"MEISEI": True,
"MTS01": False, # Until we test it
"MRZ": False, # .... except for the MRZ, until we know it works.
"WXR301": False, # No fsk_demod chain for this yet.
"WXR301": True, # No fsk_demod chain for this yet.
"UDP": False,
}

Expand Down
44 changes: 44 additions & 0 deletions auto_rx/autorx/decode.py
Original file line number Diff line number Diff line change
Expand Up @@ -1266,6 +1266,49 @@ def generate_decoder_command_experimental(self):
demod_stats = FSKDemodStats(averaging_time=1.0, peak_hold=True)
self.rx_frequency = self.sonde_freq

elif self.sonde_type == "WXR301":
# Weathex WxR-301D Sondes.

_baud_rate = 4800
_sample_rate = 96000

# Limit FSK estimator window to roughly +/- 40 kHz
_lower = -40000
_upper = 40000

demod_cmd = get_sdr_iq_cmd(
sdr_type = self.sdr_type,
frequency = self.sonde_freq,
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,
bias = self.bias,
dc_block = True
)

# Add in tee command to save IQ to disk if debugging is enabled.
if self.save_decode_iq:
demod_cmd += f" tee {self.save_decode_iq_path} |"

demod_cmd += "./fsk_demod --cs16 -s -b %d -u %d --stats=%d 2 %d %d - -" % (
_lower,
_upper,
_stats_rate,
_sample_rate,
_baud_rate,
)

# Soft-decision decoding, inverted.
decode_cmd = f"./weathex301d --softin -i --json 2>/dev/null"

# Weathex sondes transmit continuously - average over the last frame, and use a peak hold
demod_stats = FSKDemodStats(averaging_time=5.0, peak_hold=True)
self.rx_frequency = self.sonde_freq

else:
return None

Expand Down Expand Up @@ -1660,6 +1703,7 @@ def handle_decoder_line(self, data):
"%Y-%m-%dT%H:%M:%SZ"
)


# Grab a snapshot of modem statistics, if we are using an experimental decoder.
if self.demod_stats is not None:
if self.demod_stats.snr != -999.0:
Expand Down
5 changes: 5 additions & 0 deletions auto_rx/autorx/scan.py
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,8 @@ def detect_sonde(
else:
_score = float(_score.strip())
_offset_est = 0.0


except Exception as e:
logging.error(
"Scanner - Error parsing dft_detect output: %s" % ret_output.strip()
Expand Down Expand Up @@ -608,6 +610,9 @@ def detect_sonde(
% (_sdr_name, _score, _offset_est)
)
_sonde_type = "WXR301"
# Clear out the offset estimate for WxR-301's as it's not accurate
# to do no whitening on the signal.
_offset_est = 0.0

else:
_sonde_type = None
Expand Down
6 changes: 6 additions & 0 deletions auto_rx/autorx/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,12 @@ def generate_aprs_id(sonde_data):
_id_suffix = int(sonde_data["id"].split("-")[1])
_id_hex = hex(_id_suffix).upper()
_object_name = "LMS6" + _id_hex[-5:]

elif "WXR" in sonde_data["type"]:
# Use the last 6 hex digits of the sonde ID.
_id_suffix = int(sonde_data["id"].split("-")[1])
_id_hex = hex(_id_suffix).upper()
_object_name = "WXR" + _id_hex[-6:]

elif "MEISEI" in sonde_data["type"] or "IMS100" in sonde_data["type"] or "RS11G" in sonde_data["type"]:
# Convert the serial number to an int
Expand Down
123 changes: 98 additions & 25 deletions weathex/weathex301d.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ int option_verbose = 0,
option_b = 0,
option_json = 0,
option_timestamp = 0,
option_softin = 0,
wavloaded = 0;
int wav_channel = 0; // audio channel: left

Expand Down Expand Up @@ -229,6 +230,28 @@ int read_rawbit(FILE *fp, int *bit) {
return 0;
}


int f32soft_read(FILE *fp, float *s) {
unsigned int word = 0;
short *b = (short*)&word;
float *f = (float*)&word;
int bps = 32;

if (fread( &word, bps/8, 1, fp) != 1) return EOF;

if (bps == 32) {
*s = *f;
}
else {
if (bps == 8) { *b -= 128; }
*s = *b/128.0;
if (bps == 16) { *s /= 256.0; }
}

return 0;
}


int compare() {
int i=0;
while ((i < HEADLEN) && (buf[(bufpos+i) % HEADLEN] == header[HEADLEN+HEADOFS-1-i])) {
Expand Down Expand Up @@ -428,24 +451,24 @@ int print_frame() {
val = xframe[OFS+13] | (xframe[OFS+14]<<8) | (xframe[OFS+15]<<16);
val >>= 4;
val &= 0x7FFFF; // int19 ?
//if (val & 0x40000) val -= 0x80000;
//if (val & 0x40000) val -= 0x80000; ?? or sign bit ?
float alt = val / 10.0f;
printf(" alt: %.1f ", alt); // MSL
gpx.alt = alt;

// lat
val = xframe[OFS+15] | (xframe[OFS+16]<<8) | (xframe[OFS+17]<<16) | (xframe[OFS+18]<<24);
val >>= 7;
val &= 0x1FFFFFF; // int25 ?
if (val & 0x1000000) val -= 0x2000000; // sign ? (or 90 -> -90 wrap ?)
val &= 0x1FFFFFF; // int25 ? ?? sign NMEA N/S ?
//if (val & 0x1000000) val -= 0x2000000; // sign bit ? (or 90 -> -90 wrap ?)
float lat = val / 1e5f;
printf(" lat: %.4f ", lat);
gpx.lat = lat;

// lon
val = xframe[OFS+19] | (xframe[OFS+20]<<8) | (xframe[OFS+21]<<16)| (xframe[OFS+22]<<24);
val &= 0x3FFFFFF; // int26 ?
if (val & 0x2000000) val -= 0x4000000; // sign ? (or 180 -> -180 wrap ?)
val &= 0x3FFFFFF; // int26 ? ?? sign NMEA E/W ?
//if (val & 0x2000000) val -= 0x4000000; // or sign bit ? (or 180 -> -180 wrap ?)
float lon = val / 1e5f;
printf(" lon: %.4f ", lon);
gpx.lon = lon;
Expand Down Expand Up @@ -518,6 +541,7 @@ int main(int argc, char **argv) {
else if ( (strcmp(*argv, "-v") == 0) || (strcmp(*argv, "--verbose") == 0) ) {
option_verbose = 1;
}
else if (strcmp(*argv, "--softin") == 0) { option_softin = 1; } // float32 soft input
else if (strcmp(*argv, "-b" ) == 0) { option_b = 1; }
else if (strcmp(*argv, "-t" ) == 0) { option_timestamp = 1; }
else if ( (strcmp(*argv, "-r") == 0) || (strcmp(*argv, "--raw") == 0) ) {
Expand Down Expand Up @@ -549,26 +573,29 @@ int main(int argc, char **argv) {
if (!wavloaded) fp = stdin;


i = read_wav_header(fp);
if (i) return -1;
if ( !option_softin ) {
i = read_wav_header(fp);
if (i) return -1;
}


if (cfreq > 0) gpx.jsn_freq = (cfreq+500)/1000;


bit_count = 0;
frames = 0;
while (!read_bits_fsk(fp, &bit, &len)) {

if (len == 0) {
bufpos--;
if (bufpos < 0) bufpos = HEADLEN-1;
buf[bufpos] = 'x';
continue;
}
if (option_softin)
{
float s = 0.0f;
int bit = 0;
sample_rate = BAUD_RATE;
sample_count = 0;

while (!f32soft_read(fp, &s)) {

bit = option_inv ? (s<=0.0f) : (s>=0.0f); // softbit s: bit=0 <=> s<0 , bit=1 <=> s>=0

for (j = 0; j < len; j++) {
bufpos--;
if (bufpos < 0) bufpos = HEADLEN-1;
buf[bufpos] = 0x30 + bit;
Expand Down Expand Up @@ -597,23 +624,69 @@ int main(int argc, char **argv) {

print_frame();
}

sample_count += 1;
}
if (header_found && option_b) {
bitstart = 1;
}
else
{
while (!read_bits_fsk(fp, &bit, &len)) {

if (len == 0) {
bufpos--;
if (bufpos < 0) bufpos = HEADLEN-1;
buf[bufpos] = 'x';
continue;
}


for (j = 0; j < len; j++) {
bufpos--;
if (bufpos < 0) bufpos = HEADLEN-1;
buf[bufpos] = 0x30 + bit;

if (!header_found)
{
h = compare(); //h2 = compare2();
if ((h >= HEADLEN)) {
header_found = 1;
fflush(stdout);
if (option_timestamp) printf("<%8.3f> ", sample_count/(double)sample_rate);
strncpy(frame_bits, header, HEADLEN);
bit_count += HEADLEN;
frames++;
}
}
else
{
frame_bits[bit_count] = 0x30 + bit;
bit_count += 1;
}

if (bit_count >= BITFRAMELEN) {
bit_count = 0;
header_found = 0;

print_frame();
}

while ( bit_count < BITFRAMELEN ) {
if (read_rawbit(fp, &bit) == EOF) break;
frame_bits[bit_count] = 0x30 + bit;
bit_count += 1;
}
if (header_found && option_b) {
bitstart = 1;

bit_count = 0;
header_found = 0;
while ( bit_count < BITFRAMELEN ) {
if (read_rawbit(fp, &bit) == EOF) break;
frame_bits[bit_count] = 0x30 + bit;
bit_count += 1;
}

print_frame();
bit_count = 0;
header_found = 0;

print_frame();
}
}
}

printf("\n");

fclose(fp);
Expand Down

0 comments on commit 0877ecc

Please sign in to comment.