DMR-данные (SMS) на TYT MD-UV380 под OpenGD77
Восстановлено из транскрипта сессии после потери рабочего дерева на сервере сборки. Что внутри: - четыре новых модуля прошивки (приём, сборка исходящего, меню Messages); - правки существующих файлов в виде скриптов, с порядком применения; - инструменты стенда: снятие экрана рации по USB, дамп кадров, эталонная сборка пакета; - NOTES.md: что проверено в эфире, что не доделано, где грабли. Работало в эфире в августе 2026: данные ходят в обе стороны в режиме хотспота, рация принимает SMS и показывает на экране. Отправка собрана и сверена с эталоном сервера побайтово, но в эфире не проверялась. Claude-Session: https://claude.ai/code/session_01GJtvG5WwqYNe1b7s9LLtgy
Этот коммит содержится в:
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Fix: a stale "this frame is packet data" marker could suppress the Voice LC Header
|
||||
of an ordinary voice transmission.
|
||||
|
||||
hrc.txDataType is only ever set on the hotspot path, and was only cleared after a data
|
||||
burst was actually sent. If a data transmission was cut short before that, the marker
|
||||
stayed set - and the next PTT from the radio itself started without a Voice LC Header,
|
||||
so receivers never recognised the call.
|
||||
|
||||
Two guards:
|
||||
- the start-of-transmission checks now only apply while acting as a hotspot modem;
|
||||
- the marker is cleared whenever a normal (non-hotspot) transmission begins.
|
||||
"""
|
||||
W = "/home/viktor/ogd77rel/uv_src/OpenGD77_MDUV380_DM1701_20260130/MDUV380_firmware/application"
|
||||
p = W + "/source/hardware/HR-C6000.c"
|
||||
s = open(p).read()
|
||||
|
||||
if "isHotspotDataTx" in s:
|
||||
print("already patched")
|
||||
raise SystemExit(0)
|
||||
|
||||
# 1. helper right after the struct instance, so all three call sites can use it
|
||||
anchor = "\t\t.txDataType = HOTSPOT_TX_TYPE_VOICE,\n"
|
||||
assert anchor in s, "hrc initialiser not found"
|
||||
|
||||
# find the end of the initialiser block to place the helper after it
|
||||
marker = "static void hrc6000SendPcOrTgLCHeader(void);"
|
||||
assert marker in s, "forward declaration anchor not found"
|
||||
helper = """// True only when the frame about to be sent is a packet data burst queued by the host.
|
||||
// Outside hotspot mode there is no such thing, so ordinary voice transmissions are never
|
||||
// affected by a leftover marker.
|
||||
static inline bool isHotspotDataTx(void)
|
||||
{
|
||||
return ((settingsUsbMode == USB_MODE_HOTSPOT) && (hrc.txDataType != HOTSPOT_TX_TYPE_VOICE));
|
||||
}
|
||||
|
||||
"""
|
||||
s = s.replace(marker, marker + "\n" + helper, 1)
|
||||
|
||||
# 2. use it in the three start-of-transmission checks
|
||||
a1 = "\t\t\tif (hrc.txDataType != HOTSPOT_TX_TYPE_VOICE)\n\t\t\t{\n\t\t\t\t// A data burst is queued: don't announce a voice call in front of it."
|
||||
assert a1 in s, "TX_START_1 check not found"
|
||||
s = s.replace(a1, "\t\t\tif (isHotspotDataTx())\n\t\t\t{\n\t\t\t\t// A data burst is queued: don't announce a voice call in front of it.", 1)
|
||||
|
||||
a2 = "((hrc.txDataType != HOTSPOT_TX_TYPE_VOICE) ? (DT_IDLE << 4) : 0x10)"
|
||||
n2 = s.count(a2)
|
||||
assert n2 == 2, "expected 2 shared checks, found %d" % n2
|
||||
s = s.replace(a2, "(isHotspotDataTx() ? (DT_IDLE << 4) : 0x10)")
|
||||
|
||||
# 3. and in the ongoing-TX branch, so a stale marker cannot divert voice frames either
|
||||
a3 = "\t\t\t\t\tif (hrc.txDataType != HOTSPOT_TX_TYPE_VOICE)\n"
|
||||
assert a3 in s, "TX_2 data branch not found"
|
||||
s = s.replace(a3, "\t\t\t\t\tif (isHotspotDataTx())\n", 1)
|
||||
|
||||
# 4. belt and braces: clear the marker when a non-hotspot transmission starts
|
||||
a4 = """ if (settingsUsbMode != USB_MODE_HOTSPOT)
|
||||
{
|
||||
codecInit(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
hrc.hotspotPostponedFrameHandling = (HS_NUM_OF_SILENCE_SEQ_ON_STARTUP * 6);"""
|
||||
assert a4 in s, "TX start branch not found"
|
||||
s = s.replace(a4, """ if (settingsUsbMode != USB_MODE_HOTSPOT)
|
||||
{
|
||||
hrc.txDataType = HOTSPOT_TX_TYPE_VOICE;// plain voice call: never a data burst
|
||||
codecInit(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
hrc.hotspotPostponedFrameHandling = (HS_NUM_OF_SILENCE_SEQ_ON_STARTUP * 6);""", 1)
|
||||
|
||||
open(p, "w").write(s)
|
||||
print("HR-C6000.c: voice transmissions can no longer be suppressed by a stale data marker")
|
||||
Ссылка в новой задаче
Block a user