Как подружить PLUTO и HDSDR

в 13:26, , рубрики: ADALM PLUTO, diy или сделай сам, HDSDR, SDR, Разработка систем связи

Как подружить PLUTO и HDSDR - 1

Не так давно импульсивно купил симпатичный SDR трансивер для детей и юношества – ADALM PLUTO. К моему сожалению он работает с кучей софта под LINUX, а вот мой любимый HDSDR его не поддерживает. Недолго думая стал разбираться с этой проблемой и вот что из этого получилось:

Analog Devices адресует свой PLUTO студентам. Весь софт для PLUTO открытый и находится в свободном доступе. На сайте компании есть страничка, на которой можно найти почти всю необходимую информацию о функционировании PLUTO. Большая часть софта написана под Linux и студентам рекомендуют пользоваться GNU Radio, MATLAB и т.п.

У меня же чисто радиолюбительский интерес к PLUTO. SDR с диапазоном от 70МГц до 6ГГц (после раскрытия) всего за 150 американских денег — это чудо. Сколько всяких экспериментов можно провести! Посмотрите как много там всего интегрировано:

Как подружить PLUTO и HDSDR - 2

По всей видимости AD считает, что радиолюбители сами должны писать драйвера для популярных программ, поэтому до недавнего времени даже SDR# не поддерживался. Но меня SDR# не устраивает, поскольку мне нужна хорошая поддержка CAT в программе для синхронизации частоты с трансивером. HDSDR же хочется попробовать использовать в качестве панорамного приёмника, подключив его к первой промежуточной частоте трансивера. Итак, выход один – интегрировать HDSDR и PLUTO самому.

С помощью гугла я довольно быстро выяснил, что для решения моей задачи нужно создать специальную ExtIO_.dll библиотеку в формате Winrad. Эта библиотека служит программным мостом между HDSDR и желаемым SDR приёмником. К счастью, интерфейс библиотеки неплохо документирован. Кроме того, на github довольно много готовых реализаций библиотек для различных приёмников: RTL_SDR, LimeSDR и пр. Было где подсмотреть как надо писать код. Сама же библиотека совсем олдскульная, никаких новых технологий, чистый C89, как писали лет 20 лет назад. По крайней мере не надо учить новый язык программирования, что уже вселяло надежду на успех.

По сути в ExtIO_.dll нужно реализовать с десяток функций, которые позволяют инициализировать оборудование SDR, запускать и останавливать приём сигнала, сохранять и восстанавливать заданные настройки. Для меня самым непонятным моментом явился формат обмена потоковыми данными между приёмником и HDSDR, но об этом чуть ниже.

Теперь возник вопрос как управлять PLUTO программным способом. На самом деле есть несколько вариантов управления. Я нашёл минимум два: напрямую чипом через библиотеку libad9361.dll, либо через библиотеку IIO. Последний вариант мне показался более простым и хорошо описанным, поэтому остановился на нём. В этой библиотеке все настройки оборудования доступны в виде какого-то подобия XML структуры, обращение к отдельному элементу идёт по текстовому названию свойства, что довольно удобно. Подробнее описание библиотеки можно посмотреть здесь. Огромным преимуществом библиотеки является то, что она поставляется с утилитами командной строки, с помощью которых всегда можно быстро поменять нужную настройку приёмника. Таким образом, не нужно реализовывать все настройки SDR в интерфейсе HDSDR, можно обойтись необходимым минимумом. А загрузку какого-нибудь экзотического FIR фильтра можно сделать из командной строки, если вообще когда-нибудь такая необходимость появится. Потоки данных в IIO:

Как подружить PLUTO и HDSDR - 3

Программно научиться управлять PLUTO из HDSDR получилось довольно быстро и просто. Несколько сложнее было получить удовлетворительный результат по передаче потоковых данных, тем более ранее опыта работы с SDR у меня не было. Тут надо понимать, что данные поступают из SDR приёмника в виде потока I/Q/I/Q … I /Q сэмплов. Каждый сэмпл это без знаковое 16 битное целое число, из которого только 12 младших бит имеют значение. В то же время у HDSDR есть с десяток вариантов принимаемых потоков данных. Какой из них удобнее и лучше не совсем мне понятно. В результате я остановился на варианте, который в ExtIO называется exthwUSBdata16, т.е. фактически один в один как отдаёт данные библиотека IIO.
Следующей проблемой стала передача данных между буферами приёма IIO и HDSDR. Последний принимает данные блоками, кратными 512 байтам, а IIO в таком формате выдавать данные не может. Пришлось сделать промежуточный буфер и передавать поток через него. Код передачи показан ниже.

DWORD WINAPI GeneratorThreadProc( __in  LPVOID lpParameter )
{
	int16_t	iqbuf[EXT_BLOCKLEN * 2];
	ssize_t	nbytes_rx;
	char	*p_dat, *p_end;
	ptrdiff_t	p_inc;

	int	iqcnt = 0; // pointer to sample in iqbuf
	
	while ( !gbExitThread )
	{
		nbytes_rx = iio_buffer_refill(rxbuf);
		p_inc = iio_buffer_step(rxbuf);
		p_end = (char *)iio_buffer_end(rxbuf);
		for (p_dat = (char *)iio_buffer_first(rxbuf, rx0_i); p_dat < p_end; p_dat += p_inc) {

			iqbuf[iqcnt++] = ((int16_t*)p_dat)[0];
			iqbuf[iqcnt++] = ((int16_t*)p_dat)[1];

			if (iqcnt == EXT_BLOCKLEN * 2) { // buffer full
				iqcnt = 0;
				pfnCallback(EXT_BLOCKLEN, 0, 0.0F, &iqbuf[0]);
			}
		}
	}
	gbExitThread = false;
	gbThreadRunning = false;
	return 0;
}

Используя указанный цикл удалось достичь передачи потока в 4 MS/s, выше этого значения данные не успевают передаваться и приём сигнала идёт с заиканиями, хотя железо вроде способно отдавать и 20 MS/s и даже выше. Увеличил приоритет потока, в котором крутится цикл до THREAD_PRIORITY_TIME_CRITICAL, увеличивал размер буферов. Без результата. Причём при увеличении буфера до 1 МБ, нормальный приём был невозможен и на минимальной скорости потока. Больше тут не значит лучше. Если есть идеи как повысить скорость, прошу поделиться в комментариях.

Надо сказать, что 4 MS/s для моих целей вполне достаточно, полоса с лихвой перекрывает любой радиолюбительский КВ диапазон. Да и на УКВ и СВЧ полосы хватит для большинства задач. В результате библиотека написана, окно HDSDR с включенным на приём PLUTO выглядит примерно так:

Как подружить PLUTO и HDSDR - 4

Весь код библиотеки доступен на github здесь. Можете смело использовать его для своих экспериментов с ADALM PLUTO.

73 de R2AJP

Автор: lesha108

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js