Управление SDR-платами РИТМ в Engee
Для дистанционной работы с SDR-платами DA-AX-FMC-RF9 на машине РИТМ используются EngeeDeviceManager.Targets.RITM_API.SDR — функции программного управления Engee. Подробное описание всех функций приведено на странице Программное управление SDR-платами РИТМ.
В статье приняты следующие сокращения:
-
SDR — программно-определяемая радиосистема;
-
RF — радиочастотная часть;
-
DDS — цифровой синтезатор;
-
JESD — цифровой интерфейс между FPGA и трансивером;
-
FHM — режим перестройки несущей;
-
MCS — синхронизация нескольких плат.
Текущая реализация программного управления рассчитана на два передающих (TX) и два приемных (RX) канала. С помощью программного управления можно обнаружить платы и инициализировать их, управлять несущей, синхронизацией, калибровкой, радиотрактом, затуханием TX, усилением RX и DDS, а также читать состояние платы и линий JESD. Передача и прием массивов I/Q-отсчетов относятся к отдельному интерфейсу.
Как устроено управление
Управление SDR-платами РИТМ в Engee осуществляется с помощью Engee.Интеграции. Engee обменивается данными по AMQP с клиентской программой Engee.Интеграции, установленной на управляющем компьютере пользователя. Клиентская программа обращается по HTTP к менеджеру на машине РИТМ; менеджер выполняет команду ritm-sdr для выбранной платы. Первый аргумент функций SDR — имя зарегистрированной машины, ее сохраненный IP-адрес или полный URL. Имя и IP-адрес должны быть добавлены в Engee; полный URL можно передать напрямую. Аргумент board — идентификатор платы, возвращаемый функцией listBoards, а не порядковый номер платы в списке.
Перед запуском примеров
-
Приложение Engee.Интеграции должно быть запущено и подключено на компьютере пользователя.
-
На машине РИТМ нужна совместимая версия прошивки не ниже
v7.10.0. -
В секции Подготовка замените
RITM 1и192.168.56.3данными своей машины. Идентификаторы плат берите изlistBoards. -
До операций с TX подготовьте RF-подключения: успешное выполнение
initialize,calibrateиsetTxAttenuationв текущей версии драйвера может оставлять радиотракт включенным.
Параметры и порядок работы
Несущая и частота DDS задаются в Гц, границы FHM — в МГц, затухание TX — в миллидецибелах (32_000 = 32 дБ), усиление RX — индексом таблицы, масштаб DDS — в миллионных долях (1_000_000 = 1.0). TX/RX-каналы имеют номера 0 и 1, индексы DDS — от 0 до 3. Для FHM указывайте обе границы в BoardConfig; setFrequency применим к плате, уже инициализированной с FHM. Для MCS конфигурации master и slave передаются одним вызовом initialize; отдельной команды MCS в программном управлении нет.
Выполните подготовку один раз, затем запускайте нужные секции отдельно. Каждая секция меняет состояние оборудования; не выполняйте все секции подряд. Методы изменения возвращают словарь с success и msg, поэтому проверяйте результат. Чтение возвращает значение непосредственно и при неуспешном запросе выбрасывает исключение. Групповая инициализация не атомарна; после ошибки или таймаута сначала прочитайте состояние затронутых плат и только потом решайте, повторять ли команду. Автоматического повтора команд SDR нет. radioOff выключает RF, сохраняя инициализацию; deinitialize завершает работу платы.
Пример использования программного управления для работы с SDR-платами РИТМ
Подготовка
Выполните код ниже один раз в текущей сессии перед выбранной секцией. Он подключает функции программного управления, задает имя машины РИТМ (ritm_name) и при необходимости добавляет ее в Engee через addMachine. Здесь же определяется проверка результата операций. После изменения имени или адреса машины выполните код повторно.
ritm_name = "RITM 1"
if !RITM_API.isMachineExists(ritm_name)
RITM_API.addMachine(ritm_name, "192.168.56.3")
end
sdr = RITM_API.SDR
require_success = result -> begin
if !get(result, "success", false)
message = get(result, "msg", "operation failed")
error("RITM SDR: " * string(message))
end
return result
end
Инициализация одиночной платы
Инициализация платы на фиксированной несущей с внутренней синхронизацией.
let
board_id = 0
carrier_frequency_hz = 300_000_000
config = sdr.BoardConfig(
id=board_id,
frequency_hz=carrier_frequency_hz,
topology="internal",
)
require_success(sdr.initialize(ritm_name, config))
end
Деинициализация одиночной платы
Остановка и деинициализация выбранной платы.
let
board_id = 0
require_success(sdr.deinitialize(ritm_name, board_id))
end
Инициализация двух плат в MCS
Инициализация master и slave одним групповым вызовом. MCS выполняется драйвером во время этой операции; отдельной команды MCS нет.
let
master_id = 0
slave_id = 1
master_frequency_hz = 300_000_000
slave_frequency_hz = 300_000_000
configs = [
sdr.BoardConfig(
id=master_id,
frequency_hz=master_frequency_hz,
topology="master",
),
sdr.BoardConfig(
id=slave_id,
frequency_hz=slave_frequency_hz,
topology="slave",
),
]
require_success(sdr.initialize(ritm_name, configs; slave_fallback=true))
end
Деинициализация двух плат
Деинициализация обеих плат одним групповым вызовом.
let
board_ids = [0, 1]
require_success(sdr.deinitialize(ritm_name, board_ids))
end
Калибровка каналов
Плата должна быть инициализирована. В примере выполняется последовательная калибровка каналов 0 и 1. Драйвер оставляет RF включенным после калибровки, поэтому секция выключает RF в блоке finally.
let
board_id = 0
channels = (0, 1)
results = Dict{Int,Any}()
try
for channel in channels
results[channel] = require_success(
sdr.calibrate(ritm_name, board_id; channel=channel),
)
end
finally
radio_result = sdr.radioOff(ritm_name, board_id)
if !get(radio_result, "success", false)
@warn "Не удалось выключить RF после калибровки" radio_result
end
end
results
end
Установка затухания
Плата должна быть инициализирована. Затухание передатчика задается в миллидецибелах: 32_000 соответствует 32 дБ.
let
board_id = 0
channel = 0
attenuation_mdb = 32_000
require_success(
sdr.setTxAttenuation(ritm_name, board_id, channel, attenuation_mdb),
)
end
Установка чувствительности
Плата должна быть инициализирована. Чувствительность приемника задается индексом таблицы усиления, а не значением в дБ.
let
board_id = 0
channel = 0
gain_table_index = 255
require_success(
sdr.setRxGain(ritm_name, board_id, channel, gain_table_index),
)
end
Контроль RF: включение и выключение
Плата должна быть инициализирована. Первая команда включает радиотракт, вторая выключает его. Запускайте включение только на подготовленном стенде.
let
board_id = 0
enabled = require_success(sdr.radioOn(ritm_name, board_id))
disabled = require_success(sdr.radioOff(ritm_name, board_id))
Dict("enabled" => enabled, "disabled" => disabled)
end
Получение параметров одной платы
Чтение затухания и чувствительности обоих RF-каналов, состояния инициализации и топологии синхронизации. Функции чтения не включают радиотракт — параметры можно читать в любой момент.
let
board_id = 0
channels = (0, 1)
Dict(
"tx_attenuation_mdb" => Dict(
channel => sdr.getTxAttenuation(ritm_name, board_id, channel)
for channel in channels
),
"initialized" => sdr.isInitialized(ritm_name, board_id),
"topology" => sdr.getSyncTopology(ritm_name, board_id),
)
end