jketterl / openwebrx

Open source, multi-user SDR receiver software with a web interface
https://www.openwebrx.de
GNU Affero General Public License v3.0
996 stars 145 forks source link

HF Packet? #95

Open azwirko opened 4 years ago

azwirko commented 4 years ago

Hi I'm trying to copy HF APRS packet radio on 30m. I note when I select DIG Packet mode in owrx, it appears to default to FM and therefore I'm assuming 1200 baud.

Is it possible to redefine the Digital Packet mode in owrx to support SSB for HF? Also I note from this link

https://kypn.wordpress.com/2020/01/11/hf-robust-packet-freq-list-january-2020-draft/

that they use both USB & LSB, so maybe there needs to be an Packet HF (LSB) and Packet HF (USB).

I'm using direwolf with HDSDR and a virtual audio cable and noted I have to change the direwolf.conf to "MODEM 300". I assume then there would have to be separate VHF & HF direwolf.conf files for owrx to for HF Packet support?

Thanks for any assistance.

73

andyz - K1RA

jketterl commented 4 years ago

You're right, Packet is currently limited to decoding 1k2 in FM, and can only parse APRS packets. That's basically the featureset that could be achieved easily.

It can only display useful information for APRS because there's currently no proper interface to display arbitrary packet content.

There's a hard link between the digital mode and the underlying demodulator (i.e. Packet is currently always using FM and can't be switched to USB / LSB) which will need to be removed. Interestingly, that limitation is useful for other modes, where there is no need to switch demodulators, and prevents you from using the wrong one, so there's a need for an intelligent replacement.

There's even more problem when looking at 9k6 packet since that requires wider filters, but the resulting audio cannot be transmitted over the current pipeline.

I'll tag this as a feature request since it is a valid idea, however there is a lot of groundwork to be layed out before this can be adressed.

azwirko commented 4 years ago

Thanks for the feedback. I understand some packet related items are hard coded to FM & 1200 baud, so I used that info to dig into the .py and .js code. I tried hacking something together myself to fit my needs and did manage to get something working. With the following changes -

In csdr.py I did the following (using wsjt-x SSB config as a guide):

        elif which == "packet":
            chain += ["csdr realpart_cf"]
#            chain += ["csdr fmdemod_quadri_cf"]

In kiss.py I changed the MODEM to 300 like:

MYCALL {callsign}
MODEM 300

In openwebrx.js I did the following:

        case "packet":
            secondary_demod_start(subtype);
            demodulator_analog_replace('lsb', true);
//            demodulator_analog_replace('nfm', true);

After restarting owrx and tuning to 10.151 MHz, picking DIG Packet and waiting for a few minutes I finally catch a 30m APRS packet see the attached file

image

Hopefully in the future this can become a truly integrated capability for all to use.

73 & tnx for all your efforts!

andyz - K1RA

jketterl commented 4 years ago

well, it's great you got it working, but I need to leave this comment at this point: You won't be able to decode any 1k2 Packet on FM with that modification in place, just because I can't have people thinking this is a solution that is just waiting to be accepted into the code ;)

azwirko commented 4 years ago

Sure - I understand, but I did want to let those hackers know there is a temporary fix for those who aren't interested in VHF APRS, but are interested in HF APRS, I can see looking at the code, there is much work to do bring both options into the GUI.

andyz - K1RA

jketterl commented 4 years ago

I'm calling for developer who can come up with a proper solution that everybody can profit from. Don't get me wrong, but I don't encourage people to modify code because all it does is bring up additional issues when the next update is due. It is pretty exhausting and slows down the project overall.

azwirko commented 4 years ago

I thought closed source prevents people from making any modifications. This is open source right? What's the point of Open Source if you cannot hack it for ones own personal benefit? Or better yet learn what does work and what doesn't? I would think my information would at least be a starting point for a developer. Don't you? If so, then how else is one to spread the word on what works and what doesn't? Don't get me wrong. I understand about code dev, I just don't consider my self a true dev. Code diffs, branches, sync'ing, etc. Plenty to contend with for sure, but to discourage hacking, learning and providing info? That i just don't understand.

jketterl commented 4 years ago

Oh this is not about what you're allowed to do. This is about what's reasonable to keep this project advancing. I'm already spending a good portion of my available time on answering E-Mails. There's a lot of good ideas and requests at the moment, and at the same time, there's only one person continuously working on it. All I'm doing is trying to streamline this so that the project doesn't grind to a halt.

azwirko commented 4 years ago

I applaud your efforts and understand it is currently a one-man-show. I'm just a bit surprised at your attitude toward anyone who provides you information about what could possibly be or can be done with the current code base. To discourage any hacking basically will keep this project a one-man-show and you won't get anyone helping you. Appreciating any efforts toward growing the functionality should at least be welcomed if not also applauded. Sure you can be in charge of prioritizing what is most important to be part of a future release. I understand that it is the job of a program manager to keep any project on track. That is to be expected and I surely didn't expect APRS HF to be number 1. That's why I provided code snippets to anyone else who want to play with this now. Fostering developer contribution is still a necessary part of a project if you're looking to get any assistance, if that's truly what you need or are looking for. Thanks again for your efforts.

73

andyz - K1RA

azwirko commented 4 years ago

A caveat to what follows...I am not a software developer nor have I ever written a line of Python code in my life, so take what follows with that in mind! I've continued to look at supporting both the 1200bd FM packet and 300bd SSB packet modems in OWRX, since it was pointed out my initial hack broke that functionality. To that extent I've made some additional modifications to the .html, .js and .py code to allow switching between each Digital mode through the UI. I hope what follows will be of some use sometime in the future. Before I provide the actual code changes, here is what my DIG Menu now looks like:

DIG-menu

I've changed Packet to Packet 1200bd FM and added two additional 300bd modes below that. I can successfully switch between say 144.390 MHz Packet 1200bd FM mode and copy VHF APRS packets or one of the many HF Packet 300bd LSB mode frequencies and copy both APRS and non-APRS AX.25 packets. Here's a decode of some HF 300bd APRS packets from 30m LSB on 10.151 MHz.

Packet-decodes-APRS

Here is what some 20m non-APRS packet activity on 14.105 LSB looks like in the decode window

Packet-decodes-non-APRS

For non-APRS, I've essentially taken then entire packet and stuffed it into the Comment field. I do strip any non-printable characters as to keep that window clean and readable.

To reiterate, this is just a hack and if there is a better way to do this, then I hope at least this is a useful starting point for someone else.

Regarding the code changes, I'll admit I have no idea if this is right or if I've missed or broke something else, but this has run for the last few days and seems to work OK.

For the UI HTML piece I've made the following changes:

diff index.html ../htdocs.orig/index.html
191,193c191
<                         <option value="packet" data-feature="packet">Packet 1200bd FM</option>
<                         <option value="packethfu" data-feature="packethfu">Packet 300bd USB</option>
<                         <option value="packethfl" data-feature="packethfl">Packet 300bd LSB </option>
---
>                         <option value="packet" data-feature="packet">Packet</option>

For the UI Javascript to support and handle the additional menu options I've made the following changes:

diff openwebrx.js ../htdocs.orig/openwebrx.js
2050,2063d2049
<         case "packethfu":
<             secondary_demod_start(subtype);
<             demodulator_analog_replace('usb', true);
<             demodulators[0].low_cut = 1200;
<             demodulators[0].high_cut = 2000;
<             demodulators[0].set();
<             break;
<         case "packethfl":
<             secondary_demod_start(subtype);
<             demodulator_analog_replace('lsb', true);
<             demodulators[0].low_cut = -2000;
<             demodulators[0].high_cut = -1200;
<             demodulators[0].set();
<             break;
2076c2062
<     toggle_panel("openwebrx-panel-packet-message", ["packet", "packethfu", "packethfl"].indexOf(subtype) >= 0);
---
>     toggle_panel("openwebrx-panel-packet-message", subtype === "packet");

As far as the Python code changes, first in the Features code I did the following. I'm not certain if there is a better way to be adding this, or if its really needed.

 diff feature.py ../owrx.orig/feature.py
39,40d38
<         "packethfu": ["direwolf", "sox"],
<         "packethfl": ["direwolf", "sox"],

In the CSDR code to support the new demodulation I made the following changes:

diff csdr.py ../csdr.orig/csdr.py
247,256d246
<         elif which == "packethfu":
<             chain += ["csdr realpart_cf"]
<             if self.last_decimation != 1.0:
<                 chain += ["csdr fractional_decimator_ff {last_decimation}"]
<             return chain + ["csdr convert_f_s16", "direwolf -c {direwolf_config} -r {audio_rate} -t 0 -q d -q h 1>&2"]
<         elif which == "packethfl":
<             chain += ["csdr realpart_cf"]
<             if self.last_decimation != 1.0:
<                 chain += ["csdr fractional_decimator_ff {last_decimation}"]
<             return chain + ["csdr convert_f_s16", "direwolf -c {direwolf_config} -r {audio_rate} -t 0 -q d -q h 1>&2"]
311c301
<         self.try_create_configs(secondary_command_demod, self.secondary_demodulator)
---
>         self.try_create_configs(secondary_command_demod)
491c481
<         return demodulator in ["packet", "packethfu", "packethfl"]
---
>         return demodulator == "packet"
610c600
<     def try_create_configs(self, command, demod):
---
>     def try_create_configs(self, command):
617c607
<             file.write(DirewolfConfig().getConfig(self.direwolf_port, self.is_service, demod))
---
>             file.write(DirewolfConfig().getConfig(self.direwolf_port, self.is_service))

