05.10.2011 Структура программного приёмника

Материал из SRNS
Перейти к: навигация, поиск

Logo SR31

Содержание

Данный материал написан с целью знакомства с организацией и модульной структурной программного приёника.

Структура каталога исходников

В каталоге исходников есть несколько подкаталогов, каждый из которых отвечает за определённый блок приёмника.

  • Makefile - правила сборки проекта для программы make;
  • main.c - файл, с которого начинается исполнение программы;
  • Common - здесь хранятся заголовочные файлы *.h;
  • RFint - каталог для программы-интерфейса с платой ввода данных;
  • Correlator - здесь расположены исходники программного коррелятора;
  • Detector - блок быстрого поиска сигнала;
  • Tracker - следящие системы (ФАП, ССЗ, ЧАП) и допоиск;
  • Solution - блок решения навигационной задачи;
  • Interf - блок интерфейса (вывод данных на экран).

Кроме того, есть вспомогательные каталоги:

  • lib - библиотеки, используемые в проекте (например, FFTW);
  • Downloader - программа, записывающая выборку сигнала в файл;
  • Simulator - программа-симулятор, формирующая тестовую выборку данных;
  • OffSolver - программа, решающая навигационную задачу по записям приёмника в логах;
  • Convertor - программа преобразования бинарных форматов файлов.

Описание отдельных частей приёмника

Заголовочные файлы (каталог Common)

В данном каталоге расположены заголовочные файлы, общие для разных блоков приёмника. Кроме того, здесь собраны настройки приёмника.

  • global.h - главный заголовочный файл, здесь описаны структуры хранения данных о каналах;
  • RF_desc.h - описание частотного плана (частота дискретизации, промежуточная частота и прочее);
  • gps_desc.h - параметры сигнала GPS C/A;
  • ph_consts.h - разные константы (скорость света, pi и прочее);
  • cputick.h - макросы для точного измерения времени исполнения.

Коррелятор (Correlator)

Коррелятор - наиболее вычислительно сложная и ответственная часть программного приёмника. Достаточно большие усилия потрачены были для того, чтобы блок коррелятора успевал исполнятся с необходимой скоростью. Коррелятор должен успевать за темпом поступления входных данных - это блок реального времени. Небольшие изменения в данном блоке могут привести к его неработоспособности - к этому вопросу надо относиться серьёзно.

Интерфейс с коррелятором описан в файле correlator.h. Предполагается, что управление коррелятором осуществляется не непостредственно, а с использованием макросов, описанных в данном файле. Например, для установки номинальной частоты опорного сигнала можно использовать макрос PHASEAdd(w):

 Parm->corr->PhaseAdd = PHASEAdd( (wi + Parm->xf[1] ));	     

Данный фрагмент кода, позаимствованный из tracker.c, записывает в коррелятор код частоты. Код частоты рассчитывается макросом PHASEAdd(w), в качестве параметра которому передаётся сумма номинальной промежуточной частоты wi и текущая оценка смещения частоты Parm->xf[1]. Частоты заданы в рад/с.

Использовать данные макросы необходимо, т.к. в случае изменения коррелятора достаточно будет переписать только макросы, а остальные блоки приёмника при этом не будут затронуты.

Блок быстрого поиска (Detector)

В программном приёмнике используется блок быстрого поиска, основанный на БПФ. Возможно использование библиотеки FFTW (она работает быстрее), либо собственной реализацией БПФ (она работает медленнее).

Блок быстрого поиска - зарегистрированная программа, свидетельство № 2010613888.

Структура блока быстрого поиска рассчитана на поиск только сигналов с периодичной ПСП, таких, как GPS C/A. На данный момент блок расчитан на поиск только сигнала GPS C/A, но возможна его переделка и на другие виды сигналов.

Блок поиска имеет свой отдельный процесс detector, исполняясь параллельно с другими блоками приёмника. Для того, чтобы искать сигнал, нужно указать режим поиска для требуемого канала:

     Chnl[iS].mode = Searching;

После обнаружения сигнала блок поиска автоматически передаст сигнал на слежение.

Блок интерфейса с платой ввода данных (RFint)

Существует несколько вариантов данного блока в зависимости от источника данных:

  • usb_reader.c - ввод данных по USB;
  • file_reader.c - ввод выборки сигнала из файла.

Раньше был ещё plx_reader.c - ввод данных по шине PCI, но от него отказались в пользу USB.

В любом случае каждый из этих блоков создаёт процесс reader. Данный процесс считывает сигнал блоками. Объём блока данных определяется макросом BYTES_PER_BLOCK и подбирается под оптимизацию производительности приёмника. На данный момент объём блока данных соответствует входной выборке длиной 22~мс.

После получения новой порции данных процесс reader начинает записывать данные в другой блок (их всего два), а накопленный блок передаёт другим процессам для обработки - коррелятору и блоку поиска.

ВАЖНО!!! Для работы с платой ввода данных USB нужен модуль ядра FrontEnd.ko. Продробное описание на соответствующей странице

