We drive long distances in remote places. Sometimes we want people to be able to check-in on us while we are out and about. While cell coverage is getting better we still often find ourselves in places with no coverage.
Often we leave our HF radio tuned to a known frequency (usually 7045 kHz LSB) while we are driving and have VSC or power level squelch enabled. However this has false triggers. When driving through towns there is usually a lot of RF noise and even when we aren’t there’s noise from our car, other HF radios, or even just ionsondes or CW operators.
Random noises while driving are very frustrating. In the commercial space radios are fitted with selective calling (Selcall) functionality. This allows one radio to call another radio provided you know the ID number of the other radio.
The great thing about standards is that there are so many to chose from - Selcall being no exception. While there are many different Selcall variations today we are going to talk about the Codan specific Selcall - specifically the not the CCIR / UN / WA2 / RDD / Customs variants. Nor aircraft SelCal. The proprietary Codan “standard” is what we want to look at. The reason behind this is that there are numerous Selcall users on 7045kHz already using Codan Selcall and while it’s proprietary we can still interoperate with those users.
Modulating
The actual Codan Selcall process is actually pretty well documented with VK5QI already creating an open modulator including some of the less documented features such as channel test modes.
I decided to use freedvtnc2 as a skeleton project as it already has an FSK modem (Codec2), audio and rigctl components. From there I implemented the Selcall protocol while testing and researching some of the extra modes from our Codan 9323. Modulating a Selcall signal was now trivial - but we already knew and had that. What we really wanted was an opensource decoder. Something that could detect Selcalls.
Demodulating
Demodulating is a little bit harder, but given that we know what the signal looks like and Codec2 provides a good FSK demodulator it was not outside my skill level.
Codan Selcalls start with a preamble, usually quite long to allow radios scanning channels enough time to detect the signal. To an extent we can ignore the preamble as the Codec2 modem will handle locking onto the signal for us.
After the preamble there is a phasing pattern. This is a header that is at the start of every Codan Selcall. It’s nearly as simple as looking for this pattern to determine when a Selcall has started. But you don’t want to do an exact match as in HF radio its likely that noise has caused some bits to flip. I settled for a 85% threshold, however I think it could be even lower in practice.
Once the phasing pattern is found it’s matter of decoding the bits as they come in. There’s a few fun things in here. Codan uses a 7 bit word and 3 bits of parity, so you have to handle the incoming data as a series of bits rather than your typical bytes. Parity is only at the word level. There is no checksum on the entire message. The data is effectively sent twice (offset) so if parity fails on one word you might be able to recover it from the other.
The parity is a count of the number of 0’s in the word.
For my demodulator it works like this:
- Store a rolling buffer long enough to fit a Selcall
- Look for phasing pattern
- If a phasing pattern is found try to decode each field - check parity - use the redundant field if required and available
Fun fact - if you are really unlucky both copies of a field could return a successful parity check but have different data - as there is no overall checksum for the message you won’t know which one is correct. When receiving a Selcall we just check if either field is our Selcall ID.
So you decoded a Selcall - what now?
Decoding the Selcall is only part of the process. We need a way of alerting the user that there’s a call for them. It would be really really really nice if ICOM allowed user defined messages (more on this later) and activating a beeper - but in the meantime lets aim for something simple. Rigctl.
When we send a Selcall we actually need to control the rig - turn the radio to data mode, trigger ptt, return the radio to voice mode. Since we already have rigctl for that, how about we use it for alerting the use as well.
The simplest solution I thought of is using the squelch adjust. On our rig you can configure the USB audio output to remain active even when the radio is squelched on the head unit. So the flow looks like this now.
- Squelch the radio to a fairly high level - unlikely to get false triggers
- Software listens for the Selcall
- When it receives a Selcall for our configured ID number use rigctl to unsquelch the radio
- (additionally) if the Selcall requested the channel test mode and the option is enabled send back a test signal
Freeselcall
I built all of this over a couple of days and have called it freeselcall. It’s had some over the air tests - but I wouldn’t say it’s battle hardened.
I realised that most people, myself included, wouldn’t want to use a terminal to perform selcalls so I’ve also added a web interface. It uses websockets so it should be easy to integrate with other systems as well.
(It even has browser notifications for those so inclined)
More than just Selcall
Freeselcall allows for sending and receiving Selcalls with various priority types along with the option for channel tests. However Codan radios can do more. They can do paging (short messages).
Today freeselcall can receive pages. It also has code to send pages however Codan decided to add some security words to process. As it stands a Codan radio will not receive the page messages from freeselcall.
I’ve spent a lot of time in Ghidra along with building a Codan 9323 emulator (it can display the LCD boot up message!) to help reverse engineer how these security bytes work. Hopefully in part 2 I can share how the paging messages work. Emulating a unique flavour of 8051 along with the hardware it connects to has been fun.
The future (and a terrible idea)
As I alluded to earlier - being able to display a message on our ICOM 7100 would be ideal. However there’s no rigctl or CI-V way of displaying a message on the 7100. Or so I thought. It was only when I was dialing in a repeater on the 7100 that I came across an idea that might work. I haven’t tested this, but here’s the plan.
- Dedicate a memory channel for freeselcall.
- When a call comes, if the radio is in memory mode, store what memory the radio is in.
- Use CI-V command to save the current radio state as a memory in the predefined freeselcall memory channel overwriting any existing configuration in that slot.
- Update the channel name with the message / selcall id / ect….
- Tell the radio to load that memory
- After some time has passed and the radio hasn’t PTT’d in awhile, either restore the radio to the memory it was set to or turn off memory mode
I think this will work? But I have no idea until I try
The other addition I want to add is either implementing more sensible Selcall protocols or building a more modern robust one. This can run in parallel for backwards compatibility.
I haven’t even looked into 6 digit pagecall. I haven’t seen it used on amateur bands so I’m not overly interested.
A final note….
Part 2 won’t be coming out until I’ve either been able to emulate the Codan firmware (just because thats cool in its own right) or I’ve been able to figure out the magic for the secret words. The emulator is at the point where I need to have the base and the head unit emulated at the same time and talk via the I2C bus. This shouldn’t be hard, however it’s also not something that is trivial.
Please do not send me yet another a copy of the Codan CCIR 493-4 PDF. This afaik doesn’t contain any information on the secret words and I have enough copies of it from people being helpful.