kopia lustrzana https://github.com/pa3gsb/Radioberry-2.x
support parallel rx tx
rodzic
b7129605d3
commit
2e3c8f6d69
|
@ -23,119 +23,131 @@ typedef enum radioberrysdrStreamFormat {
|
|||
RADIOBERRY_SDR_CS16
|
||||
} radioberrysdrStreamFormat;
|
||||
|
||||
class SoapyRadioberry : public SoapySDR::Device{
|
||||
class sdr_stream
|
||||
{
|
||||
public:
|
||||
sdr_stream(int dir)
|
||||
{
|
||||
direction = dir;
|
||||
}
|
||||
int get_direction() { return direction; }
|
||||
void set_stream_format(radioberrysdrStreamFormat sf) { streamFormat = sf; };
|
||||
radioberrysdrStreamFormat get_stream_format() { return streamFormat; };
|
||||
|
||||
public:
|
||||
|
||||
SoapyRadioberry( const SoapySDR::Kwargs & args );
|
||||
~SoapyRadioberry();
|
||||
private:
|
||||
int direction;
|
||||
radioberrysdrStreamFormat streamFormat;
|
||||
};
|
||||
|
||||
/*******************************************************************
|
||||
|
||||
|
||||
class SoapyRadioberry : public SoapySDR::Device
|
||||
{
|
||||
|
||||
public:
|
||||
SoapyRadioberry(const SoapySDR::Kwargs &args);
|
||||
~SoapyRadioberry();
|
||||
|
||||
/*******************************************************************
|
||||
* Identification API
|
||||
******************************************************************/
|
||||
|
||||
std::string getDriverKey( void ) const;
|
||||
std::string getDriverKey(void) const;
|
||||
|
||||
std::string getHardwareKey( void ) const;
|
||||
|
||||
SoapySDR::Kwargs getHardwareInfo( void ) const;
|
||||
|
||||
/*******************************************************************
|
||||
std::string getHardwareKey(void) const;
|
||||
|
||||
SoapySDR::Kwargs getHardwareInfo(void) const;
|
||||
|
||||
/*******************************************************************
|
||||
* Channels API
|
||||
******************************************************************/
|
||||
|
||||
size_t getNumChannels( const int direction ) const;
|
||||
size_t getNumChannels(const int direction) const;
|
||||
|
||||
bool getFullDuplex( const int direction, const size_t channel ) const;
|
||||
|
||||
/*******************************************************************
|
||||
bool getFullDuplex(const int direction, const size_t channel) const;
|
||||
|
||||
/*******************************************************************
|
||||
* Stream API
|
||||
******************************************************************/
|
||||
SoapySDR::RangeList getSampleRateRange(const int direction, const size_t channel) const;
|
||||
SoapySDR::RangeList getSampleRateRange(const int direction, const size_t channel) const;
|
||||
|
||||
std::vector<std::string> getStreamFormats(const int direction, const size_t channel) const;
|
||||
std::vector<std::string> getStreamFormats(const int direction, const size_t channel) const;
|
||||
|
||||
std::string getNativeStreamFormat(const int direction, const size_t channel, double &fullScale) const;
|
||||
std::string getNativeStreamFormat(const int direction, const size_t channel, double &fullScale) const;
|
||||
|
||||
SoapySDR::ArgInfoList getStreamArgsInfo(const int direction, const size_t channel) const;
|
||||
SoapySDR::ArgInfoList getStreamArgsInfo(const int direction, const size_t channel) const;
|
||||
|
||||
void closeStream(SoapySDR::Stream *stream);
|
||||
|
||||
SoapySDR::Stream *setupStream(
|
||||
const int direction,
|
||||
const std::string &format,
|
||||
const std::vector<size_t> &channels = std::vector<size_t>(),
|
||||
const SoapySDR::Kwargs &args = SoapySDR::Kwargs() );
|
||||
|
||||
int readStream(
|
||||
SoapySDR::Stream *stream,
|
||||
void * const *buffs,
|
||||
const size_t numElems,
|
||||
int &flags,
|
||||
long long &timeNs,
|
||||
const long timeoutUs = 100000 );
|
||||
|
||||
int writeStream(
|
||||
SoapySDR::Stream *stream,
|
||||
const void * const *buffs,
|
||||
const size_t numElems,
|
||||
int &flags,
|
||||
const long long timeNs = 0,
|
||||
const long timeoutUs = 100000);
|
||||
SoapySDR::Stream *setupStream(
|
||||
const int direction,
|
||||
const std::string &format,
|
||||
const std::vector<size_t> &channels = std::vector<size_t>(),
|
||||
const SoapySDR::Kwargs &args = SoapySDR::Kwargs());
|
||||
|
||||
int readStream(
|
||||
SoapySDR::Stream *stream,
|
||||
void *const *buffs,
|
||||
const size_t numElems,
|
||||
int &flags,
|
||||
long long &timeNs,
|
||||
const long timeoutUs = 100000);
|
||||
|
||||
/*******************************************************************
|
||||
int writeStream(
|
||||
SoapySDR::Stream *stream,
|
||||
const void *const *buffs,
|
||||
const size_t numElems,
|
||||
int &flags,
|
||||
const long long timeNs = 0,
|
||||
const long timeoutUs = 100000);
|
||||
|
||||
/*******************************************************************
|
||||
* Sample Rate API
|
||||
******************************************************************/
|
||||
|
||||
void setSampleRate( const int direction, const size_t channel, const double rate );
|
||||
void setSampleRate(const int direction, const size_t channel, const double rate);
|
||||
|
||||
double getBandwidth( const int direction, const size_t channel ) const;
|
||||
double getBandwidth(const int direction, const size_t channel) const;
|
||||
|
||||
std::vector<double> listBandwidths(const int direction, const size_t channel) const;
|
||||
std::vector<double> listSampleRates(const int direction, const size_t channel) const;
|
||||
|
||||
std::vector<double> listBandwidths( const int direction, const size_t channel ) const;
|
||||
std::vector<double> listSampleRates( const int direction, const size_t channel ) const;
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
/*******************************************************************
|
||||
* Frequency API
|
||||
******************************************************************/
|
||||
|
||||
void setFrequency(
|
||||
const int direction,
|
||||
const size_t channel,
|
||||
const double frequency,
|
||||
const SoapySDR::Kwargs &args = SoapySDR::Kwargs());
|
||||
|
||||
void setFrequency(
|
||||
const int direction,
|
||||
const size_t channel,
|
||||
const double frequency,
|
||||
const SoapySDR::Kwargs &args = SoapySDR::Kwargs());
|
||||
|
||||
SoapySDR::RangeList getFrequencyRange( const int direction, const size_t channel) const;
|
||||
|
||||
SoapySDR::RangeList getFrequencyRange(const int direction, const size_t channel) const;
|
||||
|
||||
/*******************************************************************
|
||||
/*******************************************************************
|
||||
* Antenna API
|
||||
******************************************************************/
|
||||
|
||||
std::vector<std::string> listAntennas( const int direction, const size_t channel ) const;
|
||||
std::vector<std::string> listAntennas(const int direction, const size_t channel) const;
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
/*******************************************************************
|
||||
* Gain API
|
||||
******************************************************************/
|
||||
|
||||
std::vector<std::string> listGains( const int direction, const size_t channel ) const;
|
||||
std::vector<std::string> listGains(const int direction, const size_t channel) const;
|
||||
|
||||
void setGain( const int direction, const size_t channel, const double value );
|
||||
void setGain(const int direction, const size_t channel, const double value);
|
||||
|
||||
SoapySDR::Range getGainRange( const int direction, const size_t channel ) const;
|
||||
SoapySDR::Range getGainRange(const int direction, const size_t channel) const;
|
||||
|
||||
void controlRadioberry(uint32_t command, uint32_t command_data);
|
||||
|
||||
void controlRadioberry(uint32_t command, uint32_t command_data);
|
||||
|
||||
/*******************************************************************
|
||||
* I2C API
|
||||
******************************************************************/
|
||||
|
||||
std::string readI2C(const int addr, const size_t numBytes);
|
||||
void writeI2C(const int addr, const std::string &data);
|
||||
|
||||
std::string readI2C(const int addr, const size_t numBytes);
|
||||
void writeI2C(const int addr, const std::string &data);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -144,8 +156,9 @@ class SoapyRadioberry : public SoapySDR::Device{
|
|||
int rx_frequency;
|
||||
int no_channels;
|
||||
struct rb_info_arg_t rb_control;
|
||||
std::unique_ptr<rpihw::driver::i2c> i2c_ptr;
|
||||
bool i2c_available = false;
|
||||
radioberrysdrStreamFormat streamFormat;
|
||||
std::mutex send_command;
|
||||
std::vector<sdr_stream *> streams;
|
||||
std::unique_ptr<rpihw::driver::i2c> i2c_ptr;
|
||||
bool i2c_available;
|
||||
bool mox;
|
||||
};
|
||||
|
|
|
@ -13,25 +13,26 @@ SoapyRadioberry::SoapyRadioberry( const SoapySDR::Kwargs &args ){
|
|||
|
||||
SoapySDR_setLogLevel(SOAPY_SDR_INFO);
|
||||
SoapySDR_log(SOAPY_SDR_INFO, "SoapyRadioberry::SoapyRadioberry constructor called");
|
||||
|
||||
mox = false;
|
||||
no_channels = 1;
|
||||
fd_rb = open("/dev/radioberry", O_RDWR);
|
||||
try
|
||||
{
|
||||
i2c_ptr = std::make_unique<rpihw::driver::i2c> (rpihw::driver::i2c("/dev/i2c-1"));
|
||||
i2c_ptr = std::make_unique<rpihw::driver::i2c>(rpihw::driver::i2c("/dev/i2c-1"));
|
||||
i2c_available = true;
|
||||
}
|
||||
catch (std::string s)
|
||||
{
|
||||
printf("I2c not found %s", s.c_str());
|
||||
i2c_available = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SoapyRadioberry::~SoapyRadioberry(void){
|
||||
|
||||
SoapyRadioberry::~SoapyRadioberry(void)
|
||||
{
|
||||
SoapySDR_log(SOAPY_SDR_INFO, "SoapyRadioberry::SoapyRadioberry destructor called");
|
||||
|
||||
for (auto con : streams)
|
||||
delete (con);
|
||||
if (fd_rb != 0) close(fd_rb);
|
||||
}
|
||||
|
||||
|
@ -130,21 +131,10 @@ bool SoapyRadioberry::getFullDuplex( const int direction, const size_t channel )
|
|||
|
||||
std::vector<double> SoapyRadioberry::listBandwidths( const int direction, const size_t channel ) const
|
||||
{
|
||||
|
||||
// radioberry does nor support bandwidth
|
||||
SoapySDR_log(SOAPY_SDR_INFO, "SoapyRadioberry::listBandwidths called");
|
||||
|
||||
|
||||
|
||||
std::vector<double> options;
|
||||
|
||||
if (direction == SOAPY_SDR_RX) {
|
||||
options.push_back(0.048e6);
|
||||
options.push_back(0.096e6);
|
||||
options.push_back(0.192e6);
|
||||
options.push_back(0.384e6);
|
||||
}
|
||||
if (direction == SOAPY_SDR_TX) {
|
||||
options.push_back(0.048e6);
|
||||
}
|
||||
return(options);
|
||||
}
|
||||
|
||||
|
@ -242,17 +232,24 @@ void SoapyRadioberry::setGain( const int direction, const size_t channel, const
|
|||
|
||||
if (direction == SOAPY_SDR_RX)
|
||||
{
|
||||
command = 0x14;
|
||||
if (mox)
|
||||
command = 0x15;
|
||||
else
|
||||
command = 0x14;
|
||||
command_data = (0x40 | (((uint32_t)value + 12) & 0x3F));
|
||||
}
|
||||
|
||||
if(direction==SOAPY_SDR_TX)
|
||||
{ // 0 -7 TX RF gain
|
||||
{ // 0 -7 TX RF gain
|
||||
if (!mox)
|
||||
return;
|
||||
|
||||
uint32_t z = (uint32_t)value;
|
||||
if (value > 15) z = 15;
|
||||
if (value < 0.0) z = 0;
|
||||
z = z << 28;
|
||||
command = 0x13;
|
||||
command_data = z;
|
||||
command_data = z;
|
||||
}
|
||||
|
||||
this->SoapyRadioberry::controlRadioberry(command, command_data);
|
||||
|
@ -266,10 +263,22 @@ void SoapyRadioberry::setFrequency( const int direction, const size_t channel,
|
|||
SoapySDR_log(SOAPY_SDR_INFO, "SoapyRadioberry::setFrequency called");
|
||||
|
||||
uint32_t command = 0;
|
||||
|
||||
if(direction==SOAPY_SDR_RX) command = 4;
|
||||
if(direction==SOAPY_SDR_TX) command = 3;
|
||||
|
||||
|
||||
if (direction == SOAPY_SDR_RX)
|
||||
{
|
||||
if (mox)
|
||||
command = 5;
|
||||
else
|
||||
command = 4;
|
||||
}
|
||||
|
||||
if (direction == SOAPY_SDR_TX)
|
||||
{
|
||||
if (!mox)
|
||||
return;
|
||||
command = 3;
|
||||
}
|
||||
|
||||
uint32_t command_data = (uint32_t) frequency;
|
||||
|
||||
this->SoapyRadioberry::controlRadioberry(command, command_data);
|
||||
|
@ -277,27 +286,27 @@ void SoapyRadioberry::setFrequency( const int direction, const size_t channel,
|
|||
|
||||
void SoapyRadioberry::writeI2C(const int addr, const std::string &data)
|
||||
{
|
||||
SoapySDR_log(SOAPY_SDR_INFO, "SoapyRadioberry::writeI2C called");
|
||||
|
||||
SoapySDR_log(SOAPY_SDR_INFO, "SoapyRadioberry::writeI2C called");
|
||||
|
||||
if (!i2c_available)
|
||||
return;
|
||||
i2c_ptr->addr(addr);
|
||||
try
|
||||
{
|
||||
i2c_ptr->write((uint8_t *)data.c_str(), data.size());
|
||||
i2c_ptr->write((uint8_t *)data.c_str(), data.size());
|
||||
}
|
||||
catch (std::string s)
|
||||
{
|
||||
printf("%s", s.c_str());
|
||||
}
|
||||
printf("%s", s.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
std::string SoapyRadioberry::readI2C(const int addr, const size_t numBytes)
|
||||
{
|
||||
SoapySDR_log(SOAPY_SDR_INFO, "SoapyRadioberry::readI2C called");
|
||||
|
||||
SoapySDR_log(SOAPY_SDR_INFO, "SoapyRadioberry::readI2C called");
|
||||
|
||||
std::string data;
|
||||
|
||||
|
||||
if (!i2c_available)
|
||||
return std::string("");
|
||||
i2c_ptr->addr(addr);
|
||||
|
@ -310,7 +319,7 @@ std::string SoapyRadioberry::readI2C(const int addr, const size_t numBytes)
|
|||
catch (std::string s)
|
||||
{
|
||||
printf("%s", s.c_str());
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
// end of source.
|
||||
|
|
|
@ -12,13 +12,21 @@
|
|||
SoapySDR_log(SOAPY_SDR_INFO, "SoapyRadioberry::setSampleRate called");
|
||||
|
||||
int irate = floor(rate);
|
||||
uint32_t ucom =0x00000004;
|
||||
uint32_t ucom =0x4;
|
||||
uint32_t command = 0;
|
||||
|
||||
if (direction == SOAPY_SDR_TX)
|
||||
{
|
||||
command = 0x1;
|
||||
if (!mox)
|
||||
return;
|
||||
}
|
||||
if (direction == SOAPY_SDR_RX)
|
||||
{
|
||||
sample_rate = rate;
|
||||
if (mox)
|
||||
command = 1;
|
||||
}
|
||||
|
||||
// incase of transmit still the receive samplerate need to be send
|
||||
if (sample_rate < 48001.0)
|
||||
|
@ -99,14 +107,18 @@ SoapySDR::Stream *SoapyRadioberry::setupStream(
|
|||
SoapySDR_log(SOAPY_SDR_INFO, "SoapyRadioberry::setupStream called");
|
||||
startTime = std::chrono::high_resolution_clock::now();
|
||||
//check the format
|
||||
sdr_stream *ptr;
|
||||
ptr = new sdr_stream(direction);
|
||||
|
||||
if (format == SOAPY_SDR_CF32) {
|
||||
SoapySDR_log(SOAPY_SDR_INFO, "Using format CF32.");
|
||||
streamFormat = RADIOBERRY_SDR_CF32;
|
||||
ptr->set_stream_format(RADIOBERRY_SDR_CF32);
|
||||
}
|
||||
else if(format == SOAPY_SDR_CS16 && direction == SOAPY_SDR_TX)
|
||||
{
|
||||
SoapySDR_log(SOAPY_SDR_INFO, "Using format CS16.");
|
||||
streamFormat = RADIOBERRY_SDR_CS16;
|
||||
ptr->set_stream_format(RADIOBERRY_SDR_CS16);
|
||||
mox = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -114,8 +126,27 @@ SoapySDR::Stream *SoapyRadioberry::setupStream(
|
|||
"setupStream invalid format '" + format + "' -- Only CF32 is supported by SoapyRadioberrySDR module.");
|
||||
}
|
||||
|
||||
return (SoapySDR::Stream *) this;
|
||||
streams.push_back(ptr);
|
||||
return (SoapySDR::Stream *)ptr;
|
||||
}
|
||||
|
||||
void SoapyRadioberry::closeStream(SoapySDR::Stream *stream)
|
||||
{
|
||||
int i = 0;
|
||||
for (auto con : streams)
|
||||
{
|
||||
if ((sdr_stream *)stream == con)
|
||||
{
|
||||
if (((sdr_stream *)stream)->get_direction() == SOAPY_SDR_TX)
|
||||
{ // switch off TX stream
|
||||
mox = false;
|
||||
setSampleRate(SOAPY_SDR_RX, 0, sample_rate);
|
||||
}
|
||||
delete ((sdr_stream *)stream);
|
||||
streams.erase(streams.begin() + i);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
int SoapyRadioberry::readStream(
|
||||
|
@ -133,14 +164,15 @@ int SoapyRadioberry::readStream(
|
|||
int16_t *itarget_buffer = (int16_t *) buff_base;
|
||||
int32_t left_sample;
|
||||
int32_t right_sample;
|
||||
|
||||
sdr_stream *ptr = (sdr_stream *)handle;
|
||||
|
||||
char rx_buffer[512];
|
||||
for(int ii = 0 ; ii < npackages ; ii++)
|
||||
{
|
||||
no_bytes = read(fd_rb, rx_buffer, sizeof(rx_buffer));
|
||||
nr_samples = no_bytes / 6;
|
||||
//printf("nr_samples %d sample: %d %d %d %d %d %d\n",nr_samples, (int)rx_buffer[0],(int)rx_buffer[1],(int)rx_buffer[2],(int)rx_buffer[3],(int)rx_buffer[4],(int)rx_buffer[5]);
|
||||
if(streamFormat == RADIOBERRY_SDR_CF32)
|
||||
if (ptr->get_stream_format() == RADIOBERRY_SDR_CF32)
|
||||
{
|
||||
for (int i = 0; i < no_bytes; i += 6) {
|
||||
left_sample = (int32_t)((signed char) rx_buffer[i]) << 16;
|
||||
|
@ -155,7 +187,7 @@ int SoapyRadioberry::readStream(
|
|||
target_buffer[iq++] = (float)right_sample / 8388608.0; // 24 bit sample
|
||||
}
|
||||
}
|
||||
if (streamFormat == RADIOBERRY_SDR_CS16)
|
||||
if (ptr->get_stream_format() == RADIOBERRY_SDR_CS16)
|
||||
{
|
||||
for (int i = 0; i < no_bytes; i += 6) {
|
||||
left_sample = (int32_t)((signed char) rx_buffer[i]) << 16;
|
||||
|
@ -181,8 +213,6 @@ union uTxBuffer
|
|||
unsigned char i8TxBuffer[4];
|
||||
};
|
||||
|
||||
uTxBuffer tx;
|
||||
|
||||
int SoapyRadioberry::writeStream(SoapySDR::Stream *stream, const void * const *buffs, const size_t numElems, int &flags, const long long timeNs, const long timeoutUs)
|
||||
{
|
||||
int iq = 0;
|
||||
|
@ -192,8 +222,10 @@ int SoapyRadioberry::writeStream(SoapySDR::Stream *stream, const void * const *b
|
|||
void const *buff_base = buffs[0];
|
||||
float *target_buffer = (float *) buff_base;
|
||||
int16_t *itarget_buffer = (int16_t *) buff_base;
|
||||
uTxBuffer tx;
|
||||
sdr_stream *ptr = (sdr_stream *)stream;
|
||||
|
||||
if (streamFormat == RADIOBERRY_SDR_CF32)
|
||||
if (ptr->get_stream_format() == RADIOBERRY_SDR_CF32)
|
||||
{
|
||||
for (int ii = 0; ii < numElems; ii++)
|
||||
{
|
||||
|
@ -202,7 +234,7 @@ int SoapyRadioberry::writeStream(SoapySDR::Stream *stream, const void * const *b
|
|||
ret = write(fd_rb, &tx, 4 * sizeof(uint8_t));
|
||||
}
|
||||
}
|
||||
if (streamFormat == RADIOBERRY_SDR_CS16)
|
||||
if (ptr->get_stream_format() == RADIOBERRY_SDR_CS16)
|
||||
{
|
||||
int j = 0;
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue