Amateur Radio

A stereo/binaural tactical headset

One thing I hate doing when I’m taking down notes at a radio comms event is juggling a hand-microphone and pen/paper/tablet/computer simultaneously. So I tend to prefer a headset for my radios rather than a hand-microphone. Some models (especially Kenwood) have lots of selections available, but some are very much restricted. In particular, I prefer a binaural headset as I find it more difficult to hear a voice on one side than via both sides — particularly in noisy conditions. The only options I could find for Yaesu/Alinco sets were big chunky earmuff headsets — great in those noisy situations, but not so great if you need situational awareness.

The plan thus is to cobble together my own binaural tactical headset. Stereo using my standard headset connection, so I can re-use it elsewhere.

I did have a Kenwood TH-D72A — a good solid performer… but sadly no longer manufactured (neither is its successor, not that Kenwood ever sold that here), and my particular specimen now refuses to have anything to do with the internal battery. I bought an Alinco DJ-G7T as a back-up hand-held for pure voice comms, and more recently a Yaesu FT5DR. I had made my own Kenwood headset adaptor to use with my headsets, but I had nothing equivalent for the Alinco or Yaesu sets.

As it happens, the headset pin-out of the Alinco is nearly identical to that of the earlier Yaesu VX-6/VX-7: 3.5mm threaded TRRS. Both radios put the speaker on the tip, microphone+PTT (in series) on the sleeve-most ring and 0V on the sleeve. Alinco use the tip-most ring for a 3.3V rail, whereas Yaesu use this same ring for a data/clone connection. Maybe it’s a UART which “idles” at 3.3V on Yaesu rigs, but I wouldn’t bet on all Yaesu accessories working on Alinco and vice-versa — however headsets rarely need a 3.3V rail. (Maybe the VOX ones do… not sure.)

The FT5DR is actually compatible with the earlier VX-6/VX-7, however the connector is on the side of the radio, and while the threaded 3.5mm connectors fit, they stick out the side like a sore thumb: a right-angled 3.5mm TRRS is a better “fit”.

Luckily, Amazon have quite a few options that convert these radios to a U94 “Nexus” military-style connector. I managed to pick up a U94 adaptor that works quite well with the Alinco, and does work with the Yaesu (although is mechanically not optimal due to the “straight” style of the plug and side-mounting of the socket).

Tactical headsets come in a few varieties:

  • ear-tube covert-style headsets
  • D-loop style
  • throat-mic headsets
  • “bowman”-style headband headsets
  • earmuff-style headsets
  • motorcycle headsets

The only ones of this list that are binaural out-of-the-box are the earmuff headsets and the motorcycle headsets. I figured I’d pick up a couple of cheap “bowman”-style ones and see if I can cobble two mono headsets into one stereo set. I looked around, and bought two of these.

The adaptor turned up a week or so ago, and the headsets turned up today. There’s two different varieties of pin-out for the U94 connector — the “NATO” standard interleaves the speaker and microphone pins, whereas the “civilian” standard puts the speaker on the sleeve/sleeve-most ring and microphone on the tip-most ring/tip. Both adaptor and headset turned out to be “civilian” standard, so the first hurdle was cleared.

I tested both headsets and confirmed they both worked. I tried the headsets both with voice comms, then tried tuning to a local FM broadcast station to assess audio quality. They work, but audio quality is not what I’d call wonderful. Very tinny, fine for voice comms, but maybe telephone quality at best. Ookay, so using these as a stereo headset can be done — but if I wanted to use them for anything but straight voice comms, I’d want to swap the speakers out for something decent. Tear-down time!

I picked a “victim” and attempted to disassemble it. These units appear to be glued together, so you wind up partially destroying them to get at the speaker:

The speaker is a conventional 8ohm 500mW jobbie, nothing remarkable… and a frequency response that’s truly awful for anything other than voice comms. Fine for the intended task, but as I say, not really sufficient for what I was after.

I’ll see if I can swap this speaker out with one liberated from some headphones and see about replacing the strip of plastic I had to unceremoniously and destructively rip out — this shouldn’t be a difficult job. The other thing that might help is some sound-damping material behind the speaker, which might account for some tinniness.

If I get this headset working acceptably, I’ll do the same mod to the other, then can look at wiring the two together into a stereo set using a DIN-5 matching my other headsets. I can then re-purpose the U94 plug to make an adaptor to convert my other headsets to use with the U94 adaptors.

Yaesu FT5DR: First thoughts

I had a sad day the other day… the old faithful, my Kenwood TH-D72A finally bit the dust. It had been limping along ever since vibration damaged the barrel jack DC connector… I hacked up my own fix and got it going again, and it seemed mostly reliable and that kept it going for a few years… but in the recent downpours, it seems the battery management circuit died. Wouldn’t charge (just reports “Charge Error”) and wouldn’t run off a charged battery.

So… time for a new one. Kenwood basically no longer exist as a manufacturer of radio equipment now — they refused to sell the successor here in Australia and basically have abandoned us. Thus, it’s time for me to move on.

I had a look at a few options, a big issue is the chip shortage has greatly reduced the options available. I mainly use the Kenwood for APRS, it’s nice that it can function as a full-blown AX.25 TNC too, but by far, the feature I use more is APRS. Icom basically only care about D-Star and its DPRS equivalent. There are some DMR-based radios that do what they call “analog APRS” — whatever that is. The mode that gets used in SE Queensland is 1200 baud AFSK: aka Bell 203 modulation. Not the most reliable, and in many ways a dodgy hack, but that’s what everyone else uses. I wound up buying another Yaesu, the FT5DR. In fact, I bought two, just in case my father’s Kenwood bites the dust.

I haven’t put it through its full paces yet, but last night charged the units up, and this morning had mine running just beaconing on APRS and monitoring a local repeater.

General comments

The unit is reasonably lightweight… bright clear screen, the audio isn’t too shabby for something its size. I haven’t tried the C4FM mode yet but FM and WFM reception seemed decent. It’ll even begrudgingly receive AM broadcast — including with a 9kHz offset (unlike my Alinco set), although sensitivity is not great.

Text entry quirks

Set-up wasn’t too difficult, it prompts for a call-sign, which you enter from the touchscreen. Text entry is a little inconsistent, and very reminiscent of late 90s mobile phones: there’s no predictive text and the letters are layed out like they would be on a telephone keypad. To type a Z for instance, you’d look for a button labelled wxyz and hit it 8 times if you want capital Z, or 4 for lower-case. Frustrating if you miss and have to cycle around again. Sometimes touching a different button advances the pointer, sometimes not and it just overwrites the current character.

Repeater settings somewhat buried

The handbook does not discuss repeater settings much at all… which is odd since hand-held radios are not known for their DX range unless you’re up high.

To set up CTCSS, one must hit F-Menu, tap SQTYP, then use the channel knob to select TONE and hit PTT, then hit F-Menu again, go to CODE, and use the same knob to select a CTCSS frequency.

To change a repeater offset, one must long-press the F-Menu, tap CONFIG, then use the knob to scroll down to 15. RPT SHIFT, hit F-Menu, then use the channel knob to select between -, SIMPLEX or + and using PTT to confirm.

I’d have made these a simple toggle from the F-Menu options, but sadly, no.

Bluetooth still useless

I tried Bluetooth on a radio back with the VX-8DR. There, I found it was an incompatible mess… might work great if you buy Yaesu’s headset, but the whole point of Bluetooth is to be interoperable with other Bluetooth headsets which may be in a more suitable form-factor for your use case.

I tried the FT5DR with two headsets, a Behringer BB 560M, and a Logitech Zone Wireless. It could see the Behringer, but would not connect. It flatly refused to even recognise the Zone Wireless.

GPS and APRS working quite well

I’m yet to go mobile with this, but it soon found my position and getting the radio beaconing was not difficult. It lacks some niceties of the Kenwood set (e.g. reporting the frequency of the other band), and sadly no digipeating, but it otherwise is a capable APRS implementation.

SD Card support welcome

This radio can take a MicroSD card for various things, including settings back-up and restore, GPS logging, audio recordings, and even storing pictures if you buy the camera microphone option (I didn’t).

I put a few memory channels into the radio then told it to back-up to the SD card… apparently Yaesu’s own desktop software can read/write these files if you have a Windows PC handy (I don’t). That said, the format doesn’t look complex:

