Код Неймана-Хоффмана в Beidou (Compass)

Сигнал Beidou, в принципе, очень похож на сигнал GPS C/A L1 [src].

В системе также используется кодовое разделение каналов, при помощи фазовой манипуляции на несущую накладываются следующие двоичные последовательности:

  1. Дальномерный код с чиповой частотой 2.046 Мбит/с;
  2. Навигационное сообщение с частотой 50 бит/с;
  3. А также дополнительный код Неймана-Хоффмана (в дальнейшем NH-код) длительностью 20 бит с частотой 1000 бит/с

Структура сигнала

Первые две последовательности (если не обращать внимания на чиповую скорость) совпадают по структуре с сигналом GPS C/A L1. Сигнал ГЛОНАСС L1 отличается лишь наличием дополнительно наложенного меандра с периодом 10 мс.

Так зачем нужен NH-код? Он позиционируется как средство для обеспечения символьной синхронизации в приёмнике, а также как дополнительное средство расширения спектра.

Нашей целью является снять модуляцию, полученную в результате получения этого кода. Когда сигнал достаточно мощный, в этом нет никаких проблем: приёмник запоминает последние 20 знаков I-компоненты с выхода ФАП, сравнивает их со сдвинутой битовой маской и, если есть совпадение, то ура, мы нашли смещение и задача решена!

uint64_t NH_code = 0x72B20;  
uint64_t input = 0xB208D;  
for (uint64_t shift = 0; shift < 20; ++shift){  
  //...  
  //Generate shifted code  
   if(shifted_code == input){  
    return shift;  
   }            
}  

Выглядит здорово и очевидно, не правда ли? Этот вариант является быстрым (даже очень быстрым), тратит не так много памяти, и, что самое главное, он является простым. Его просто понять и, следовательно, просто поддерживать.

Но он не покрывает два крайне важных сценария:

  1. Смена знака навигационного сообщения;
  2. Ошибки ФАП из-за низкого отношения сигнал/шум, ведущие к ошибке в знаке I-компоненты,

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

А второй сценарий делает картину ещё хуже. Мы больше не можем рассчитывать на условие if(shifted_code == input). Теперь приёмник должен на каждом шагу запоминать (больше никакого низкого потребления памяти) количество различающихся бит между входным вектором и опорной последовательностью. И так четыре раза для всех комбинаций знаков навигационного сообщения.

Звучит не очень-то эффективно. Поэтому я предлагаю алгоритм, построенный на согласованном фильтре. Ему на вход подаётся 30 бит (секунд) с выхода ФАП, после чего генерируется вектор длиной 20 элементов, в котором оссуществляетсся поиск максимума. Положение максимума является сдвигом, а его знак — знаком навигационного сообщение. Реализация этого алгоритма примерно следующая:

 #include <cstdint>  
 #include <cmath>  
 namespace {  
      void MatchedFilter1ms(const int16_t *src, size_t src_len,   
           const int16_t *stretched_code, size_t stretched_code_len, int16_t *dst){  
           for (size_t i = 0; i < src_len; ++i) {  
                dst[i] = 0;  
                for (size_t j = 0; j < stretched_code_len; j++)  
                     dst[i] += stretched_code[j] * src[(i + j) % src_len];  
           }  
      }  
 }  
 void main() {  
      MatchedFilter1ms(src, SAMPLES, NH_code, NH_SAMPLES, matched);  
      for (size_t el = 0; el < SAMPLES; ++el){  
           if (abs(matched[el]) > max){  
                max = abs(matched[el]);  
                imax = el;  
           }  
      }  
      int16_t sign = matched[imax] > 0 ? 1 : -1;  
}  

Да, он использует больше памяти, что не очень-то приветствуется в встраиваемых системах, но он немного быстрее аналога на битовых масках с использованием оптимизации в компиляторе (-O2), а также гораздо надёжнее, как видно на графике снизу.

Вероятность

На этом пока всё. В этом алгоритме ещё есть пространство для оптимизации, но я рад и с его нынешней производительностью. Ещё, насколько я знаю, укороченный NH-код длительностью всего 10 бит будет использован в сигнале ГЛОНАСС L3. С небольшими изменениями этот алгоритм можно будет использовать и для этих целей.


© 2018. All rights reserved.

Powered by Hydejack v7.5.1