And in the OWRX initialization I setup some defaults for the bandwidth and modes

diff __init__.py ../../owrx.orig/service/__init__.py
93,94d92
<             "packethfu": "packet",
<             "packethfl": "packet",
225c223
<         if ( mode == "packet" ) or ( mode == "packethfu" ) or ( mode == "packethfl" ):
---
>         if mode == "packet":
235,242d232
<         elif mode == "packethfu":
<             d.set_demodulator("usb")
<             # HF packet only samples between 1200 and 2000 Hz
<             d.set_bpf(1200, 2000)
<         elif mode == "packethfl":
<             d.set_demodulator("lsb")
<             # HF packet only samples between 1200 and 2000 Hz
<             d.set_bpf(-2000, -1200)

In the KISS code as well as handling the new 300bd MODEM change I noted two other errors in the code. For some reason the original I-gate login configuration code was not being written to the /tmp/openwebrx/openwebrx_direwolf.conf file. I'm not sure what "is_service" is doing, but when I removed it, then the section of the config file would be generated properly. Also the calculation for the PBEACON lat/lon is incorrect. The code was testing for +/- and inserting N/S or E/W but not removing or ABS() the lat/lon values as it should.

diff kiss.py ../owrx.orig/kiss.py
16c16
<     def getConfig(self, port, is_service, demod):
---
>     def getConfig(self, port, is_service):
24a25
> MODEM 1200
28d28
<
33,43c33
<         if demod == "packet":
<             config += """
< MODEM 1200
<         """
<         else:
<             config += """
< MODEM 300
<         """
<
<         if pm["aprs_igate_enabled"]:
---
>         if is_service and pm["aprs_igate_enabled"]:
53,54c43,44
<                 lat = "{0}^{1:.2f}{2}".format(abs(int(lat)), abs(lat - int(lat)) * 60, "N" if lat > 0 else "S")
<                 lon = "{0}^{1:.2f}{2}".format(abs(int(lon)), abs(lon - int(lon)) * 60, "E" if lon > 0 else "W")
---
>                 lat = "{0}^{1:.2f}{2}".format(int(lat), (lat - int(lat)) * 60, "N" if lat > 0 else "S")
>                 lon = "{0}^{1:.2f}{2}".format(int(lon), (lon - int(lon)) * 60, "E" if lon > 0 else "W")

Finally in the APRS code to handle non-APRS packets and stuff data into the Comment field I changed:

diff aprs.py ../owrx.orig/aprs.py
9d8
< import string
285,288c284
<         else:
<             aprsData["type"] = "regular"
<             aprsData["comment"] = re.sub(r'[^\x20-\x7f]',r'', information[0:])
<
---
>

I have a .tgz file of all my files comprising OWRX from /usr/lib/python3/dist-packages csdr, htdocs and owrx folders if anyone would just like to replace theirs and play with what I've done.

73 & happy HF AX.25 packet decoding!

andyz - K1RA

jketterl commented 4 years ago

This is more of a UX thing, but I'd really like to implement some more structure at some point. Yes it will work that way, but at the point I start adding 9k6 and some more digital modes the dropdown is about to explode. Also, LSB and USB should be using the buttons that are already there to avoid confusion.

The PSK63 already was too much, but that has already been in place partially.

jketterl commented 4 years ago

P.S. this should become simpler once the remaining frontend demodulator code has been cleaned up. It's not very intitive to work with, has some unnecessary limitations and side effects. It's a lot of work though.

azwirko commented 4 years ago

OK about the modes in the DIG list, but since I tune/set the BPF differently than for regular SSB, I wasn't sure using the mode buttons would be the right way to handle switching for the narrow 1600-1800 hz tones used by HF packet. As I said, a hack :) Look forward to your future digital mode support work and a better UX.

jshuggins commented 4 years ago

A key result from the above dialog is the use of DireWolf for packet decode work. That's really cool and provides an upgrade path for newer packet modes that may find their way into DireWolf in time. Well done.