История эта началась три года назад, когда я осознал, что мне скоро исполнится 50 лет, что я погряз в бумажной работе, и что мне хочется чего-то нового. Работу поменять в моём возрасте уже проблематично, поэтому я решил начать pet-проект.
Первое, что приходит в таких случаях на ум старому радиолюбителю: новая радиостанция. Стопроцентно аппаратные решения остались в далёком прошлом. Сейчас гораздо более актуальны SDR-трансиверы: решение это программно-аппаратное, есть опубликованные примеры реализации, к некоторым из них даже выложены исходные коды прошивок.
Основная проблема в разработке заключалась в том, что несложные SDR-радиостанции, работающие в связке со звуковой картой, требуют наличия у компьютера, к которому они подключены, двухканальных линейных входа и выхода для работы приёмо-передающего тракта, а также COM-порта для работы CAT-интерфейса. В современных же ноутбуках аудиовход обычно предназначен для подключения микрофона гарнитуры и бывает только монофоническим.
Решением проблемы стала реализация составного устройства USB, состоящего из виртуального COM-порта и дуплексной звуковой карты. Кому интересно, как я с этим справился, не имея опыта программирования, милости прошу под cut.
TL/DR: Как я с этим справился, не имея опыта программирования? Просто начал программировать на C, а остальное приложилось само: MVP проекта реализован, а исходные коды публикуемой реализации составного устройства USB, состоящего из виртуального COM-порта и дуплексной звуковой карты находятся здесь: http://github.com/dmitrii-rudnev/selenite-habr
… и опыт, сын ошибок трудных...
И опыт и навыки формируются практикой. Для их формирования необходимо:
- изучать документацию;
- проводить анализ существующих решений;
- разрабатывать собственные решения;
- воплощать собственные решения в «железе»;
- возвращаться к началу цикла если не заработало.
Любую технологию освоить гораздо проще, когда понимаешь, для решения каких проблем она в своё время создавалась.
Язык C разрабатывался инженерами и для инженеров. Использование языка программирования C дало мне возможность абстрагироваться от ассемблера и машинных кодов с одной стороны, но в тоже время обращаться напрямую к регистрам или к памяти.
Нелюбимый многими STM32CubeMX с библиотекой HAL значительно облегчил мне процесс разработки хотя бы тем, что не надо было за каждой мелочью заглядывать в Reference Manual.
Кроме того, я очень многому научился, разбирая сгенерированный STM32CubeMX код:
- его писали разные люди, но он выдержан в одном стиле;
- назначение переменных и функций понятно из имени;
- комментарии к коду позволяют документировать его через Doxygen и т.п.
Так или иначе, но за несколько месяцев упражнений с STM32CubeMX и изучения чужого кода мне удалось научиться писать и оформлять свой код так, что коллеги-программисты, к которым приходилось обращаться за советами, перестали при виде меня ехидно улыбаться.
В силу того, что я не мог гарантировать результат своей программистской деятельности, пришлось вводить градации по функционалу MVP проекта от простого к сложному.
Минимальный функционал MVP подразумевал подключение приёмной части радиостанции к линейному входу звуковой карты компьютера и приём на фиксированной частоте.
Следующим шагом планировалась реализация перестройки частоты через CAT-интерфейс, подключение приёмного и передающего трактов радиостанции к линейным входу и выходу звуковой карты и приём-передача на любительских диапазонах.
И только после этого планировалось подключение SDR-трансивера к компьютеру как звукового устройства USB с управлением по CAT-интерфейсу.
Такой подход сразу дал плоды: уже к началу 2019 года, всего через шесть месяцев после установки на мой компьютер STM32CubeMX, был реализован минимальный MVP проекта: функциональный аналог SDR-приёмника Softrock Lite II RX уверенно принимал сигналы точного времени на частоте 9996 кГц.
В настоящее время MVP проекта является функциональным аналогом SDR-трансивера Peaberry SDR V2 и работает как на приём, так и на передачу.
Структура приёмопередающего тракта SDR-трансивера
Описываемое в публикации составное устройство USB работает в составе SDR-трансивера. Структура приёмопередающего тракта разрабатываемого SDR-трансивера включает в себя пока только самый необходимый минимум и представлена на рисунке ниже:
При приёме радиосигнал поступает из антенны через полосовой фильтр (BPF) в квадратурный детектор (QSD). Полученный в результате квадратурный сигнал (IQ) через двухканальный вход дуплексного звукового устройства USB поступает в компьютер для дальнейшей обработки.
При передаче сформированный в компьютере квадратурный сигнал (IQ) через двухканальный выход дуплексного звукового устройства USB поступает в квадратурный возбудитель (QSE).
Полученный в результате радиосигнал подаётся через полосовой фильтр (BPF) в антенну.
Обработка сигналов на стороне компьютера осуществляется программой HDSDR.
Частота приёма и передачи задаётся настройками генератора плавного диапазона (VFO). Управление VFO и режимом работы (приём-передача) осуществляется из программы HDSDR через CAT-интерфейс, подключенный к виртуальному COM-порту.
Связь HDSDR с виртуальным COM-портом осуществляется посредством программы OmniRig, созданной канадским радиолюбителем Alex Shovkoplyas (VE3NEA).
CAT-интерфейс трансивера использует ограниченный набор команд популярного во всём мире трансивера Yaesu FT-817.
Виртуальный COM-порт и дуплексное звуковое устройство объединены в составное устройство USB, работа которого и будет разобрана в данной публикации. Для облегчения проверки работоспособности публикуемого решения на входные и выходные потоки устройств установлены шлейфы.
Вся необходимая для разработки описанного в публикации составного устройства USB документация была найдена поиском по сайту usb.org.
Техническое решение разрабатывалось на основе анализа созданной немецким радиолюбителем Andreas Richter (DF8OE) open source прошивки для трансивера mcHF M0NKA и его клонов. Ряд нюансов был проработан при попытках разобраться в кодах дуплексного звукового устройства USB на базе расширения X-CUBE-AUDIO для STM32CubeMХ.
Структура составного устройства USB
Описываемое в публикации составное устройство USB состоит из виртуального COM-порта и дуплексного звукового устройства USB 16 бит 48 кГц. Публикуемое решение реализовано на микроконтроллере STM32F446ZET6 из состава платы NUCLEO-F446ZE.
Упрощенная структура дескриптора представлена на рисунке ниже:
Дескриптор составного устройства USB создан по рекомендациям, содержащимся в документе:
[1] USB Interface Association Descriptor Device Class Code and Use Model. rev.1.0. July 23 2003
Хотел бы заострить внимание на том, что в структуре дескриптора составного устройства USB важен порядок описания интерфейсов: сначала идёт описание интерфейса 0, затем интерфейса 1 и т.д. Номера используемых интерфейсами конечных точек (EP) могут идти не по порядку.
При генерации кода STM32CubeMX размещает дескриптор устройства (Device Descriptor) в файле usbd_desc.c. Нужно отметить, что STM32CubeMX при последующей генерации кода не сохранит изменения, вручную внесённые в дескриптор, т.к. они не находятся в области, помеченной как USER CODE.
Дескрипторы конфигурации и классов устройств размещаются в файлах usbd_cdc.c и usbd_audio.c, размещённых в папках директории Middlewares/ST/Class. Важно помнить, что STM32CubeMX даёт выбрать за раз только один класс устройств. Если ранее был выбран другой класс, при генерации кода файлы с драйверами этого класса из проекта будут удалены.
От автора
В следующей части публикации будет разобрана:
- подготовка проекта в STM32CubeMX;
- настройка параметров звукового устройства USB;
- работа звукового устройства USB, которое STM32CubeMX генерирует по умолчанию «из коробки».
Читайте продолжение:
Составное устройство USB на STM32. Часть 2: USB Audio Speaker
Больше информации в моём телеграм-канале «Проект Селенит»