mirror of
https://github.com/n0mjs710/ipsc2hbpc.git
synced 2026-11-08 12:26:46 +00:00
IPSC->HBP late entry: test burst E control bits, not the whole byte
Late entry required data[32] == 0x16 exactly. On a weak signal the repeater also sets 0x01 (AMBE frame 1 bad) and 0x80 (embedded LC failed its check). In the OTA capture every 0x80 burst E carried a corrupt LC, while 0x17 carried a good one, so the exact match was right to reject 0x9x but also rejected 0x17 and delayed late entry a superframe. Identify burst E by the embedded-LC-present bit (0x10) and reject it only when the LC-error bit is set. The data[32] flags now share one set of named constants. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
603501e55c
commit
640a952df5
4 files changed
+105
-14
No files matched your search
+8
-9
@@ -58,16 +58,15 @@
|
||||
#define GV_BURST_TYPE_OFF 30
|
||||
#define GV_PAYLOAD_OFF 31
|
||||
#define GV_MIN_LEN 31
|
||||
/* Voice burst control byte (data[32]); bit names after node-dmr-lib DMRVoicePayload. */
|
||||
#define GV_CTRL_OFF 32
|
||||
#define GV_CTRL_LC_ERR 0x80 /* embedded LC failed its check (burst E LC is corrupt) */
|
||||
#define GV_CTRL_SYNC 0x40 /* burst carries voice sync (burst A) */
|
||||
#define GV_CTRL_EMB_LC 0x10 /* reassembled embedded LC present (burst E) */
|
||||
#define GV_CTRL_BAD1 0x01 /* AMBE frame 1 uncorrectable on RF receive */
|
||||
#define GV_AMBE_OFF 33 /* 19-byte AMBE field: three 49-bit frames at bits 0, 50, 100 */
|
||||
/* Repeater-set "bad voice" flags, one per AMBE frame (uncorrectable on RF receive):
|
||||
* frame 1 = data[32] bit 0; frames 2/3 = bits 49/99 of the AMBE field. */
|
||||
#define GV_BAD1_OFF 32
|
||||
#define GV_SYNC_OFF 32 /* data[32] & GV_SYNC_MSK: burst carries voice sync (burst A) */
|
||||
#define GV_SYNC_MSK 0x40
|
||||
#define GV_BAD1_MSK 0x01
|
||||
#define GV_BAD2_BIT 49
|
||||
#define GV_BAD3_BIT 99
|
||||
#define GV_BE_FLAG 0x16 /* data[32] value identifying burst E (carries reassembled LC repeat) */
|
||||
#define GV_BAD2_BIT 49 /* AMBE field bit: frame 2 uncorrectable */
|
||||
#define GV_BAD3_BIT 99 /* AMBE field bit: frame 3 uncorrectable */
|
||||
#define GV_BE_LC_FLCO_OFF 56 /* FLCO of the reassembled LC repeat carried only on burst E */
|
||||
#define FLCO_GROUP 0x00 /* Group Voice Channel User (real call identity); 0x04-0x08 = TA/GPS */
|
||||
#define FLCO_PRIVATE 0x03 /* Unit-to-Unit Voice Channel User (private call) */
|
||||
|
||||
+8
-3
@@ -414,7 +414,12 @@ void translator_ipsc_voice_received(translator *tr, const uint8_t *data, int len
|
||||
* group, UU_V_Ch_Usr for private). A burst E carrying Talker Alias / GPS puts
|
||||
* alias bytes in the header src/dst, so we must not adopt them — wait for the
|
||||
* next voice-LC superframe. */
|
||||
if (len <= GV_BE_LC_FLCO_OFF || data[32] != GV_BE_FLAG) return;
|
||||
int ctrl = data[GV_CTRL_OFF];
|
||||
if (len <= GV_BE_LC_FLCO_OFF || !(ctrl & GV_CTRL_EMB_LC)) return;
|
||||
if (ctrl & GV_CTRL_LC_ERR) {
|
||||
LOGD(LOGN, "IPSC late entry deferred ts=%d — burst E embedded LC failed its check", ts);
|
||||
return;
|
||||
}
|
||||
if (data[GV_BE_LC_FLCO_OFF] != (is_pvt ? FLCO_PRIVATE : FLCO_GROUP)) {
|
||||
LOGD(LOGN, "IPSC late entry deferred ts=%d — burst E embedded LC is not the voice LC "
|
||||
"(flco=0x%02x, Talker Alias/GPS); waiting for voice-LC superframe",
|
||||
@@ -439,14 +444,14 @@ void translator_ipsc_voice_received(translator *tr, const uint8_t *data, int len
|
||||
dmr_bit raw[152]; dmr_bytes_to_bits(data + GV_AMBE_OFF, 19, raw);
|
||||
dmr_bit a1_72[72], a2_72[72], a3_72[72];
|
||||
dmr_bit *a72[3] = {a1_72, a2_72, a3_72};
|
||||
int bad[3] = {data[GV_BAD1_OFF] & GV_BAD1_MSK, raw[GV_BAD2_BIT], raw[GV_BAD3_BIT]};
|
||||
int bad[3] = {data[GV_CTRL_OFF] & GV_CTRL_BAD1, raw[GV_BAD2_BIT], raw[GV_BAD3_BIT]};
|
||||
for (int i = 0; i < 3; i++) {
|
||||
if (bad[i]) dmr_bytes_to_bits(AMBE_SILENCE_MMDVM, 9, a72[i]);
|
||||
else dmr_ambe_49_to_72(raw + 50 * i, a72[i]);
|
||||
}
|
||||
if (bad[0] || bad[1] || bad[2])
|
||||
LOGD(LOGN, "IPSC bad AMBE ts=%d flags=%d%d%d — sent as silence", ts, bad[0], bad[1], bad[2]);
|
||||
if (data[GV_SYNC_OFF] & GV_SYNC_MSK) tr->out_frame_pos[ts] = 0; /* burst A: re-sync superframe */
|
||||
if (data[GV_CTRL_OFF] & GV_CTRL_SYNC) tr->out_frame_pos[ts] = 0; /* burst A: re-sync superframe */
|
||||
int pos = tr->out_frame_pos[ts] % 6;
|
||||
dmr_bit embed[48]; build_embed(tr, ts, pos, embed);
|
||||
dmr_bit fb[264]; int at=0;
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
1 1 800004c313052f9be5000002020000430e0080dd32fe69dc34dd000000000100000a800a00600000000000022f9be50bbebf0011705d
|
||||
1 1 800004c313052f9be5000002020000430e00805d32ff69dc36bd000000000100000a800a00600000000000022f9be50bbebf00116fff
|
||||
1 1 800004c313052f9be5000002020000430e00805d330069dc389d000000000100000a800a00600000000000022f9be50bbebf001170a2
|
||||
1 1 800004c313052f9be5000002020000430e00805d330169dc3a7d000000000100000a800a00600000000000022f9be50bbebf001170f0
|
||||
1 10 800004c313052f9be5000002020000430e00805d330269dc3c5d000000000a1440b80b485d4b2cb60169b678b8ab80b411c83050
|
||||
1 10 800004c313052f9be5000002020000430e00805d330369dc3e3d000000000a1906b801b80da3d0ae00e0771887ececa1c4a8aca88212060612
|
||||
1 10 800004c313052f9be5000002020000430e00805d330469dc401d000000000a1906e81755d603e12609d5b758916881b96bf4fc700f00000616
|
||||
1 10 800004c313052f9be5000002020000430e00805d330569dc41fd000000000a1906e81a0566aebeb3866c736436a981f5c320cc380c03240a16
|
||||
1 10 800004c313052f9be5000002020000430e00805d330669dc43dd000000000a2296c81255ec4ee7ba05cf14ebe2eb81f91dbaf99838a0b333840000004093239bf714
|
||||
1 10 800004c313052f9be5000002020000430e00805d330769dc45bd000000000a19069818796e21d72605c52c727e4691d48d8299b80008000010
|
||||
1 10 800004c313052f9be5000002020000430e00805d330869dc479d000000000a1440e81b5d666fafba074967f011ed81b08a8289b0
|
||||
1 10 800004c313052f9be5000002020000430e00805d330969dc497d000000000a1906e81dd67227cbfa062d771bfde872f2908d48000606060612
|
||||
1 10 800004c313052f9be5000002020000430e00805d330a69dc4b5d000000000a1906866fff4a4a80206789e8bfd72a0cb2c1e49bd80f00002616
|
||||
1 10 800004c313052f9be5000002020000430e00805d330b69dc4d3d000000000a1906a0eded3f0dd168337713e3e0cb0bda62f0b6f80c033c0a16
|
||||
1 10 800004c313052f9be5000002020000430e00805d330c69dc4f1d000000000a2216b0b6b62b255fac1d97a893fe0c03cd21321d4806323b370000000000022f9be514
|
||||
1 10 800004c313052f9be5000002020000430e00805d330d69dc50fd000000000a1906c62d1b61c96731a3d8a3e034ac64c8e51a2eb80098000010
|
||||
1 10 800004c313052f9be5000002020000430e00805d330e69dc52dd000000000a1440c63438be07d035e2ea871ac825e64e54fbb1a8
|
||||
1 10 800004c313052f9be5000002020000430e00805d330f69dc54bd000000000a1906edab6d3d8f9ca5230db4ca65e83b53e9efe0f80606868612
|
||||
1 10 800004c313052f9be5000002020000430e00805d331069dc569d000000000a190680683ebf231520d11728e411273645ae35ec701f40000616
|
||||
1 10 800004c313052f9be5000002020000430e00805d331169dc587d000000000a1906738092b47de89ce515960551a709454bc27b884c033c0c16
|
||||
1 10 800004c313052f9be5000002020000430e00805d331269dc5a5d000000000a221680801e361136202126de02b9e84661dbb22088067633330000000000022f9be514
|
||||
1 10 800004c313052f9be5000002020000430e00805d331369dc5c3d000000000a190684443d42eb01a01585d4a1006808891288c0780000000010
|
||||
1 10 800004c313052f9be5000002020000430e00805d331469dc5e1d000000000a1440809447044d87202c81e5c0b4080b5969063d20
|
||||
1 10 800004c313052f9be5000002020000430e00805d331569dc5ffd000000000a1906909d07b600a22409868862034923d1e82308380002060612
|
||||
1 10 800004c313052f9be5000002020000430e00805d331669dc61dd000000000a1906923d92591236a593ce326bc04a6bfebbf6b3880f00000616
|
||||
1 10 800004c313052f9be5000002020000430e00805d331769dc63bd000000000a1906a4aef45f0bc1252947ece2c7a91981e6e7d5c82c033c0a16
|
||||
1 10 800004c313052f9be5000002020000430e00805d331869dc659d000000000a190690c70f4c8d1da42d974ba1d48a0af0f2f085800636333310
|
||||
1 10 800004c313052f9be5000002020000430e00805d331969dc677d000000000a1906a0aa9d2ec858a82f4bcfe16d0a0cb9d2e41cf00000000010
|
||||
1 10 800004c313052f9be5000002020000430e00805d331a69dc695d000000000a1440a0c84f220126a833534782b14a0c4269343d50
|
||||
1 10 800004c313052f9be5000002020000430e00805d331b69dc6b3d000000000a1906a0ac472147f52c1be595591aeb63ba41bef7700606069686
|
||||
1 10 800004c313052f9be5000002020000430e00805d331c69dc6d1d000000000a1906b86e7a8fcb96ae0f8a8812e7cae143400363b80f04000616
|
||||
1 10 800004c313052f9be5000002020000430e00805d331d69dc6efd000000000a1906b8e2e1fb505caddf4512ce700c4c514235bf608c033c0a16
|
||||
1 10 800004c313052f9be5000002020000430e00805d331e69dc70dd000000000a2216c1a074198fe5b4240dc418b0ae252978049fa8063631330000000000022f9be514
|
||||
1 10 800004c313052f9be5000002020000430e00805d331f69dc72bd000000000a19069c38571b4fa2398f950dc1e40e830f6a06f7c80080000010
|
||||
1 10 800004c313052f9be5000002020000430e00805d332069dc749d000000000a1440d85bcd46a330b5da90d652872d86eaa01a9dd8
|
||||
1 10 800004c313052f9be5000002020000430e00805d332169dc767d000000000a1906ed2fab109f098311ce22deb52b8623477512880606060612
|
||||
1 10 800004c313052f9be5000002020000430e00805d332269dc785d000000000a1906c842279f512e26cded88e7c08e82a9a186fd588f00000616
|
||||
1 10 800004c313052f9be5000002020000430e00805d332369dc7a3d000000000a1906e82a92238fcfb5ca8581d50ccd72cbab04c0c00c033d0a16
|
||||
1 10 800004c313052f9be5000002020000430e00805d332469dc7c1d000000000a2217992867afb8e1ba0b2ea261dfaa815b53e292c806363b330000000000022f9be514
|
||||
1 10 800004c313052f9be5000002020000430e00805d332569dc7dfd000000000a1906b81a328fa9c9b205ce5592970c81f54b20aea80000240010
|
||||
1 10 800004c313052f9be5000002020000430e00805d332669dc7fdd000000000a1440c81255a6ebb626059daac0512981d23b209200
|
||||
1 10 800004c313052f9be5000002020000430e00805d332769dc81bd000000000a1906dd1465e20189a60aae0e50a0ac81273424b2880606060612
|
||||
1 10 800004c313052f9be5000002020000430e00805d332869dc839d000000000a1906c82d246e234ea2458b766b3eee82df7b2417880f00000416
|
||||
1 10 800004c313052f9be5000002020000430e00805d332969dc857d000000000a1906e810b429aba532079df4e3ea2c81755bfef2780e023c0a16
|
||||
1 10 800004c313052f9be5000002020000430e00805d332a69dc875d000000000a2216c818ff444fdaae0b2a6602abc9cf365a7e0a68063633330000000000022f9be514
|
||||
1 10 800004c313052f9be5000002020000430e00805d332b69dc893d000000000a1907be1a351a659bb5cb1e0f28f0400000000800000000000010
|
||||
1 0 800004c313052f9be5000002020000430e00805d332c69dc8b1d000000000002000a800a00600000000000022f9be504b1b000107011
|
||||
+42
-2
@@ -194,7 +194,47 @@ int main(void)
|
||||
}
|
||||
}
|
||||
printf("Superframe re-sync (IPSC->HBP): %d burst A checked, %d failures\n", sync_seen, sync_fails);
|
||||
translator_free(tr);
|
||||
|
||||
translator_free(tr); ev_free(loop);
|
||||
return (fails || in_fails || bad_fails || sync_fails) ? 1 : 0;
|
||||
/* ---- late entry on weak signal (IPSC->HBP): weak-signal call 3120101 -> TG 2.
|
||||
* Joining at packet 4, the first burst E (packet 8, ctrl 0x96) has a corrupt LC and
|
||||
* must be skipped; anchor on packet 14 (0x16). Joining at packet 33, the first
|
||||
* burst E (packet 38, ctrl 0x17: voice frame bad, LC good) is usable. ---- */
|
||||
static const int le_join[2] = {4, 33}, le_anchor[2] = {14, 38};
|
||||
int le_fails = 0;
|
||||
for (int c = 0; c < 2; c++) {
|
||||
tr = translator_new(&cfg, loop);
|
||||
translator_set_protocols(tr, (struct ipsc *)1, (struct hbp *)1);
|
||||
ncap = 0;
|
||||
int idx = -1, anchor = -1;
|
||||
fi = fopen("tests/lateentry_ipsc_in.txt", "r");
|
||||
while (fi && fgets(line, sizeof line, fi)) {
|
||||
int ts, bt; char hex[400];
|
||||
if (sscanf(line, "%d %d %399s", &ts, &bt, hex) != 3) continue;
|
||||
idx++;
|
||||
if (idx < le_join[c] || bt == 1 || (bt & 0x7F) == 0x13) continue;
|
||||
uint8_t raw[400]; int n = unhex(hex, raw);
|
||||
int before = ncap;
|
||||
translator_ipsc_voice_received(tr, raw, n, ts, bt);
|
||||
if (anchor < 0 && ncap > before) anchor = idx;
|
||||
}
|
||||
if (fi) fclose(fi);
|
||||
if (anchor != le_anchor[c]) {
|
||||
fprintf(stderr, "FAIL late entry: joined at %d, anchored at packet %d, want %d\n", le_join[c], anchor, le_anchor[c]);
|
||||
le_fails++;
|
||||
}
|
||||
for (int i = 0; i < ncap; i++) {
|
||||
unsigned src = (unsigned)(cap[i][5]<<16 | cap[i][6]<<8 | cap[i][7]);
|
||||
unsigned dst = (unsigned)(cap[i][8]<<16 | cap[i][9]<<8 | cap[i][10]);
|
||||
if (src != 3120101 || dst != 2) {
|
||||
fprintf(stderr, "FAIL late entry: joined at %d, DMRD[%d] %u->%u, want 3120101->2\n", le_join[c], i, src, dst);
|
||||
le_fails++; break;
|
||||
}
|
||||
}
|
||||
translator_free(tr);
|
||||
}
|
||||
printf("Late entry on weak signal (IPSC->HBP): %d failures\n", le_fails);
|
||||
|
||||
ev_free(loop);
|
||||
return (fails || in_fails || bad_fails || sync_fails || le_fails) ? 1 : 0;
|
||||
}
|
||||
Reference in new issue
Block a user