Реализация Manchester-L (Biphase-L) с конечными автоматами в GNU Radio

Я нахожусь в процессе реализации блоков линейного кодирования, поскольку в GnuRadio есть ограниченный выбор. Я закончил реализацию и тестирование NRZ (L \ M \ S) с использованием конечных автоматов (FSM), и они, кажется, работают нормально. Теперь я пытаюсь реализовать Манчестер (L \ M \ S), начиная с L в качестве базовой линии. Форму сигнала можно увидеть на приведенной ниже диаграмме. Извлечено из декодирования данных телеметрии сети Deep Space НАСА (208).

Формы волны модуляции

Конечный автомат был построен, как показано ниже. Я решил использовать автоматы, поскольку, на мой взгляд, это очень стандартизированный способ реализации строкового кода.
Манчестер-Л ФСМ

Ниже приведена блок-схема gnuradio, используемая для проверки реализации. Тесты проводятся путем отправки сигнала BPSK (с помощью CCSDS Reed-Solomon + Scrambler) на внешнее устройство, способное принимать сигнал и обрабатывать телеметрию. Эта реализация была успешно протестирована с NRZ-L \ M \ S. Кадры CCSDS считываются из файла, распаковываются и отправляются в OOT-блок debug_linecode_bp для манчестерского кодирования (код 0 для Manchester-L). Следующим манчестерским кодированием является блок debug_pulseshape_pam_2 блока OOT, в котором в качестве аргументов используются отводы фильтра и количество выборок на символ. Далее следует блок OOT debug_bpsk_modulator, который выполняет простое отображение BPSK (Inphase = in [i], quadrature = 0).
введите описание изображения здесь
Код для заголовочного файла показан ниже

#ifndef INCLUDED_BASEBAND_DEBUG_LINECODE_BP_IMPL_H
#define INCLUDED_BASEBAND_DEBUG_LINECODE_BP_IMPL_H

#include <baseband/debug_linecode_bp.h>

namespace gr {
namespace baseband {

class debug_linecode_bp_impl : public debug_linecode_bp
{
private:
char last_state;
int d_code;
void fsm_decode_state(char state, unsigned char &bit0, unsigned char &bit1);
void fsm_encode_state(int code, unsigned char input, char last_state, char &next_state);
public:
debug_linecode_bp_impl(int code);
~debug_linecode_bp_impl();

// Where all the action really happens
int work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};

} // namespace baseband
} // namespace gr

#endif /* INCLUDED_BASEBAND_DEBUG_LINECODE_BP_IMPL_H */

А вот файл реализации

#ifdef HAVE_CONFIG_H
#include "config.h"#endif

#include <gnuradio/io_signature.h>
#include "debug_linecode_bp_impl.h"#include <iostream>
using namespace std;
namespace gr {
namespace baseband {

debug_linecode_bp::sptr
debug_linecode_bp::make(int code)
{
return gnuradio::get_initial_sptr
(new debug_linecode_bp_impl(code));
}

/*
* The private constructor
*/
debug_linecode_bp_impl::debug_linecode_bp_impl(int code)
: gr::sync_interpolator("debug_linecode_bp",
gr::io_signature::make(1, 1, sizeof(unsigned char)),
gr::io_signature::make(1, 1, sizeof(unsigned char)), 2),
d_code(code),last_state('a')
{}

/*
* Our virtual destructor.
*/
debug_linecode_bp_impl::~debug_linecode_bp_impl()
{
}
void
debug_linecode_bp_impl::fsm_decode_state(char state, unsigned char &bit0, unsigned char &bit1)
{
switch(state)
{
case 'a':
bit0 = 0x00;
bit1 = 0x00;
break;
case 'b':
bit0 = 0x00;
bit1 = 0x01;
break;
case 'c':
bit0 = 0x01;
bit1 = 0x01;
break;
case 'd':
bit0 = 0x01;
bit1 = 0x00;
break;
}
}

void
debug_linecode_bp_impl::fsm_encode_state(int code, unsigned char input, char last_state, char &next_state)
{
switch(code)
{
case 0://Biphae-L
switch(last_state)
{
case 'a': //Illegal state
next_state = 'b';
cout << "Illegal state [a] encountered" << endl;
break;
case 'b':
next_state = (input & 0x01) ? 'd' : 'b';
break;
case 'c': //Illegal state
next_state = 'b';
cout << "Illegal state [b] encountered" << endl;
break;
case 'd':
next_state = (input & 0x01) ? 'd' : 'b';
break;
}
break;
case 1://Biphase-S
switch(last_state)
{
case 'a':
next_state = (input & 0x01) ? 'c' : 'd';
break;
case 'b':
next_state = (input & 0x01) ? 'a' : 'b';
break;
case 'c':
next_state = (input & 0x01) ? 'a' : 'b';
break;
case 'd':
next_state = (input & 0x01) ? 'c' : 'd';
break;
}
break;
case 2://Biphase-M
switch(last_state)
{
case 'a':
next_state = (input & 0x01) ? 'd' : 'c';
break;
case 'b':
next_state = (input & 0x01) ? 'b' : 'a';
break;
case 'c':
next_state = (input & 0x01) ? 'b' : 'a';
break;
case 'd':
next_state = (input & 0x01) ? 'd' : 'c';
break;
}
break;
}
}

int
debug_linecode_bp_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const unsigned char *in = (const unsigned char *) input_items[0];
unsigned char *out = (unsigned char *) output_items[0];

char next_state;
unsigned char bit0;
unsigned char bit1;
for (int i = 0; i < noutput_items/2; i++) {
fsm_encode_state(d_code,in[i],last_state, next_state);
fsm_decode_state(next_state, bit0, bit1);
for (int j = 0; j < 2; j++) {
out[i + j]     = bit0;
out[i + j + 1] = bit1;
}
last_state = next_state;
}

// Tell runtime system how many output items we produced.
return noutput_items;
}

} /* namespace baseband */
} /* namespace gr */

Испытания пока не увенчались успехом. Устройство, которое я использую для получения сигналов с этой потоковой диаграммы, не смогло выбрать даже один пакет. Мой вывод заключается в том, что ошибка исходит от манчестерского кодера. Любые мысли по поводу кода выше приветствуются.

Благодарю.

2

Решение

Через некоторое время я смог найти ошибку в коде. На самом деле, проблема была в том, как я копировал вывод. Все, что мне нужно было сделать, это удалить внутренний цикл for и напрямую скопировать вывод, используя memcpy. Вот так теперь выглядит рабочая функция

 int
debug_linecode_bp_impl::work(int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const unsigned char *in = (const unsigned char *) input_items[0];
unsigned char *out = (unsigned char *) output_items[0];

char next_state;
unsigned char bit0;
unsigned char bit1;
vector<unsigned char> bits;
for (int i = 0; i < noutput_items/2; i++) {
fsm_encode_state(d_code,in[i],last_state, next_state);
fsm_decode_state(next_state, bit0, bit1);
bits.push_back(bit0);
bits.push_back(bit1);
memcpy(out,bits.data(),2);
bits.clear();
out+=2;
last_state = next_state;
}

// Tell runtime system how many output items we produced.
return noutput_items;
}

И это форма волны на выходе модулятора
Манчестер Пульс

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]