draft: ICOM ID-52 PLUS terminal mode over Bluetooth
The code is messy, I'm putting this out there to show that it's possible.
The ID-52 PLUS supports Terminal/Access Point mode over Bluetooth. For me, the mobile apps designed for this purpose (RS-MS3A/I) do not function properly.
I thought QnetGateway was a more featureful option, but it only worked over USB serial. I adapted some of the code to work with the Bluetooth serial connection.
I have tested this patch with my ID-52A PLUS to connect to a couple reflectors with success making a few QSOs.
Important differences:
- When the HT sends voice data packets, it sends them in groups of four with the following format:
struct AMBEFrameBt {
u8 seq;
u8 ambe[9];
u8 slowdata[3];
};
struct VoiceInBt {
u8 counter; // Counts by 1, each one representing a packet of 4
u8 count;
AMBEFrameBt frames[count];
};
- The HT sends this packet with
type = 0x13, the same type QnetITAP uses to ACK single-frame voice packets over USB. - The HT does not 0x23 ACK received single-frame type 0x22 voice packets as it does over USB, although it will play them back.
- Header format is the same, and the HT ACKs headers it receives properly.
TODO:
- [ ] Can we send packets in groups of 4 to the HT? (type = 0x23?)
- [ ] How do we ACK these megapackets from the HT?
(I wrote a shitty "serial log" feature to help me figure out the data format. Included is an imHex "pattern file" to highlight the binary dump.)
ImHex pattern
``` import type.base; import std.mem; u64 currPacketStart;enum Type : u8 { IHeader = 0x10, OHeader = 0x20, VoiceOut = 0x22, VoiceIn = 0x12, VoiceInBt = 0x13, };
struct PollPacket { u8 p; }; struct HeaderPacket<auto Append> { u8 flag[3]; char RPT2[8]; char RPT1[8]; char UR[8]; char MY[8]; char NM[4]; char append[Append]; }; struct VoiceDataOut { u8 counter; u8 sequence; u8 ambe[9] [[color("FF0000")]]; char slowdata[3] [[color("00FF00")]]; };
struct AMBEFrameBt { u8 seq [[color("5601b1")]]; u8 ambe[9] [[color("FF0000")]]; u8 slowdata[3] [[color("00FF00")]]; };
struct VoiceInBt { u8 counter; // Counts by 1, each one representing a packet of 4 u8 count; AMBEFrameBt frames[count]; };
struct Packet {
currPacketStart = addressof(this);
char dir [[color(this == 'O' ? "FFFF00" : "00FFFF")]];
u8 length;
u8 type;
if (!(dir == 'O' && length == 0xFF && type == 0xFF)){
match (dir, length, type) {
(, , Type::IHeader): HeaderPacket<3> packet;
(, , Type::OHeader): HeaderPacket<0> packet;
(, , Type::VoiceOut): VoiceDataOut vd;
(,, Type::VoiceIn): VoiceDataOut vd;
('I', , Type::VoiceInBt): VoiceInBt vd;
(,,): type::Hex
};
Packet p[while(!std::mem::eof())] @ 0x00;
</details>
This is really cool, but the correct way to do this in the QnetGateway universe is to create a new modem type (QnetBT?) rather than hacking up QnetITAP. After all, it's using a completely different character device. It will also be much easier for users to config it and use it.
sure, thanks for the tip; I at least wanted to put this out here, but I'll definitely clean it up and try making a new modem type based on QnetITAP.