Как-то раз я прочитал на hackaday.com небольшую заметку об IceRadio . Это проект господина Eric Brombaugh , представляющий собой SDR на базе микроконтроллера STM32 , FPGA производства Lattice серии Ultra или Ultra Plus, АЦП AD9203 или более дорогого ADC14C105, ЦАП CS4344 с интерфейсом I2S , а также тюнера R820T2, используемого в донглах RTL-SDR. Помимо прочего, проект интересен своей модульностью. Он состоит из четырех независимых плат, каждую из которых можно использовать повторно в других проектах. Особенно меня заинтересовал модуль на базе тюнера R820T2 , о котором и пойдет речь в этом посте.

Примечание: Если вдруг вы пропустили вводную статью по Software Defined Radio, вот она — Начало работы с LimeSDR, Gqrx и GNU Radio .

Некоторые компоненты, используемых в модуле, не так-то просто достать. Тюнер R820T2 и генератор на 28.8 МГц проще всего выпаять из RTL-SDR v3 . Устройство продается на eBay. Трансформаторы MABAES0060 ( даташит [PDF] ) были найдены на AliExpress. Прочие же компоненты доступны повсеместно. Плату для модуля я заказал на OSH Park . В итоге получилось следующее:

Модуль на базе тюнера R820T2

Спаять модуль оказалось достаточно просто. Процесс этот особо ничем не примечателен. Главное иметь хороший флюс, паяльную пасту, паяльную станцию с феном, лупу с хорошим увеличением, мультиметр, прямые руки и немного терпения.

Модуль питается от 5 В (на плате есть стабилизатор на 3.3 В), общение с ним происходит по протоколу I2C . Для проверки модуля сначала я взял осциллограф и проверил, что от генератора идет сигнал с частотой 28.8 МГц. Затем я использовал HydraBus чтобы убедиться, что модуль отвечает по I2C:

i2c1> scan
Device found at address 0x1a
i2c1> [ 0x34 0x00 ] [ 0x35 r:1 ]
I2C START
WRITE: 0x34 ACK 0x00 ACK
I2C STOP
I2C START
WRITE: 0x35 ACK
READ: 0x69 NACK
I2C STOP

Напомню, что 0 x 34 — это 7 бит адреса устройства и ноль в младшем бите, означающий запись. По аналогии 0 x 35 соответствует чтению с устройства. Согласно даташитам ( основной даташит [PDF] , описание регистров [PDF] ), устройство имеет 32 регистра, каждый размером один байт. При этом в регистре с адресом 0 x 00 всегда хранится значение 0 x 96.

У устройства есть небольшая странность. При записи используется обычный порядок бит msb-first, однако при чтении данные возвращаются в lsb-first. Поэтому в HydraBus мы увидели 0 x 69 (01101001) вместо 0 x 96 (10010110). Есть и другая странность. Устройство позволяет писать данные по любому адресу, но чтение всегда происходит, начиная с адреса 0 x 00. Таким образом, если требуется прочитать данные из 15-го регистра, нужно прочитать 15 байт.

Манипулировать регистрами R820T2 напрямую — дело довольно нетривиальное, и с нуля научиться правильно их использовать займет далеко не один и не два вечера. К счастью, другие люди уже давно во всем разобрались. За основу я взял библиотеку для STM32 за авторством все того же Eric Brombaugh (он, в свою очередь, также опирался на чужие наработки — см исходники). Я портировал библиотеку на HAL, немного отрефакторил по своему вкусу, и в процессе починил баг в оригинале. Код библиотеки вы найдете в полной версии исходников к этому посту.

Интерфейс библиотеки следующий:

void R820T2_init ( void ) ;
int32_t R820T2_calibrate ( void ) ;
void R820T2_set_frequency ( uint32_t freq ) ;
void R820T2_set_bandwidth ( uint8_t bw ) ;
void R820T2_set_lna_gain ( uint8_t gain_index ) ;
void R820T2_set_mixer_gain ( uint8_t gain_index ) ;
void R820T2_set_vga_gain ( uint8_t gain_index ) ;
void R820T2_set_lna_agc ( uint8_t value ) ;
void R820T2_set_mixer_agc ( uint8_t value ) ;