Синхронизация между процессами

В программном приёмнике активно используется многозадачность, а точнее, многопотоковость. Такие блоки приёмника, как коррелятор, блок поиска, блок сбора данных исполняются в отдельных процессах. Для корректной работы между данными процессами должна быть синхронизация по времени. Синхронизация осуществляется с помощью семафоров.

Взаимодействие между процессами

Семафор - это некий сигнал, который может быть послан одним процессом (с помощью функции sem_post) другому процессу (который принимает семафор с помощью функции sem_wait). Работает это следующим образом. Если в процессе при исполнении встречается функция sem_wait, то исполнение этого процесса останавливается и он не занимает процессорное время. Когда другой процесс вызывает функцию sem_post (для соответствующего семафора), исполнение первого процесса возобновляется после функции sem_wait.

В приёмнике блок сбора данных при получении очередной порции посылает два семафора:

  • rf2correlator_sem - семафор для коррелятора;
  • rf2detector_sem - семафор для блока поиска.

Коррелятор при получении очередной порции данных начинает её обрабатывать. Напоминаю, что длина порции данных составляет 22 мс. Темп работы коррелятора сделан несколько меньше 1 мс, таким образом, выборку данных коррелятор обрабатывает более, чем за 22 шага. После отработки очередного интервала работы коррелятора вызывается функция CorrelInt(), являющаяся аналогом прерывания коррелятора в обычном приёмнике. В данной функции реализованы следящие системы (tracker.c).

Таким образом, следящие системы выполняются в процессе коррелятора. Отсюда мораль - обработчик CorrelInt должен работать как можно быстрее, чтобы не нарушить работу коррелятора.

В обработчике CorrelInt каждые 100 мс посылается семафор tracker2solver_sem, который активизирует процесс решения навигационной задачи.

Обновление структуры софта

Недостатком существующего программного приёмника является его жёсткая привязка к сигналу GPS C/A. Тут по-крупному есть два основных момента (первые два пункта ниже).

Реорганизация каналов

Данные в приёмнике хранятся по сигналам. Глобальный массив структур Chnl[] - это параметры для каждого из 32 сигналов GPS C/A. Стоит добавить, скажем, ГЛОНАСС, и вся структура ломается. Так как одной из первостепенных задач является приём сигналов Galileo, имеющих другую структуру, это всё необходимо переделать.

Более правильным является подход, когда есть глобальная структура по каналам приёмника. Проблема в том, что у программного приёмника каналы программные, "виртуальные", и их может быть столько, на сколько хватит производительности процессора. Поэтому и была привязка к сигналам, а не каналам - те сигналы, которые отсутствуют в эфире, просто не отнимали процессорное время.

Нужно всё-таки сделать структуру по каналам приёмника, аналогичную аппаратному коррелятору, но, быть может, создавать их динамически.

Таким образом, каждый элемент массива Chnl[] должен соответсвовать одному каналу приёма. Переделать это не сложно, фактически, сейчас номер канала - это номер ПСП GPS (только нумерация с нуля, а не с единицы). Нужно добавить туда поле - тип и номер сигнала, и внести соответствующие изменения в коррелятор и блок поиска. И всё.

Второе, что нужно сделать - создать отдельную структуру данных для хранения уже параметров сигналов. Дело в том, что канал может быть сборшен со слежения из-за временного пропадания сигнала. Затем канал может быть перенацелен на другой сигнал. Сейчас данные, привязанные к сигналу, а не к каналу (эфемериды и прочее), хранятся в массиве Chnl, а нужно их хранить отдельно. Если впоследствии при восстановлении слежения другой канал захватит сигнал, за которым уже было слежение, все данные могут быть получены из этой отдельной структуры для хранения параметров.

Уход от макросов

Вторая проблема всё очень сильно привязано на макросы, особенно блок поиска. Макросы хороши, когда всё определяется на этапе компиляции. Когда был только один сигнал GPS, это было нормально. Но теперь если необходимо следить за разными сигналами, это становится проблемой. Параметры сигналов разные, например, разная длительность ПСП в сигналах GPS L1 C/A и Galileo E1. Необходимо, чтобы параметры блока поиска могли быть изменены в процессе исполнения программы, а не в процессе компиляции. Для этого многие параметры нужно объявить не как макросы, а как переменные.

Перераспределение кода по файлам

Для удобства следует разбить исходный код по множеству файлов, которые, в свою очередь, распределить по каталогам. Дополнить файлы комментариями, функции - описанием прототипов в нотации Doxygen и т.д. Иначе говоря, облагородить форму кода, сделать его более удобоваримым для совместной разработки и хранения в SVN.

[ Хронологический вид ]Комментарии

(нет элементов)

Войдите, чтобы комментировать.

Персональные инструменты
Пространства имён

Варианты
Действия
SRNS Wiki
Рабочие журналы
Приватный файлсервер
QNAP Сервер
Инструменты