How to use Viterbi decoder from GNU Radio library - c++

I need to make Viterbi decoding of some convolutional-encoded signal. My application shall work with large files, therefore I cannot insert all the signal into a heap, so I need to process a data by a sequence of separate buffers. I have found a good library for Viterbi decoding - Encoder and a Viterbi decoder in C++ on the dr. Dobbs. I have applied the decoder from the libarary, it works correct, but doesn't provide a function for continuous use (call a function many times for each signal buffer with considering of previous calculations). Then I have found the GNU Radio C++ library which provide the necessary functions. But I don't understand how to use its functions, because it doesn't provide a documentation. It contains the example of Viterbi decoding with is present below:
extern "C" {
#include <gnuradio/fec/viterbi.h>
}
#include <cstdio>
#include <cmath>
#define MAXCHUNKSIZE 4096
#define MAXENCSIZE MAXCHUNKSIZE*16
int main()
{
unsigned char data[MAXCHUNKSIZE];
signed char syms[MAXENCSIZE];
int count = 0;
// Initialize metric table
int mettab[2][256];
int amp = 100; // What is it? ***
float RATE=0.5;
float ebn0 = 12.0;
float esn0 = RATE*pow(10.0, ebn0/10);
gen_met(mettab, amp, esn0, 0.0, 4);
// Initialize decoder state
struct viterbi_state state0[64];
struct viterbi_state state1[64];
unsigned char viterbi_in[16];
viterbi_chunks_init(state0);
while (!feof(stdin)) {
unsigned int n = fread(syms, 1, MAXENCSIZE, stdin);
unsigned char *out = data;
for (unsigned int i = 0; i < n; i++) {
// FIXME: This implements hard decoding by slicing the input stream
unsigned char sym = syms[i] > 0 ? -amp : amp; // What is it? ***
// Write the symbol to the decoder input
viterbi_in[count % 4] = sym;
// Every four symbols, perform the butterfly2 operation
if ((count % 4) == 3) {
viterbi_butterfly2(viterbi_in, mettab, state0, state1);
// Every sixteen symbols, perform the readback operation
if ((count > 64) && (count % 16) == 11) {
viterbi_get_output(state0, out);
fwrite(out++, 1, 1, stdout);
}
}
count++;
}
}
return 0;
}
File viterbi.c from it also contains the next function viterbi(), without a declaration:
/* Viterbi decoder */
int viterbi(unsigned long *metric, /* Final path metric (returned value) */
unsigned char *data, /* Decoded output data */
unsigned char *symbols, /* Raw deinterleaved input symbols */
unsigned int nbits, /* Number of output bits */
int mettab[2][256] /* Metric table, [sent sym][rx symbol] */
) { ...
Also I found one more implementation for Viterbi decoding - The Spiral project. But it also doesn't contain a normal description and doesn't want to compile. And two more implementation on the ExpertCore and Forward Error Correction DSP library.
My question: Can anyone understand how to use the above GNU Radio's implementation of the Viterbi algorithm for continuous use for binary interleaved digital signal (Encoder parameters of my signal: K=7 rate=1/2, every bit in my file is a demodulated sample of a signal)?

Related

Serial communication: Sending data from C++ to Arduino

i'm trying to send data from a C++ program over serial communication to an Arduino. I formed a struct for sending the data as an object:
typedef struct
{
double width;
double height;
bool passBoard;
} MachineParameters;
I'm using this Serial library: http://wjwwood.github.com/serial/ for sending the data like this:
MachineParameters mp;
mp.width = 100;
mp.height = 200;
mp.passBoard = true;
ser.write((const uint8_t *)&mp, sizeof(mp));
The library makes it possible to send the data as uint8_t, std::vector or std::string.
The Arduino does receive data, but i don't know how to parse the data into the struct. I'm using the same struct as in the cpp code.
// In Arduio
MachineParameters mp;
int byte_size = 24;
loop() {
if(Serial.available() >= 24) {
Serial.readBytes((char*) &mp , 24);
}
}
// Goal: Read received mp data just like
// mp.width or mp.height
After hours of trying, i still cannot figure it out, how to send this struct to the arduino successfully. Is there another way of sending this data to the arduino? It worked sending the data as string, but that did not seem right.
I am pretty new to programming with C++, so please excuse any obvious questions...
Thank you for helping!
UPDATE: Working solution below
After a view more tries and thanks to your tips, i figured it out. Here is the code, which worked for me. I found out that my problem was the wrong byte size, used for parsing the buffer. The size of the struct in C++ is 12, whereas on the arduino it's 9. Using the original size (12) for parsing the buffer on the Arduino, the struct was parsed correctly.
/* --- C++ CODE --- */
typedef struct
{
double width;
double height;
bool passBoard;
} MachineParameters;
// sizeof(MachineParameters) returns 12.
MachineParameters mp;
mp.width = 11.1;
mp.passBoard = false;
mp.height = 22.2;
ser.write((uint8_t *)&mp, sizeof(mp));
/* --- END OF C++ --- */
/* --- Arduino Code --- */
#define BYTE_SIZE 12
char messageBuffer[BYTE_SIZE];
typedef struct
{
double width;
double height;
bool passBoard;
} MachineParameters;
MachineParameters mp;
void setup() {
Serial.begin(9600);
}
void loop() {
if (Serial.available() >= BYTE_SIZE) {
Serial.readBytes(messageBuffer , BYTE_SIZE);
memcpy(&mp, &messageBuffer, BYTE_SIZE);
// mp.width returns 11.1
// Success :)
}
}
/* --- END OF ARDUINO --- */
on the arduino you receive the data in a buffer as raw bytes
now you have to parse this, you can do this using memcpy to copy the data in the struct
however for doing this the data has to be aligned meaning that you have to know exactly where it begins. so you should send a synchronization byte ( start / stop bytes ) to be able to fix where the data begins
then you can use the code in parsing buffer data into struct :
struct abc {
char a;
char b;
char c;
char d[2];
};
int main() {
char arr[5] = { 'a', 'b', 'c', 'd', 'e' };
struct abc sa;
memcpy(&sa, arr, 5);
return 0;
}
here arr is incoming buffer, and with memcpy all the contents are copied appropriately.
ser.write((const uint8_t *)&mp, sizeof(mp)); is correct
you can create an identical structure mp_arduino on the arduino and copy the content of the receive buffer into this structure with
memcpy ( &mp_arduino, receive_buffer+n, sizeof(mp_arduino) ); where n indicates the position / byte in receive_buffer where your data begins and receive_buffer is defined as uint8_t receive_buffer[] ( or uint8_t* receive_buffer is the same... )
( http://www.cplusplus.com/reference/cstring/memcpy/ )
this is how a struct is stored in memory : How is a struct stored in memory?
on both systems a float should be 32 bit https://www.arduino.cc/reference/en/language/variables/data-types/float/

using write() function in C/C++ on Linux to write 70kB via UART Beaglebone Black

I'm trying to write a image via UART on Beaglebone Black. But when I use the write() function in library .
int write(int handle, void *buffer, int nbyte);
Regardless of the agurment nbyte has int type, I can not transfer 70kB at once. I displayed the number of byte which is transfered, and the result is the number of byte = 4111.
length = write(fd,body.c_str(),strlen(body.c_str())); //
cout<<length<<endl; // result length = 4111;
cout<<strlen(body.c_str())<<endl; // result strlen(body.c_str()) = 72255;
I hope to hear from you!
The write call does not assure that you can write the amount of data supplied, that's why it as an integer as its return, not a Boolean. The behavior you see is actually common among different operating systems, it may be due to the underline device might does not have sufficient buffer or storage for you to write 70kb. What you need is to write in a loop, each write will write the amount that is left unwritten:
int total = body.length(); // or strlen(body.c_str())
char *buffer = body.c_str();
int written = 0;
int ret;
while (written < total) {
ret = write(fd, buffer + written, total - written);
if (ret < 0) {
// error
break;
}
written += ret;
}

gnuradio source only outputting zeros

I made a custom source block that is reading switch values on a zedboard. It is accessing them via a proc driver that I wrote. The /var/log/kern.log is reporting proper output. The debug printf in the source block is reporting proper output.
However pushing the data to a filesink as well as a GUI number sink is only reading zeros. Did I not set up the block properly?
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "switches_impl.h"
#include <stdio.h>
#include <stdlib.h>
#include <uinstd.h>
namespace gr {
namespace zedboard {
switches::sptr
switches::make()
{
return gnuradio::get_initial_sptr
(new switches_impl());
}
/*
* The private constructor
*/
switches_impl::switches_impl()
: gr::block("switches",
gr::io_signature::make(0,0,0),
gr::io_signature::make(1, 1, sizeof(unsigned int *)))
{}
/*
* Our virtual destructor.
*/
switches_impl::~switches_impl()
{
}
void
switches_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
{
/* <+forecast+> e.g. ninput_items_required[0] = noutput_items */
}
int
switches_impl::general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
//const <+ITYPE+> *in = (const <+ITYPE+> *) input_items[0];
unsigned int *out = (unsigned int *) output_items[0];
// Do <+signal processing+>
// Tell runtime system how many input items we consumed on
// each input stream.
char buffer[5];
size_t size = 1;
size_t nitems = 5;
FILE* fp;
fp = fopen("/proc/zedSwitches","r");
if (fp == NULL)
{
printf("Cannot open for read\n");
return -1;
}
/*
Expect return format:
0x00
*/
fread(buffer, size, nitems, fp);
fclose(fp);
out=(unsigned int *)strtoul(buffer,NULL,0);
printf("read: 0x%02x",out);
consume_each (noutput_items);
// Tell runtime system how many output items we produced.
return noutput_items;
}
} /* namespace zedboard */
} /* namespace gr */
A pointer is a pointer to data, usually:
unsigned int *out = (unsigned int *) output_items[0];
out refers to the buffer for your output.
But you overwrite that pointer with another pointer:
out=(unsigned int *)strtoul(buffer,NULL,0);
which just bends around your copy of that pointer, and doesn't affect the content of that buffer at all. Basic C!
You probably meant to say something like:
out[0]= strtoul(buffer,NULL,0);
That will put your value into the first element of the buffer.
However, you tell GNU Radio that you not only produced a single item (the line above), but noutput_items:
return noutput_items;
That must read
return 1;
when you're only producing a single item, or you must actually produce as many items as you return.
Your consume_each call is nonsensical – GNU Radio Sources are typically instances of gr::sync_block, which means that you'd write a work() instead of a general_work() method as you did.
From the fact alone that this is a general_work and not a work I'd say you haven't used gr_modtool (with block type set to source!) to generate the stub for this block – you really should. Again, I'd like to point you to the Guided Tutorials which should really quickly explain usage of gr_modtool as well as the underlying GNU Radio concepts.

Best way to pass variables between Arduino and PC over serial?

I've written an Arduino sketch which reads data from a remote control receiver and returns a value between 0 and 1023 for that channel. I basically want to send this data (something in the format of channel:value, eg, Channel 1 : 1023, Channel 2 : 511) to a PC program (which I plan to write myself).
The most efficient way I can think to do this is to use two bytes of data, with the first 6 bits representing the channel (2^6 = 64 possible channels, way more than I need), and the last ten representing the value (2^10 = 1024, perfect). But I'm not sure on the best way to implement this in C++, or if this is even the most ideal way to do this. So:
What is the best way to craft individual bytes and work with binary numbers in C++? Preferably storing the values in memory as such (ie, no bool arrays, where each index takes up it's own byte). Two bytes of data is more than enough for what I need.
Is this the easiest/simplest/most efficient/recommended way to implement what I am trying to achieve? I basically want to pass variables as is between programs, are there any other ways to do this?
You can declare a packed struct to hold these two values:
struct chan_value_t
{
uint8_t channel : 6;
uint16_t value : 10;
};
But to send it as two bytes, you'll need to either (1) "union" it with a two-byte array:
union chan_value_t
{
struct {
uint8_t channel : 6;
uint16_t value : 10;
};
uint8_t bytes[2];
};
chan_value_t cv;
void setup()
{
Serial.begin( 9600 );
cv.channel = 2;
cv.value = 800;
for (int i=0; i<sizeof(cv.bytes); i++) {
Serial.print( cv.bytes[i], HEX );
Serial.print( ' ' );
}
Serial.println();
}
void loop() {}
(The struct is anonymous when nested in this union; the union has the name.)
Or (2) cast a pointer to the struct to a pointer to bytes:
struct chan_value_t {
uint8_t channel : 6;
uint16_t value : 10;
};
chan_value_t cv;
void setup()
{
Serial.begin( 9600 );
cv.channel = 2;
cv.value = 800;
uint8_t *bytes = (uint8_t *) &cv; // cast &cv to a pointer to bytes
for (int i=0; i<sizeof(cv); i++) {
Serial.print( bytes[i], HEX );
Serial.print( ' ' );
}
Serial.println();
}
void loop() {}
They both print the hexadecimal value of the bytes: 0x02 and 0xC8. 800 is 0x320, shifted left by 6 bits is 0xC800.
To send this to the PC, you may want to start with a special character sequence and finish with a checksum of some sort (Fletcher checksum is easy). Then it's easy to throw away garbage characters and know when there are transmission errors.
This is aimed at your no. 2 question.
OSC (OpenSoundControl) is a convenient way to send messages across different platforms and devices. Libraries exist for most platforms.
You could use the library OSC for Arduino and implement your own solution to the specification or using a library that fits your context.
The message you mention could be sent as /channel/1 /value/1023

Parsing a binary message in C++. Any lib with examples?

I am looking for any library of example parsing a binary msg in C++. Most people asks for reading a binary file, or data received in a socket, but I just have a set of binary messages I need to decode. Somebody mentioned boost::spirit, but I haven't been able to find a suitable example for my needs.
As an example:
9A690C12E077033811FFDFFEF07F042C1CE0B704381E00B1FEFFF78004A92440
where first 8 bits are a preamble, next 6 bits the msg ID (an integer from 0 to 63), next 212 bits are data, and final 24 bits are a CRC24.
So in this case, msg 26, I have to get this data from the 212 data bits:
4 bits integer value
4 bits integer value
A 9 bit float value from 0 to 63.875, where LSB is 0.125
4 bits integer value
EDIT: I need to operate at bit level, so a memcpy is not a good solution, since it copies a number of bytes. To get first 4-bit integer value I should get 2 bits from a byte, and another 2 bits from the next byte, shift each pair and compose. What I am asking for is a more elegant way of extracting the values, because I have about 20 different messages and wanted to reach a common solution to parse them at bit level.
And so on.
Do you know os any library which can easily achieve this?
I also found other Q/A where static_cast is being used. I googled about it, and for each person recommending this approach, there is another one warning about endians. Since I already have my message, I don't know if such a warning applies to me, or is just for socket communications.
EDIT: boost:dynamic_bitset looks promising. Any help using it?
If you can't find a generic library to parse your data, use bitfields to get the data and memcpy() it into an variable of the struct. See the link Bitfields. This will be more streamlined towards your application.
Don't forget to pack the structure.
Example:
#pragma pack
include "order32.h"
struct yourfields{
#if O32_HOST_ORDER == O32_BIG_ENDIAN
unsigned int preamble:8;
unsigned int msgid:6;
unsigned data:212;
unsigned crc:24;
#else
unsigned crc:24;
unsigned data:212;
unsigned int msgid:6;
unsigned int preamble:8;
#endif
}/*__attribute__((packed)) for gcc*/;
You can do a little compile time check to assert if your machine uses LITTLE ENDIAN or BIG ENDIAN format. After that define it into a PREPROCESSOR SYMBOL::
//order32.h
#ifndef ORDER32_H
#define ORDER32_H
#include <limits.h>
#include <stdint.h>
#if CHAR_BIT != 8
#error "unsupported char size"
#endif
enum
{
O32_LITTLE_ENDIAN = 0x03020100ul,
O32_BIG_ENDIAN = 0x00010203ul,
O32_PDP_ENDIAN = 0x01000302ul
};
static const union { unsigned char bytes[4]; uint32_t value; } o32_host_order =
{ { 0, 1, 2, 3 } };
#define O32_HOST_ORDER (o32_host_order.value)
#endif
Thanks to code by Christoph # here
Example program for using bitfields and their outputs:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <memory.h>
using namespace std;
struct bitfields{
unsigned opcode:5;
unsigned info:3;
}__attribute__((packed));
struct bitfields opcodes;
/* info: 3bits; opcode: 5bits;*/
/* 001 10001 => 0x31*/
/* 010 10010 => 0x52*/
void set_data(unsigned char data)
{
memcpy(&opcodes,&data,sizeof(data));
}
void print_data()
{
cout << opcodes.opcode << ' ' << opcodes.info << endl;
}
int main(int argc, char *argv[])
{
set_data(0x31);
print_data(); //must print 17 1 on my little-endian machine
set_data(0x52);
print_data(); //must print 18 2
cout << sizeof(opcodes); //must print 1
return 0;
}
You can manipulate bits for your own, for example to parse 4 bit integer value do:
char[64] byte_data;
size_t readPos = 3; //any byte
int value = 0;
int bits_to_read = 4;
for (size_t i = 0; i < bits_to_read; ++i) {
value |= static_cast<unsigned char>(_data[readPos]) & ( 255 >> (7-i) );
}
Floats usually sent as string data:
std::string temp;
temp.assign(_data+readPos, 9);
flaot value = std::stof(temp);
If your data contains custom float format then just extract bits and do your math:
char[64] byte_data;
size_t readPos = 3; //any byte
float value = 0;
int i = 0;
int bits_to_read = 9;
while (bits_to_read) {
if (i > 8) {
++readPos;
i = 0;
}
const int bit = static_cast<unsigned char>(_data[readPos]) & ( 255 >> (7-i) );
//here your code
++i;
--bits_to_read;
}
Here is a good article that describes several solutions to the problem.
It even contains the reference to the ibstream class that the author created specifically for this purpose (the link seems dead, though). The only other mention of this class I could find is in the bit C++ library here - it might be what you need, though it's not popular and it's under GPL.
Anyway, the boost::dynamic_bitset might be the best choice as it's time-tested and community-proven. But I have no personal experience with it.