Commit 6347cb46 authored by rdoost's avatar rdoost

extended the driver to support multiple synchronized irises

parent 5ace9230
......@@ -31,13 +31,13 @@ typedef struct
// variables for Iris configuration
// --------------------------------
//! Iris device pointer
SoapySDR::Device *iris;
std::vector<SoapySDR::Device*> iris;
int device_num;
//create a send streamer and a receive streamer
//! Iris TX Stream
SoapySDR::Stream *txStream;
std::vector<SoapySDR::Stream*> txStream;
//! Iris RX Stream
SoapySDR::Stream *rxStream;
std::vector<SoapySDR::Stream*> rxStream;
//! Sampling rate
double sample_rate;
......@@ -75,13 +75,17 @@ static int trx_iris_start(openair0_device *device)
{
iris_state_t *s = (iris_state_t*)device->priv;
long long timeNs = s->iris->getHardwareTime("") + 500000;
long long timeNs = s->iris[0]->getHardwareTime("") + 500000;
int flags = 0;
//flags |= SOAPY_SDR_HAS_TIME;
int ret = s->iris->activateStream(s->rxStream, flags, timeNs, 0);
int ret2 = s->iris->activateStream(s->txStream);
int r;
for (r = 0; r < s->device_num; r++)
{
int ret = s->iris[r]->activateStream(s->rxStream[r], flags, timeNs, 0);
int ret2 = s->iris[r]->activateStream(s->txStream[r]);
if (ret < 0 | ret2 < 0)
return - 1;
}
return 0;
}
/*! \brief Terminate operation of the Iris lime transceiver -- free all associated resources
......@@ -91,9 +95,13 @@ static void trx_iris_end(openair0_device *device)
{
LOG_I(HW,"Closing Iris device.\n");
iris_state_t *s = (iris_state_t*)device->priv;
s->iris->closeStream(s->txStream);
s->iris->closeStream(s->rxStream);
SoapySDR::Device::unmake(s->iris);
int r;
for (r = 0; r < s->device_num; r++)
{
s->iris[r]->closeStream(s->txStream[r]);
s->iris[r]->closeStream(s->rxStream[r]);
SoapySDR::Device::unmake(s->iris[r]);
}
}
/*! \brief Called to send samples to the Iris RF target
......@@ -120,24 +128,31 @@ static int trx_iris_write(openair0_device *device, openair0_timestamp timestamp,
flag |= SOAPY_SDR_HAS_TIME;
long long timeNs = SoapySDR::ticksToTimeNs(timestamp, s->sample_rate/SAMPLE_RATE_DOWN);
uint32_t *samps[2]; //= (uint32_t **)buff;
int r;
for (r = 0; r < s->device_num; r++)
{
int samples_sent = 0;
uint32_t **samps = (uint32_t **)buff;
samps[0] = (uint32_t *)buff[2*r];
if (cc % 2 == 0)
samps[1] = (uint32_t *)buff[2*r+1]; //cws: it seems another thread can clobber these, so we need to save them locally.
while (samples_sent < nsamps)
{
ret = s->iris->writeStream(s->txStream, (void **)samps, (size_t)(nsamps - samples_sent), flag, timeNs, 100000);
ret = s->iris[r]->writeStream(s->txStream[r], (void **)samps, (size_t)(nsamps - samples_sent), flag, timeNs, 100000);
if (ret < 0) {
printf("Unable to write stream!\n");
break;
}
samples_sent += ret;
samps[0] += ret;
if (cc > 1)
if (cc % 2 == 0)
samps[1] += ret;
}
if (samples_sent != nsamps) {
printf("[xmit] tx samples %d != %d\n",samples_sent,nsamps);
}
}
/*
flag = 0;
size_t channel = 0;
......@@ -173,15 +188,24 @@ static int trx_iris_read(openair0_device *device, openair0_timestamp *ptimestamp
iris_state_t *s = (iris_state_t*)device->priv;
bool time_set = false;
long long timeNs = 0;
int flags = 0;
int samples_received = 0;
uint32_t *samps[2] = {(uint32_t *)buff[0], (uint32_t *)buff[1]}; //cws: it seems another thread can clobber these, so we need to save them locally.
int flags;
int samples_received;
uint32_t *samps[2]; //= (uint32_t **)buff;
//printf("Reading %d samples from Iris...\n", nsamps);
//fflush(stdout);
int r;
for (r = 0; r < s->device_num; r++)
{
flags = 0;
samples_received = 0;
samps[0] = (uint32_t *)buff[2*r];
if (cc % 2 == 0)
samps[1] = (uint32_t *)buff[2*r+1];
//uint32_t *samps[2] = {(uint32_t *)buff[2*r], (uint32_t *)buff[2*r+1]}; //cws: it seems another thread can clobber these, so we need to save them locally.
while (samples_received < nsamps)
{
flags = 0;
ret = s->iris->readStream(s->rxStream, (void **)samps, (size_t)(nsamps-samples_received), flags, timeNs, 100000);
ret = s->iris[r]->readStream(s->rxStream[r], (void **)samps, (size_t)(nsamps-samples_received), flags, timeNs, 100000);
if (ret < 0)
{
if (ret == SOAPY_SDR_TIME_ERROR)
......@@ -199,9 +223,10 @@ static int trx_iris_read(openair0_device *device, openair0_timestamp *ptimestamp
samples_received += ret;
samps[0] += ret;
if (cc > 1)
if (cc % 2 == 0)
samps[1] += ret;
if (r == 0)
{
if (samples_received == ret) // first batch
{
if (flags & SOAPY_SDR_HAS_TIME)
......@@ -215,7 +240,9 @@ static int trx_iris_read(openair0_device *device, openair0_timestamp *ptimestamp
}
}
}
}
if (r == 0)
{
if (samples_received < nsamps)
printf("[recv] received %d samples out of %d\n",samples_received,nsamps);
......@@ -231,7 +258,8 @@ static int trx_iris_read(openair0_device *device, openair0_timestamp *ptimestamp
}
nextTime += SoapySDR::ticksToTimeNs(samples_received, s->sample_rate/SAMPLE_RATE_DOWN);
}
}
}
return samples_received;
}
......@@ -241,7 +269,7 @@ static int trx_iris_read(openair0_device *device, openair0_timestamp *ptimestamp
openair0_timestamp get_iris_time(openair0_device *device)
{
iris_state_t *s = (iris_state_t*)device->priv;
return SoapySDR::timeNsToTicks(s->iris->getHardwareTime(""), s->sample_rate);
return SoapySDR::timeNsToTicks(s->iris[0]->getHardwareTime(""), s->sample_rate);
}
/*! \brief Compares two variables within precision
......@@ -257,16 +285,19 @@ void *set_freq_thread(void *arg) {
openair0_device *device=(openair0_device *)arg;
iris_state_t *s = (iris_state_t*)device->priv;
int i;
int r, i;
printf("Setting Iris TX Freq %f, RX Freq %f\n",device->openair0_cfg[0].tx_freq[0],device->openair0_cfg[0].rx_freq[0]);
// add check for the number of channels in the cfg
for(i=0; i < s->iris->getNumChannels(SOAPY_SDR_RX); i++) {
for (r = 0; r < s->device_num; r++)
{
for(i=0; i < s->iris[r]->getNumChannels(SOAPY_SDR_RX); i++) {
if (i < device->openair0_cfg[0].rx_num_channels)
s->iris->setFrequency(SOAPY_SDR_RX, i, "RF", device->openair0_cfg[0].rx_freq[i]);
s->iris[r]->setFrequency(SOAPY_SDR_RX, i, "RF", device->openair0_cfg[0].rx_freq[i]);
}
for(i=0; i < s->iris->getNumChannels(SOAPY_SDR_TX); i++) {
for(i=0; i < s->iris[r]->getNumChannels(SOAPY_SDR_TX); i++) {
if (i < device->openair0_cfg[0].tx_num_channels)
s->iris->setFrequency(SOAPY_SDR_TX, i, "RF", device->openair0_cfg[0].tx_freq[i]);
s->iris[r]->setFrequency(SOAPY_SDR_TX, i, "RF", device->openair0_cfg[0].tx_freq[i]);
}
}
}
/*! \brief Set frequencies (TX/RX)
......@@ -283,16 +314,19 @@ int trx_iris_set_freq(openair0_device* device, openair0_config_t *openair0_cfg,
pthread_create(&f_thread, NULL, set_freq_thread, (void*)device);
else
{
int i;
int r, i;
for (r = 0; r < s->device_num; r++)
{
printf("Setting Iris TX Freq %f, RX Freq %f\n",openair0_cfg[0].tx_freq[0],openair0_cfg[0].rx_freq[0]);
for(i=0; i < s->iris->getNumChannels(SOAPY_SDR_RX); i++) {
for(i=0; i < s->iris[r]->getNumChannels(SOAPY_SDR_RX); i++) {
if (i < openair0_cfg[0].rx_num_channels) {
s->iris->setFrequency(SOAPY_SDR_RX, i, "RF", openair0_cfg[0].rx_freq[i]);
s->iris[r]->setFrequency(SOAPY_SDR_RX, i, "RF", openair0_cfg[0].rx_freq[i]);
}
}
for(i=0; i < s->iris->getNumChannels(SOAPY_SDR_TX); i++) {
for(i=0; i < s->iris[r]->getNumChannels(SOAPY_SDR_TX); i++) {
if (i < openair0_cfg[0].tx_num_channels) {
s->iris->setFrequency(SOAPY_SDR_TX, i, "RF", openair0_cfg[0].tx_freq[i]);
s->iris[r]->setFrequency(SOAPY_SDR_TX, i, "RF", openair0_cfg[0].tx_freq[i]);
}
}
}
}
......@@ -308,10 +342,14 @@ int trx_iris_set_freq(openair0_device* device, openair0_config_t *openair0_cfg,
int trx_iris_set_gains(openair0_device* device,
openair0_config_t *openair0_cfg) {
iris_state_t *s = (iris_state_t*)device->priv;
s->iris->setGain(SOAPY_SDR_RX, 0, openair0_cfg[0].rx_gain[0]);
s->iris->setGain(SOAPY_SDR_TX, 0, openair0_cfg[0].tx_gain[0]);
s->iris->setGain(SOAPY_SDR_RX, 1, openair0_cfg[0].rx_gain[1]);
s->iris->setGain(SOAPY_SDR_TX, 1, openair0_cfg[0].tx_gain[1]);
int r;
for (r = 0; r < s->device_num; r++)
{
s->iris[r]->setGain(SOAPY_SDR_RX, 0, openair0_cfg[0].rx_gain[0]);
s->iris[r]->setGain(SOAPY_SDR_TX, 0, openair0_cfg[0].tx_gain[0]);
s->iris[r]->setGain(SOAPY_SDR_RX, 1, openair0_cfg[0].rx_gain[1]);
s->iris[r]->setGain(SOAPY_SDR_TX, 1, openair0_cfg[0].tx_gain[1]);
}
return(0);
}
......@@ -320,8 +358,12 @@ int trx_iris_set_gains(openair0_device* device,
*/
int trx_iris_stop(openair0_device* device) {
iris_state_t *s = (iris_state_t*)device->priv;
s->iris->deactivateStream(s->txStream);
s->iris->deactivateStream(s->rxStream);
int r;
for (r = 0; r < s->device_num; r++)
{
s->iris[r]->deactivateStream(s->txStream[r]);
s->iris[r]->deactivateStream(s->rxStream[r]);
}
return(0);
}
......@@ -423,15 +465,17 @@ extern "C" {
// Initialize Iris device
device->openair0_cfg = openair0_cfg;
char* remote_addr = device->openair0_cfg->remote_addr;
LOG_I(HW,"Attempting to open Iris device: %s\n", remote_addr);
std::string args = "driver=remote,serial="+std::string(remote_addr)+",remote:format=CS16";
char* srl = strtok(remote_addr, ",");
while (srl != NULL)
{
LOG_I(HW,"Attempting to open Iris device: %s\n", srl);
std::string args = "driver=remote,serial="+std::string(srl)+",remote:format=CS16";
s->iris.push_back(SoapySDR::Device::make(args));
srl = strtok(NULL, ",");
}
s->device_num = s->iris.size();
openair0_cfg[0].iq_txshift = 4;//if radio needs OAI to shift left the tx samples for preserving bit precision
s->iris = SoapySDR::Device::make(args);
device->type=IRIS_DEV;
s->iris->setMasterClockRate(8*openair0_cfg[0].sample_rate); // sample*8=clock_rate for Soapy
printf("tx_sample_advance %d\n", openair0_cfg[0].tx_sample_advance);
switch ((int)openair0_cfg[0].sample_rate) {
case 30720000:
//openair0_cfg[0].samples_per_packet = 1024;
......@@ -468,48 +512,47 @@ extern "C" {
exit(-1);
break;
}
printf("tx_sample_advance %d\n", openair0_cfg[0].tx_sample_advance);
int r;
for (r = 0; r < s->device_num; r++)
{
s->iris[r]->setMasterClockRate(8*openair0_cfg[0].sample_rate); // sample*8=clock_rate for Soapy
// display Iris settings
std::cout << boost::format("Actual master clock: %fMHz...") % (s->iris[r]->getMasterClockRate()/1e6) << std::endl;
for(i=0; i < s->iris->getNumChannels(SOAPY_SDR_RX); i++) {
for(i=0; i < s->iris[r]->getNumChannels(SOAPY_SDR_RX); i++) {
if (i < openair0_cfg[0].rx_num_channels) {
s->iris->setSampleRate(SOAPY_SDR_RX, i, openair0_cfg[0].sample_rate/SAMPLE_RATE_DOWN);
s->iris->setFrequency(SOAPY_SDR_RX, i, "RF", openair0_cfg[0].rx_freq[i]);
s->iris[r]->setSampleRate(SOAPY_SDR_RX, i, openair0_cfg[0].sample_rate/SAMPLE_RATE_DOWN);
s->iris[r]->setFrequency(SOAPY_SDR_RX, i, "RF", openair0_cfg[0].rx_freq[i]);
set_rx_gain_offset(&openair0_cfg[0],i,bw_gain_adjust);
s->iris->setGain(SOAPY_SDR_RX, i, openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i]);
s->iris[r]->setGain(SOAPY_SDR_RX, i, openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i]);
if (openair0_cfg[0].duplex_mode == 1) // TDD
s->iris->setAntenna(SOAPY_SDR_RX, i, (i==0)?"TRXA":"TRXB");
s->iris->setDCOffsetMode(SOAPY_SDR_RX, i, true); // move somewhere else
s->iris[r]->setAntenna(SOAPY_SDR_RX, i, (i==0)?"TRXA":"TRXB");
s->iris[r]->setDCOffsetMode(SOAPY_SDR_RX, i, true); // move somewhere else
}
}
for(i=0; i < s->iris->getNumChannels(SOAPY_SDR_TX); i++) {
for(i=0; i < s->iris[r]->getNumChannels(SOAPY_SDR_TX); i++) {
if (i < openair0_cfg[0].tx_num_channels) {
s->iris->setSampleRate(SOAPY_SDR_TX, i, openair0_cfg[0].sample_rate/SAMPLE_RATE_DOWN);
s->iris->setFrequency(SOAPY_SDR_TX, i, "RF", openair0_cfg[0].tx_freq[i]);
s->iris->setGain(SOAPY_SDR_TX, i, openair0_cfg[0].tx_gain[i]);
s->iris[r]->setSampleRate(SOAPY_SDR_TX, i, openair0_cfg[0].sample_rate/SAMPLE_RATE_DOWN);
s->iris[r]->setFrequency(SOAPY_SDR_TX, i, "RF", openair0_cfg[0].tx_freq[i]);
s->iris[r]->setGain(SOAPY_SDR_TX, i, openair0_cfg[0].tx_gain[i]);
}
}
// display Iris settings
std::cout << boost::format("Actual master clock: %fMHz...") % (s->iris->getMasterClockRate()/1e6) << std::endl;
sleep(1);
int samples=openair0_cfg[0].sample_rate;
samples/=24000;
/* Setting TX/RX BW after streamers are created due to iris calibration issue */
for(i = 0; i < openair0_cfg[0].tx_num_channels; i++) {
if (i < s->iris->getNumChannels(SOAPY_SDR_TX) ) {
s->iris->setBandwidth(SOAPY_SDR_TX, i, openair0_cfg[0].tx_bw);
printf("Setting tx freq/gain on channel %lu/%lu: BW %f (readback %f)\n",i,s->iris->getNumChannels(SOAPY_SDR_TX),openair0_cfg[0].tx_bw/1e6,s->iris->getBandwidth(SOAPY_SDR_TX, i)/1e6);
if (i < s->iris[r]->getNumChannels(SOAPY_SDR_TX) ) {
s->iris[r]->setBandwidth(SOAPY_SDR_TX, i, openair0_cfg[0].tx_bw);
printf("Setting tx freq/gain on channel %lu/%lu: BW %f (readback %f)\n",i,s->iris[r]->getNumChannels(SOAPY_SDR_TX),openair0_cfg[0].tx_bw/1e6,s->iris[r]->getBandwidth(SOAPY_SDR_TX, i)/1e6);
}
}
for(i = 0; i < openair0_cfg[0].rx_num_channels; i++) {
if (i < s->iris->getNumChannels(SOAPY_SDR_RX)) {
s->iris->setBandwidth(SOAPY_SDR_RX, i, openair0_cfg[0].rx_bw);
printf("Setting rx freq/gain on channel %lu/%lu : BW %f (readback %f)\n",i,s->iris->getNumChannels(SOAPY_SDR_RX),openair0_cfg[0].rx_bw/1e6,s->iris->getBandwidth(SOAPY_SDR_RX, i)/1e6);
if (i < s->iris[r]->getNumChannels(SOAPY_SDR_RX)) {
s->iris[r]->setBandwidth(SOAPY_SDR_RX, i, openair0_cfg[0].rx_bw);
printf("Setting rx freq/gain on channel %lu/%lu : BW %f (readback %f)\n",i,s->iris[r]->getNumChannels(SOAPY_SDR_RX),openair0_cfg[0].rx_bw/1e6,s->iris[r]->getBandwidth(SOAPY_SDR_RX, i)/1e6);
}
}
......@@ -517,41 +560,46 @@ extern "C" {
const SoapySDR::Kwargs &arg = SoapySDR::Kwargs();
std::vector<size_t> channels={};
for (i = 0; i<openair0_cfg[0].rx_num_channels; i++)
if (i < s->iris->getNumChannels(SOAPY_SDR_RX))
if (i < s->iris[r]->getNumChannels(SOAPY_SDR_RX))
channels.push_back(i);
s->rxStream = s->iris->setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, channels, arg);
s->rxStream.push_back(s->iris[r]->setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, channels, arg));
std::vector<size_t> tx_channels={};
for (i = 0; i<openair0_cfg[0].tx_num_channels; i++)
if (i < s->iris->getNumChannels(SOAPY_SDR_TX))
if (i < s->iris[r]->getNumChannels(SOAPY_SDR_TX))
tx_channels.push_back(i);
s->txStream = s->iris->setupStream(SOAPY_SDR_TX, SOAPY_SDR_CS16, tx_channels, arg);
s->iris->setHardwareTime(0, "");
s->txStream.push_back(s->iris[r]->setupStream(SOAPY_SDR_TX, SOAPY_SDR_CS16, tx_channels, arg));
s->iris[r]->setHardwareTime(0, "");
for (i = 0; i < openair0_cfg[0].rx_num_channels; i++) {
if (i < s->iris->getNumChannels(SOAPY_SDR_RX)) {
if (i < s->iris[r]->getNumChannels(SOAPY_SDR_RX)) {
printf("RX Channel %lu\n",i);
std::cout << boost::format("Actual RX sample rate: %fMSps...") % (s->iris->getSampleRate(SOAPY_SDR_RX, i)/1e6) << std::endl;
std::cout << boost::format("Actual RX frequency: %fGHz...") % (s->iris->getFrequency(SOAPY_SDR_RX, i)/1e9) << std::endl;
std::cout << boost::format("Actual RX gain: %f...") % (s->iris->getGain(SOAPY_SDR_RX, i)) << std::endl;
std::cout << boost::format("Actual RX bandwidth: %fM...") % (s->iris->getBandwidth(SOAPY_SDR_RX, i)/1e6) << std::endl;
std::cout << boost::format("Actual RX antenna: %s...") % (s->iris->getAntenna(SOAPY_SDR_RX, i)) << std::endl;
std::cout << boost::format("Actual RX sample rate: %fMSps...") % (s->iris[r]->getSampleRate(SOAPY_SDR_RX, i)/1e6) << std::endl;
std::cout << boost::format("Actual RX frequency: %fGHz...") % (s->iris[r]->getFrequency(SOAPY_SDR_RX, i)/1e9) << std::endl;
std::cout << boost::format("Actual RX gain: %f...") % (s->iris[r]->getGain(SOAPY_SDR_RX, i)) << std::endl;
std::cout << boost::format("Actual RX bandwidth: %fM...") % (s->iris[r]->getBandwidth(SOAPY_SDR_RX, i)/1e6) << std::endl;
std::cout << boost::format("Actual RX antenna: %s...") % (s->iris[r]->getAntenna(SOAPY_SDR_RX, i)) << std::endl;
}
}
for (i=0;i<openair0_cfg[0].tx_num_channels;i++) {
if (i < s->iris->getNumChannels(SOAPY_SDR_TX)) {
if (i < s->iris[r]->getNumChannels(SOAPY_SDR_TX)) {
printf("TX Channel %lu\n",i);
std::cout << std::endl<<boost::format("Actual TX sample rate: %fMSps...") % (s->iris->getSampleRate(SOAPY_SDR_TX, i)/1e6) << std::endl;
std::cout << boost::format("Actual TX frequency: %fGHz...") % (s->iris->getFrequency(SOAPY_SDR_TX, i)/1e9) << std::endl;
std::cout << boost::format("Actual TX gain: %f...") % (s->iris->getGain(SOAPY_SDR_TX, i)) << std::endl;
std::cout << boost::format("Actual TX bandwidth: %fM...") % (s->iris->getBandwidth(SOAPY_SDR_TX, i)/1e6) << std::endl;
std::cout << boost::format("Actual TX antenna: %s...") % (s->iris->getAntenna(SOAPY_SDR_TX, i)) << std::endl;
std::cout << std::endl<<boost::format("Actual TX sample rate: %fMSps...") % (s->iris[r]->getSampleRate(SOAPY_SDR_TX, i)/1e6) << std::endl;
std::cout << boost::format("Actual TX frequency: %fGHz...") % (s->iris[r]->getFrequency(SOAPY_SDR_TX, i)/1e9) << std::endl;
std::cout << boost::format("Actual TX gain: %f...") % (s->iris[r]->getGain(SOAPY_SDR_TX, i)) << std::endl;
std::cout << boost::format("Actual TX bandwidth: %fM...") % (s->iris[r]->getBandwidth(SOAPY_SDR_TX, i)/1e6) << std::endl;
std::cout << boost::format("Actual TX antenna: %s...") % (s->iris[r]->getAntenna(SOAPY_SDR_TX, i)) << std::endl;
}
}
std::cout << boost::format("Device timestamp: %f...") % (s->iris->getHardwareTime()/1e9) << std::endl;
}
s->iris[0]->writeSetting("SYNC_DELAYS","");
for (r = 0; r < s->device_num; r++)
s->iris[r]->setHardwareTime(0, "TRIGGER");
s->iris[0]->writeSetting("TRIGGER_GEN","");
for (r = 0; r < s->device_num; r++)
std::cout << boost::format("Device timestamp: %f...") % (s->iris[r]->getHardwareTime("TRIG")/1e9) << std::endl;
device->priv = s;
device->trx_start_func = trx_iris_start;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment