Сэмплирование в airspy mini

Введение

Я решил немного отвлечься от программирования микроконтроллеров и сделать то, до чего руки давно не доходили: добавить поддержку airspy mini в sdr-server.

airspy mini - это SDR приёмник, который конвертирует аналоговый радиосигнал в цифровой (АЦП) и передаёт в компьютер для обработки. Как и его ближайший и наиболее распространённый конкурент RTL-SDR v3 он основан на чипе R820T. Его основным отличием является хорошая чувствительность и большой динамический диапазон. Это достигается за счёт того, что каждый сэмпл имеет разрешение 12 бит против 8 бит RTL-SDR. Помимо этого airspy mini сэмплирует на достаточно большой скорости и поддерживает только 4 значения: 10Мгц, 6Мгц, 3Мгц и 4.096Мгц. Мне это показалось интересным и я решил разобраться почему.

Супергетеродинный приёмник

Чтобы разобраться что к чему, я решил начать с самого начала: понять как работает супергетеродинный приёмник на примере RTL-SDR.

Если отбросить все ненужные блоки, то схема выглядит следующим образом:

LNA
LNA
TXCO
TXCO
PLL
PLL
R820T
R820T
Mixer
Mixer
Filter
Filter
ADC
ADC
Filter I
Filter I
Filter Q
Filter Q
USB
USB
RTL2832U
RTL2832U
28.8Mhz
28.8Mhz
146Mhz
146Mhz
144Mhz
144Mhz
2Mhz
2Mhz
2Mhz
2Mhz
5Mhz
5Mhz
225KSPS-3.2MSPS
225KSPS-3.2MSPS
225KSPS-3.2MSPS
225KSPS-3.2MSPS
28.8Mhz
28.8Mhz
Mixer 0°
Mixer 0°
Mixer 90°
Mixer 90°
Text is not SVG - cannot display

RTL-SDR состоит из двух частей: аналогового тюнера R820T и цифрового демодулятора RTL2832U. Тюнер предназначен для того, чтобы выделить нужную частоту и преобразовать её до промежуточной. Работать с промежуточной частотой гораздо проще и поскольку она значительно меньше основной, то и требования к элетронике значительно ниже. Второй чип получает на вход сигнал на промежуточной частоте и преобразует в цифровой вид. А вот дальше происходит интересное. RTL2832U создан как приёмник DVB-T сигнала, поэтому он имеет блоки демодуляции DVB-T сигнала, применения автокорректирующих кодов протокола и финальное преобразование в видео-поток. Но умельцы смогли найти специальный режим “тестирования” при котором чип отправляет по USB сырой сигнал. Это и послужило взрывному росту популярности SDR приёмников и RTL-SDR.

Поскольку меня больше всего интересовал принцип сэмплирования, то я решил сосредоточится на нём. Для примера я взял сигнал на частоте 146Мгц. Он попадает в тюнер и через усилитель сигнала в смеситель. Смеситель - это специальный блок, который на вход получает две частоты F1 и F2, а на выходе выдаёт сигнал, где есть F1+F2 и F1-F2. Сумма частот отфильтровывается, а вот разница используется дальше.

Для того, чтобы сгенерировать F2, которая по частоте близка к нужной, используется блок PLL. Он получает на вход крайне стабильную заранее фиксированную частоту. В случае с RTL-SDR - это 28.8Мгц от специального термокомпенсированного генератора (TXCO). Далее, PLL повышает входящую частоту пока она не совпадёт с нужной. В данном случае, чтобы получить частоту близкую к 146Мгц, нужно использовать делитель 5: 28.8 * 5 = 144.

После смесителя нужный сигнал оказывается на частоте 2Мгц. Дальше он фильтруется и отправляется в RTL2832U.

АЦП в RTL2832U работает на частоте 28.8Мгц. На каждый такт АЦП генерирует один сэмпл, поэтому согласно теореме Найквиста-Шеннона на выходе можно получить сигналы от 0 до 14.4Мгц. Но для DVB-T - такое количество сэмплов слишком много, поэтому они дополнительно децимируются. После этого сигнал переводится в I/Q сигнал и отправляется в USB.

Согласно даташиту, RTL2832U позволяет получать частоту из внешнего источника и было бы логично использовать тот же TXCO кристалл и для RTL2832U, но я нигде не нашёл этому подтверждения. Вероятно в RTL2832U используется не такой точный (~100ppm) внутренний кристалл.

К сожалению, спецификации на RTL2832U изначально были закрыты, и даже сейчас информации в Интернете не так много, поэтому остаётся только гадать как именно понижается частота после АЦП. Многие энтузиасты со всего мира пытались проанализировать результат работы тех или иных регистров, и выяснили, что чип может выдавать в USB сэмплы со скоростью от 225Кгц до 3.2Мгц. На практике получалось максимум 2.8Мгц.

Ещё стоит отметить, что вся система работает не с какой-то одной частотой, а с диапазоном частот. Это значит, что приёмник может одновременно получать сигналы с различных устройств. Это активно используется в sdr-server.

