Skip to content

draft: ICOM ID-52 PLUS terminal mode over Bluetooth#22

Draft
nullobsi wants to merge 1 commit into
n7tae:masterfrom
nullobsi:test-bluetooth
Draft

draft: ICOM ID-52 PLUS terminal mode over Bluetooth#22
nullobsi wants to merge 1 commit into
n7tae:masterfrom
nullobsi:test-bluetooth

Conversation

@nullobsi

@nullobsi nullobsi commented Jul 8, 2025

Copy link
Copy Markdown
Contributor

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 {
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 data2[0];
}
if ($-currPacketStart-1 < length) {
type::Hex data[length-($-currPacketStart)+1] [[color("0000FF")]];
}
}

};

Packet p[while(!std::mem::eof())] @ 0x00;

</details>

@n7tae

n7tae commented Jul 8, 2025

Copy link
Copy Markdown
Owner

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.

@nullobsi

nullobsi commented Jul 8, 2025

Copy link
Copy Markdown
Contributor Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants