DMR-данные (SMS) на TYT MD-UV380 под OpenGD77
Восстановлено из транскрипта сессии после потери рабочего дерева на сервере сборки. Что внутри: - четыре новых модуля прошивки (приём, сборка исходящего, меню Messages); - правки существующих файлов в виде скриптов, с порядком применения; - инструменты стенда: снятие экрана рации по USB, дамп кадров, эталонная сборка пакета; - NOTES.md: что проверено в эфире, что не доделано, где грабли. Работало в эфире в августе 2026: данные ходят в обе стороны в режиме хотспота, рация принимает SMS и показывает на экране. Отправка собрана и сверена с эталоном сервера побайтово, но в эфире не проверялась. Claude-Session: https://claude.ai/code/session_01GJtvG5WwqYNe1b7s9LLtgy
Этот коммит содержится в:
@@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Patch 2 of RX support: hand received data bursts to the MMDVM host."""
|
||||
W = "/home/viktor/ogd77rel/uv_src/OpenGD77_MDUV380_DM1701_20260130/MDUV380_firmware/application"
|
||||
p = W + "/source/functions/hotspot.c"
|
||||
s = open(p).read()
|
||||
|
||||
if "sendDataFrameToHost" in s:
|
||||
print("already patched")
|
||||
raise SystemExit(0)
|
||||
|
||||
# --- 1. MS sourced data sync pattern (frames we originate towards the host) ---
|
||||
a = "static const uint8_t MS_SOURCED_AUDIO_SYNC[] = { 0x07, 0xF7, 0xD5, 0xDD, 0x57, 0xDF, 0xD0 };\n"
|
||||
assert a in s, "sync constant anchor missing"
|
||||
s = s.replace(a, a + "static const uint8_t MS_SOURCED_DATA_SYNC[] = { 0x0D, 0x5D, 0x7F, 0x77, 0xFD, 0x75, 0x70 };\n", 1)
|
||||
|
||||
# --- 2. the function itself, placed right before the voice header builder ---
|
||||
anchor = "static bool sendVoiceHeaderLC_Frame(volatile const uint8_t *receivedDMRDataAndAudio)\n{"
|
||||
assert anchor in s, "sendVoiceHeaderLC_Frame not found"
|
||||
|
||||
func = '''// Rebuild a packet data burst that was received off air and pass it to the MMDVM host.
|
||||
//
|
||||
// The HR-C6000 hands us the decoded 96 bit payload (it strips the FEC itself), while the
|
||||
// host expects a complete 33 byte DMR burst. So we run the payload back through BPTC,
|
||||
// stamp the data sync pattern and the Slot Type (colour code + data type) into the middle
|
||||
// of the burst, and send it as a normal DMR data frame.
|
||||
static void sendDataFrameToHost(volatile const uint8_t *receivedData, uint8_t dataType)
|
||||
{
|
||||
\tuint8_t frameData[DMR_FRAME_LENGTH_BYTES + MMDVM_HEADER_LENGTH + 2] = {MMDVM_FRAME_START, (DMR_FRAME_LENGTH_BYTES + MMDVM_HEADER_LENGTH + 2), MMDVM_DMR_DATA2, DMR_SYNC_DATA | dataType};
|
||||
|
||||
\tBPTCglobalsInit();
|
||||
\tBPTCencode((uint8_t *)receivedData, frameData + MMDVM_HEADER_LENGTH);
|
||||
|
||||
\t// data sync pattern goes into the middle of the burst
|
||||
\tfor (uint8_t i = 0; i < 7; i++)
|
||||
\t{
|
||||
\t\tframeData[i + EMBEDDED_DATA_OFFSET + MMDVM_HEADER_LENGTH] =
|
||||
\t\t\t\t(frameData[i + EMBEDDED_DATA_OFFSET + MMDVM_HEADER_LENGTH] & ~SYNC_MASK[i]) | MS_SOURCED_DATA_SYNC[i];
|
||||
\t}
|
||||
|
||||
\tDMRSlotTypeEncode(trxGetDMRColourCode(), dataType, frameData + MMDVM_HEADER_LENGTH);
|
||||
|
||||
\tsetRSSIToFrame(frameData);
|
||||
|
||||
\tenqueueUSBData(frameData, frameData[1]);
|
||||
}
|
||||
|
||||
'''
|
||||
|
||||
s = s.replace(anchor, func + anchor, 1)
|
||||
open(p, "w").write(s)
|
||||
print("hotspot.c: sendDataFrameToHost added")
|
||||
Ссылка в новой задаче
Block a user