airspy mini

В отличие от RTL-SDR, в airspy mini вместо RTL2832U используется полноценный микроконтроллер - LPC4370.

LNA
LNA
PLL
PLL
R820T
R820T
Mixer
Mixer
Filter
Filter
ADCHS
ADCHS
USB
USB
LPC4370
LPC4370
146Mhz
146Mhz
144Mhz
144Mhz
2Mhz
2Mhz
24Mhz
24Mhz
GP_CLKIN
GP_CLKIN
CGU
CGU
12/6/20/8.192Mhz
12/6/20/8.192Mhz
12/6/20/8.192Msps
12/6/20/8.192Msps
12/6/20/8.192Msps
12/6/20/8.192Msps
48/480Mhz
48/480Mhz
Text is not SVG - cannot display

Самое интересное в нём - это два блока:

  • ADCHS - 12-битный АЦП, который может работать на частоте до 80Мгц!
  • CGU, Clock Generation Unit. Он позволяет на уровне конфигурации прошивки связывать разные источники частоты с потребителями. Схематически он выглядит следующим образом:
12 Mhz IRC
12 Mhz IRC
32khz OSC
32khz OSC
Crystal OSC
Crystal OSC
PLL0
(USB0)
PLL0...
PLL0
(Audio)
PLL0...
PLL1
PLL1
IDIVA /4
IDIVA /4
IDIVB /16
IDIVB /16
IDIVC /16
IDIVC /16
IDIVD /16
IDIVD /16
IDIVE /256
IDIVE /256
BASE_SAFE_CLK
BASE_SAFE_CLK
BASE_USB0_CLK
BASE_USB0_CLK
OUTCLK_20/26/27
OUTCLK_20/26/27
BASE_USB1_CLK
BASE_USB1_CLK
OUTCLK_2,4-19
(BASE_XXX_CLK)
OUTCLK_2,4-19...
BASE_AUDIO_CLK
BASE_AUDIO_CLK
CGU
CGU
Oscillators,
clock inputs
Oscillators,...
PLL
PLL
Integer
dividers
Integer...
Output
Generators
Output...
RTCX1
RTCX1
RTCX2
RTCX2
XTAL1
XTAL1
XTAL2
XTAL2
ENET_RX_CLK
ENET_RX_CLK
ENET_TX_CLK
ENET_TX_CLK
GP_CLKIN
GP_CLKIN
Text is not SVG - cannot display

CGU позволяет контролировать совершенно разные часы процессора. Начиная от скорости работы I2C интерфейса, а заканчивая собственной инициализацией. Я раньше не работал с полноценными ARM ядрами, и поэтому такая гибкость меня крайне удивила. Даже в ESP32, на котором основан мой другой проект r2lora, контролирование частот спрятано внутри фреймворка.

Внутри CGU есть множество разных блоков, которые могут быть логически соединены друг с другом. Например, в airspy mini используется источник частоты GP_CLKIN (24Мгц), который далее может быть подсоединён к:

  • PLL, чтобы получить дробное изменение частоты
  • делитель IDIVB, когда нужно получить целочисленное изменение частоты. Например, с 24Мгц получить 3Мгц.
  • соединение напрямую, когда нужно получить максимальную скорость сэмплирования и избежать шумов PLL

Так как один такт АЦП будет создавать 1 сэмпл, то контролируя скорость работы АЦП, можно получить необходимую скорость сэмплирования. Всё просто.

Методом пристального вглядывания в скриншоты платы, я не смог понять используется ли термокомпенсированный генератор (TXCO) частоты. Судя по вот этой фотографии, там есть что-то похожее на внешний генератор:

На официальном сайте ничего про это не написано, но независимые исследователи пишут, что генератор хороший и ppm низкий.

Пример конфигурации

Если вооружиться всем этим знанием, то можно добавить допонительные скорости сэмплирования в конфигурацию. Например, конфигурация 2.4MSPS выглядит так:

{
    /*
      airspy_sys_samplerate_t airspy_m4_conf
    */
    {
        /* PLL0AUDIO */
        0x00000000, // uint32_t pll0audio_mdiv;
        0x00000000, // uint32_t pll0audio_npdiv;
        0x00000000, // uint32_t pll0audio_ctrl_flags; DirectI=PLL0AUDIO_CTRL_FLAG_DIRECT_I or/and DirectO=PLL0AUDIO_CTRL_FLAG_DIRECT_O */
        /* IDIVB not used set it to 0 */
        4, // uint8_t adchs_idivb; /* 0 to 15 (0 means direct connection GP_CLKIN to ADCHS_CLK) */
        { 0, 0, 0 } /* uint8_t padding[3] */
    },
    /* airspy_m0_conf_t airspy_m0_conf */
    {
        1200000, // Freq 4.8MHz => 2.4MHz IQ => IF Freq = 1.2MHz (r820t_if_freq)
        16, // uint8_t r820t_bw;
        0, // uint8_t padding0;
        0 // uint16_t padding1;
    }
}