Files
opengd77-uv380-sms/patches/patch_sms1.py
T
viktor b5a8e92e45 DMR-данные (SMS) на TYT MD-UV380 под OpenGD77
Восстановлено из транскрипта сессии после потери рабочего дерева на сервере сборки.

Что внутри:
- четыре новых модуля прошивки (приём, сборка исходящего, меню Messages);
- правки существующих файлов в виде скриптов, с порядком применения;
- инструменты стенда: снятие экрана рации по USB, дамп кадров, эталонная сборка пакета;
- NOTES.md: что проверено в эфире, что не доделано, где грабли.

Работало в эфире в августе 2026: данные ходят в обе стороны в режиме хотспота,
рация принимает SMS и показывает на экране. Отправка собрана и сверена с эталоном
сервера побайтово, но в эфире не проверялась.

Claude-Session: https://claude.ai/code/session_01GJtvG5WwqYNe1b7s9LLtgy
2026-09-11 02:39:24 +09:00

61 строка
2.2 KiB
Python

#!/usr/bin/env python3
"""SMS step 1: capture data bursts in normal radio mode too, and route them to an
assembler module. In hotspot mode nothing changes - bursts still go to the host."""
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 "smsRxHandleBurst" in s:
print("HR-C6000.c already routed to the SMS assembler")
else:
old = """ if ((settingsUsbMode == USB_MODE_HOTSPOT) && hrc6000CrcIsValid() && (rxSyncClass == SYNC_CLASS_DATA) &&
((rxDataType == DT_CSBK) || (rxDataType == DT_DATA_HEADER) || (rxDataType == DT_RATE_12_DATA)) &&
hrc6000CheckColourCodeFilter())
{
if (SPI0ReadPageRegByteArray(0x02, 0x00, (uint8_t *)DMR_frame_buffer, LC_DATA_LENGTH) == kStatus_Success)
{
DMR_frame_buffer[AMBE_AUDIO_LENGTH + LC_DATA_LENGTH] = HOTSPOT_RX_DATA_FRAME;
DMR_frame_buffer[AMBE_AUDIO_LENGTH + LC_DATA_LENGTH + 1] = rxDataType;
hrc.hotspotDMRRxFrameBufferAvailable = true;
}
return;
}
"""
assert old in s, "existing capture block not found"
new = """ if (hrc6000CrcIsValid() && (rxSyncClass == SYNC_CLASS_DATA) &&
((rxDataType == DT_CSBK) || (rxDataType == DT_DATA_HEADER) || (rxDataType == DT_RATE_12_DATA)) &&
hrc6000CheckColourCodeFilter())
{
uint8_t dataBurst[LC_DATA_LENGTH];
if (SPI0ReadPageRegByteArray(0x02, 0x00, dataBurst, LC_DATA_LENGTH) == kStatus_Success)
{
if (settingsUsbMode == USB_MODE_HOTSPOT)
{
// Acting as a modem: hand the burst to the host untouched.
memcpy((uint8_t *)DMR_frame_buffer, dataBurst, LC_DATA_LENGTH);
DMR_frame_buffer[AMBE_AUDIO_LENGTH + LC_DATA_LENGTH] = HOTSPOT_RX_DATA_FRAME;
DMR_frame_buffer[AMBE_AUDIO_LENGTH + LC_DATA_LENGTH + 1] = rxDataType;
hrc.hotspotDMRRxFrameBufferAvailable = true;
}
else
{
// Normal radio operation: collect the bursts into a message.
smsRxHandleBurst(dataBurst, rxDataType);
}
}
return;
}
"""
s = s.replace(old, new, 1)
# include the new module
anchor = '#include "functions/hotspot.h"\n'
assert anchor in s, "include anchor missing"
s = s.replace(anchor, anchor + '#include "functions/sms.h"\n', 1)
open(p, "w").write(s)
print("HR-C6000.c: data bursts now captured in normal mode too")