/*!
* \file raw_array_impl.cc
* \brief GNU Radio source block to acces to experimental GNSS Array platform.
* \author Javier Arribas, 2014. jarribas(at)cttc.es
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2014 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see .
*
* -------------------------------------------------------------------------
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include
#include "raw_array_impl.h"
#include
#include
#include
#include
#include
#include
#include
#define FIFO_SIZE 1000000
#define DBFCTTC_NUM_CHANNELS 8
namespace gr {
namespace dbfcttc {
raw_array::sptr
raw_array::make(const char *src_device,short number_of_channels, int snapshots_per_frame, int inter_frame_delay, int sampling_freq)
{
return gnuradio::get_initial_sptr
(new raw_array_impl(src_device, number_of_channels, snapshots_per_frame, inter_frame_delay, sampling_freq));
}
/*
* The private constructor
*/
raw_array_impl::raw_array_impl(const char *src_device,short number_of_channels, int snapshots_per_frame, int inter_frame_delay, int sampling_freq)
: gr::sync_block("raw_array",
gr::io_signature::make(0, 0, 0),
gr::io_signature::make(8, 8, sizeof(gr_complex)))
{
// constructor code here
fprintf(stdout,"DBFCTTC Start\n");
d_src_device=src_device;
d_number_of_channels=number_of_channels;
d_snapshots_per_frame=snapshots_per_frame;
d_inter_frame_delay=inter_frame_delay;
d_sampling_freq=sampling_freq;
d_flag_start_frame=true;
d_fifo_full=false;
d_last_frame_counter=0;
d_num_rx_errors=0;
flag_16_bits_sample=true;
//allocate signal samples buffer
//TODO: Check memory pointers
fifo_buff_ch=new gr_complex*[DBFCTTC_NUM_CHANNELS];
for (int i=0;i beamforming config
// command=2 -> start
// command=3 -> stop
// command=4 -> raw array config
char data[20];
for(int i=0;i<20;i++)
{
data[i]=0x00;
}
data[0]=4; //command to activate RAW array
data[1]=d_number_of_channels;
data[2]=d_snapshots_per_frame>>8;
data[3]=d_snapshots_per_frame & 255;
printf("\n Total bytes in snapshots payload = %i\n",d_snapshots_per_frame*d_number_of_channels*2);
printf("\n Estimated eth RAW frame size [bytes] %i\n",12+2+3+d_snapshots_per_frame*d_number_of_channels*2+1);
data[4]=d_inter_frame_delay>>8;
data[5]=d_inter_frame_delay & 255;
data[6]=0xB;
data[7]=0xF;
//send the frame
struct ether_header myheader;
myheader.ether_type=0xbfcd; //this is the ethenet layer II protocol ID for the CTTC array hardware
memset(myheader.ether_dhost,0xff,sizeof(myheader.ether_dhost));
memset(myheader.ether_shost,0x11,sizeof(myheader.ether_shost));
unsigned char frame[sizeof(struct ether_header)+sizeof(data)];
memcpy(frame,&myheader,sizeof(struct ether_header));
memcpy(frame+sizeof(struct ether_header),&data,sizeof(data));
if (pcap_inject(descr,frame,sizeof(frame))==-1) {
printf("Error sending configuration packet\n");
pcap_perror(descr,0);
return false;
}else{
printf("Sent configuration packet OK\n");
return true;
}
}
bool raw_array_impl::start_array()
{
char data[20];
for(int i=0;i<20;i++)
{
data[i]=0x00;
}
data[0]=2; //command to start the array operation (configured previously)
//send the frame
struct ether_header myheader;
myheader.ether_type=0xbfcd; //this is the ethenet layer II protocol ID for the CTTC array hardware
memset(myheader.ether_dhost,0xff,sizeof(myheader.ether_dhost));
memset(myheader.ether_shost,0x11,sizeof(myheader.ether_shost));
unsigned char frame[sizeof(struct ether_header)+sizeof(data)];
memcpy(frame,&myheader,sizeof(struct ether_header));
memcpy(frame+sizeof(struct ether_header),&data,sizeof(data));
if (pcap_inject(descr,frame,sizeof(frame))==-1) {
printf("Error sending start packet\n");
pcap_perror(descr,0);
return false;
}else{
printf("Sent start packet OK\n");
return true;
}
}
bool raw_array_impl::stop_array()
{
char data[20];
for(int i=0;i<20;i++)
{
data[i]=0x00;
}
data[0]=3; //command to stop the array operation (configured previously)
//send the frame
struct ether_header myheader;
myheader.ether_type=0xbfcd; //this is the ethenet layer II protocol ID for the CTTC array hardware
memset(myheader.ether_dhost,0xff,sizeof(myheader.ether_dhost));
memset(myheader.ether_shost,0x11,sizeof(myheader.ether_shost));
unsigned char frame[sizeof(struct ether_header)+sizeof(data)];
memcpy(frame,&myheader,sizeof(struct ether_header));
memcpy(frame+sizeof(struct ether_header),&data,sizeof(data));
if (pcap_inject(descr,frame,sizeof(frame))==-1) {
printf("Error sending stop packet\n");
pcap_perror(descr,0);
return false;
}else{
printf("Sent stop packet OK\n");
return true;
}
}
/*
* Our virtual destructor.
*/
raw_array_impl::~raw_array_impl()
{
// destructor code here
if (stop_array()==true)
{
printf("Array stopped!\n");
}else{
exit(1); //ethernet error!
}
if(descr != NULL)
{
pcap_breakloop(descr);
d_pcap_thread->join();
pcap_close(descr);
}
for (int i=0;ipcap_callback(args, pkthdr, packet);
}
void raw_array_impl::pcap_callback(u_char *args, const struct pcap_pkthdr* pkthdr,
const u_char* packet)
{
boost::mutex::scoped_lock lock(d_mutex); // hold mutex for duration of this function
int numframebyte;
short int real,imag;
// eth frame parameters
int number_of_channels;
unsigned short int snapshots_per_frame;
// **** CTTC DBF PACKET DECODER ****
if ((packet[12]==0xCD) & (packet[13]==0xBF))
{
//printf(".");
// control parameters
number_of_channels=(int)packet[14];
//std::cout<<"number_of_channels="<1)
{
int missing_frames=abs(d_last_frame_counter-numframebyte);
if (missing_frames!=255 )
{
//fake samples generation to help tracking loops
std::complex last_sample[DBFCTTC_NUM_CHANNELS];
if (fifo_write_ptr == 0)
{
for (int ch=0;ch(real, imag);
fifo_buff_ch[ch][fifo_write_ptr] = std::complex(imag, real); //inverted due to inversion in front-end
//std::cout<<"["<=num_samples_readed)
{
//read all in a single memcpy
for (int ch=0;ch )*num_samples_readed);
}
fifo_read_ptr=fifo_read_ptr+num_samples_readed; //increase the fifo pointer
if (fifo_read_ptr==FIFO_SIZE) fifo_read_ptr=0;
}else{
//two step wrap read
for (int ch=0;ch )*aligned_read_items);
}
fifo_read_ptr=fifo_read_ptr+aligned_read_items; //increase the fifo pointer
if (fifo_read_ptr==FIFO_SIZE) fifo_read_ptr=0;
for (int ch=0;ch)*(num_samples_readed-aligned_read_items));
}
fifo_read_ptr=fifo_read_ptr+(num_samples_readed-aligned_read_items); //increase the fifo pointer
}
fifo_items=fifo_items-num_samples_readed;
// int num_samples_readed=0;
// for(int i=0;i 0) {
// //TODO: optimize-me with memcpy!!
// for (int ch=0;ch