kopia lustrzana https://github.com/cariboulabs/cariboulite
separation of soapy objects - two channels, two objects
rodzic
0935f22b47
commit
a45958561c
|
@ -683,10 +683,10 @@ static int caribou_smi_set_driver_streaming_state(caribou_smi_st* dev, int state
|
|||
|
||||
//=========================================================================
|
||||
int caribou_smi_setup_stream(caribou_smi_st* dev,
|
||||
caribou_smi_stream_type_en type,
|
||||
caribou_smi_channel_en channel,
|
||||
caribou_smi_data_callback cb,
|
||||
void* serviced_context)
|
||||
caribou_smi_stream_type_en type,
|
||||
caribou_smi_channel_en channel,
|
||||
caribou_smi_data_callback cb,
|
||||
void* serviced_context)
|
||||
{
|
||||
int stream_id = CARIBOU_SMI_GET_STREAM_ID(type, channel);
|
||||
ZF_LOGI("Setting up stream channel (%d) of type (%d)", channel, type);
|
||||
|
|
|
@ -34,7 +34,9 @@ typedef enum
|
|||
caribou_smi_stream_end = 0xFF,
|
||||
} caribou_smi_stream_type_en;
|
||||
|
||||
#define CARIBOU_SMI_GET_STREAM_ID(type, ch) ( ((type)<<1) | (ch) )
|
||||
#define CARIBOU_SMI_GET_STREAM_ID(type, ch) ( ((type)<<1) | (ch) )
|
||||
#define CARIBOU_SMI_GET_STREAM_TYPE(id) ( (caribou_smi_stream_type_en)(((id)>>1)&0x1) )
|
||||
#define CARIBOU_SMI_GET_STREAM_CH(id) ( (caribou_smi_channel_en)((id)&0x1) )
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
//============================================================
|
||||
int caribou_smi_check_modules_loaded(char* mod_name)
|
||||
{
|
||||
char line[256] = {0};
|
||||
|
@ -29,10 +30,23 @@ int caribou_smi_check_modules_loaded(char* mod_name)
|
|||
return found;
|
||||
}
|
||||
|
||||
//============================================================
|
||||
int caribou_smi_insert_smi_modules(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================
|
||||
int caribou_smi_remove_module(char* module_name)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================
|
||||
int caribou_smi_check_modules()
|
||||
{
|
||||
int bcm_smi_dev = caribou_smi_check_smi_modules_loaded("bcm2835_smi_dev");
|
||||
int bcm_smi = caribou_smi_check_smi_modules_loaded("bcm2835_smi");
|
||||
int bcm_smi_dev = caribou_smi_check_modules_loaded("bcm2835_smi_dev");
|
||||
int bcm_smi = caribou_smi_check_modules_loaded("bcm2835_smi");
|
||||
|
||||
if (bcm_smi_dev == -1 || bcm_smi == -1)
|
||||
{
|
||||
|
@ -47,13 +61,3 @@ int caribou_smi_check_modules()
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int caribou_smi_insert_smi_modules()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int caribou_smi_remove_module(char* module_name)
|
||||
{
|
||||
|
||||
}
|
|
@ -17,24 +17,24 @@ Cariboulite::Cariboulite(const SoapySDR::Kwargs &args)
|
|||
args.at("channel").c_str());
|
||||
|
||||
// Initialize the stream Sample Queues
|
||||
sample_queue_tx = new SampleQueue(getStreamMTU(NULL)*NUM_BYTES_PER_CPLX_ELEM, NUM_SAMPLEQUEUE_BUFS);
|
||||
sample_queue_rx = new SampleQueue(getStreamMTU(NULL)*NUM_BYTES_PER_CPLX_ELEM, NUM_SAMPLEQUEUE_BUFS);
|
||||
sample_queue_tx = new SoapySDR::Stream();
|
||||
sample_queue_rx = new SoapySDR::Stream();
|
||||
|
||||
if (!args.at("channel").compare ("HiF"))
|
||||
{
|
||||
sample_queue_tx->AttachStreamId(0, caribou_smi_stream_type_write, caribou_smi_channel_2400);
|
||||
sample_queue_rx->AttachStreamId(1, caribou_smi_stream_type_read, caribou_smi_channel_2400);
|
||||
//sample_queue_tx->AttachStreamId(0, caribou_smi_stream_type_write, caribou_smi_channel_2400);
|
||||
//sample_queue_rx->AttachStreamId(1, caribou_smi_stream_type_read, caribou_smi_channel_2400);
|
||||
cariboulite_radio_init(&radio, &sess.cariboulite_sys, cariboulite_channel_6g);
|
||||
}
|
||||
else if (!args.at("channel").compare ("S1G"))
|
||||
{
|
||||
sample_queue_tx->AttachStreamId(0, caribou_smi_stream_type_write, caribou_smi_channel_900);
|
||||
sample_queue_rx->AttachStreamId(1, caribou_smi_stream_type_read, caribou_smi_channel_900);
|
||||
//sample_queue_tx->AttachStreamId(0, caribou_smi_stream_type_write, caribou_smi_channel_900);
|
||||
//sample_queue_rx->AttachStreamId(1, caribou_smi_stream_type_read, caribou_smi_channel_900);
|
||||
cariboulite_radio_init(&radio, &sess.cariboulite_sys, cariboulite_channel_s1g);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::string("Channel type is not specified correctly");
|
||||
throw std::runtime_error( "Channel type is not specified correctly" );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -368,23 +368,25 @@ static double convertTxBandwidth(at86rf215_radio_tx_cut_off_en bw_en)
|
|||
//========================================================
|
||||
void Cariboulite::setBandwidth( const int direction, const size_t channel, const double bw )
|
||||
{
|
||||
int filt = 0;
|
||||
double setbw = bw;
|
||||
if (bw == 200000.0f) filt = 4;
|
||||
else if (bw == 100000.0f) filt = 3;
|
||||
else if (bw == 50000.0f) filt = 2;
|
||||
else if (bw == 20000.0f) filt = 1;
|
||||
|
||||
if (setbw < 200000) setbw = 200000;
|
||||
double modem_bw = bw;
|
||||
|
||||
if (direction == SOAPY_SDR_RX)
|
||||
{
|
||||
cariboulite_radio_set_rx_bandwidth(&radio, convertRxBandwidth(setbw));
|
||||
sample_queue_rx->dig_filt = filt;
|
||||
if (modem_bw < (160000*BW_SHIFT_FACT) )
|
||||
{
|
||||
modem_bw = 160000*BW_SHIFT_FACT;
|
||||
if (bw <= 20000.0f) sample_queue_rx->setDigitalFilter(SoapySDR::Stream::DigitalFilter_20KHz);
|
||||
else if (bw <= 50000.0f) sample_queue_rx->setDigitalFilter(SoapySDR::Stream::DigitalFilter_50KHz);
|
||||
else if (bw <= 100000.0f) sample_queue_rx->setDigitalFilter(SoapySDR::Stream::DigitalFilter_100KHz);
|
||||
else sample_queue_rx->setDigitalFilter(SoapySDR::Stream::DigitalFilter_None);
|
||||
}
|
||||
else sample_queue_rx->setDigitalFilter(SoapySDR::Stream::DigitalFilter_None);
|
||||
|
||||
cariboulite_radio_set_rx_bandwidth(&radio, convertRxBandwidth(modem_bw));
|
||||
}
|
||||
else if (direction == SOAPY_SDR_TX)
|
||||
{
|
||||
cariboulite_radio_set_tx_bandwidth(&radio, convertTxBandwidth(setbw));
|
||||
cariboulite_radio_set_tx_bandwidth(&radio, convertTxBandwidth(modem_bw));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -431,11 +433,6 @@ std::vector<double> Cariboulite::listBandwidths( const int direction, const size
|
|||
options.push_back( 1250000*fact );
|
||||
options.push_back( 1600000*fact );
|
||||
options.push_back( 2000000*fact );
|
||||
|
||||
//options.push_back( 2500000*fact );
|
||||
//options.push_back( 3000000*fact );
|
||||
//options.push_back( 4000000*fact );
|
||||
//options.push_back( 5000000*fact );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -13,63 +13,15 @@
|
|||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <Iir.h>
|
||||
|
||||
//#define ZF_LOG_LEVEL ZF_LOG_ERROR
|
||||
#define ZF_LOG_LEVEL ZF_LOG_VERBOSE
|
||||
|
||||
#include "datatypes/circular_buffer.h"
|
||||
#include "CaribouliteSampleQueue.hpp"
|
||||
#include "cariboulite_setup.h"
|
||||
#include "cariboulite_radios.h"
|
||||
#include "cariboulite_radio.h"
|
||||
|
||||
enum Cariboulite_Format
|
||||
{
|
||||
CARIBOULITE_FORMAT_FLOAT32 = 0,
|
||||
CARIBOULITE_FORMAT_INT16 = 1,
|
||||
CARIBOULITE_FORMAT_INT8 = 2,
|
||||
CARIBOULITE_FORMAT_FLOAT64 = 3,
|
||||
};
|
||||
|
||||
#define NUM_SAMPLEQUEUE_BUFS ( 3 )
|
||||
#define NUM_BYTES_PER_CPLX_ELEM ( 4 )
|
||||
|
||||
#pragma pack(1)
|
||||
// associated with CS8 - total 2 bytes / element
|
||||
typedef struct
|
||||
{
|
||||
int8_t i; // LSB
|
||||
int8_t q; // MSB
|
||||
} sample_complex_int8;
|
||||
|
||||
// associated with CS12 - total 3 bytes / element
|
||||
typedef struct
|
||||
{
|
||||
int16_t i :12; // LSB
|
||||
int16_t q :12; // MSB
|
||||
} sample_complex_int12;
|
||||
|
||||
// associated with CS32 - total 8 bytes / element
|
||||
typedef struct
|
||||
{
|
||||
int32_t i; // LSB
|
||||
int32_t q; // MSB
|
||||
} sample_complex_int32;
|
||||
|
||||
// associated with CF32 - total 8 bytes / element
|
||||
typedef struct
|
||||
{
|
||||
float i; // LSB
|
||||
float q; // MSB
|
||||
} sample_complex_float;
|
||||
|
||||
// associated with CF64 - total 16 bytes / element
|
||||
typedef struct
|
||||
{
|
||||
double i; // LSB
|
||||
double q; // MSB
|
||||
} sample_complex_double;
|
||||
#pragma pack()
|
||||
|
||||
class SoapyCaribouliteSession
|
||||
{
|
||||
|
@ -83,49 +35,6 @@ public:
|
|||
static size_t sessionCount;
|
||||
};
|
||||
|
||||
|
||||
class SampleQueue
|
||||
{
|
||||
public:
|
||||
SampleQueue(int mtu_bytes, int num_buffers);
|
||||
~SampleQueue();
|
||||
int AttachStreamId(int id, int dir, int channel);
|
||||
int Write(caribou_smi_sample_complex_int16 *buffer, size_t num_samples, uint8_t* meta, long timeout_us);
|
||||
int Read(caribou_smi_sample_complex_int16 *buffer, size_t num_samples, uint8_t *meta, long timeout_us);
|
||||
|
||||
int ReadSamples(caribou_smi_sample_complex_int16* buffer, size_t num_elements, long timeout_us);
|
||||
int ReadSamples(sample_complex_float* buffer, size_t num_elements, long timeout_us);
|
||||
int ReadSamples(sample_complex_double* buffer, size_t num_elements, long timeout_us);
|
||||
int ReadSamples(sample_complex_int8* buffer, size_t num_elements, long timeout_us);
|
||||
|
||||
int stream_id;
|
||||
int stream_dir;
|
||||
int stream_channel;
|
||||
int is_cw;
|
||||
Cariboulite_Format chosen_format;
|
||||
int dig_filt;
|
||||
private:
|
||||
circular_buffer<caribou_smi_sample_complex_int16> *queue;
|
||||
size_t mtu_size_bytes;
|
||||
uint8_t *partial_buffer;
|
||||
int partial_buffer_start;
|
||||
int partial_buffer_length;
|
||||
|
||||
caribou_smi_sample_complex_int16 *interm_native_buffer;
|
||||
#define FILT_ORDER 6
|
||||
#define FILT_ORDER1 8
|
||||
Iir::Butterworth::LowPass<FILT_ORDER> filt20_i;
|
||||
Iir::Butterworth::LowPass<FILT_ORDER> filt20_q;
|
||||
Iir::Butterworth::LowPass<FILT_ORDER> filt50_i;
|
||||
Iir::Butterworth::LowPass<FILT_ORDER> filt50_q;
|
||||
Iir::Butterworth::LowPass<FILT_ORDER> filt100_i;
|
||||
Iir::Butterworth::LowPass<FILT_ORDER> filt100_q;
|
||||
Iir::Butterworth::LowPass<FILT_ORDER> filt200_i;
|
||||
Iir::Butterworth::LowPass<FILT_ORDER> filt200_q;
|
||||
Iir::Butterworth::LowPass<FILT_ORDER1> filt2p5M_i;
|
||||
Iir::Butterworth::LowPass<FILT_ORDER1> filt2p5M_q;
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
* Device interface
|
||||
**********************************************************************/
|
||||
|
@ -234,8 +143,8 @@ public:
|
|||
|
||||
public:
|
||||
cariboulite_radio_state_st radio;
|
||||
SampleQueue* sample_queue_tx;
|
||||
SampleQueue* sample_queue_rx;
|
||||
SoapySDR::Stream* sample_queue_tx;
|
||||
SoapySDR::Stream* sample_queue_rx;
|
||||
|
||||
// Static load time initializations
|
||||
static SoapyCaribouliteSession sess;
|
||||
|
|
|
@ -2,87 +2,124 @@
|
|||
#include <Iir.h>
|
||||
#include <byteswap.h>
|
||||
|
||||
#define NUM_BYTES_PER_CPLX_ELEM ( sizeof(caribou_smi_sample_complex_int16) )
|
||||
#define NUM_NATIVE_MTUS_PER_QUEUE ( 10 )
|
||||
|
||||
// each MTU = 131072 samples
|
||||
// Sized 524,288 bytes per MTU = 32.768 milliseconds
|
||||
// In total, each queue contains ~5 MB = ~320 milliseconds of depth
|
||||
size_t SoapySDR::Stream::mtu_size_elements = (1024 * 1024 / 2 / NUM_BYTES_PER_CPLX_ELEM );
|
||||
|
||||
//=================================================================
|
||||
SampleQueue::SampleQueue(int mtu_bytes, int num_buffers)
|
||||
SoapySDR::Stream::Stream()
|
||||
{
|
||||
SoapySDR_logf(SOAPY_SDR_INFO, "Creating SampleQueue MTU: %d bytes, NumBuffers: %d", mtu_bytes, num_buffers);
|
||||
queue = new circular_buffer<caribou_smi_sample_complex_int16>(mtu_bytes / 4 * num_buffers*10);
|
||||
mtu_size_bytes = mtu_bytes;
|
||||
stream_id = -1;
|
||||
stream_dir = -1;
|
||||
stream_channel = -1;
|
||||
SoapySDR_logf(SOAPY_SDR_INFO, "Creating SampleQueue MTU: %d I/Q samples (%d bytes), NumBuffers: %d",
|
||||
mtu_size_elements,
|
||||
mtu_size_elements * sizeof(caribou_smi_sample_complex_int16),
|
||||
NUM_NATIVE_MTUS_PER_QUEUE);
|
||||
|
||||
partial_buffer = new uint8_t[mtu_size_bytes];
|
||||
partial_buffer_start = mtu_size_bytes;
|
||||
partial_buffer_length = 0;
|
||||
dig_filt = 0;
|
||||
// create the actual native queue
|
||||
queue = new circular_buffer<caribou_smi_sample_complex_int16>(
|
||||
mtu_size_elements * NUM_NATIVE_MTUS_PER_QUEUE);
|
||||
|
||||
// a buffer for conversion betwen native and emulated formats
|
||||
// the maximal size is the 2*(mtu_size in bytes)
|
||||
interm_native_buffer = new caribou_smi_sample_complex_int16[2*mtu_size_bytes];
|
||||
is_cw = 0;
|
||||
format = CARIBOULITE_FORMAT_INT16;
|
||||
is_cw = 0;
|
||||
smi_stream_id = -1;
|
||||
|
||||
// Init the internal IIR filters
|
||||
// a buffer for conversion between native and emulated formats
|
||||
// the maximal size is the twice the MTU
|
||||
interm_native_buffer = new caribou_smi_sample_complex_int16[2 * mtu_size_elements];
|
||||
filterType = DigitalFilter_None;
|
||||
filter_i = NULL;
|
||||
filter_q = NULL;
|
||||
filt20_i.setup(4e6, 20e3/2);
|
||||
filt50_i.setup(4e6, 50e3/2);
|
||||
filt100_i.setup(4e6, 100e3/2);
|
||||
filt200_i.setup(4e6, 200e3/2);
|
||||
filt2p5M_i.setup(4e6, 2.5e6/2);
|
||||
|
||||
filt20_q.setup(4e6, 20e3/2);
|
||||
filt50_q.setup(4e6, 50e3/2);
|
||||
filt100_q.setup(4e6, 100e3/2);
|
||||
filt200_q.setup(4e6, 200e3/2);
|
||||
filt2p5M_q.setup(4e6, 2.5e6/2);
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
SampleQueue::~SampleQueue()
|
||||
void SoapySDR::Stream::setDigitalFilter(DigitalFilterType type)
|
||||
{
|
||||
stream_id = -1;
|
||||
stream_dir = -1;
|
||||
stream_channel = -1;
|
||||
delete[] partial_buffer;
|
||||
switch (type)
|
||||
{
|
||||
case DigitalFilter_20KHz: filter_i = &filt20_i; filter_q = &filt20_q; break;
|
||||
case DigitalFilter_50KHz: filter_i = &filt50_i; filter_q = &filt50_q; break;
|
||||
case DigitalFilter_100KHz: filter_i = &filt100_i; filter_q = &filt100_q; break;
|
||||
case DigitalFilter_2500KHz: filter_i = &filt2p5M_i; filter_q = &filt2p5M_q; break;
|
||||
case DigitalFilter_None:
|
||||
default:
|
||||
filter_i = NULL;
|
||||
filter_q = NULL;
|
||||
break;
|
||||
}
|
||||
filterType = type;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
SoapySDR::Stream::~Stream()
|
||||
{
|
||||
smi_stream_id = -1;
|
||||
delete[] interm_native_buffer;
|
||||
filter_i = NULL;
|
||||
filter_q = NULL;
|
||||
filterType = DigitalFilter_None;
|
||||
delete queue;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
int SampleQueue::AttachStreamId(int id, int dir, int channel)
|
||||
int SoapySDR::Stream::getInnerStreamType(void)
|
||||
{
|
||||
//printf("SampleQueue::AttachStreamId\n");
|
||||
if (stream_id != -1)
|
||||
{
|
||||
SoapySDR_logf(SOAPY_SDR_ERROR, "Cannot attach stream_id - already attached to %d", stream_id);
|
||||
return -1;
|
||||
}
|
||||
stream_id = id;
|
||||
stream_dir = dir;
|
||||
stream_channel = channel;
|
||||
return 0;
|
||||
if (smi_stream_id < 0)
|
||||
{
|
||||
return SOAPY_SDR_RX;
|
||||
}
|
||||
return CARIBOU_SMI_GET_STREAM_TYPE(smi_stream_id) == caribou_smi_stream_type_read ? SOAPY_SDR_RX : SOAPY_SDR_TX;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
int SampleQueue::Write(caribou_smi_sample_complex_int16 *buffer, size_t num_samples, uint8_t* meta, long timeout_us)
|
||||
int SoapySDR::Stream::setFormat(const std::string &fmt)
|
||||
{
|
||||
if (!fmt.compare(SOAPY_SDR_CS16))
|
||||
format = CARIBOULITE_FORMAT_INT16;
|
||||
else if (!fmt.compare(SOAPY_SDR_CS8))
|
||||
format = CARIBOULITE_FORMAT_INT8;
|
||||
else if (!fmt.compare(SOAPY_SDR_CF32))
|
||||
format = CARIBOULITE_FORMAT_FLOAT32;
|
||||
else if (!fmt.compare(SOAPY_SDR_CF64))
|
||||
format = CARIBOULITE_FORMAT_FLOAT64;
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
int SoapySDR::Stream::Write(caribou_smi_sample_complex_int16 *buffer, size_t num_samples, uint8_t* meta, long timeout_us)
|
||||
{
|
||||
return queue->put(buffer, num_samples);
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
int SampleQueue::Read(caribou_smi_sample_complex_int16 *buffer, size_t num_samples, uint8_t *meta, long timeout_us)
|
||||
int SoapySDR::Stream::Read(caribou_smi_sample_complex_int16 *buffer, size_t num_samples, uint8_t *meta, long timeout_us)
|
||||
{
|
||||
return queue->get(buffer, num_samples);
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
int SampleQueue::ReadSamples(caribou_smi_sample_complex_int16* buffer, size_t num_elements, long timeout_us)
|
||||
int SoapySDR::Stream::ReadSamples(caribou_smi_sample_complex_int16* buffer, size_t num_elements, long timeout_us)
|
||||
{
|
||||
static int once = 100;
|
||||
static uint16_t last_q = 0;
|
||||
|
||||
int res = Read(buffer, num_elements, NULL, timeout_us);
|
||||
if (res < 0)
|
||||
{
|
||||
// todo!!
|
||||
SoapySDR_logf(SOAPY_SDR_ERROR, "Reading %d elements failed from queue", num_elements);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -90,45 +127,12 @@ int SampleQueue::ReadSamples(caribou_smi_sample_complex_int16* buffer, size_t nu
|
|||
|
||||
return tot_read_elements;
|
||||
|
||||
// digital filters - TBD
|
||||
if (dig_filt == 0)
|
||||
if (filterType != DigitalFilter_None && filter_i != NULL && filter_q != NULL)
|
||||
{
|
||||
for (int i = 0; i < res; i++)
|
||||
{
|
||||
buffer[i].i = (int16_t)filt2p5M_i.filter((float)buffer[i].i);
|
||||
buffer[i].q = (int16_t)filt2p5M_q.filter((float)buffer[i].q);
|
||||
}
|
||||
}
|
||||
else if (dig_filt == 1)
|
||||
{
|
||||
for (int i = 0; i < res; i++)
|
||||
{
|
||||
buffer[i].i = (int16_t)filt20_i.filter((float)buffer[i].i);
|
||||
buffer[i].q = (int16_t)filt20_q.filter((float)buffer[i].q);
|
||||
}
|
||||
}
|
||||
else if (dig_filt == 2)
|
||||
{
|
||||
for (int i = 0; i < res; i++)
|
||||
{
|
||||
buffer[i].i = (int16_t)filt50_i.filter((float)buffer[i].i);
|
||||
buffer[i].q = (int16_t)filt50_q.filter((float)buffer[i].q);
|
||||
}
|
||||
}
|
||||
else if (dig_filt == 3)
|
||||
{
|
||||
for (int i = 0; i < res; i++)
|
||||
{
|
||||
buffer[i].i = (int16_t)filt100_i.filter((float)buffer[i].i);
|
||||
buffer[i].q = (int16_t)filt100_q.filter((float)buffer[i].q);
|
||||
}
|
||||
}
|
||||
else if (dig_filt == 4)
|
||||
{
|
||||
for (int i = 0; i < res; i++)
|
||||
{
|
||||
buffer[i].i = (int16_t)filt200_i.filter((float)buffer[i].i);
|
||||
buffer[i].q = (int16_t)filt200_q.filter((float)buffer[i].q);
|
||||
buffer[i].i = (int16_t)filter_i->filter((float)buffer[i].i);
|
||||
buffer[i].q = (int16_t)filter_q->filter((float)buffer[i].q);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,123 +140,59 @@ int SampleQueue::ReadSamples(caribou_smi_sample_complex_int16* buffer, size_t nu
|
|||
}
|
||||
|
||||
//=================================================================
|
||||
int SampleQueue::ReadSamples(sample_complex_float* buffer, size_t num_elements, long timeout_us)
|
||||
int SoapySDR::Stream::ReadSamples(sample_complex_float* buffer, size_t num_elements, long timeout_us)
|
||||
{
|
||||
uint32_t max_native_samples = 2*(mtu_size_bytes / sizeof(caribou_smi_sample_complex_int16));
|
||||
|
||||
// do not allow to store more than is possible in the intermediate buffer
|
||||
if (num_elements > max_native_samples)
|
||||
{
|
||||
num_elements = max_native_samples;
|
||||
}
|
||||
num_elements = num_elements > mtu_size_elements ? mtu_size_elements : num_elements;
|
||||
|
||||
// read out the native data type
|
||||
int res = ReadSamples(interm_native_buffer, num_elements, timeout_us);
|
||||
if (res < 0)
|
||||
{
|
||||
// todo!!
|
||||
return res;
|
||||
}
|
||||
|
||||
float max_val = (float)(4095);
|
||||
float max_val = 4096.0f;
|
||||
|
||||
for (int i = 0; i < res; i++)
|
||||
{
|
||||
buffer[i].i = (float)interm_native_buffer[i].i / max_val;
|
||||
buffer[i].q = (float)interm_native_buffer[i].q / max_val;
|
||||
buffer[i].i = (float)(interm_native_buffer[i].i) / max_val;
|
||||
buffer[i].q = (float)(interm_native_buffer[i].q) / max_val;
|
||||
}
|
||||
|
||||
double sumI = 0.0;
|
||||
double sumQ = 0.0;
|
||||
for (int i = 0; i < res; i++)
|
||||
{
|
||||
sumI += buffer[i].i;
|
||||
sumQ += buffer[i].q;
|
||||
}
|
||||
sumI /= (double)res;
|
||||
sumQ /= (double)res;
|
||||
|
||||
for (int i = 0; i < res; i++)
|
||||
{
|
||||
buffer[i].i -= sumI;
|
||||
buffer[i].q -= sumQ;
|
||||
}
|
||||
|
||||
/*double theta1 = 0.0;
|
||||
double theta2 = 0.0;
|
||||
double theta3 = 0.0;
|
||||
for (int i = 0; i < res; i++)
|
||||
{
|
||||
int sign_I = (buffer[i].i > 0 ? 1 : -1);
|
||||
int sign_Q = (buffer[i].q > 0 ? 1 : -1);
|
||||
theta1 += sign_I * buffer[i].q;
|
||||
theta2 += sign_I * buffer[i].i;
|
||||
theta3 += sign_Q * buffer[i].q;
|
||||
}
|
||||
theta1 = - theta1 / (double)res;
|
||||
theta2 /= (double)res;
|
||||
theta3 /= (double)res;
|
||||
|
||||
double c1 = theta1 / theta2;
|
||||
double c2 = sqrt( (theta3*theta3 - theta1*theta1) / (theta2*theta2) );
|
||||
|
||||
for (int i = 0; i < res; i++)
|
||||
{
|
||||
float ii = buffer[i].i;
|
||||
float qq = buffer[i].q;
|
||||
buffer[i].i = c2 * ii;
|
||||
buffer[i].q = c1 * ii + qq;
|
||||
}*/
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
int SampleQueue::ReadSamples(sample_complex_double* buffer, size_t num_elements, long timeout_us)
|
||||
int SoapySDR::Stream::ReadSamples(sample_complex_double* buffer, size_t num_elements, long timeout_us)
|
||||
{
|
||||
uint32_t max_native_samples = 2*(mtu_size_bytes / sizeof(caribou_smi_sample_complex_int16));
|
||||
|
||||
// do not allow to store more than is possible in the intermediate buffer
|
||||
if (num_elements > max_native_samples)
|
||||
{
|
||||
num_elements = max_native_samples;
|
||||
}
|
||||
num_elements = num_elements > mtu_size_elements ? mtu_size_elements : num_elements;
|
||||
|
||||
// read out the native data type
|
||||
int res = ReadSamples(interm_native_buffer, num_elements, timeout_us);
|
||||
if (res < 0)
|
||||
{
|
||||
// todo!!
|
||||
return res;
|
||||
}
|
||||
|
||||
double max_val = (double)(4095);
|
||||
double max_val = 4096.0;
|
||||
|
||||
for (int i = 0; i < res; i++)
|
||||
{
|
||||
buffer[i].i = (double)interm_native_buffer[i].i / max_val;
|
||||
buffer[i].q = (double)interm_native_buffer[i].q / max_val;
|
||||
buffer[i].i = (double)(interm_native_buffer[i].i) / max_val;
|
||||
buffer[i].q = (double)(interm_native_buffer[i].q) / max_val;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
int SampleQueue::ReadSamples(sample_complex_int8* buffer, size_t num_elements, long timeout_us)
|
||||
int SoapySDR::Stream::ReadSamples(sample_complex_int8* buffer, size_t num_elements, long timeout_us)
|
||||
{
|
||||
uint32_t max_native_samples = 2*(mtu_size_bytes / sizeof(caribou_smi_sample_complex_int16));
|
||||
|
||||
// do not allow to store more than is possible in the intermediate buffer
|
||||
if (num_elements > max_native_samples)
|
||||
{
|
||||
num_elements = max_native_samples;
|
||||
}
|
||||
num_elements = num_elements > mtu_size_elements ? mtu_size_elements : num_elements;
|
||||
|
||||
// read out the native data type
|
||||
int res = ReadSamples(interm_native_buffer, num_elements, timeout_us);
|
||||
if (res < 0)
|
||||
{
|
||||
// todo!!
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -263,4 +203,18 @@ int SampleQueue::ReadSamples(sample_complex_int8* buffer, size_t num_elements, l
|
|||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
int SoapySDR::Stream::ReadSamplesGen(void* buffer, size_t num_elements, long timeout_us)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case CARIBOULITE_FORMAT_FLOAT32: return ReadSamples((sample_complex_float*)buffer, num_elements, timeout_us); break;
|
||||
case CARIBOULITE_FORMAT_INT16: return ReadSamples((caribou_smi_sample_complex_int16*)buffer, num_elements, timeout_us); break;
|
||||
case CARIBOULITE_FORMAT_INT8: return ReadSamples((sample_complex_int8*)buffer, num_elements, timeout_us); break;
|
||||
case CARIBOULITE_FORMAT_FLOAT64: return ReadSamples((sample_complex_double*)buffer, num_elements, timeout_us); break;
|
||||
default: return ReadSamples((caribou_smi_sample_complex_int16*)buffer, num_elements, timeout_us); break;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
#pragma once
|
||||
#include <SoapySDR/Device.hpp>
|
||||
#include <SoapySDR/Logger.h>
|
||||
#include <SoapySDR/Types.h>
|
||||
#include <SoapySDR/Formats.hpp>
|
||||
#include <stdexcept>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <Iir.h>
|
||||
|
||||
//#define ZF_LOG_LEVEL ZF_LOG_ERROR
|
||||
#define ZF_LOG_LEVEL ZF_LOG_VERBOSE
|
||||
|
||||
#include "datatypes/circular_buffer.h"
|
||||
#include "cariboulite_setup.h"
|
||||
#include "cariboulite_radios.h"
|
||||
#include "cariboulite_radio.h"
|
||||
|
||||
#define DIG_FILT_ORDER 6
|
||||
|
||||
#pragma pack(1)
|
||||
// associated with CS8 - total 2 bytes / element
|
||||
typedef struct
|
||||
{
|
||||
int8_t i; // LSB
|
||||
int8_t q; // MSB
|
||||
} sample_complex_int8;
|
||||
|
||||
// associated with CS12 - total 3 bytes / element
|
||||
typedef struct
|
||||
{
|
||||
int16_t i :12; // LSB
|
||||
int16_t q :12; // MSB
|
||||
} sample_complex_int12;
|
||||
|
||||
// associated with CS32 - total 8 bytes / element
|
||||
typedef struct
|
||||
{
|
||||
int32_t i; // LSB
|
||||
int32_t q; // MSB
|
||||
} sample_complex_int32;
|
||||
|
||||
// associated with CF32 - total 8 bytes / element
|
||||
typedef struct
|
||||
{
|
||||
float i; // LSB
|
||||
float q; // MSB
|
||||
} sample_complex_float;
|
||||
|
||||
// associated with CF64 - total 16 bytes / element
|
||||
typedef struct
|
||||
{
|
||||
double i; // LSB
|
||||
double q; // MSB
|
||||
} sample_complex_double;
|
||||
#pragma pack()
|
||||
|
||||
// The forward declared Stream Class
|
||||
class SoapySDR::Stream
|
||||
{
|
||||
public:
|
||||
enum CaribouliteFormat
|
||||
{
|
||||
CARIBOULITE_FORMAT_FLOAT32 = 0,
|
||||
CARIBOULITE_FORMAT_INT16 = 1,
|
||||
CARIBOULITE_FORMAT_INT8 = 2,
|
||||
CARIBOULITE_FORMAT_FLOAT64 = 3,
|
||||
};
|
||||
CaribouliteFormat format;
|
||||
|
||||
enum DigitalFilterType
|
||||
{
|
||||
DigitalFilter_None = 0,
|
||||
DigitalFilter_20KHz,
|
||||
DigitalFilter_50KHz,
|
||||
DigitalFilter_100KHz,
|
||||
DigitalFilter_200KHz,
|
||||
DigitalFilter_2500KHz,
|
||||
};
|
||||
|
||||
public:
|
||||
Stream();
|
||||
~Stream();
|
||||
int Write(caribou_smi_sample_complex_int16 *buffer, size_t num_samples, uint8_t* meta, long timeout_us);
|
||||
int Read(caribou_smi_sample_complex_int16 *buffer, size_t num_samples, uint8_t *meta, long timeout_us);
|
||||
|
||||
int ReadSamples(caribou_smi_sample_complex_int16* buffer, size_t num_elements, long timeout_us);
|
||||
int ReadSamples(sample_complex_float* buffer, size_t num_elements, long timeout_us);
|
||||
int ReadSamples(sample_complex_double* buffer, size_t num_elements, long timeout_us);
|
||||
int ReadSamples(sample_complex_int8* buffer, size_t num_elements, long timeout_us);
|
||||
int ReadSamplesGen(void* buffer, size_t num_elements, long timeout_us);
|
||||
|
||||
int getInnerStreamType(void);
|
||||
void setDigitalFilter(DigitalFilterType type);
|
||||
int setFormat(const std::string &fmt);
|
||||
|
||||
int smi_stream_id;
|
||||
int is_cw;
|
||||
|
||||
private: // Internal data
|
||||
circular_buffer<caribou_smi_sample_complex_int16> *queue;
|
||||
|
||||
caribou_smi_sample_complex_int16 *interm_native_buffer;
|
||||
DigitalFilterType filterType;
|
||||
Iir::Butterworth::LowPass<DIG_FILT_ORDER>* filter_i;
|
||||
Iir::Butterworth::LowPass<DIG_FILT_ORDER>* filter_q;
|
||||
Iir::Butterworth::LowPass<DIG_FILT_ORDER> filt20_i;
|
||||
Iir::Butterworth::LowPass<DIG_FILT_ORDER> filt20_q;
|
||||
Iir::Butterworth::LowPass<DIG_FILT_ORDER> filt50_i;
|
||||
Iir::Butterworth::LowPass<DIG_FILT_ORDER> filt50_q;
|
||||
Iir::Butterworth::LowPass<DIG_FILT_ORDER> filt100_i;
|
||||
Iir::Butterworth::LowPass<DIG_FILT_ORDER> filt100_q;
|
||||
Iir::Butterworth::LowPass<DIG_FILT_ORDER> filt2p5M_i;
|
||||
Iir::Butterworth::LowPass<DIG_FILT_ORDER> filt2p5M_q;
|
||||
|
||||
public:
|
||||
static size_t mtu_size_elements;
|
||||
static size_t getMTUSizeElements(void) {return mtu_size_elements;}
|
||||
};
|
|
@ -77,28 +77,25 @@ Type Cariboulite::readSensor(const int direction, const size_t channel, const st
|
|||
if (key == "RSSI")
|
||||
{
|
||||
float rssi = 0.0f;
|
||||
cariboulite_get_rssi((cariboulite_radios_st*)&radios,(cariboulite_channel_en)channel, &rssi);
|
||||
cariboulite_radio_get_rssi((cariboulite_radio_state_st*)&radio, &rssi);
|
||||
return rssi;
|
||||
}
|
||||
if (key == "ENERGY")
|
||||
{
|
||||
float energy = 0.0f;
|
||||
cariboulite_get_energy_det((cariboulite_radios_st*)&radios,(cariboulite_channel_en)channel, &energy);
|
||||
cariboulite_radio_get_energy_det((cariboulite_radio_state_st*)&radio, &energy);
|
||||
return energy;
|
||||
}
|
||||
}
|
||||
|
||||
cariboulite_radio_state_st* rad = (cariboulite_radio_state_st* )
|
||||
((channel == cariboulite_channel_s1g) ? &radios.radio_sub1g : &radios.radio_6g);
|
||||
|
||||
if (key == "PLL_LOCK_MODEM")
|
||||
{
|
||||
return rad->modem_pll_locked;
|
||||
return radio.modem_pll_locked;
|
||||
}
|
||||
|
||||
if (channel == cariboulite_channel_6g && key == "PLL_LOCK_MIXER")
|
||||
{
|
||||
return rad->lo_pll_locked;
|
||||
return radio.lo_pll_locked;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,36 +2,41 @@
|
|||
#include "cariboulite_config/cariboulite_config_default.h"
|
||||
|
||||
//=================================================================
|
||||
static void caribou_stream_data_event( void *ctx,
|
||||
void *service_context,
|
||||
caribou_smi_stream_type_en type,
|
||||
caribou_smi_channel_en ch,
|
||||
size_t sample_count,
|
||||
caribou_smi_sample_complex_int16 *cmplx_vec,
|
||||
caribou_smi_sample_meta *meta_vec,
|
||||
size_t buffers_capacity_samples)
|
||||
void caribou_stream_data_event( void *ctx,
|
||||
void *service_context,
|
||||
caribou_smi_stream_type_en type,
|
||||
caribou_smi_channel_en ch,
|
||||
size_t sample_count,
|
||||
caribou_smi_sample_complex_int16 *cmplx_vec,
|
||||
caribou_smi_sample_meta *meta_vec,
|
||||
size_t buffers_capacity_samples)
|
||||
{
|
||||
cariboulite_st* sys = (cariboulite_st*)ctx;
|
||||
Cariboulite *obj = (Cariboulite*)service_context;
|
||||
//cariboulite_st* sys = (cariboulite_st*)ctx;
|
||||
Cariboulite *soapy_obj = (Cariboulite*)service_context;
|
||||
|
||||
int dir = (type == caribou_smi_stream_type_read) ? SOAPY_SDR_RX : SOAPY_SDR_TX;
|
||||
int channel = (ch == caribou_smi_channel_900) ? cariboulite_channel_s1g : cariboulite_channel_6g;
|
||||
// Basic sanity checking
|
||||
cariboulite_channel_en ch_type = ch == caribou_smi_channel_900 ? cariboulite_channel_s1g : cariboulite_channel_6g;
|
||||
if (soapy_obj->radio.type != ch_type)
|
||||
{
|
||||
SoapySDR_logf(SOAPY_SDR_ERROR, "caribou_stream_data_event: reaceived wrong CH <=> service_context pair");
|
||||
return;
|
||||
}
|
||||
|
||||
switch(type)
|
||||
{
|
||||
//-------------------------------------------------------
|
||||
case caribou_smi_stream_type_read:
|
||||
{
|
||||
int sample_queue_index = CARIBOU_SMI_GET_STREAM_ID(type, ch);
|
||||
obj->sample_queues[sample_queue_index]->Write(cmplx_vec, sample_count, 0, 10000L);
|
||||
// SMI read samples from Caribou and these samples are written into the Soapy buffer
|
||||
soapy_obj->sample_queue_rx->Write(cmplx_vec, sample_count, 0, 10000L);
|
||||
}
|
||||
break;
|
||||
|
||||
//-------------------------------------------------------
|
||||
case caribou_smi_stream_type_write:
|
||||
{
|
||||
int sample_queue_index = CARIBOU_SMI_GET_STREAM_ID(dir, channel);
|
||||
printf("Wrote to sample_queue_index %d\n", sample_queue_index);
|
||||
// SMI requests to get (read) samples from Soapy and write them to Caribou
|
||||
soapy_obj->sample_queue_tx->Read(cmplx_vec, sample_count, 0, 10000L);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -66,7 +71,6 @@ static void caribou_stream_data_event( void *ctx,
|
|||
*/
|
||||
std::vector<std::string> Cariboulite::getStreamFormats(const int direction, const size_t channel) const
|
||||
{
|
||||
//printf("getStreamFormats\n");
|
||||
std::vector<std::string> formats;
|
||||
formats.push_back(SOAPY_SDR_CS16);
|
||||
formats.push_back(SOAPY_SDR_CS8);
|
||||
|
@ -87,7 +91,6 @@ std::vector<std::string> Cariboulite::getStreamFormats(const int direction, cons
|
|||
*/
|
||||
std::string Cariboulite::getNativeStreamFormat(const int direction, const size_t channel, double &fullScale) const
|
||||
{
|
||||
//printf("getNativeStreamFormat\n");
|
||||
fullScale = (double)((1<<12)-1);
|
||||
return SOAPY_SDR_CS16;
|
||||
}
|
||||
|
@ -101,7 +104,6 @@ std::string Cariboulite::getNativeStreamFormat(const int direction, const size_t
|
|||
*/
|
||||
SoapySDR::ArgInfoList Cariboulite::getStreamArgsInfo(const int direction, const size_t channel) const
|
||||
{
|
||||
//printf("getStreamArgsInfo start\n");
|
||||
SoapySDR::ArgInfoList streamArgs;
|
||||
return streamArgs;
|
||||
}
|
||||
|
@ -161,71 +163,50 @@ SoapySDR::Stream *Cariboulite::setupStream(const int direction,
|
|||
const std::vector<size_t> &channels,
|
||||
const SoapySDR::Kwargs &args)
|
||||
{
|
||||
int cw = (args.count("CW") != 0) ? std::atoi(args.at("CW").c_str()) : 0;
|
||||
SoapySDR_logf(SOAPY_SDR_INFO, "setupStream: dir= %s, format= %s, is_cw= %d, ch= %d",
|
||||
direction == SOAPY_SDR_TX?"TX":"RX", format.c_str(), cw,
|
||||
channels.size()?channels[0]:0);
|
||||
|
||||
std::vector<size_t> channels_internal = channels;
|
||||
// is it a CW TX channel
|
||||
int cw = (args.count("CW") != 0) ? std::atoi(args.at("CW").c_str()) : 0;
|
||||
if (direction == SOAPY_SDR_RX && cw)
|
||||
{
|
||||
SoapySDR_logf(SOAPY_SDR_ERROR, "setupStream: CW channel can only be used with TX channel");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// default channel - sub1GHz
|
||||
if ( channels_internal.size() == 0 )
|
||||
{
|
||||
channels_internal.push_back(cariboulite_channel_s1g);
|
||||
}
|
||||
SoapySDR_logf(SOAPY_SDR_INFO, "setupStream: dir= %s, format= %s, is_cw= %d",
|
||||
direction == SOAPY_SDR_TX ? "TX" : "RX",
|
||||
format.c_str(), cw);
|
||||
|
||||
// currently we take only the first channel
|
||||
size_t ch = channels_internal[0];
|
||||
|
||||
// calculate the stream_id
|
||||
caribou_smi_stream_type_en type = (direction == SOAPY_SDR_RX) ? caribou_smi_stream_type_read : caribou_smi_stream_type_write;
|
||||
caribou_smi_channel_en channel = (ch == cariboulite_channel_s1g) ? caribou_smi_channel_900 : caribou_smi_channel_2400;
|
||||
int stream_id = CARIBOU_SMI_GET_STREAM_ID(type, channel);
|
||||
sample_queues[stream_id]->is_cw = cw;
|
||||
|
||||
// Setup the SampleQueue's format
|
||||
if (format == SOAPY_SDR_CS16)
|
||||
{
|
||||
sample_queues[stream_id]->chosen_format = CARIBOULITE_FORMAT_INT16;
|
||||
}
|
||||
else if (format == SOAPY_SDR_CS8)
|
||||
{
|
||||
sample_queues[stream_id]->chosen_format = CARIBOULITE_FORMAT_INT8;
|
||||
}
|
||||
else if (format == SOAPY_SDR_CF32)
|
||||
{
|
||||
sample_queues[stream_id]->chosen_format = CARIBOULITE_FORMAT_FLOAT32;
|
||||
}
|
||||
else if (format == SOAPY_SDR_CF64)
|
||||
{
|
||||
sample_queues[stream_id]->chosen_format = CARIBOULITE_FORMAT_FLOAT64;
|
||||
}
|
||||
else
|
||||
{
|
||||
SoapySDR_logf(SOAPY_SDR_ERROR, "the specified format %s is not supported", format.c_str());
|
||||
// configure the queue
|
||||
SoapySDR::Stream* queue = direction == SOAPY_SDR_RX ? sample_queue_rx : sample_queue_tx;
|
||||
queue->smi_stream_id = -1; // by default, the smi stream is not configured (e.g. with CS / BB-FSK...)
|
||||
queue->is_cw = cw;
|
||||
if (queue->setFormat(format) != 0)
|
||||
{
|
||||
SoapySDR_logf(SOAPY_SDR_ERROR, "the specified format %s is not supported", format.c_str());
|
||||
throw std::runtime_error( "setupStream invalid format " + format );
|
||||
}
|
||||
}
|
||||
|
||||
// create the stream (only for non CW streams)
|
||||
if (sample_queues[stream_id]->is_cw)
|
||||
// configure the radio channel to CW if needed
|
||||
cariboulite_radio_set_cw_outputs(&radio, false, queue->is_cw);
|
||||
|
||||
// configure the smi stream and attach it to the queue
|
||||
if (!cw)
|
||||
{
|
||||
cariboulite_set_cw_outputs(&radios, (cariboulite_channel_en)ch, false, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
cariboulite_set_cw_outputs(&radios, (cariboulite_channel_en)ch, false, false);
|
||||
stream_id = caribou_smi_setup_stream(&sess.cariboulite_sys.smi,
|
||||
type, channel,
|
||||
caribou_stream_data_event,
|
||||
this);
|
||||
if (stream_id < 0)
|
||||
// find out the SMI channel info
|
||||
caribou_smi_stream_type_en type = direction == SOAPY_SDR_RX ? caribou_smi_stream_type_read : caribou_smi_stream_type_write;
|
||||
caribou_smi_channel_en channel = radio.type == cariboulite_channel_s1g ? caribou_smi_channel_900 : caribou_smi_channel_2400;
|
||||
queue->smi_stream_id = caribou_smi_setup_stream(&sess.cariboulite_sys.smi,
|
||||
type,
|
||||
channel,
|
||||
caribou_stream_data_event,
|
||||
this);
|
||||
if (queue->smi_stream_id < 0)
|
||||
{
|
||||
throw std::runtime_error( "setupStream caribou_smi_setup_stream failed" );
|
||||
}
|
||||
}
|
||||
|
||||
//SoapySDR_logf(SOAPY_SDR_INFO, "finished setup stream, stream_id = %d, CW=%d", stream_id, cw);
|
||||
return (SoapySDR::Stream *)((void*)(stream_id));
|
||||
// Queue inherits Stream class
|
||||
return queue;
|
||||
}
|
||||
|
||||
//========================================================
|
||||
|
@ -236,10 +217,18 @@ SoapySDR::Stream *Cariboulite::setupStream(const int direction,
|
|||
*/
|
||||
void Cariboulite::closeStream(SoapySDR::Stream *stream)
|
||||
{
|
||||
if (stream == NULL) return;
|
||||
int stream_id = (intptr_t)stream;
|
||||
// if it is a CW stream, disable the output
|
||||
if (stream->is_cw)
|
||||
{
|
||||
cariboulite_radio_set_cw_outputs(&radio, false, false);
|
||||
}
|
||||
|
||||
caribou_smi_destroy_stream(&sess.cariboulite_sys.smi, stream_id);
|
||||
// check if this is a valid SMI stream
|
||||
if (stream->smi_stream_id != -1)
|
||||
{
|
||||
caribou_smi_destroy_stream(&sess.cariboulite_sys.smi, stream->smi_stream_id);
|
||||
stream->smi_stream_id = -1;
|
||||
}
|
||||
}
|
||||
|
||||
//========================================================
|
||||
|
@ -254,7 +243,7 @@ void Cariboulite::closeStream(SoapySDR::Stream *stream)
|
|||
*/
|
||||
size_t Cariboulite::getStreamMTU(SoapySDR::Stream *stream) const
|
||||
{
|
||||
return 1024 * 1024 / 2 / 4;
|
||||
return stream->getMTUSizeElements();
|
||||
}
|
||||
|
||||
//========================================================
|
||||
|
@ -280,17 +269,11 @@ int Cariboulite::activateStream(SoapySDR::Stream *stream,
|
|||
const long long timeNs,
|
||||
const size_t numElems)
|
||||
{
|
||||
//printf("activateStream\n");
|
||||
//SoapySDR_logf(SOAPY_SDR_INFO, "activateStream");
|
||||
int stream_id = (intptr_t)stream;
|
||||
cariboulite_radio_activate_channel(&radio, true);
|
||||
|
||||
cariboulite_activate_channel(&radios,
|
||||
(cariboulite_channel_en)sample_queues[stream_id]->stream_channel,
|
||||
true);
|
||||
|
||||
if ((cariboulite_channel_en)sample_queues[stream_id]->is_cw == 0)
|
||||
if (!stream->is_cw)
|
||||
{
|
||||
caribou_smi_run_pause_stream (&sess.cariboulite_sys.smi, (intptr_t)stream, 1);
|
||||
caribou_smi_run_pause_stream (&sess.cariboulite_sys.smi, stream->smi_stream_id, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -312,18 +295,13 @@ int Cariboulite::activateStream(SoapySDR::Stream *stream,
|
|||
*/
|
||||
int Cariboulite::deactivateStream(SoapySDR::Stream *stream, const int flags, const long long timeNs)
|
||||
{
|
||||
//SoapySDR_logf(SOAPY_SDR_INFO, "deactivateStream");
|
||||
int stream_id = (intptr_t)stream;
|
||||
|
||||
if ((cariboulite_channel_en)sample_queues[stream_id]->is_cw == 0)
|
||||
if (!stream->is_cw)
|
||||
{
|
||||
caribou_smi_run_pause_stream (&sess.cariboulite_sys.smi, (intptr_t)stream, 0);
|
||||
sleep(1);
|
||||
caribou_smi_run_pause_stream (&sess.cariboulite_sys.smi, stream->smi_stream_id, 0);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
cariboulite_activate_channel(&radios,
|
||||
(cariboulite_channel_en)sample_queues[stream_id]->stream_channel,
|
||||
false);
|
||||
cariboulite_radio_activate_channel(&radio, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -356,35 +334,11 @@ int Cariboulite::readStream(
|
|||
long long &timeNs,
|
||||
const long timeoutUs)
|
||||
{
|
||||
//printf("readStream\n");
|
||||
int stream_id = (intptr_t)stream;
|
||||
|
||||
if (sample_queues[stream_id]->stream_dir != SOAPY_SDR_RX)
|
||||
// Verify that it is an RX stream
|
||||
if (stream->getInnerStreamType() != SOAPY_SDR_RX)
|
||||
{
|
||||
// wrong sample queue => wrong stream_id
|
||||
return SOAPY_SDR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
uint32_t metadata = 0;
|
||||
int res = 0;
|
||||
switch(sample_queues[stream_id]->chosen_format)
|
||||
{
|
||||
case CARIBOULITE_FORMAT_FLOAT32:
|
||||
{
|
||||
res = sample_queues[stream_id]->ReadSamples((sample_complex_float*)buffs[0], numElems, timeoutUs);
|
||||
}
|
||||
break;
|
||||
case CARIBOULITE_FORMAT_INT16:
|
||||
res = sample_queues[stream_id]->ReadSamples((caribou_smi_sample_complex_int16*)buffs[0], numElems, timeoutUs);
|
||||
break;
|
||||
case CARIBOULITE_FORMAT_INT8:
|
||||
res = sample_queues[stream_id]->ReadSamples((sample_complex_int8*)buffs[0], numElems, timeoutUs);
|
||||
break;
|
||||
case CARIBOULITE_FORMAT_FLOAT64:
|
||||
res = sample_queues[stream_id]->ReadSamples((sample_complex_double*)buffs[0], numElems, timeoutUs);
|
||||
break;
|
||||
default: return -1; break;
|
||||
}
|
||||
|
||||
return res;
|
||||
return stream->ReadSamplesGen((void*)buffs[0], numElems, timeoutUs);
|
||||
}
|
Ładowanie…
Reference in New Issue