In my first post about the IC-706 remote kit I wrote that we don’t really need to care about what data protocol is used between the radio and the front panel; all we need is to route the data between a serial port and a network socket. However, it turns out that taking a closer look at the protocol is not only a good idea but also necessary for efficient remote control.
OK1ZIA has posted some very good documentation about what kind of data is exchanged between the IC-706 radio and the front panel. We can see that the protocol is actually very simple and there are only a few different type of messages exchanged. My own logs revealed that there are also two other kind of messages exchanged during initialization:
R → P : FE F0 FD
R → P : FE F0 FD
R → P : FE F0 FD
R → P : FE F0 FD
R → P : FE F0 FD
R → P : FE F0 FD
R → P : FE F0 FD
R → P : FE F0 FD
R → P : FE F0 FD
R → P : FE F0 FD
P → R : FE F0 FD
P → R : FE F1 FD
R → P : FE F1 FD
I have no idea what they mean, except that they are sent only during power on. I also noticed that when the session ends with a power off both the panel and the radio sends a 0x00 to each other. These messages have no particular significance within the scope of this post, I just wanted to mention them.
Using the analysis done by OK1ZIA and my own observations, I can conclude that there is actually very little data exchanged between the radio and the front panel:
- The panel sends keep-alive messages every 100 ms.
- The panel sends button and knob messages whenever a state changes.
- The radio sends display information every 500 ms or whenever a relevant event occurs (e.g. tuning).
The above listed messages are exchanged asynchronously, i.e. there is no active “dialog” and we don’t have to worry about responding to queries within a certain amount of time.
The only time critical event seems to be the keep-alive messages which are used as watchdog by the radio. If no keep-alive message is received in 200 ms the radio will turn itself off. When using mobile networks we can not rely on a keep-alive message to arrive within 200 ms and so this message will have to be emulated at the server side. The good news is that we will not have to send these messages over the network. Perhaps we can still send them once in a while as a sort of ping between the client and the server, although a different kind of message that also measures latency may turn out tot be more useful for that purpose. In any case, this invalidates my claim that all we need is a simple serial-to-net gateway. Intercepting the messages read from the UART and processing them according to their type can enhance the efficiency of the remote connection.
Now the question arises, how to intercept the messages?
In my previous post I have included a video where you can watch the data being read from the UARTs and exchanged between the client and the server. If you look closely and compare the data dumps with the data format posted by OK1ZIA, you will notice that the data is being read from the UARTs in random chunks. It’s not that we read one message at a time starting with 0xFE and ending with 0xFD. The boundary between consecutive reads is arbitrary and there is hardly a single case where a complete message is read at once instead of being split up in at least two reads.
This fragmentation of the messages is quite unfortunate because it leads to very inefficient use of the network connection and makes interpreting the messages quite difficult.
To get rid of this fragmentation I have added some basic buffering to both the client and the server since the issue exists at both ends. Data is now read from the UARTs until we encounter a 0xFD as the last character. If you take a look at the screenshot below you will see that the messages are no longer split over several lines but always come as multiples of whole messages:
While this increases the efficiency of the network connection is also has an unfortunate side effect. The assumption that message end character 0xFD will only occur at the end of a read operation is false and occasionally leads to large queues containing many messages. You can actually see a large chunk in the top of the screenshot above. As you can see on the screenshot it is a bunch of display updates that get queued up and sent in one big chunk. In practice this will feel like the display is sluggish when you turn the tuning dial. So a little more intelligence will have to be added to the server to ensure that display updates to not get queued up beyond a certain limit. What that limit is is TBD.
But I am making progress 🙂