RC=0 stuartl@rikishi /media/sdb1/FT5D_MEMORY-CH $ hexdump -C MEMORY.dat 
00000000  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
000012c0  03 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000012d0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00001350  00 00 00 00 00 03 00 00  00 00 00 00 00 00 00 00  |................|
00001360  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00001380  00 00 00 00 00 00 00 03  00 00 00 00 00 00 00 00  |................|
00001390  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000013b0  00 00 00 00 00 00 00 00  00 03 00 00 00 00 03 00  |................|
000013c0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
000016a0  00 00 00 00 00 00 03 00  00 00 00 00 00 00 00 00  |................|
000016b0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00001710  00 00 00 00 03 03 03 03  03 03 03 03 03 03 03 03  |................|
00001720  03 03 03 03 03 03 03 03  03 03 03 03 03 03 03 03  |................|
00001800  02 00 14 50 00 d0 00 00  ff ff ff ff ff ff ff ff  |...P............|
00001810  ff ff ff ff ff ff ff ff  00 06 00 0c 00 0d 80 18  |................|
00001820  02 00 14 55 20 00 00 00  ff ff ff ff ff ff ff ff  |...U ...........|
00001830  ff ff ff ff ff ff ff ff  00 06 00 08 00 0d 00 08  |................|
00001840  02 00 14 55 20 40 00 00  ff ff ff ff ff ff ff ff  |...U @..........|
00001850  ff ff ff ff ff ff ff ff  00 06 00 08 00 0d 00 08  |................|
00001860  02 00 14 55 20 80 00 00  ff ff ff ff ff ff ff ff  |...U ...........|
00001870  ff ff ff ff ff ff ff ff  00 06 00 08 00 0d 00 08  |................|
00001880  43 07 43 55 00 c0 00 00  ff ff ff ff ff ff ff ff  |C.CU............|
00001890  ff ff ff ff ff ff ff ff  00 50 00 08 00 0d 00 08  |.........P......|
000018a0  43 07 43 55 00 00 00 00  ff ff ff ff ff ff ff ff  |C.CU............|
000018b0  ff ff ff ff ff ff ff ff  00 50 00 08 00 0d 00 08  |.........P......|
000018c0  43 07 43 55 00 40 00 00  ff ff ff ff ff ff ff ff  |C.CU.@..........|
000018d0  ff ff ff ff ff ff ff ff  00 50 00 08 00 0d 00 08  |.........P......|
000018e0  43 07 43 55 00 80 00 00  ff ff ff ff ff ff ff ff  |C.CU............|
000018f0  ff ff ff ff ff ff ff ff  00 50 00 08 00 0d 00 08  |.........P......|
00001900  02 00 14 55 20 c0 00 00  ff ff ff ff ff ff ff ff  |...U ...........|
00001910  ff ff ff ff ff ff ff ff  00 06 00 08 00 0d 00 08  |................|
00001920  02 00 14 55 20 00 00 00  ff ff ff ff ff ff ff ff  |...U ...........|
00001930  ff ff ff ff ff ff ff ff  00 06 00 08 00 0d 00 08  |................|
00001940  02 00 14 55 20 40 00 00  ff ff ff ff ff ff ff ff  |...U @..........|
00001950  ff ff ff ff ff ff ff ff  00 06 00 08 00 0d 00 08  |................|
00001960  02 00 14 55 20 80 00 00  ff ff ff ff ff ff ff ff  |...U ...........|
00001970  ff ff ff ff ff ff ff ff  00 06 00 08 00 0d 00 08  |................|
00001980  43 07 43 55 00 c0 00 00  ff ff ff ff ff ff ff ff  |C.CU............|
00001990  ff ff ff ff ff ff ff ff  00 50 00 08 00 0d 00 08  |.........P......|
000019a0  43 07 43 55 00 00 00 00  ff ff ff ff ff ff ff ff  |C.CU............|
000019b0  ff ff ff ff ff ff ff ff  00 50 00 08 00 0d 00 08  |.........P......|
000019c0  43 07 43 55 00 40 00 00  ff ff ff ff ff ff ff ff  |C.CU.@..........|
000019d0  ff ff ff ff ff ff ff ff  00 50 00 08 00 0d 00 08  |.........P......|
000019e0  43 07 43 55 00 80 00 00  ff ff ff ff ff ff ff ff  |C.CU............|
000019f0  ff ff ff ff ff ff ff ff  00 50 00 08 00 0d 00 08  |.........P......|
00001a00  02 00 14 55 20 c0 00 00  ff ff ff ff ff ff ff ff  |...U ...........|
00001a10  ff ff ff ff ff ff ff ff  00 06 00 08 00 0d 00 08  |................|
00001a20  43 07 43 45 00 c0 00 00  ff ff ff ff ff ff ff ff  |C.CE............|
00001a30  ff ff ff ff ff ff ff ff  00 50 00 08 00 0d 00 08  |.........P......|
00001a40  43 07 43 45 00 c2 00 00  ff ff ff ff ff ff ff ff  |C.CE............|
00001a50  ff ff ff ff ff ff ff ff  00 50 00 08 00 0d 00 08  |.........P......|
00001a60  43 07 43 45 00 c3 00 00  ff ff ff ff ff ff ff ff  |C.CE............|
00001a70  ff ff ff ff ff ff ff ff  00 50 00 08 00 0d 00 08  |.........P......|
00001a80  02 00 14 55 20 e0 00 00  ff ff ff ff ff ff ff ff  |...U ...........|
00001a90  ff ff ff ff ff ff ff ff  00 06 00 08 00 0d 00 08  |................|
00001aa0  43 07 43 45 00 e0 00 00  ff ff ff ff ff ff ff ff  |C.CE............|
00001ab0  ff ff ff ff ff ff ff ff  00 50 00 08 00 0d 00 08  |.........P......|
00001ac0  02 00 14 48 40 c0 00 00  ff ff ff ff ff ff ff ff  |...H@...........|
00001ad0  ff ff ff ff ff ff ff ff  00 06 00 08 00 0d 00 08  |................|
00001ae0  43 07 43 55 00 c0 00 00  ff ff ff ff ff ff ff ff  |C.CU............|
00001af0  ff ff ff ff ff ff ff ff  00 50 00 08 00 0d 00 08  |.........P......|
00001b00  07 00 05 25 00 c0 00 00  ff ff ff ff ff ff ff ff  |...%............|
00001b10  ff ff ff ff ff ff ff ff  00 00 00 0c 00 0d 00 18  |................|
00001b20  02 00 14 55 20 c0 00 00  ff ff ff ff ff ff ff ff  |...U ...........|
00001b30  ff ff ff ff ff ff ff ff  00 06 00 08 00 0d 00 08  |................|
00001b40  07 06 22 25 00 c0 00 00  ff ff ff ff ff ff ff ff  |.."%............|
00001b50  ff ff ff ff ff ff ff ff  00 00 00 0c 00 0d 00 18  |................|
00001b60  07 04 85 99 00 c0 00 00  ff ff ff ff ff ff ff ff  |................|
00001b70  ff ff ff ff ff ff ff ff  00 00 00 0c 00 0d 00 18  |................|
00001b80  02 00 14 55 20 e0 00 00  ff ff ff ff ff ff ff ff  |...U ...........|
00001b90  ff ff ff ff ff ff ff ff  00 06 00 08 00 0d 00 08  |................|
00001ba0  43 07 43 55 00 e0 00 00  ff ff ff ff ff ff ff ff  |C.CU............|
00001bb0  ff ff ff ff ff ff ff ff  00 50 00 08 00 0d 00 08  |.........P......|
00001bc0  02 00 14 57 20 c0 00 00  ff ff ff ff ff ff ff ff  |...W ...........|
00001bd0  ff ff ff ff ff ff ff ff  00 06 00 08 00 0d 00 08  |................|
00001be0  07 00 05 20 20 c0 00 00  ff ff ff ff ff ff ff ff  |...  ...........|
00001bf0  ff ff ff ff ff ff ff ff  00 00 00 0c 00 0d 00 18  |................|
00001c00  02 00 14 50 20 c0 00 00  ff ff ff ff ff ff ff ff  |...P ...........|
00001c10  ff ff ff ff ff ff ff ff  00 06 00 08 00 0d 00 08  |................|
00001c20  03 00 43 50 20 c0 00 00  ff ff ff ff ff ff ff ff  |..CP ...........|
00001c30  ff ff ff ff ff ff ff ff  00 50 00 08 00 0d 00 08  |.........P......|
00001c40  07 04 85 99 00 c0 00 00  ff ff ff ff ff ff ff ff  |................|
00001c50  ff ff ff ff ff ff ff ff  00 00 00 0c 00 0d 00 18  |................|
00001c60  02 00 14 50 20 c0 00 00  ff ff ff ff ff ff ff ff  |...P ...........|
00001c70  ff ff ff ff ff ff ff ff  00 06 00 08 00 0d 00 08  |................|
00001c80  43 07 43 50 20 c0 00 00  ff ff ff ff ff ff ff ff  |C.CP ...........|
00001c90  ff ff ff ff ff ff ff ff  00 50 00 08 00 0d 00 08  |.........P......|
00001ca0  02 00 14 55 50 60 00 00  ff ff ff ff ff ff ff ff  |...UP`..........|
00001cb0  ff ff ff ff ff ff ff ff  00 06 00 08 00 0d 00 08  |................|
00001cc0  43 07 43 56 00 c0 00 00  ff ff ff ff ff ff ff ff  |C.CV............|
00001cd0  ff ff ff ff ff ff ff ff  00 50 00 08 00 0d 00 08  |.........P......|
00001ce0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00002aa0  02 10 14 68 75 c1 00 00  34 44 42 20 52 65 64 6c  | Redl|
00002ab0  61 6e 64 73 20 32 6d ff  00 06 00 09 00 0d 00 18  |ands 2m.........|
00002ac0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
000030e0  03 17 43 82 00 c1 00 00  34 5a 42 20 42 72 69 73  |..C.....4ZB Bris|
000030f0  62 61 6e 65 20 37 30 63  00 50 00 09 00 0d 00 18  |bane 70c.P......|
00003100  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
00003720  02 00 14 75 00 c0 00 00  57 49 43 45 4e 20 32 6d  |...u....WICEN 2m|
00003730  ff ff ff ff ff ff ff ff  00 06 00 09 00 0d 00 18  |................|
00003740  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
000037c0  03 07 43 95 00 d0 00 00  55 48 46 20 53 69 6d 70  |..C.....UHF Simp|
000037d0  6c 65 78 ff ff ff ff ff  00 50 00 0c 00 0d 80 18  |lex......P......|
000037e0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
000094c0  02 00 14 51 75 d0 00 00  41 50 52 53 20 32 6d ff  |...Qu...APRS 2m.|
000094d0  ff ff ff ff ff ff ff ff  00 06 00 0c 00 0d 80 18  |................|
000094e0  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0000a180  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
0000a240  00 00 00 00 00 00 00 00  ff ff ff ff ff ff ff ff  |................|
0000a250  ff ff ff ff ff ff ff ff  ff ff ff ff ff ff ff ff  |................|
0000a280  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
0000ab10  00 00 00 00 00 00 00 00  00 99 42 8b 00 00 00 00  |..........B.....|
0000ab20  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

That’s a complete hex dump of the memory back-up… I can see each memory channel is 32 bytes, and the frequency in kHz is given in BCD format:

000030e0  03 17 43 82 00 c1 00 00  34 5a 42 20 42 72 69 73  |..C.....4ZB Bris|
000030f0  62 61 6e 65 20 37 30 63  00 50 00 09 00 0d 00 18  |bane 70c.P......|

That’s the Mt. Coot-tha WICEN repeater VK4RZB (which I’ve labelled as “4ZB Brisbane 70c“); 438.200MHz, 91.5Hz CTCSS, negative 5MHz offset. I put it at memory location 200. I’m not sure how 12.5kHz offsets are encoded… maybe I might try programming some more in when I get time and see what they look like, but even that might be enough to “generate” a file with the repeaters I want. We’ll see.

New project: a replacement head unit for the Yaesu FT-857(D)

So, for a long while now I’ve been a user of a Yaesu FT-857D. I bought it back in 2011 as shop-soiled stock (someone bought it before me thinking they could make it work on 27MHz!) and have used it on the bicycle pretty much ever since.

The FT-857D is a great rig. Capable of all common amateur bands from 160m through to 70cm, 100W on MF/HF/6m, 50W on 2m, 20W on 70cm, and able to work AM/FM/SSB/CW, in a nice small package. It’s ideal for the bike in that regard. The only thing I could wish for is an actually waterproof head unit, but the stock one has been good, until now.

Last time I rode the bike I had no issues with the head unit display, things were stable and working just fine. That was some months back. Today fired it up to check the battery voltage: it seems I’ve got the dreadded zebra stripe issue. The bike has been in the garage for the past few months, so under cover, not in the sun… anecdotal evidence is that this problem is caused by vibration/heat in vehicle installations, but some reports suggest this can happen for indoor fixed installations too.

The problem

Either way, the zebra has made its home in my radio’s head unit and the display is now pretty much unreadable. Reports suggest I can send it back to Yaesu, pay them $200 (I presume that’s USD, and does not include shipping), and they will replace the defective LCD. However… given they discontinued making these things a few years back, I think I’ve missed the boat on that one!

Time for replacement?

Buying a new replacement isn’t viable right now — Yaesu don’t make anything equivalent: the FT-991A is too big (same size as the FT-897D), the FT-891 doesn’t do 2m/70cm, the FT-818ND is only QRP. Icom’s IC-7100 is the nearest competitor, not out of the question, except it’s a pricey unit for something that will be out in the weather.

Also, a lot of these options are out-of-stock with a big lead time.

Most of the Chinese units only do FM, and are at best quad-banders. Not that I’m interested in buying one: I hear they’re not the longest-lived of transceivers and right now I wish to avoid buying from China anyway.

Kenwood are basically out of the market here in Australia, and they never had an offering like the Icom or Yaesu units; their TS-480SAT was the closest, but does not cover 2m/70cm. The TS-2000 is a monster.

Alinco don’t have anything in a mobile format that competes either. The DX-SR9T does not cover 2m/70cm and is rather big; none of their 2m/70cm sets do HF or SSB.

Keeping the old faithful going

The radio itself works fine. It looks like the wreck of the Hesperus… with paintwork rubbed off the body, screws missing, a DIY fix on the antenna ports, and miscellaneous fixes to other bits. It still works though.

DIY Repair

This could be tricky as I’m not entirely sure what the issue is. It could be just a need for re-flowing everything, or there’s talk of parts needing replacement. The information I have is pretty murky and I could wind up making my partially-working head unit completely non-working.

Replacement used head unit

If someone had a working head unit that they were willing to part with, that might be an option. That said, the used unit could have the same problems my existing unit has, so no guarantee it’ll fix the problem.

CAT port auxiliary display

There are projects that link to the CAT port and present a UI on a separate screen. I was planning on putting a Raspberry Pi 4 there for SDR work, so that’s an option.

Homebrew head unit

Another option is to make a new front head unit. It turns out this has been partially reverse-engineered, so might be a worthy avenue to consider. That would give me a head unit that I can purpose-build for the bike: an attractive option. The hardware interface is 5V TTL UART with a 62kbps baud rate and 8-bits, no parity, two stop bits.

I have a big LCD (128×64) that has been kicking around for a while as well as some TFT resistive touchscreen displays with STM32F103VEs.

The Raspberry Pi 4 scraping the data and presenting it via a remote UI is also an option, in fact may be the direction I wind up going simply because Python on an ARM CPU is much easier to use prototyping something than doing C on a MCU whilst I bed down the finer details of the protocol.

The attraction of this is that I can use what I have on-hand now. Possibly use my tablet as the front-end in the short term. Not good in the rain, but can’t argue with the price!

I’ll go ponder this some more… one thing I am short of though is time to work on this stuff. This week-end is through, and the next one I’ll already be tied up on the Saturday, so I guess I’ll have to squeeze something in.

Thinking about SDR on the bike

So, for close to a decade now, I’ve had a bicycle-mobile station. Originally just restricted to 2m/70cm FM, it expanded to 2m SSB with the FT-290RII, then later all-band using a FT-857D.

It’s remained largely unchanged all this time. The station is able to receive MW/SW stations as well, and with some limitations, FM broadcast as well. My recent radio purchases will expand this a bit, freeing up the FT-857D’s general-coverage receiver to just focus on amateur bands. It’s been a long-term project though to move to SDR for reception.

What I have now

Already acquired is a Raspberry Pi 4 (8GB model) and a NWDR DRAWS interface board. I actually started out with a Raspberry Pi 3 + DRAWS and was waiting for the case for it to fit into. At that stage was the idea that the FT-897D would do much as it does now, no SDR involved, and I’d put a small hand-held with its own antenna as an APRS rig being driven by the second port on the DRAWS.

Since then; I bought the HackRF One for work (I needed something that could give me a view of the 2.4GHz ISM band for development of the WideSky Hub), the SDR bug firmly bit. Initially it was just DAB+ reception, I decided to get a RTL-SDR to do that so my radio listening wouldn’t be interrupted when a colleague needed to borrow the HackRF. That RTL-SDR saw some use receiving UHF CB traffic at horse endurance ride events at Imbil — I stated to consider whether maybe this might be a better option as a receiver for more than just commercial radio broadcasts.

Hence I purchased the Pi4: I figured that’d have enough CPU grunt that it’d still be able to decode a reasonable amount even if the CPU throttled itself for thermal management purposes. A pair of SDR interfaces would allow me to monitor a couple of bands simultaneously, such as 2m and 70cm together, or 2m/70cm and one of the HF bands.

Even the RTL-SDR v3 dongles are wide enough to watch the entire 2m band. With CAT control of the FT-857D, it’d be possible for the Pi4 to switch the FT-857D to the same frequency and possibly manage some antenna switching relays as well.

A rough design

This morning I came up with this:

A rough design of the SDR set-up

A critical design feature is that this must have a “pass-through” option so that in the event the computer crashes/fails, I can bypass all the fancy stuff and still use the FT-857D safely as I do now without all the fancy SDR stuff.

So while in SDR mode: the station pushbuttons on the handlebar go to a small sequencing MCU that can report events to the Pi4, on transmit the Pi4 can then instruct that MCU to connect the antennas into bypass mode, short-out the SDR inputs to protect them, then engage the PTT on the FT-857D, and transmit audio can either be delivered direct via the analogue inputs as they are now, or over USB/WiFi/Bluetooth through the MiniDIN6 DATA port.

The thinking is to have two SDRs, one of which is “agile” between HF/6m and 2m/70cm modes.

The front-end will be handled via the tablet: a Samsung Galaxy Active3 which can connect over WiFi or USB CDC-Ethernet.

I’ve shown gain-blocks between the antennas and the receivers, this is largely for impedance matching as well as to account for the losses involved in antenna sharing. Not sure what these will technically look like.

The two on the HF side should be ideally 0-60MHz devices. If I use the AirSpy HF+ as pictured, the VHF/UHF LNA connected to it only has to concentrate on the VHF band below 260MHz (really 144-148MHz, but let’s widen that to 87-230MHz for FM broadcast, air-band and DAB+) since that’s where the AirSpy stops.

The other, for now I’m looking at a RTL-SDR since I have one spare, but that could be any VHF/UHF capable SDR including the AirSpy Mini — the LNA on it, as well as the one feeding the FT-857D in receive mode will both need to handle 144-450MHz at a minimum.

It may be these frequency bands are “too wide” for a single device, and so I need to consider band-pass filters + separate band-specific LNAs and additional switching circuitry.

SDR selection

There are a couple of options I’ve considered:

The thing I don’t like about the SDRPlay Duo is the non-free nature of its libraries which seem to be only available for i386 or AMD64. Otherwise on paper it looks like a nice option.

KerberosSDR/KrakenSDR seems like overkill. It’s basically four (or five) RTL-SDRs sharing a common oscillator which is essential for direction-finding, but let’s face it, I’ll never have enough antennas to make such an application feasible on the bicycle. It looks like an echidna now!

BladeRF looks nice, but is pricey and stops short of the HF band so would need an up-converter like the RTL-SDR — not a show-stopper. That said, it’s dual-channel and can transmit as well as receive, so cross-band repeater would be doable.

I should try this with the HackRF One some day, see if I can combine a conventional transceiver + RPi + DRAWS/UDRC + HackRF One to make a cross-band repeater.

The Airspy HF+ is available domestically, and isn’t too badly priced. It doesn’t transmit like the HackRF does, but then again I could stuff one of my Wouxun KG-UVD1Ps in there wired up to the second DRAWS port if I wanted a traditional cross-band set-up.

Next steps

It would seem the LNA / antenna sharing side of things needs consideration next. RF relays will need to be procured that can handle seeing 100W of RF. Where I’ve drawn a single switch, that’ll likely be multiple in reality — when the transmitter is connected to the antenna, the receivers should all be shorted to ground so they don’t get blown up by stray RF.

Maybe the LNAs feeding the FT-857D will need to be connected to a dummy-load to protect them, not sure. Perhaps LNAs aren’t strictly necessary, and I can “cheat” by just connecting receivers in parallel, but I’m not comfortable with this idea right now. So this is the area of research I’m focusing on right now.

A couple of small radio purchases

Lately, I’ve been stuck at home with not much bicycle mobile operation happening, and it’s given me time to review where I’m going with the station and the onboard communications systems.

At home, I’ve been listening to a lot of commercial radio, whereas on the bicycle, in pre-COVID times I was basically restricted to recorded music unless I wanted to use the FT-897D for broadcast radio reception.

Now, the Yaesu rig actually isn’t a bad receiver for broadcast radio… but a few downsides:

  • Wideband FM sounds good, but is only received in mono
  • Medium wave and shortwave broadcast requires a rather bulky HF antenna to be deployed
  • The FT-897D is thirsty for power: about 1A on receive
  • When receiving broadcast radio, I obviously cannot monitor amateur frequencies
  • Some of the stations I like listening to are on DAB+, which the FT-897D will never receive

Long-term plan

Long term, the plan is to use SDR to augment the FT-897D, basically I rig up a Raspberry Pi 4 (already procured) with a SDR, and through some antenna switching, basically use the FT-897D as the transmitter with the Raspberry Pi 4 implementing an all-band scanning receiver. That would give me dual-watch (actually, I could watch entire bands) capability which I miss on the FT-897D.

Likely, the SDR chosen will either be a multi-channel one so I can watch a couple of bands: 2m + 70cm; or maybe I monitor 2m whilst listening to a radio broadcast on the other. SDR would also open up DAB+ to me.

This is a long-way off though. And also is rather fixed to the bike, I can’t take any of this stuff on a walk, which lately in COVID times has been my more likely form of exercise.

Current MW rig

For medium wave reception, I do have a small portable transistor radio, a Sanyo BC-088 which I was given years ago in non-working condition. The fault at first was broken PCB traces from the unit being thrown against a wall by its previous owner, which was fixed and allowed the radio to give many years of entertainment for over a decade until another incident on the bike smacked it against Waterworks Road, breaking a few connections to the internal loop-stick antenna.

I’ve repaired that, and the unit now works, but found it does not get along with any microprocessor-based device; picking up all manner of hash when placed near my handheld GPS (Garmin Rino 650) and squealing like a banshee next to my desktop PC. It also seems to be a tad deaf.

SDR is one possible option, but the SDRs I have in my possession: a couple of RTL-SDR v3 dongles and a HackRF One, none of them will tune down to 693kHz where I normally have the BC-088 tuned. The HackRF One gets close at 1MHz, but anything below 10MHz sounds terrible with noise and birdies galore. Even for shortwave, the HackRF One seems to suffer; trying it out on the HF antenna at home, I find myself picking up 4BH at 18883kHz — they normally broadcast at 882kHz.

Thus, I figured I’d try a couple of off-the-shelf options for the short-term and see how they go. Ideally I wanted a single radio that could do MW, FM and DAB+ bands… bonus points if it could do shortwave too.

New DAB+ rig: Digitech AR-1690

I bought this at a time when I noticed all the Australian Radio Network stations (4KQ, 97.3) suddenly go mute on the Brisbane channel 9A multiplex. I wasn’t sure if it was my end or the station, as other DAB+ stations seemed to be fine, and thought this little rig would both be a useful observer, and scratch that itch of portable listening.

The Digitech AR-1690

This is a basic entry-level DAB+/FM set. It’s a smallish unit, roughly 125mm×73mm×30mm. There’s no real special features of this unit. It has 40 station presets; 20 each for FM and DAB+, and there’s two alarm functions that can be set. The clock is set by the radio transmitter time broadcast. The front panel features the volume and channel buttons, along with a SELECT button. The rest of the controls are on the top.

Top controls
  • Info/Menu button:
    • Long-press → enters a configuration menu where you can configure the system time, set the two alarms, see the firmware version or do a factory reset
    • Short press → scrolls through different pieces of information on the LCD display:
      • Frequency
      • Current time
      • Current date
      • (DAB+): Signal strength?
      • (DAB+): Genre
      • (DAB+): DAB+ Multiplex name
      • (DAB+): Frequency and channel
      • (DAB+): Signal error rate
      • (DAB+): Bit rate and standard (DAB or DAB+)
      • (FM RDS): Station name
      • (FM RDS): Genre
  • Mode: Switches between FM and DAB+ mode
  • Scan: Initiates a scan on the currently selected mode (so, all FM broadcast, or all DAB+ channels)
  • Alarm: A shortcut button for setting the alarms (same as holding Info/Menu, then navigating to Alarms)
  • Preset: Used for accessing memory presets, short press recalls a preset, long press to store a station preset
  • Power: Switches the radio on, stand-by (short press) or off (long press)

For power, it can either run on 3 AAA cells, or you can buy separately a Nokia BL-5C Lithium battery.

The back of the radio, nothing much to see here.
The battery compartment, with Nokia BL-5C installed

As for ports, there’s just the two on the right-hand side:


The power jack is a small ~3mm barrel jack, the radio is supplied with a USB cable that interfaces to this connector. Looks like a dead ringer for the old Nokia phone connectors, I might dig up one of my old chargers and see if it works. (Update 2022-03-11: Found one, it doesn’t… the barrel is the same size but the tip in the radio is too big to fit in the bore of the connector.)

In operation

The set seems to do a reasonable job. I’m close to Mt. Coot-tha, so receiving DAB+ really isn’t that difficult. The sound is quite reasonable for the size, I thought the speaker would be a bit on the tinny side, but it’s perfectly listen-able. Certainly it’s a big improvement on the BC-088!

One gripe I do have with this set is that the volume steps are very coarse, and there’s no real “quiet” setting. Minimum volume is mute, one step up is comfortable listening level in a small room. I would have liked maybe 3 or four steps in between.

In both DAB+ mode, it can report the station dynamic labels.

DAB+ dynamic labels

It also can pull a similar stunt with RDS data on FM:

FM RDS reception

New Short wave rig: Tecsun PL-398MP

Now, when I bought the above DAB+ receiver, I ideally wanted something that would do MW broadcast as well, as one of the stations pictured on the DAB set is in fact, a MW station as well.

There is such a beast, Sangean make the DPR-45 which can do MW/FM and DAB+, but it’s enormous. Too big for my needs. Plus I found it after purchasing the little AR-1690 (not that it mattered, as size pretty much rules the DPR-45 out). I figured the next best thing was to get a portable set that had a line-in feature so it could provide the stereo speakers that the AR-1690 lacks.

Enter the Tecsun PL-398MP.

The Tecsun PL-398MP

As the text above the screen suggests, this is quad-band radio; supporting LW/MW/SW and FM bands, as well as a (primitive!) MP3 player. Unlike the Sanyo BC-088 it’s replacing, which boasted 8 transistors (wow!), this unit is a DSP-based receiver using the common Silicon Labs Si4734 radio receiver IC.

Most of the controls are on the front. The labels marked in red are activated when the radio is turned off; so holding 1 down allows you to switch the FM radio band from the default 88-108MHz to 64-108MHz or 76-108MHz. Holding 2 down switches the clock between 12-hour and 24-hour time, 3 will switch the MW band between using 9kHz steps and 10kHz steps, 0 turns keypad beep on/off and the ST button toggles the “intelligent backlight”.

Unlike the AR-1690, this thing runs on either standard disposable dry-cells, or you can install Ni-MH cells and by holding the M button whilst the radio is turned off, you can enable a built-in charger. Dry cells are not exactly my favourite way of powering a device, for no other reason than the reduced energy density and their nasty habit of leaking electrolyte.

Maybe a future project will be to hack a LiPo cell into this thing.

On the back, are the controls for the MP3 player.

Back of the PL-398MP

I’ll get to the MP3 player part in a moment, but in short, don’t bother!

For tuning and volume, there are two thumbwheels on the right-hand side. These are both rotary encoders driving a small microcontroller inside.

Volume and tuning controls

The “digital” volume control steps aren’t too bad for resolution, certainly nowhere near as coarse as the AR-1690! The tuning knob works well enough for small adjustments, and for moving between presets. Thankfully for moving between stations, there’s the keypad for entering frequencies directly.

On the left are all the ports:

FM/SW antenna, line-in, earphone output, and a 5V mini-USB input

The line-in feature is what set this apart from other MW and SW-capable sets. Being able to connect an external shortwave antenna is a welcome feature, and with this radio, I purchased a Sangean ANT-60 antenna for this purpose.

On top, there’s just the Light/Snooze button; pressing it momentarily turns the lighting on. I presume it’ll also silence the wake-up alarm if you have one set, but I haven’t tried this.

Light / Snooze button on top

In operation

FM Stereo reception

I’m close to the Mt Coot-tha transmitter site, so this isn’t much of a strain for the receiver, I guess I’ll know more when I take it out of town with me, but it seems to receive the local stations well, without getting overloaded from the strong ones (looking at you ABC Classic FM).

Being a dual-speaker device, this can provide stereo without additional hardware. Audio quality is actually decent for a radio this size. The speaker drivers are about 50mm in diameter, appear to be a low-profile mylar construction; not going to win audiophile magazine awards and are outperformed by many Bluetooth speakers, but are decent enough.

Short wave reception

The shortwave feature of this set seems good so far. There’s not as much to listen to on the shortwave bands as there used to be, but I’ve been able to receive China Radio International and Radio New Zealand both quite clearly, and one evening managed to pick up the BBC World service.

It performs decently with its built-in antenna, even without me telescoping it out. I haven’t had a chance to fully try the set with the ANT-60 — I did try it indoors in my room, but I suspect I haven’t really got enough wire “in the air” to make much difference. I’ll have to try it at a camp site some evening.

Medium wave reception

This blew me away actually. Okay, so maybe a late 60’s era transistor radio with leaky vintage germanium transistors that’s had a hard life and more than one ham-fisted repair attempt is not much of a contest, but it left the old Sanyo in the dust.

4KQ on 693kHz was a bit of a fiddle to get tuned on the Sanyo, and even then, I found I had to have the radio oriented right to receive it. 4QR on 612kHz of course, was loud and strong. Both stations are very clear on the PL-398MP. Ohh, and while this set’s no rich console radio, it’s nowhere near as tinny as what I was expecting to hear. For a portable rig, quite acceptable.

Out of the box, my unit used 9kHz frequency steps, which will also suit Europe. For those in the USA, you’ll want to hold that “3” button with the power off to switch the radio to a 10kHz spacing. This will also switch the temperature display to show °F instead of °C.

Long wave reception

Firstly, to even get at LW took a bit of fiddling. The handbook is a little inaccurate, telling you to press a non-existent MW/LW button. The correct procedure to enable LW is to turn the radio off, then long-press the AM button. The display will then show “LW” and “On” to indicate the feature is now enabled.

Turning on LW mode.

The same procedure turns the LW feature off too.

Having done so, when you turn the radio back on, pressing the AM button momentarily will now switch between MW and LW.

Now, ITU region 3 where I am, does not have any official LW stations. Nor does region 2 (Americas), this is a feature that’s more useful to those in Europe.

There used to be a LW weather beacon on 359kHz broadcasting out of Amberley Air base, and my Sony ST-2950F (my very first LW-capable receiver) could pick it up with its loop-stick antenna. Neither it, nor the PL398-MP do today. I guess I could drag out one of my amateur sets out to get a third opinion, but smart money is that the transmitter is now turned off.

Never mind, I’ll just turn LW back off and not worry about it.

Line-in feature

This works pretty simple, the radio is supplied with a 3.5mm male-male stereo cable. Plug one end into the line-in port on the radio, and the other into your audio device. On the LCD screen, a “>>” symbol appears on the right-hand side. Turn the radio on, and get your source playing, you’ll hear it through the radio speakers.

Nice and simple. I’ll be able to use it with the aforementioned AR-1690, my tablet, and the little portable media player I already use on the bike.

MP3 Player

Yes, I did mention it has one. The controls are on the back, and the device takes a SD card via a port hiding under the rear stand.

The SD card port

Plugging in a FAT32-formatted SD card with some MP3s on it (The Goons Show, what else?) and turning the radio on, I then tried getting it to play something. Hitting Pause/Play at first seemed to do nothing, but eventually I must’ve either waited long enough, or managed to coax it to play something, it started playing the first track it found.

I could navigate between the tracks — I have no idea whether it sorts the files by file name or not, the display is too primitive to support showing any track metadata, but it did work. There’s no playlist capability in this device, no random shuffle mode, as I say, it’s primitive.

So I think I’ll just ignore it and pretend it’s not there. A Bluetooth receiver would have had greater utility, but never mind. There is a sister-model to this one, the PL398-BT with exactly this feature… but good luck getting one unless you order direct from China.

Hidden function #1: A lithium charger?

So, fiddling with the radio, I noticed a few hidden features that are undocumented. With the radio off, holding the VM button triggers the display to show “Li On” and the “Ni-MH Battery” indicator starts flashing.

Is this a “Lithium battery” mode?

Exactly what this is doing I’m not sure. There are radios in Tecsun’s line-up that do support and include Lithium batteries, so maybe the project to add this feature isn’t out of the question. I guess a trip into the set with a screw driver will be my next move, but maybe some of that work is done for me.

Hidden feature #2: Self test?

Holding the BW button whilst the radio is turned off seems to perform a self-test of the display.

All segments on the LCD turned on

When the button is released, it switches back to showing the time, plus some 4-digit code (firmware version perhaps?):

“3985”, a code for the gurus to meditate over

Not sure what this is.

Final comments

All in all, both seem to be decent sets. The little DAB+ set is more-or-less a one-trick pony, it’ll be interesting to see if it does any better or worse than the Tecsun. I’m also yet to introduce these to the Garmin GPS that caused my Sanyo so much grief.

It’s nice to know that short wave sets are still being manufactured, and the performance of this set is quite remarkable. Tecsun themselves are based out of Hong Kong, and seem to have a decent reputation from what I’ve seen in reviews online.

While lately it’s been my policy to avoid buying stuff that’s made in China / by Chinese companies — in this case the feature set I wanted was practically a unicorn, no one else makes something like this, and this set seems to perform decently, so we’ll see how it looks after a year or two to see how it is long-term. After all, the little Sanyo has been in my possession since the early 90s, and it was an old radio then… it still goes. Will the Tecsun last as long? We’ll see.

As for the Digitech unit; well, DAB+ has a crazy amount of DSP going on to pick out one station out of a multiplex. I expect being more complicated, it’ll perhaps have a shorter longevity, but hopefully long enough for me to cobble up a replacement. Time will tell.

6LoWHAM: TCP over sensor networks

I stumbled across this article regarding the use of TCP over sensor networks. Now, TCP has been done with AX.25 before, and generally suffers greatly from packet collisions. Apparently (I haven’t read more than the first few paragraphs of this article), implementations TCP can be tuned to improve performance in such networks, which may mean TCP can be made more practical on packet radio networks.

Prior to seeing this, I had thought 6LoWHAM would “tunnel” TCP over a conventional AX.25 connection using I-frames and S-frames to carry TCP segments with some header prepended so that multiple TCP connections between two peers can share the same AX.25 connection.

I’ve printed it out, and made a note of it here… when I get a moment I may give this a closer look. Ultimately I still think multicast communications is the way forward here: radio inherently favours one-to-many communications due to it being a shared medium, but there are definitely situations in which being able to do one-to-one communications applies; and for those, TCP isn’t a bad solution.

Comments having read the article

So, I had a read through it. The take-aways seem to be this:

  • TCP was historically seen as “too heavy” because the MCUs of the day (circa 2002) lacked the RAM needed for TCP data structures. More modern MCUs have orders of magnitude more RAM (32KiB vs 512B) today, and so this is less of an issue.
    • For 6LoWHAM, intended for single-board computers running Linux, this will not be an issue.
  • A lot of early experiments with TCP over sensor networks tried to set a conservative MSS based on the actual link MTU, leading to TCP headers dominating the lower-level frame. Leaning on 6LoWPAN’s ability to fragment IP datagrams lead to much improved performance.
    • 6LoWHAM uses AX.25 which can support 256-byte frames; vs 128-byte 802.15.4 frames on 6LoWPAN. Maybe gains can be made this way, but we’re already a bit ahead on this.
  • Much of the document considered battery-powered nodes, in which the radio transceiver was powered down completely for periods of time to save power, and the effects this had on TCP communications. Optimisations were able to be made that reduced the impact of such power-down events.
    • 6LoWHAM will likely be using conventional VHF/UHF transceivers. Hand-helds often implement a “battery saver” mode — often this is configured inside the device with no external control possible (thus it will not be possible for us to control, or even detect, when the receiver is powered down). Mobile sets often do not implement this, and you do not want to frequently power-cycle a modern mobile transceiver at the sorts of rates that 802.15.4 radios get power-cycled!
  • Performance in ideal conditions favoured TCP, with the article authors managing to achieve 30% of the raw link bandwidth (75kbps of a theoretical 250kbps maximum), with the underlying hardware being fingered as a possible cause for performance issues.
    • Assuming we could manage the same percentage; that would equate to ~360bps on 1200-baud networks, or 2.88kbps on 9600-baud networks.
  • With up to 15% packet loss, TCP and CoAP (its nearest contender) can perform about the same in terms of reliability.
  • A significant factor in effective data rate is CSMA/CA. aioax25 effectively does CSMA/CA too.

Its interesting to note they didn’t try to do anything special with the TCP headers (e.g. Van Jacobson compression). I’ll have to have a look at TCP and see just how much overhead there is in a typical segment, and whether the roughly double MTU of AX.25 will help or not: the article recommends using MSS of approximately 3× the link MTU for “fair” conditions (so ~384 bytes), and 5× in “good” conditions (~640 bytes).

It’s worth noting a 256-byte AX.25 frame takes ~2 seconds to transmit on a 1200-baud link. You really don’t want to make that a habit! So smaller transmissions using UDP-based protocols may still be worthwhile in our application.

6LoWHAM: Thoughts on how to distribute context and applications

So, one evening I was having difficulty sleeping, so like some people count sheep, turned to a different problem…6LoWPAN relies on all nodes sharing a common “context”. This is used as a short-hand to “compress” the rather lengthy IPv6 addresses for allowing two nodes to communicate with one another by substituting particular IPv6 address subnets with a “context number” which can be represented in 4 bits.

Fundamentally, this identifier is a stand-in for the subnet address. This was a sticking-point with earlier thoughts on 6LoWHAM: how do we agree on what the context should be? My thought was, each network should be assigned a 3-bit network ID. Why 3-bit? Well, this means we can reserve some context IDs for other uses. We use SCI/DCI values 0-7 and leave 8-15 reserved; I’ll think of a use for the other half of the contexts.

The node “group” also share a SSID; the “group” SSID. This is a SSID that receives all multicast traffic for the nodes on the immediate network. This might be just a generic MCAST-n SSID, where n is the network ID; or it could be a call-sign for a local network coordinator, e.g. I might decide my network will use VK4MSL-0 for my group SSID (network 0). Probably nodes that are listening on a custom SSID should still listen for MCAST-n traffic, in case a node is attempting to join without knowing the group SSID.

AX.25 allows for 16 SSIDs per call-sign, so what about the other 8? Well, if we have a convention that we reserve SSIDs 0-7 for groups; that leaves 8-15 for stations. This can be adjusted for local requirements where needed, and would not be enforced by the protocol.

Joining a network

How does a new joining node “discover” this network? Firstly, the first node in an area is responsible for “forming” the network — a node which “forms” a network must be manually programmed with the local subnet, group SSID and other details. Ensuring all nodes with “formation” capability for a given network is beyond the scope of 6LoWHAM.

When a node joins; at first it only knows how to talk to immediate nodes. It can use MCAST-n to talk to immediate neighbours using the fe80::/64 subnet. Anyone in earshot can potentially reply. Nodes simply need to be listening for traffic on a reserved UDP port (maybe 61631; there’s an optimisation in 6LoWPAN for 61616-61631). The joining node can ask for the network context, maybe authenticate itself if needed (using asymmetric cryptography – digital signatures, no encryption).

The other nodes presumably already know the answer, but for all nodes to reply simultaneously, would lead to a pile-up. Nodes should wait a randomised delay, and if nothing is heard in that period, they then transmit what they know of the context for the given network ID.

The context information sent back should include:

  • Group SSID
  • Subnet prefix
  • (Optional) Authentication data:
    • Public key of the forming network (joining node will need to maintain its own “trust” database)
    • Hash of all earlier data items
    • Digital signature signed with included public key

Once a node knows the context for its chosen network, it is officially “joined”.

Routing to non-local endpoints

So, a node may wish to send a message to another node that’s not directly reachable. This is, after-all, the whole point of using a routing protocol atop AX.25. If we knew a route, we could encode it in the digipeater path, and use conventional AX.25 source routing. Nodes that know a reliable route are encouraged to do exactly that. But what if you don’t know your way around?

APRS uses WIDEN-n to solve this problem: it’s a dumb broadcast, but it achieves this aim beautifully. n just stands for the number of hops, and it gets decremented with each hop. Each digipeater inserts itself into the path as it sends the frame on. APRS specs normally call for everyone to broadcast all at once, pile-up be damned. FM capture effect might help here, but I’m not sure its a good policy. Simple, but in our case, we can do a little better.

We only need to broadcast far enough to reach a node that knows a route. We’ll use ROUTE-n to stand for a digipeater that is no more than n hops away from the station listed in the AX.25 destination field. n must be greater than 0 for a message to be relayed. AX.25 2.0 limits the number of digipeaters to 8 (and 2.2 to 2!), so naturally n cannot be greater than 8.

So we’ll have a two-tier approach.

Routing from a node that knows a viable route

If a node that receives a ROUTE-n destination message, knows it has a good route that is n or less hops away from the target; it picks a randomised delay (maybe 0-5 seconds range), and if no reply is heard from another node; it relays the message: the ROUTE-n is replaced by its own SSID, followed by the required digipeater path to reach the target node.

Routing from a node that does not know a viable route

In the case where a node receives this same ROUTE-n destination message, does not know a route, and hasn’t heard anyone else relay that same message; it should pick a randomised delay (5-10 second range), and if it hasn’t heard the message relayed via a specific path in that time, should do one of the following:

If n is greater than 1:

Substitute ROUTE-n in the digipeater path with its own SSID followed by ROUTE-(n-1) then transmit the message.

If n is 1 (or 0):

Substitute ROUTE-n with its own SSID (do not append ROUTE-0) then transmit the message.

Routing multicast traffic

Discovering multicast listeners

I’ll have to research MLD (RFC-3810 / RFC-4604), but that seems the sensible way forward from here.

Relaying multicast traffic

If a node knows of downstream nodes that ordinarily rely on it to contact the sender of a multicast message, and it knows the downstream nodes are subscribers to the destination multicast group, it should wait a randomised period, and forward the message on (appending its SSID in the digipeater path) to the downstream nodes.

Application thoughts

I think I have done some thoughts on what the applications for this system may be, but the other day I was looking around for “prior art” regarding one-to-many file transfer applications.

One such system that could be employed is UFTP. Yes, it mentions encryption, but that is an optional feature (and could be useful in emcomm situations). That would enable SSTV-style file sharing to all participants within the mesh network. Its ability to be proxied also lends itself to bridging to other networks like AMPRnet, D-Star packet, DMR and other systems.

Cataloguing Chaos

So, this last 2 years, I’ve been trying to keep multiple projects on the go, then others come along and pile their own projects on top. It kinda makes a mess of one’s free time, including for things like keeping on top of where things have been put.

COVID-19 has not helped here, as it’s meant I’ve lugged a lot of gear that belongs to my workplace, or belongs at my workplace, home, to use there. This all needs tracking to ensure nothing is lost.

Years ago, I threw together a crude parts catalogue system. It was built on Django, django-mptt and PostgreSQL, and basically abused the admin part of Django to manage electronic parts storage.

I later re-purposed some of its code for an estate database for my late grandmother: I just wrote a front-end so that members of the family could be given login accounts, and “claim” certain items of the estate. In that sense, the concept was extremely powerful.

The overarching principle of how both these systems worked is that you had “items” stored within “locations”. Locations were in a tree-structure (hence django-mptt) where a location could contain further “locations”… e.g. a root-level location might be a bed room, within that might be a couple of wardrobes and draws, and there might be containers within those.

You could nest locations as deeply as you liked. In my parts database, I didn’t consider rooms, but I’d have labelled boxes like “IC Parts 1”, “IC Parts 2”, these were Plano StowAway 932 boxes… which work okay, although I’ve since discovered you don’t leave the inner boxes exposed to UV light: the plastic becomes brittle and falls apart.

The inner boxes themselves were labelled by their position within the outer box (row, column), and each “bin” inside the inner box was labelled by row and column.

IC tubes themselves were also labelled, so if I had several sitting in a box, I could identify them and their location. Some were small enough to fit inside these boxes, others were stored in large storage tubs (I have two).

If I wanted to know where I had put some LM311 op-amps, I might look up the database and it’d tell me that there were 3 of them in IC Box 1/Row 2/Row 3/Column 5. If luck was on my side, I’d go to that box, pull out the inner box, open it up and find what I was looking for plugged into some anti-static foam or stashed in a small IC tube.

The parts themselves were fairly basic, just a description, a link to a data sheet, and some other particulars. I’d then have a separate table that recorded how many of each part was present, and in which location.

So from the locations perspective, it did everything I wanted, but parametric search was out of the question.

The place here looks like a tip now, so I really do need to get on top of what I have, so much so I’m telling people no more projects until I get on top of what I have now.

Other solutions exist. OpenERP had a warehouse inventory module, and I suspect Odoo continues this, but it’s a bit of a beast to try and figure out and it seems customisation has been significantly curtailed from the OpenERP days.

PartKeepr (if you can tolerate deliberate bad spelling) is another option. It seems to have very good parametric search of parts, but one downside is that it has a flat view of locations. There’s a proposal to enhance this, but it’s been languishing for 4 years now.

VRT used to have a semi-active track-and-trace business built on a tracking software package called P-Trak. P-Trak had some nice ideas (including a surprisingly modern message-passing back-end, even if it was a proprietary one), but is overkill of my needs, and it’s a pain to try and deploy, even if I was licensed to do so.

That doesn’t mean though I can’t borrow some ideas from it. It integrated barcode scanners as part of the user interface, something these open-source part inventory packages seem to overlook. I don’t have a dedicated barcode scanner, but I do have a phone with a camera, and a webcam on my netbook. Libraries exist to do this from a web browser, such as this one for QR codes.

My big problem right now is the need to do a stock-take to see what I’ve still got, and what I’ve added since then, along with where it has gone. I’ve got a lot of “random boxes” now which are unlabelled, and just have random items thrown in due to lack-of-time. It’s likely those items won’t remain there either. I need some frictionless way to record where things are getting put. It doesn’t matter exactly where something gets put, just so long as I record that information for use later. If something is going to move to a new location, I want to be able to record that with as little fuss as possible.

So the thinking is this:

  • Print labels for all my storage locations with UUIDs stored as barcodes
  • Enter those storage locations into a database using the UUIDs allocated
  • Expand (or re-write) my parts catalogue database to handle these UUIDs:
    • adding new locations (e.g. when a consignment comes in)
    • recording movement of containers between parent locations
    • sub-dividing locations (e.g. recording the content of a consignment)
    • (partial and complete) merging locations (e.g. picking parts from stock into a project-specific container)

The first step on this journey is to catalogue the storage containers I have now. Some are already entered into the old system, so I’ve grabbed a snapshot of that and can pick through it. Others are new boxes that have arrived since, and had additional things thrown in.

I looked at ways I could label the boxes. Previously that was a spirit pen hand-writing a label, but this does not scale. If I’m to do things efficiently, then a barcode seems the logical way to go since it uses what I already have.

Something new comes in? Put a barcode on the box, scan it, enter it into the system as a new location, then mark where that box is being stored by scanning the location barcode where I’ll put the box. Later, I’ll grab the box, open it up, and I might repeat the process with any IC tubes or packets of parts inside, marking them as being present inside that box.

Need something? Look up where it is, then “check it out” into my work area… now, ideally when I’m finished, it should go back there, but if I’m in a hurry, I just throw it in a box, somewhere, then record that I put it there. Next time I need it, I can look up where it is. Logical order isn’t needed up front, and can come later.

So, step 1 is to label all the locations. Since I’m doing this before the database is fully worked-out, I want to avoid ID clashes, I’m using UUIDs to label all the locations. Initially I thought of QR codes, but then realised some of the “locations” are DIP IC storage tubes, which do not permit large square labels. I did some experiments with Code-128, but found it was near impossible to reliably encode a UUID that way, my phone had difficulty recognising the entire barcode.

I returned to the idea of QR-codes, and found that my phone will scan a 10mm×10mm QR code printed on a page. That’s about the right height for the side of an IC tube. We had some inkjet labels kicking around, small 38.1×21.2mm labels arranged in a 5×11 grid (Avery J8651/L7651 layout). Could I make a script that generated a page full of QR codes?

Turns out, pylabels will do this. It is built on reportlab which amongst other things, embeds a barcode generator that supports various symbologies including QR codes. @hugohadfield had contributed a pull request which demonstrated using this tool with QR codes. I just had to tweak this for my needs.

# This file is part of pylabels, a Python library to create PDFs for printing
# labels.
# Copyright (C) 2012, 2013, 2014 Blair Bonnett
# pylabels is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
# pylabels is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along with
# pylabels.  If not, see <>.

import uuid

import labels
from import qr
from reportlab.lib.units import mm

# Create an A4 portrait (210mm x 297mm) sheets with 5 columns and 13 rows of
# labels. Each label is 38.1mm x 21.2mm with a 2mm rounded corner. The margins
# are automatically calculated.
specs = labels.Specification(210, 297, 5, 13, 38.1, 21.2, corner_radius=2,
        left_margin=6.7, right_margin=3, top_margin=10.7, bottom_margin=10.7)

def draw_label(label, width, height, obj):
    size = 12 * mm
            barHeight=height, barWidth=size, barBorder=2))

# Create the sheet.
sheet = labels.Sheet(specs, draw_label, border=True)

sheet.add_labels(range(1, 66))

# Save the file and we are done.'basic.pdf')
print("{0:d} label(s) output on {1:d} page(s).".format(sheet.label_count, sheet.page_count))

The alignment is slightly off, but not severely. I’ll fine tune it later. I’m already through about 30 of those labels. It’s enough to get me started.

For the larger J8165 2×4 sheets, the following specs work. (I can see this being a database table!)

# Specifications for Avery J8165 2×4 99.1×67.7mm
specs = labels.Specification(210, 297, 2, 4, 99.1, 67.7, corner_radius=3,
        left_margin=5.5, right_margin=4.5, top_margin=13.5, bottom_margin=12.5)

Later when I get the database ready (standing up a new VM to host the database and writing the code) I can enter this information in and get back on top of my inventory once again.

New headset: AudioTechnica ATH-G1WL

So, for a decade now, I’ve been looking at a way of un-tethering myself from VoIP and radio applications. Headsets are great, but it does mean you’re chained to whatever it’s plugged into by your head.

Two solutions exist for this: get a headset with a wireless interface, or get a portable device to plug the headset into.

The devices I’d like to use are a combination of analogue and computer-based devices. Some have Bluetooth… I did buy the BU-1 module for my Yaesu VX-8DR years, and still have it installed in the FTM-350AR, but found it was largely a gimmick as it didn’t work with the majority of Bluetooth headsets on the market, and was buggy with the ones it did work with.

Years ago, I hit upon a solution using a wireless USB headset and a desktop PC connected to the radio. Then, the headset was one of the original Logitech wireless USB headsets, which I still have and still works… although it is in need of a re-build as the head-band is falling to pieces and the leatherette covering on the earpieces has long perished.

One bug bear I had with it though, is that the microphone would only do 16kHz sample rates. At the time when I did that set-up, I was running a dual-Pentium III workstation with a PCI sound-card which was fairly frequency-agile, so it could work to the limitations of the headset, however newer sound cards are generally locked to 48kHz, and maybe support 44.1kHz if you’re lucky.

I later bought a Logitech G930 headset, but found it had the same problem. It also was a bit “flat” sounding, given it is a “surround sound” headset, it compromises on the audio output. This, and the fact that JACK just would not talk to it any higher than 16kHz, meant that it was relegated to VoIP only. I’ve been using VoIP a lot thanks to China’s little gift, even doing phone patches using JACK, Twinkle and Zoom for people who don’t have Internet access.

I looked into options. One option I considered was the AstroGaming A50 Gen 4. These are a pricey option, but one nice feature is they do have an analogue interface, so in theory, it could wire direct to my old radios. That said, I couldn’t find any documentation on the sample rates supported, so I asked.

… crickets chirping …

After hearing nothing, I decided they really didn’t want my business, and there were things that made me uneasy about sinking $500 on that set. In the end I stumbled on these.

Reading the specs, the microphone frequency range was 30Hz to 20kHz… that meant for them to not be falsely advertising, they had to be sampling at at least 40kHz. 44.1 or 48kHz was fine by me. These are pricey too, but not as bad as the A50s, retailing at AU$340.

I took the plunge:

RC=0 stuartl@rikishi ~ $ cat /proc/asound/card1/stream0 
Unknown manufacturer ATH-G1WL at usb-0000:00:14.0-4, full speed : USB Audio

  Status: Running
    Interface = 1
    Altset = 1
    Packet Size = 200
    Momentary freq = 48000 Hz (0x30.0000)
  Interface 1
    Altset 1
    Format: S16_LE
    Channels: 2
    Endpoint: 1 OUT (ADAPTIVE)
    Rates: 48000
    Bits: 16

  Status: Running
    Interface = 2
    Altset = 1
    Packet Size = 100
    Momentary freq = 48000 Hz (0x30.0000)
  Interface 2
    Altset 1
    Format: S16_LE
    Channels: 1
    Endpoint: 2 IN (ASYNC)
    Rates: 48000
    Bits: 16

Okay, so these are locked to 48kHz… that works for me. Oddly enough, I used to get a lot of XRUNS in jackd with the Logitech sets… I don’t get any using this set, even with triple the sample rate. This set is very well behaved with jackd. Allegedly the headset is “broadcast”-grade.

Well, not sure about that, but it performs a lot better than the Logitech ones did. AudioTechnica have plenty of skin in the audio game, have done for decades (the cartridge on my father’s turntable… an old Rotel from the late 70s) was manufactured by them. So it’s possible, but it’s also possible it’s marketing BS.

The audio quality is decent though. I’ve only used it for VoIP applications so far, people have noticed the microphone is more “bassy”.

The big difference from my end, is notifications from Slack and my music listening. Previously, since I was locked to 16kHz on the headset, it was no good listening to music there since I got basically AM radio quality. So I used the on-board sound card for that with PulseAudio. Slack though (which my workplace uses), refuses to send notification sounds there, so I missed hearing notifications as I didn’t have the headset on.

Now, I have the music going through the headset with the notification sounds. I miss nothing. PulseAudio also had a habit of “glitching”, momentary drop-outs in audio. This is gone when using JACK.

My latency is just 64msec. I can’t quite ditch PulseAudio, as without it, tools like Zoom won’t see the JACK virtual source/sink… this seems to be a limitation of the QtMultimedia back-end being used: it doesn’t list virtual sound interfaces and doesn’t let people put in arbitrary ALSA device strings (QAudioDeviceInfo just provides a list).

At the moment though, I don’t need to route between VoIP applications (other than Twinkle, which talks to ALSA direct), so I can live with it staying there for now.

Phone patching to Zoom

Brisbane Area WICEN Group (Inc) lately has been caught up in this whole COVID-19 situation, unable to meet face-to-face for business meetings. Like a lot of groups, we’ve had to turn to doing things online.

Initially, Cisco WebEx was trialled, however this had significant compatibility issues, most notably, under Linux — it just straight plain didn’t work. Zoom however, has proven fairly simple to operate and seems to work, so we’ve been using that for a number of “social” meetings and at least one business meeting so far.

A challenge we have though, is that one of our members does not have a computer or smart-phone. Mobile telephony is unreliable in his area (Kelvin Grove), and so yee olde PSTN is the most reliable service. For him to attend meetings, we need some way of patching that PSTN line into the meeting.

The first step is to get something you can patch to. In my case, it was a soft-phone and a SIP VoIP service. I used Twinkle to provide that link. You could also use others like baresip, Linphone or anything else of your choosing. This connects to your sound card at one end, and a Voice Service Provider; in my case it’s my Asterisk server through Internode NodePhone.

The problem is though, while you can certainly make a call outbound whilst in a conference, the person on the phone won’t be able to hear the conference, nor will the conference attendees be able to hear the person on the phone.

Enter JACK

JACK is a audio routing framework for Unix-like operating systems that allows for audio to be routed between applications. It is geared towards multimedia production and professional audio, but since there’s a plug-in in the ALSA framework, it is very handy for linking audio between applications that would otherwise be incompatible.

For this to work, one application has to work either directly with JACK, or via the ALSA plug-in. Many support, and will use, an alternate framework called PulseAudio. Conference applications like Zoom and Jitsi almost universally rely on this as their sound card interface on Linux.

PulseAudio unfortunately is not able to route audio with the same flexibility, but it can route audio to JACK. In particular, JACKv2 and its jackdbus is the path of least resistance. Once JACK starts, PulseAudio detects its presence, and loads a module that connects PulseAudio as a client of JACK.

A limitation with this is PulseAudio will pre-mix all audio streams it receives from its clients into one single monolithic (stereo) feed before presenting that to JACK. I haven’t figured out a work-around for this, but thankfully for this use case, it doesn’t matter. For our purposes, we have just one PulseAudio application: Zoom (or Jitsi), and so long as we keep it that way, things will work.

Software tools

  • jack2: The audio routing daemon.
  • qjackctl: This is a front-end for controlling JACK. It is optional, but if you’re not familiar with JACK, it’s the path of least resistance. It allows you to configure, start and stop JACK, and to control patch-bay configuration.
  • SIP Client, in my case, Twinkle.
  • ALSA JACK Plug-in, part of alsa-plugins.
  • PulseAudio JACK plug-in, part of PulseAudio.

Setting up the JACK ALSA plug-in

To expose JACK to ALSA applications, you’ll need to configure your ${HOME}/.asoundrc file. Now, if your SIP client happens to support JACK natively, you can skip this step, just set it up to talk to JACK and you’re set.

Otherwise, have a look at guides such as this one from the ArchLinux team.

I have the following in my .asoundrc:

pcm.!default {
        type plug
        slave { pcm "jack" }

pcm.jack {
        type jack
        playback_ports {
                0 system:playback_1
                1 system:playback_2
        capture_ports {
                0 system:capture_1
                1 system:capture_1

The first part sets my default ALSA device to jack, then the second block defines what jack is. You could possibly skip the first block, in which case your SIP client will need to be told to use jack (or maybe plug:jack) as the ALSA audio device for input/output.

Configuring qjackctl

At this point, to test this we need a JACK audio server running, so start qjackctl. You’ll see a window like this:

qjackctl in operation

This shows it actually running, most likely for you this will not be the case. Over on the right you’ll see Setup… — click that, and you’ll get something like this:

Parameters screen

The first tab is the parameters screen. Here, you’ll want to direct this at your audio device that your speakers/microphone are connected to.

The sample rate may be limited by your audio device. In my experience, JACK hates devices that can’t do the same sample rate for input and output.

My audio device is a Logitech G930 wireless USB headset, and it definitely has this limitation: it can play audio right up to 48kHz, but will only do a meagre 16kHz on capture. JACK thus limits me to both directions running 16kHz. If your device can do 48kHz, that’d be better if you intend to use it for tasks other than audio conferencing. (If your device is also wireless, I’d be interested in knowing where you got it!)

JACK literature seems to recommend 3 periods/buffer for USB devices. The rest is a matter of experiment. 1024 samples/period seems to work fine on my hardware most of the time. Your mileage may vary. Good setups may get away with less, which will decrease latency (mine is 192ms… good enough for me).

The other tab has more settings:

Advanced settings

The things I’ve changed here are:

  • Force 16-bit: since my audio device cannot do anything but 16-bit linear PCM, I force 16-bit mode (rather than the default of 32-bit mode)
  • Channels I/O: output is stereo but input is mono, so I set 1 channel in, two channels out.

Once all is set, Apply then OK.

Now, on qjackctl itself, click the “Start” button. It should report that it has started. You don’t need to click any play buttons to make it work from here. You may have noticed that PulseAudio has detected the JACK server and will now connect to it. If click “Graph”, you’ll see something like this:

qjackctl‘s Graph window

This is the thing you’ll use in qjackctl the most. Here, you can see the “system” boxes represent your audio device, and “PulseAudio JACK Sink”/”PulseAudio JACK Source” represent everything that’s connected to PulseAudio.

You should be able to play sound in PulseAudio, and direct applications there to use the JACK virtual sound card. pavucontrol (normally shipped with PulseAudio) may be handy for moving things onto the JACK virtual device.

Configuring your telephony client

I’ll use Twinkle as the example here. In the preferences, look for a section called Audio. You should see this:

Twinkle audio settings

Here, I’ve set my ringing device to pulse to have that ring PulseAudio. This allows me to direct the audio to my laptop’s on-board sound card so I can hear the phone ring without the headset on.

Since jack was made my default device, I can leave the others as “Default Device”. Otherwise, you’d specify jack or plug:jack as the audio device. This should be set on both Speaker and Microphone settings.

Click OK once you’re done.

Configuring Zoom

I’ll use Zoom here, but the process is similar for Jitsi. In the settings, look for the Audio section.

Zoom audio settings

Set both Speaker and Microphone to JACK (sink and source respectively). Use the “Test Speaker” function to ensure it’s all working.

The patch up

Now, it doesn’t matter whether you call first, then join the meeting, or vice versa. You can even have the PSTN caller call you. The thing is, you want to establish a link to both your PSTN caller and your conference.

The assumption is that you now have a session active in both programs, you’re hearing both the PSTN caller and the conference in your headset, when you speak, both groups hear you. To let them hear each other, do this:

Go to qjackctl‘s patch bay. You’ll see PulseAudio is there, but you’ll also see the instance of the ALSA plug-in connected to JACK. That’s your telephony client. Both will be connected to the system boxes. You need to draw new links between those two new boxes, and the PulseAudio boxes like this:

qjackctl patching Twinkle to Zoom

Here, Zoom is represented by the PulseAudio boxes (since it is using PulseAudio to talk to JACK), and Twinkle is represented by the boxes named alsa-jack… (tip: the number is the PID of the ALSA application if you’re not sure).

Once you draw the connections, the parties should be able to hear each-other. You’ll need to monitor this dialogue from time to time: if either of PulseAudio or the phone client disconnect from JACK momentarily, the connections will need to be re-made. Twinkle will do this if you do a three-way conference, then one person hangs up.

Anyway, that’s the basics covered. There’s more that can be done, for example, recording the audio, or piping audio from something else (e.g. a media player) is just a case of directing it either at JACK directly or via the ALSA plug-in, and drawing connections where you need them.