Я нахожусь в процессе реализации блоков линейного кодирования, поскольку в 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 */
Испытания пока не увенчались успехом. Устройство, которое я использую для получения сигналов с этой потоковой диаграммы, не смогло выбрать даже один пакет. Мой вывод заключается в том, что ошибка исходит от манчестерского кодера. Любые мысли по поводу кода выше приветствуются.
Благодарю.
Через некоторое время я смог найти ошибку в коде. На самом деле, проблема была в том, как я копировал вывод. Все, что мне нужно было сделать, это удалить внутренний цикл 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;
}
Других решений пока нет …