Все довольно просто — инициализация разбита на две части, init и calibrate. Я хотел убедиться, что калибровка действительно необходима. Оказалось, что необходима, без нее вообще ничего не работает 🙂 Дальше у нас ручки для выставления частоты и полосы пропускания, три ручки для управления gain’ом и две ручки для включения/выключения automatic gain control (по умолчанию оба выключены). Также есть процедуры для хождения напрямую в регистры, но вы скорее всего не должны этого хотеть.

Для удобства была написана прошивка, позволяющая использовать все это хозяйство по UART:

r820t2> help
help              — show this message
scan              — perform I2C scan
dump              — read all registers
read <reg>        — read given register value
(e.g `read 0A`)
write <reg> <val> — write <val> to register <reg>
(e.g. `write 0A E1`)
init              — initialize R820T2
calibrate         — calibrate R820T2
frequency <val>   — set frequency to <val>
(e.g. `frequency 144000000`)
bandwidth <val>   — Set IF bandwidth [0-15]
lna_gain <val>    — Set gain of LNA [0-15]
vga_gain <val>    — Set gain of VGA [0-15]
mixer_gain <val>  — Set gain Mixer [0-15]
lna_agc <val>     — Enable/disable LNA AGC [0-1]
mixer_agc <val>   — Enable/disable Mixer AGC [0-1]
r820t2> dump
96 80 CA FF E0 00 00 00   00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00   00 00 00 00 00 00 00 00
r820t2> init
r820t2> calibrate
r820t2> frequency 432500000
r820t2> bandwidth 15
r820t2> lna_gain 12
r820t2> mixer_gain 12
r820t2> vga_gain 5
r820t2> dump
96 80 BC FF E7 9C 80 6C   80 40 B0 EF 45 63 75 F8
5C 83 80 00 1B 1C 87 30   48 CC 61 00 54 AE 0A C0

Как можно заметить, здесь значения регистров конвертируются в msb-first. Тюнер был настроен на частоту 432.5 МГц с широкой полосой пропускания (значение bandwidth задается от 0 до 15). Если воспользоваться подходящей антенной и подключить выход тюнера к осциллографу, можно увидеть радио-сигналы. Например, такие:

Сигнал с OOK-модуляцией в осциллографе

Узнали? Это же наш старый знакомый, пульт от гаража с OOK-модуляцией . Для полноты картины отмечу, что здесь модуль подключается к осциллографу без нагрузки. Нагрузку в 50 Ом R820T2 не тянет. Само собой разумеется, с тем же успехом можно ловить сигналы с другой несущей и другой модуляцией. Кажется, все работает!

Чисто теоретически, мы уже можем подключить модуль к входу для наушников компьютера, и назвать это SDR. Для этого нам понадобится буфер (например, операционный усилитель в режиме повторителя напряжения), а также фильтр нижних частот . Однако полоса пропускания такого решения составит не более 20 кГц, поскольку звуковая карта все-таки рассчитана на работу со звуком. К тому же, на входе для микрофона вполне могут резаться верхние частоты. В общем, курам на смех.

Для получения чего-то, что будет больше похоже на SDR, нам понадобится приличный АЦП, хотя бы 8-и битный и с частотой дискретизации 5 Msps. Например, уже знакомый нам AD9280 (8 bit, 32 Msps) вполне сгодится. Но в этом случае мы имеем дело с потоком данных не менее 40 Mbps, которые нужно успевать либо передавать на компьютер, либо обрабатывать в реальном времени, либо куда-то сохранять, чтобы обработать потом ( SD-карта класса C6 или C10 должна справиться). Но это уже тема для другой заметки.

Полную версию исходников к посту вы найдете в этом репозитории на GitHub .

Дополнение: Вас также может заинтересовать статья Микроконтроллеры STM32: пишем драйвер для Si5351 .

EnglishRussianUkrainian