# DMR-данные (SMS) на TYT MD-UV380 под OpenGD77 Что это: доработка прошивки OpenGD77, которая учит рацию передавать и принимать пакетные данные DMR — текстовые сообщения. В апстриме этого нет: в официальном README прямо написано, что отправка и приём SMS не поддерживаются. Базовый исходник — официальный релиз **R20260131** (ветка `MDUV380_DM1701`), скачан с opengd77.com. Первый коммит в этом репозитории — он же, без единого изменения. Всё, что дальше — наши правки, так что `git diff` первого и второго коммита показывает ровно их. --- ## Что работает (проверено в эфире) **Режим модема (хотспот), обе стороны.** Раньше SMS через рацию-модем молча пропадали: модем подтверждал кадры хосту, а в эфир ничего не уходило. Теперь данные проходят насквозь в обе стороны. Проверено с настоящим сервером и вторым приёмником. **Приём SMS на самой рации.** В обычном режиме (не модем) рация принимает сообщение из эфира, собирает его из кадров, разбирает сетевую обёртку и показывает на экране: отправитель, текст, кнопка OK. **Меню Messages** в главном меню: `New msg`, `Inbox`, `Outbox`; у папок — список сообщений и `Delete All`. Хранится по 6 сообщений на папку, текст до 64 символов (ограничение оперативной памяти, см. ниже). **Отправка с рации** — код написан, собран, но **в эфире не проверялась**. Сборка пакета при этом сверена побайтово с эталоном сервера (два разных сообщения, приватное и групповое, включая контрольные суммы и нарезку на кадры). ## Чего нет - Отправка не проверена в эфире, ввод текста с клавиатуры не написан: `New msg` шлёт фиксированный текст, кнопка «Ответить» — короткое `OK`. - Подтверждение доставки (TMS-ACK) не отправляется: отправитель, запросивший его, покажет «не доставлено», даже если текст на экране появился. - Контрольные суммы принятых блоков не проверяются. - Кириллица не поддержана — символы вне ASCII заменяются на `?`. Нужен кириллический шрифт (в проекте есть образец: отдельный набор для японского). - Режим `rate 3/4` не декодируется (там иное кодирование). Практическое следствие: приватные сообщения от AnyTone напрямую не читаются, групповые `rate 1/2` — читаются. --- ## Как это устроено Ключевая находка: **чип HR-C6000 умеет собирать кадры данных сам** — это уже использовалось прошивкой для пробуждения репитера. Нужно положить 12 байт полезной нагрузки на страницу регистров `0x02` и записать тип кадра в регистр `0x50` (значение — тип из стандарта, сдвинутый на 4 бита). Чип добавит помехоустойчивое кодирование и синхронизацию. Приём симметричен: принятые данные читаются с той же страницы `0x02`. Новые файлы: - `application/source/functions/sms.c` + `include/functions/sms.h` — сборка входящих сообщений, хранилище Inbox/Outbox, очередь передачи. - `application/source/functions/smsSend.c` — построение исходящего пакета: TMS, IP/UDP, контрольная сумма сообщения, заголовок данных, преамбулы. - `application/source/user_interface/menuMessages.c` — экраны меню. Изменённые файлы: - `hardware/HR-C6000.c` — захват кадров данных в обоих режимах, передача данных вместо голоса. - `functions/hotspot.c` — разбор типа кадра от хоста, отправка данных хосту. - `applicationMain.c` — разбор принятого и показ на экране. - `user_interface/menuSystem.{c,h}` — регистрация экранов, пункт меню. - языковые файлы — добавлена строка `messages` (во все 21). --- ## Сборка Проект рассчитан на STM32CubeIDE, Makefile в нём нет — он написан нами: `MDUV380_firmware/Makefile.opengd77`. Нужен `arm-none-eabi-gcc` (проверено на 14.2). ``` cd MDUV380_firmware tools/codec_cleaner.Linux -C # из каталога application/source/linkerdata make -f Makefile.opengd77 -j$(nproc) ``` Первый шаг обязателен: он создаёт пустую секцию под AMBE-кодек, которого в исходниках нет. **Про кодек.** Официально его «донорит» заводская прошивка TYT. Если её нет, кодек можно взять из дампа самой рации (она уже работает в DMR): секция лежит по смещению `0x6937C` от начала образа, длина `0x48BB0`, и в дампе она в открытом виде. Скрипт слияния — в истории работ, логика тривиальна: заменить эту область в собранном `.bin` на область из дампа. Без кодека прошивка соберётся, но DMR работать не будет (только FM). ## Прошивка ``` sudo python3 MDUV380_firmware/tools/opengd77_stm32_firmware_loader.py \ -f OpenMDUV380.bin -m MD-UV380 ``` Рация должна быть в режиме DFU (`0483:df11`) — вход только кнопками при включении, программного способа нет. Нужен `python3-usb` и root. Калибровка и codeplug при прошивке не страдают: они в отдельной микросхеме памяти, прошивается только флеш микроконтроллера. Проверено побайтовым сравнением до и после. --- ## Ловушки, на которые мы потратили время **Не то дерево.** Для MD-UV380 нужна ветка `MDUV380_DM1701` (STM32). Ветка `MK22` — это GD-77/DM-1801/RD-5R, там другая структура и другой код хотспота. Исходники OpenGD77 не публикуются на GitHub — только zip-архивами на сайте. **Линковка кодека.** Современный `ld` отвергает вызов по абсолютному числовому адресу. Адреса AMBE заменены на символы через `.thumb_set` — машинный код получается идентичный (проверено дизассемблером). **Уведомление на экране не годится для показа.** `uiNotificationShow()` из главного цикла затирается штатной перерисовкой экрана. Из-за этого несколько часов казалось, что приём не работает, хотя он работал. Правильно — `menuSystemPushNewMenu(UI_MESSAGE_BOX)`: экран держится до нажатия кнопки. **Правка передачи может сломать голос.** Признак «это кадр данных» ставится только на пути хотспота, а сбрасывается после отправки. Если передача оборвалась, признак залипал — и обычная голосовая передача уходила без заголовка вызова, то есть рация излучала, а приёмники её не понимали. Вывод: любую правку передающего тракта проверять голосом с самой рации, а не только в режиме модема. **Оперативной памяти мало.** Дважды упирались в переполнение при линковке (360 и 240 байт). Отсюда ограничения: 6 сообщений на папку, текст 64 символа. Если понадобится больше — хранить сообщения во флеш-памяти, а не в ОЗУ. **Диагностика.** Счётчики сборщика публикуются в хвост звукового буфера (сигнатура `SMSD`) и читаются по USB штатным протоколом CPS (область 7). Это надёжнее экрана. Тем же протоколом (область 6) можно снимать содержимое экрана рации — удобно для отладки. Осторожно: частый опрос подпирает главный цикл прошивки и мешает приёму. **Режим модема.** Рация входит в него автоматически от первого же кадра MMDVM по USB. Штатно она выходила из него после 20 секунд молчания хоста; по просьбе владельца это заменено на выход при отсоединении USB-хоста — так режим не отваливается при живой программе, но рация сама возвращается в норму, когда кабель вынут. --- ## Лицензия Исходный код OpenGD77 распространяется под собственной лицензией авторов (BSD-подобная, но пункт 4 прямо запрещает коммерческое использование и включение в проекты, допускающие коммерческое использование). Эти правки — производная работа и наследуют те же условия.