...
 
Commits (14)
#include "include/BaseRadioSet.h"
#include "include/Radio.h"
#include "include/comms-lib.h"
#include "include/macros.h"
#include "include/matplotlibcpp.h"
#include "include/sdr-lib.h"
#include "include/utils.h"
namespace plt = matplotlibcpp;
std::vector<std::complex<float>> BaseRadioSet::snoopSamples(SoapySDR::Device* dev, size_t channel, size_t readSize)
static std::vector<std::complex<float>> snoopSamples(SoapySDR::Device* dev, size_t channel, size_t readSize)
{
std::vector<uint32_t> samps_int = dev->readRegisters("RX_SNOOPER", channel, readSize);
std::vector<std::complex<float>> samps = Utils::uint32tocfloat(samps_int, "IQ");
return samps;
}
void BaseRadioSet::adjustCalibrationGains(std::vector<SoapySDR::Device*> rxDevs, SoapySDR::Device* txDev, size_t channel, double fftBin, bool plot)
static void adjustCalibrationGains(std::vector<SoapySDR::Device*> rxDevs, SoapySDR::Device* txDev,
size_t channel, double fftBin, bool plot = false)
{
using std::cout;
using std::endl;
......@@ -51,7 +52,7 @@ void BaseRadioSet::adjustCalibrationGains(std::vector<SoapySDR::Device*> rxDevs,
std::vector<float> toneLevels(rxDevsSize, 0);
size_t remainingRadios = adjustedRadios.size();
for (size_t r = 0; r < rxDevsSize; r++) {
const auto samps = BaseRadioSet::snoopSamples(rxDevs[r], channel, N);
const auto samps = snoopSamples(rxDevs[r], channel, N);
auto toneLevel = CommsLib::measureTone(samps, win, windowGain, fftBin, N);
if (toneLevel >= targetLevel) {
adjustedRadios[r] = true;
......@@ -85,7 +86,7 @@ void BaseRadioSet::adjustCalibrationGains(std::vector<SoapySDR::Device*> rxDevs,
for (size_t r = 0; r < rxDevsSize; r++) {
if (adjustedRadios[r])
continue;
const auto samps = BaseRadioSet::snoopSamples(rxDevs[r], channel, N);
const auto samps = snoopSamples(rxDevs[r], channel, N);
float toneLevel = CommsLib::measureTone(samps, win, windowGain, fftBin, N);
if (toneLevel >= targetLevel) {
adjustedRadios[r] = true;
......@@ -117,7 +118,7 @@ void BaseRadioSet::adjustCalibrationGains(std::vector<SoapySDR::Device*> rxDevs,
for (size_t r = 0; r < rxDevsSize; r++) {
if (adjustedRadios[r])
continue;
const auto samps = BaseRadioSet::snoopSamples(rxDevs[r], channel, N);
const auto samps = snoopSamples(rxDevs[r], channel, N);
auto toneLevel = CommsLib::measureTone(samps, win, windowGain, fftBin, N);
if (toneLevel > targetLevel) {
adjustedRadios[r] = true;
......@@ -145,7 +146,7 @@ void BaseRadioSet::adjustCalibrationGains(std::vector<SoapySDR::Device*> rxDevs,
for (size_t r = 0; r < rxDevsSize; r++) {
if (adjustedRadios[r])
continue;
auto samps = BaseRadioSet::snoopSamples(rxDevs[r], channel, N);
auto samps = snoopSamples(rxDevs[r], channel, N);
float toneLevel = CommsLib::measureTone(samps, win, windowGain, fftBin, N);
if (toneLevel > targetLevel) {
adjustedRadios[r] = true;
......@@ -180,7 +181,7 @@ void BaseRadioSet::adjustCalibrationGains(std::vector<SoapySDR::Device*> rxDevs,
std::cout << rxDevsSize - remainingRadios << " radios reached target level" << std::endl;
}
void BaseRadioSet::setIQBalance(SoapySDR::Device* dev, int direction, size_t channel, int gcorr, int iqcorr)
static void setIQBalance(SoapySDR::Device* dev, int direction, size_t channel, int gcorr, int iqcorr)
{
auto gcorri = (gcorr < 0) ? 2047 - std::abs(gcorr) : 2047;
auto gcorrq = (gcorr > 0) ? 2047 - std::abs(gcorr) : 2047;
......@@ -190,7 +191,7 @@ void BaseRadioSet::setIQBalance(SoapySDR::Device* dev, int direction, size_t cha
dev->setIQBalance(direction, channel, IQcorr);
}
void BaseRadioSet::dciqMinimize(SoapySDR::Device* targetDev, SoapySDR::Device* refDev, int direction, size_t channel, double rxCenterTone, double txCenterTone)
static void dciqMinimize(SoapySDR::Device* targetDev, SoapySDR::Device* refDev, int direction, size_t channel, double rxCenterTone, double txCenterTone)
{
size_t N = 1024;
std::vector<float> win = CommsLib::hannWindowFunction(N);
......@@ -276,7 +277,7 @@ void BaseRadioSet::dciqMinimize(SoapySDR::Device* targetDev, SoapySDR::Device* r
for (int i = start; i < stop; i += step) {
const int gcorr = ((iter % 2) == 0) ? i : bestgcorr;
const int iqcorr = ((iter % 2) == 1) ? i : bestiqcorr;
BaseRadioSet::setIQBalance(targetDev, direction, channel, gcorr, iqcorr);
setIQBalance(targetDev, direction, channel, gcorr, iqcorr);
//measure the efficacy
std::this_thread::sleep_for(std::chrono::milliseconds(SETTLE_TIME_MS));
......@@ -293,7 +294,7 @@ void BaseRadioSet::dciqMinimize(SoapySDR::Device* targetDev, SoapySDR::Device* r
}
//apply the ideal correction
BaseRadioSet::setIQBalance(targetDev, direction, channel, bestgcorr, bestiqcorr);
setIQBalance(targetDev, direction, channel, bestgcorr, bestiqcorr);
auto gcorri = (bestgcorr < 0) ? 2047 - std::abs(bestgcorr) : 2047;
auto gcorrq = (bestgcorr > 0) ? 2047 - std::abs(bestgcorr) : 2047;
std::cout << "Optimized IQ Imbalance Setting: GCorr (" << gcorri << "," << gcorrq << "), iqcorr=" << bestiqcorr << "\n";
......@@ -350,12 +351,12 @@ void BaseRadioSet::dciqCalibrationProc(size_t channel)
// Tune rx gains for calibration on all radios except reference radio
// Tune tx gain on reference radio
BaseRadioSet::adjustCalibrationGains(allButRefDevs, refDev, channel, toneBBFreq / sampleRate, true);
adjustCalibrationGains(allButRefDevs, refDev, channel, toneBBFreq / sampleRate, true);
// Minimize Rx DC offset and IQ Imbalance on all receiving radios
// TODO: Parallelize this loop
for (size_t r = 0; r < radioSize - 1; r++) {
BaseRadioSet::dciqMinimize(allButRefDevs[r], allButRefDevs[r], SOAPY_SDR_RX, channel, 0.0, toneBBFreq / sampleRate);
dciqMinimize(allButRefDevs[r], allButRefDevs[r], SOAPY_SDR_RX, channel, 0.0, toneBBFreq / sampleRate);
}
refDev->writeSetting(SOAPY_SDR_TX, channel, "TSP_TSG_CONST", "NONE");
......@@ -382,8 +383,8 @@ void BaseRadioSet::dciqCalibrationProc(size_t channel)
// Tune rx gain for calibraion on reference radio
// Tune tx gain on neighboring radio to reference radio
BaseRadioSet::adjustCalibrationGains(refDevContainer, refRefDev, channel, toneBBFreq / sampleRate);
BaseRadioSet::dciqMinimize(refDev, refDev, SOAPY_SDR_RX, channel, 0.0, toneBBFreq / sampleRate);
adjustCalibrationGains(refDevContainer, refRefDev, channel, toneBBFreq / sampleRate);
dciqMinimize(refDev, refDev, SOAPY_SDR_RX, channel, 0.0, toneBBFreq / sampleRate);
refRefDev->writeSetting(SOAPY_SDR_TX, channel, "TSP_TSG_CONST", "NONE");
refRefDev->writeSetting(SOAPY_SDR_TX, channel, "TX_ENB_OVERRIDE", "false");
......@@ -407,8 +408,8 @@ void BaseRadioSet::dciqCalibrationProc(size_t channel)
// Tune tx gain for calibraion on reference antenna
// Tune rx gain on neighboring radio to reference radio
BaseRadioSet::adjustCalibrationGains(refRefDevContainer, refDev, channel, (toneBBFreq + txToneBBFreq) / sampleRate);
BaseRadioSet::dciqMinimize(refDev, refRefDev, SOAPY_SDR_TX, channel, toneBBFreq / sampleRate, txToneBBFreq / sampleRate);
adjustCalibrationGains(refRefDevContainer, refDev, channel, (toneBBFreq + txToneBBFreq) / sampleRate);
dciqMinimize(refDev, refRefDev, SOAPY_SDR_TX, channel, toneBBFreq / sampleRate, txToneBBFreq / sampleRate);
// kill TX on ref at the end
refDev->writeSetting(SOAPY_SDR_TX, channel, "TSP_TSG_CONST", "NONE");
......@@ -429,8 +430,8 @@ void BaseRadioSet::dciqCalibrationProc(size_t channel)
allButRefDevs[r]->writeSetting(SOAPY_SDR_TX, channel, "TX_ENB_OVERRIDE", "true");
// Tune tx gain for calibraion of the current radio
// Tune rx gain on the reference radio
BaseRadioSet::adjustCalibrationGains(refDevContainer, allButRefDevs[r], channel, (toneBBFreq + txToneBBFreq) / sampleRate);
BaseRadioSet::dciqMinimize(allButRefDevs[r], refDev, SOAPY_SDR_TX, channel, toneBBFreq / sampleRate, txToneBBFreq / sampleRate);
adjustCalibrationGains(refDevContainer, allButRefDevs[r], channel, (toneBBFreq + txToneBBFreq) / sampleRate);
dciqMinimize(allButRefDevs[r], refDev, SOAPY_SDR_TX, channel, toneBBFreq / sampleRate, txToneBBFreq / sampleRate);
allButRefDevs[r]->writeSetting(SOAPY_SDR_TX, channel, "TX_ENB_OVERRIDE", "false");
allButRefDevs[r]->writeSetting(SOAPY_SDR_TX, channel, "TSP_TSG_CONST", "NONE");
allButRefDevs[r]->setFrequency(SOAPY_SDR_TX, channel, "BB", 0);
......
......@@ -10,7 +10,7 @@
---------------------------------------------------------------------
*/
#include "include/sdr-lib.h"
#include "include/BaseRadioSet.h"
#include "include/Radio.h"
#include "include/comms-lib.h"
#include "include/macros.h"
......
......@@ -35,6 +35,6 @@ message(STATUS "HDF5_INCLUDE_DIRS: ${HDF5_INCLUDE_DIRS}")
message(STATUS "HDF5_LIBRARIES: ${HDF5_LIBRARIES}")
include_directories(${SoapySDR_INCLUDE_DIRS} ${HDF5_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS})
add_executable(sounder main.cc ClientRadioSet.cc config.cc Radio.cc receiver.cc recorder.cc sdr-lib.cc sdr-calibrate.cc comms-lib.cc utils.cc signalHandler.cpp)
add_executable(sounder main.cc ClientRadioSet.cc config.cc Radio.cc receiver.cc recorder.cc BaseRadioSet.cc BaseRadioSet-calibrate.cc comms-lib.cc utils.cc signalHandler.cpp)
target_link_libraries(sounder -lpthread -lhdf5_cpp --enable-threadsafe ${SoapySDR_LIBRARIES} ${HDF5_LIBRARIES} ${CMAKE_SOURCE_DIR}/mufft/libmuFFT.a ${CMAKE_SOURCE_DIR}/mufft/libmuFFT-sse.a ${CMAKE_SOURCE_DIR}/mufft/libmuFFT-sse3.a ${CMAKE_SOURCE_DIR}/mufft/libmuFFT-avx.a ${PYTHON_LIBRARIES})
......@@ -7,6 +7,8 @@
#include <SoapySDR/Formats.hpp>
#include <SoapySDR/Time.hpp>
static void initAGC(SoapySDR::Device* dev, Config* cfg);
ClientRadioSet::ClientRadioSet(Config* cfg)
: _cfg(cfg)
{
......@@ -33,7 +35,7 @@ ClientRadioSet::ClientRadioSet(Config* cfg)
radios.back()->dev_init(_cfg, ch, rxgain, txgain);
}
initAGC(dev);
initAGC(dev, _cfg);
}
radios.shrink_to_fit();
......@@ -113,7 +115,7 @@ void ClientRadioSet::radioStop(void)
dev->writeSetting("CORR_CONFIG", corrConfStr);
const auto timeStamp = SoapySDR::timeNsToTicks(dev->getHardwareTime(""), _cfg->rate);
std::cout << "device " << i << ": Frame=" << (timeStamp >> 32)
<< ", Symbol=" << ((timeStamp && 0xFFFFFFFF) >> 16) << std::endl;
<< ", Symbol=" << ((timeStamp & 0xFFFFFFFF) >> 16) << std::endl;
dev->writeSetting("TDD_CONFIG", tddConfStr);
dev->writeSetting("TDD_MODE", "false");
radios[i]->reset_DATA_clk_domain();
......@@ -142,19 +144,19 @@ int ClientRadioSet::radioTx(size_t radio_id, const void* const* buffs, int numSa
return radios[radio_id]->xmit(buffs, numSamps, flags, frameTime);
}
void ClientRadioSet::initAGC(SoapySDR::Device* dev)
static void initAGC(SoapySDR::Device* dev, Config* cfg)
{
/*
* Initialize AGC parameters
*/
#ifdef JSON
json agcConf;
agcConf["agc_enabled"] = _cfg->clAgcEn;
agcConf["agc_gain_init"] = _cfg->clAgcGainInit;
agcConf["agc_enabled"] = cfg->clAgcEn;
agcConf["agc_gain_init"] = cfg->clAgcGainInit;
std::string agcConfStr = agcConf.dump();
#else
std::string agcConfStr = "{\"agc_enabled\":" + _cfg->clAgcEn ? "true" : "false";
agcConfStr += ",\"agc_gain_init\":" + std::to_string(_cfg->clAgcGainInit);
std::string agcConfStr = "{\"agc_enabled\":" + cfg->clAgcEn ? "true" : "false";
agcConfStr += ",\"agc_gain_init\":" + std::to_string(cfg->clAgcGainInit);
agcConfStr += "}";
#endif
dev->writeSetting("AGC_CONFIG", agcConfStr);
......
......@@ -16,8 +16,8 @@ void Radio::dev_init(Config* _cfg, int ch, double rxgain, double txgain)
dev->setFrequency(SOAPY_SDR_TX, ch, "BB", _cfg->nco);
// Unified gains for both lime and frontend
dev->setGain(SOAPY_SDR_RX, ch, rxgain); // w/CBRS 3.6GHz [0:105], 2.5GHZ [0:108]
dev->setGain(SOAPY_SDR_TX, ch, txgain); // w/CBRS 3.6GHz [0:105], 2.5GHZ [0:105]
dev->setGain(SOAPY_SDR_RX, ch, rxgain); // w/CBRS 3.6GHz [0:105], 2.5GHZ [0:108]
dev->setGain(SOAPY_SDR_TX, ch, txgain); // w/CBRS 3.6GHz [0:105], 2.5GHZ [0:105]
// DC Offset
dev->setDCOffsetMode(SOAPY_SDR_RX, ch, true);
}
......
......@@ -116,7 +116,7 @@ Config::Config(const std::string& jsonfile)
dlSymsPerFrame = DLSymbols[0].size();
// read commons from Client json config
if (!clPresent) {
nClSdrs = std::count(frames.at(0).begin(), frames.at(0).end(), 'P');
nClSdrs = nClAntennas = std::count(frames.at(0).begin(), frames.at(0).end(), 'P');
clDataMod = tddConf.value("modulation", "QPSK");
}
}
......@@ -130,6 +130,7 @@ Config::Config(const std::string& jsonfile)
if (clChannel != "A" && clChannel != "B" && clChannel != "AB")
throw std::invalid_argument("error channel config: not any of A/B/AB!\n");
clSdrCh = (clChannel == "AB") ? 2 : 1;
nClAntennas = nClSdrs * clSdrCh;
clAgcEn = tddConfCl.value("agc_en", false);
clAgcGainInit = tddConfCl.value("agc_gain_init", 70); // 0 to 108
clDataMod = tddConfCl.value("modulation", "QPSK");
......@@ -267,7 +268,7 @@ Config::Config(const std::string& jsonfile)
int syms = nSamps / ofdmSize;
std::vector<std::complex<float>> pre1(prefix, 0);
std::vector<std::complex<float>> post1(nSamps % ofdmSize + postfix, 0);
for (unsigned int i = 0; i < nClSdrs; i++) {
for (unsigned int i = 0; i < nClAntennas; i++) {
std::vector<std::complex<float>> data_cf;
std::vector<std::complex<float>> data_freq_dom;
data_cf.insert(data_cf.begin(), pre1.begin(), pre1.end());
......@@ -332,8 +333,7 @@ Config::Config(const std::string& jsonfile)
tm* ltm = localtime(&now);
int cell_num = nCells;
int ant_num = getNumAntennas();
int ue_num = nClSdrs;
std::string filename = "logs/Argos-" + std::to_string(1900 + ltm->tm_year) + "-" + std::to_string(1 + ltm->tm_mon) + "-" + std::to_string(ltm->tm_mday) + "-" + std::to_string(ltm->tm_hour) + "-" + std::to_string(ltm->tm_min) + "-" + std::to_string(ltm->tm_sec) + "_" + std::to_string(cell_num) + "x" + std::to_string(ant_num) + "x" + std::to_string(ue_num) + ".hdf5";
std::string filename = "logs/Argos-" + std::to_string(1900 + ltm->tm_year) + "-" + std::to_string(1 + ltm->tm_mon) + "-" + std::to_string(ltm->tm_mday) + "-" + std::to_string(ltm->tm_hour) + "-" + std::to_string(ltm->tm_min) + "-" + std::to_string(ltm->tm_sec) + "_" + std::to_string(cell_num) + "x" + std::to_string(ant_num) + "x" + std::to_string(pilotSymsPerFrame) + ".hdf5";
trace_file = tddConf.value("trace_file", filename);
}
......@@ -358,7 +358,7 @@ Config::Config(const std::string& jsonfile)
}
if (clPresent && core_alloc)
printf("allocating %d cores to client threads ... \n", nClSdrs);
printf("allocating %zu cores to client threads ... \n", nClSdrs);
running = true;
......
......@@ -41,10 +41,6 @@ private:
void sync_delays(int cellIdx);
SoapySDR::Device* baseRadio(size_t cellId);
void collectCSI(bool&);
static void dciqMinimize(SoapySDR::Device*, SoapySDR::Device*, int, size_t, double, double);
static void setIQBalance(SoapySDR::Device*, int, size_t, int, int);
static void adjustCalibrationGains(std::vector<SoapySDR::Device*>, SoapySDR::Device*, size_t, double, bool plot = false);
static std::vector<std::complex<float>> snoopSamples(SoapySDR::Device*, size_t, size_t);
void dciqCalibrationProc(size_t);
void readSensors(void);
......
......@@ -13,7 +13,6 @@ public:
void radioStop(void);
private:
void initAGC(SoapySDR::Device* iclSdrs);
Config* _cfg;
std::vector<Radio*> radios;
};
......@@ -21,9 +21,9 @@
#include <stdio.h> /* for fprintf */
#include <stdlib.h>
#include <string.h> /* for memcpy */
#include <thread>
#include <unistd.h>
#include <vector>
#include <thread>
class CommsLib {
public:
......
......@@ -74,9 +74,10 @@ public:
std::string trace_file;
// Clients features
unsigned int nClSdrs;
std::vector<std::string> cl_sdr_ids;
int clSdrCh;
size_t nClSdrs;
size_t clSdrCh;
size_t nClAntennas;
std::string clChannel;
bool clAgcEn;
int clAgcGainInit;
......@@ -101,9 +102,9 @@ public:
std::vector<double> clTxgain_vec[2];
std::vector<double> clRxgain_vec[2];
size_t getPackageLength()
size_t getPackageDataLength()
{
return sizeof(int) * 4 + sizeof(ushort) * (size_t)sampsPerSymbol * 2;
return (2 * sampsPerSymbol * sizeof(short));
}
size_t getNumAntennas();
int getClientId(int, int);
......
......@@ -12,8 +12,8 @@
#ifndef DATARECEIVER_HEADER
#define DATARECEIVER_HEADER
#include "BaseRadioSet.h"
#include "concurrentqueue.h"
#include "sdr-lib.h"
#include <algorithm>
#include <arpa/inet.h>
#include <cassert>
......@@ -69,14 +69,6 @@ public:
struct dev_profile {
int tid;
int nsamps;
int txSyms;
int rxSyms;
int txStartSym;
unsigned txFrameDelta;
double rate;
std::string data_file;
int core;
Receiver* ptr;
};
......@@ -89,9 +81,9 @@ public:
std::vector<pthread_t> startClientThreads();
void go();
static void* loopRecv_launch(void* in_context);
void loopRecv(ReceiverContext* context);
void loopRecv(int tid, int core_id, SampleBuffer* rx_buffer);
static void* clientTxRx_launch(void* in_context);
void clientTxRx(dev_profile* context);
void clientTxRx(int tid);
void getPathLoss();
private:
......
......@@ -56,13 +56,6 @@ std::vector<pthread_t> Receiver::startClientThreads()
// record the thread id
dev_profile* profile = new dev_profile;
profile->tid = i;
profile->rate = config_->rate;
profile->nsamps = config_->sampsPerSymbol;
profile->txSyms = config_->clULSymbols[i].size();
profile->rxSyms = config_->clDLSymbols[i].size();
profile->txStartSym = config_->clULSymbols[i].empty() ? 0 : config_->clULSymbols[i][0];
profile->txFrameDelta = frameTimeDelta;
profile->core = i + 1 + config_->rx_thread_num + config_->task_thread_num;
profile->ptr = this;
// start socket thread
if (pthread_create(&cl_thread_, NULL, Receiver::clientTxRx_launch, profile) != 0) {
......@@ -86,9 +79,9 @@ std::vector<pthread_t> Receiver::startRecvThreads(SampleBuffer* rx_buffer, unsig
// record the thread id
ReceiverContext* context = new ReceiverContext;
context->ptr = this;
context->buffer = rx_buffer;
context->core_id = in_core_id;
context->tid = i;
context->buffer = rx_buffer;
// start socket thread
if (pthread_create(&created_threads[i], NULL, Receiver::loopRecv_launch, context) != 0) {
perror("socket recv thread create failed");
......@@ -118,17 +111,17 @@ void Receiver::go()
void* Receiver::loopRecv_launch(void* in_context)
{
ReceiverContext* context = (ReceiverContext*)in_context;
context->ptr->loopRecv(context);
auto me = context->ptr;
auto tid = context->tid;
auto core_id = context->core_id;
auto buffer = context->buffer;
delete context;
me->loopRecv(tid, core_id, buffer);
return 0;
}
void Receiver::loopRecv(ReceiverContext* context)
void Receiver::loopRecv(int tid, int core_id, SampleBuffer* rx_buffer)
{
SampleBuffer* rx_buffer = context->buffer;
int tid = context->tid;
int core_id = context->core_id;
delete context;
if (config_->core_alloc) {
printf("pinning thread %d to core %d\n", tid, core_id + tid);
if (pin_to_core(core_id + tid) != 0) {
......@@ -150,7 +143,8 @@ void Receiver::loopRecv(ReceiverContext* context)
moodycamel::ProducerToken local_ptok(*message_queue_);
const int bsSdrCh = config_->bsChannel.length();
int buffer_chunk_size = rx_buffer[0].buffer.size() / config_->getPackageLength();
size_t packageLength = sizeof(Package) + config_->getPackageDataLength();
int buffer_chunk_size = rx_buffer[0].buffer.size() / packageLength;
// handle two channels at each radio
// this is assuming buffer_chunk_size is at least 2
......@@ -183,8 +177,9 @@ void Receiver::loopRecv(ReceiverContext* context)
}
// Receive data into buffers
size_t packageLength = sizeof(Package) + config_->getPackageDataLength();
for (auto ch = 0; ch < bsSdrCh; ++ch) {
pkg[ch] = (Package*)(buffer + (cursor + ch) * config_->getPackageLength());
pkg[ch] = (Package*)(buffer + (cursor + ch) * packageLength);
samp[ch] = pkg[ch]->data;
}
long long frameTime;
......@@ -228,42 +223,47 @@ void* Receiver::clientTxRx_launch(void* in_context)
{
dev_profile* context = (dev_profile*)in_context;
Receiver* receiver = context->ptr;
receiver->clientTxRx(context);
int tid = context->tid;
delete context;
receiver->clientTxRx(tid);
return 0;
}
void Receiver::clientTxRx(dev_profile* context)
void Receiver::clientTxRx(int tid)
{
int tid = context->tid;
int txSyms = context->txSyms;
int rxSyms = context->rxSyms;
int txStartSym = context->txStartSym;
unsigned txFrameDelta = context->txFrameDelta;
int NUM_SAMPS = context->nsamps;
int txSyms = config_->clULSymbols[tid].size();
int rxSyms = config_->clDLSymbols[tid].size();
int txStartSym = config_->clULSymbols[tid].empty() ? 0 : config_->clULSymbols[tid][0];
double frameTime = config_->sampsPerSymbol * config_->clFrames[0].size() * 1e3 / config_->rate; // miliseconds
unsigned txFrameDelta = (unsigned)(std::ceil(TIME_DELTA / frameTime));
int NUM_SAMPS = config_->sampsPerSymbol;
if (config_->core_alloc) {
printf("pinning client thread %d to core %d\n", tid, context->core);
if (pin_to_core(context->core) != 0) {
printf("pin client thread %d to core %d failed\n", tid, context->core);
int core = tid + 1 + config_->rx_thread_num + config_->task_thread_num;
printf("pinning client thread %d to core %d\n", tid, core);
if (pin_to_core(core) != 0) {
printf("pin client thread %d to core %d failed\n", tid, core);
exit(0);
}
}
//while(!d_mutex.try_lock()){}
//thread_count++;
//std::cout << "Thread " << tid << ", txSyms " << txSyms << ", rxSyms " << rxSyms << ", txStartSym " << txStartSym << ", rate " << context->rate << ", txFrameDelta " << txFrameDelta << ", nsamps " << NUM_SAMPS << std::endl;
//std::cout << "Thread " << tid << ", txSyms " << txSyms << ", rxSyms " << rxSyms << ", txStartSym " << txStartSym << ", rate " << config_->rate << ", txFrameDelta " << txFrameDelta << ", nsamps " << NUM_SAMPS << std::endl;
//d_mutex.unlock();
delete context;
std::vector<std::complex<float> > buffs(NUM_SAMPS, 0);
std::vector<std::complex<float>> buffs(NUM_SAMPS, 0);
std::vector<void*> rxbuff(2);
rxbuff[0] = buffs.data();
rxbuff[1] = buffs.data();
std::vector<void*> txbuff(2);
if (txSyms > 0) {
txbuff[0] = config_->txdata[tid].data();
txbuff[1] = config_->txdata[tid].data();
size_t txIndex = tid * config_->clSdrCh;
txbuff[0] = config_->txdata[txIndex].data();
if (config_->clSdrCh == 2)
txbuff[1] = config_->txdata[txIndex+1].data();
std::cout << txSyms << " uplink symbols will be sent per frame..." << std::endl;
}
......
This diff is collapsed.
......@@ -2,8 +2,8 @@ function y = getRxVec(tx_data, n_bs, n_ue, chan_type, snr, bs_param, ue_param, h
%%% Returns Rx vector passed through the channel type given in the input
%%% list.
assert(length(bs_param) == n_bs);
assert(length(ue_param) == n_ue);
assert(length(bs_param.id) == n_bs);
assert(length(ue_param.id) == n_ue);
if chan_type == "awgn"
% AWGN
......
......@@ -119,14 +119,14 @@ classdef iris_py < handle
sched = convertStringsToChars(tdd_sched);
for ipy = 1:obj.n_sdrs
obj.py_obj_array{ipy}.config_sdr_tdd( pyargs('tdd_sched', sched, ...
'is_bs', is_bs, 'prefix_len', obj.n_zpad_samp, 'max_frames', obj.n_frame));
'is_bs', is_bs, 'prefix_len', obj.n_zpad_samp, 'max_frames', 1));
end
end
function set_tddconfig_single(obj, is_bs, tdd_sched, index)
sched = convertStringsToChars(tdd_sched);
obj.py_obj_array{index}.config_sdr_tdd( pyargs('tdd_sched', sched, ...
'is_bs', is_bs, 'prefix_len', obj.n_zpad_samp, 'max_frames', obj.n_frame));
'is_bs', is_bs, 'prefix_len', obj.n_zpad_samp, 'max_frames', 1));
end
function sdrrxsetup(obj)
......
......@@ -317,17 +317,17 @@ if __name__ == '__main__':
parser.add_argument("--rate", type=float, dest="rate",
help="Sample rate", default=5e6)
parser.add_argument("--txGain", type=float, dest="txGain",
help="Optional Tx gain (dB)", default=43)
help="Optional Tx gain (dB)", default=70)
parser.add_argument("--rxGain", type=float, dest="rxGain",
help="Optional Rx gain (dB)", default=20)
help="Optional Rx gain (dB)", default=50)
parser.add_argument("--freq", type=float, dest="freq",
help="Optional Tx freq (Hz)", default=2.5e9)
help="Optional Tx freq (Hz)", default=3.6e9)
parser.add_argument("--bw", type=float, dest="bw",
help="Optional filter bw (Hz)", default=None)
args = parser.parse_args()
siso_bs = Iris_py(
serial_id="0339",
serial_id="0268",
sample_rate=args.rate,
tx_freq=args.freq,
rx_freq=args.freq,
......@@ -338,7 +338,7 @@ if __name__ == '__main__':
)
siso_ue = Iris_py(
serial_id="RF3C000045",
serial_id="RF3C000025",
sample_rate=args.rate,
tx_freq=args.freq,
rx_freq=args.freq,
......
......@@ -21,8 +21,8 @@ if ~isloaded
end
% Params:
N_BS_NODE = 8; % Number of nodes/antennas at the BS
N_UE = 2; % Number of UE nodes
N_BS_NODE = 8;
N_UE = 2;
WRITE_PNG_FILES = 0; % Enable writing plots to PNG
SIM_MOD = 0;
DEBUG = 0;
......@@ -35,21 +35,42 @@ else
%Iris params:
TX_SCALE = 0.5; % Scale for Tx waveform ([0:1])
chan_type = "iris";
USE_HUB = 1;
USE_HUB = 0;
TX_FRQ = 2.5e9;
RX_FRQ = TX_FRQ;
TX_GN = 45;
TX_GN_ue = 48;
RX_GN = 23;
TX_GN = 70;
TX_GN_ue = 70;
RX_GN = 60;
SMPL_RT = 5e6;
N_FRM = 50;
bs_ids = string.empty();
ue_ids = string.empty();
ue_scheds = string.empty();
end
fprintf("Channel type: %s \n",chan_type);
if USE_HUB
% Using chains of different size requires some internal
% calibration on the BS. This functionality will be added later.
% For now, we use only the 4-node chains:
bs_ids = ["RF3E000134", "RF3E000191", "RF3E000171", "RF3E000105",...
"RF3E000053", "RF3E000177", "RF3E000192", "RF3E000117",...
"RF3E000183", "RF3E000152", "RF3E000123", "RF3E000178", "RF3E000113", "RF3E000176", "RF3E000132", "RF3E000108", ...
"RF3E000143", "RF3E000160", "RF3E000025", "RF3E000034",...
"RF3E000189", "RF3E000024", "RF3E000139", "RF3E000032", "RF3E000154", "RF3E000182", "RF3E000038", "RF3E000137", ...
"RF3E000103", "RF3E000180", "RF3E000181", "RF3E000188"];
hub_id = "FH4A000001";
else
bs_ids = ["RF3E000189", "RF3E000024", "RF3E000139", "RF3E000032", "RF3E000154", "RF3E000182", "RF3E000038", "RF3E000137"];
end
ue_ids= ["RF3E000060", "RF3E000157"];
N_BS_NODE = length(bs_ids); % Number of nodes/antennas at the BS
N_UE = length(ue_ids); % Number of UE nodes
end
fprintf("Channel type: %s \n",chan_type);
MIMO_ALG = 'ZF'; % MIMO ALGORITHM: ZF or Conjugate
......@@ -147,25 +168,7 @@ if (SIM_MOD)
else
% Create BS Hub and UE objects. Note: BS object is a collection of Iris
% nodes.
if USE_HUB
% Using chains of different size requires some internal
% calibration on the BS. This functionality will be added later.
% For now, we use only the 4-node chains:
bs_ids = ["RF3E000134", "RF3E000191", "RF3E000171", "RF3E000105",...
"RF3E000053", "RF3E000177", "RF3E000192", "RF3E000117",...
"RF3E000183", "RF3E000152", "RF3E000123", "RF3E000178", "RF3E000113", "RF3E000176", "RF3E000132", "RF3E000108", ...
"RF3E000143", "RF3E000160", "RF3E000025", "RF3E000034",...
"RF3E000189", "RF3E000024", "RF3E000139", "RF3E000032", "RF3E000154", "RF3E000182", "RF3E000038", "RF3E000137", ...
"RF3E000103", "RF3E000180", "RF3E000181", "RF3E000188"];
hub_id = "FH4A000001";
else
bs_ids = ["RF3E000189", "RF3E000024", "RF3E000139", "RF3E000032", "RF3E000154", "RF3E000182", "RF3E000038", "RF3E000137"];
end
ue_ids= ["RF3E000060", "RF3E000145"];
bs_sched = ["BGGGGGGGGGGRGGGG"]; % BS schedule
ue_sched = ["GGGGGGGGGGGPGGGG"]; % UE schedule
......
......@@ -23,8 +23,7 @@ end
WRITE_PNG_FILES = 0; % Enable writing plots to PNG
CHANNEL = 11; % Channel to tune Tx and Rx radios
SIM_MOD = 0;
N_BS_NODE = 32;
N_UE = 1;
if SIM_MOD
chan_type = "awgn";
......@@ -42,11 +41,11 @@ else
%Iris params:
USE_HUB = 1;
TX_FRQ = 2.5e9;
USE_HUB = 0;
TX_FRQ = 2.5e9;
RX_FRQ = TX_FRQ;
TX_GN = 40;
RX_GN = 20;
TX_GN = 70;
RX_GN = 60;
SMPL_RT = 5e6;
N_FRM = 10;
bs_ids = string.empty();
......@@ -163,10 +162,13 @@ else
else
bs_ids = ["RF3E000189", "RF3E000024", "RF3E000139", "RF3E000032", "RF3E000154", "RF3E000182", "RF3E000038", "RF3E000137"];
end
ue_id= ["RF3E000060"];
ue_ids= ["RF3E000060"];
N_BS_NODE = length(bs_ids);
N_UE = length(ue_ids);
bs_sched = ["BGGGGGRG"]; % BS schedule
ue_sched = ["GGGGGGPG"]; % UE schedule
......
......@@ -49,8 +49,8 @@ N_BS_NODE = 1;
N_UE = 1;
TX_FRQ = 2.5e9;
RX_FRQ = TX_FRQ;
TX_GN = 43;
RX_GN = 20;
TX_GN = 70;
RX_GN = 60;
SMPL_RT = 5e6;
N_FRM = 10;
......
......@@ -263,6 +263,7 @@ def analyze_hdf5(hdf5, frame=10, cell=0, zoom=0, pl=0):
symbol_num = int(metadata['BS_FRAME_LEN'])
timestep = symbol_length*symbol_num/rate
num_cl = int(metadata['CL_NUM'])-1
num_pilots = int(metadata['PILOT_NUM'])
cp = int(metadata['CP_LEN'])
prefix_len = int(metadata['PREFIX_LEN'])
postfix_len = int(metadata['POSTFIX_LEN'])
......@@ -271,7 +272,7 @@ def analyze_hdf5(hdf5, frame=10, cell=0, zoom=0, pl=0):
# compute CSI for each user and get a nice numpy array
# Returns csi with Frame, User, LTS (there are 2), BS ant, Subcarrier
#also, iq samples nicely chunked out, same dims, but subcarrier is sample.
csi, _ = hdf5_lib.samps2csi(pilot_samples, num_cl+1, symbol_length, offset=offset)
csi, _ = hdf5_lib.samps2csi(pilot_samples, num_pilots, symbol_length, offset=offset)
csi = csi[:, cell, :, :, :, :]
# zoom in too look at behavior around peak (and reduce processing time)
if zoom > 0:
......