-
Notifications
You must be signed in to change notification settings - Fork 3
/
radio_lib.cpp
150 lines (137 loc) · 5.11 KB
/
radio_lib.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include "radio_lib.hpp"
RadioConfig::RadioConfig(std::vector<std::string> radioId, int numCh, double rate,
double freq, double rxgain, double txgain, int symlen, int symnum, int maxFrame, std::vector<int> sched):
_numCh(numCh), // 1 or 2
_symlen(symlen),
_symnum(symnum),
_maxFrame(maxFrame),
_rate(rate),
_freq(freq),
_rxgain(rxgain),
_txgain(txgain),
_tddSched(sched)
{
SoapySDR::Kwargs args;
//load channels
std::vector<size_t> channels;
if (_numCh == 1) channels = {0};
else if (_numCh == 2) channels = {0, 1};
else
{
std::cout << "Error! Supported number of channels 1 or 2, setting to 2!" << std::endl;
_numCh = 2;
channels = {0, 1};
}
this->_radioNum = _radioId.size();
for (int i = 0; i < this->_radioNum; i++)
{
args["serial"] = _radioId.at(i);
baStn.push_back(SoapySDR::Device::make(args));
}
for (int i = 0; i < this->_radioNum; i++)
{
//use the RX only antenna, and TRX for tx
for (auto ch : channels) baStn[i]->setAntenna(SOAPY_SDR_RX, ch, "TRX");
std::cout << "setting samples rates to " << rate/1e6 << " Msps..." << std::endl;
SoapySDR::Kwargs info = baStn[i]->getHardwareInfo();
for (auto ch : channels)
{
baStn[i]->setSampleRate(SOAPY_SDR_RX, ch, _rate);
baStn[i]->setSampleRate(SOAPY_SDR_TX, ch, _rate);
baStn[i]->setFrequency(SOAPY_SDR_RX, ch, _freq);
baStn[i]->setFrequency(SOAPY_SDR_TX, ch, _freq);
baStn[i]->setGain(SOAPY_SDR_RX, ch, _rxgain);
if (info["frontend"] == "CBRS")
{
baStn[i]->setGain(SOAPY_SDR_RX, ch, "ATTN", 0);
baStn[i]->setGain(SOAPY_SDR_RX, ch, "PGA", 0);
}
baStn[i]->setGain(SOAPY_SDR_TX, ch, _txgain);
if (info["frontend"] == "CBRS")
{
baStn[i]->setGain(SOAPY_SDR_TX, ch, "PAD", (_txgain>45) ? -7 : _txgain-52);
baStn[i]->setGain(SOAPY_SDR_TX, ch, "ATTN", 0);
baStn[i]->setGain(SOAPY_SDR_TX, ch, "PA1", 15);
baStn[i]->setGain(SOAPY_SDR_TX, ch, "PA2", 0);
baStn[i]->setGain(SOAPY_SDR_TX, ch, "PA3", 30);
}
baStn[i]->setDCOffsetMode(SOAPY_SDR_RX, ch, true);
}
this->rxStreams.push_back(baStn[i]->setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, channels));
this->txStreams.push_back(baStn[i]->setupStream(SOAPY_SDR_TX, SOAPY_SDR_CS16, channels));
}
}
void RadioConfig::radioStart(std::vector<void *> buffs)
{
int flags = SOAPY_SDR_END_BURST | SOAPY_SDR_TX_REPLAY;
long long frameTime(0);
for (int i = 0; i < this->_radioNum; i++)
{
baStn[i]->writeRegister("RFCORE", 104, this->_symlen);
baStn[i]->writeRegister("RFCORE", 108, this->_symnum);
baStn[i]->writeRegister("RFCORE", 112, this->_maxFrame);
baStn[i]->writeSetting("TX_SW_DELAY", "30"); // experimentally good value for dev front-end
baStn[i]->writeSetting("TDD_MODE", std::to_string(0x80000000));
// write schedule
for (int j = 0; j < 16; j++)
for(int k = 0; k < this->_symnum; k++) // symnum <= 256
{
baStn[i]->writeRegister("RFCORE", 116, j*256+k);
baStn[i]->writeRegister("RFCORE", 120, this->_tddSched[k]);
}
// write beacons to FPGA buffers
baStn[i]->writeStream(this->txStreams[i], buffs.data(), this->_symlen, flags, frameTime);
}
}
void RadioConfig::radioStop()
{
for (int i = 0; i < this->_radioNum; i++)
{
baStn[i]->writeSetting("TDD_MODE", "0");
// write schedule
for (int j = 0; j < 16; j++)
for(int k = 0; k < this->_symnum; k++) // symnum <= 256
{
baStn[i]->writeRegister("RFCORE", 116, j*256+k);
baStn[i]->writeRegister("RFCORE", 120, 0);
}
baStn[i]->closeStream(this->rxStreams[i]);
baStn[i]->closeStream(this->txStreams[i]);
}
}
void RadioConfig::radioTx(std::vector<void *> buffs)
{
int flags = 0;
long long frameTime(0);
for (int i = 0; i < this->_radioNum; i++)
{
baStn[i]->writeStream(this->txStreams[i], buffs.data(), this->_symlen, flags, frameTime, 1000000);
}
}
void RadioConfig::radioRx(std::vector<void *> buffs)
{
int flags = 0;
long long frameTime(0);
for (int i = 0; i < this->_radioNum; i++)
{
baStn[i]->readStream(this->rxStreams[i], buffs.data(), this->_symlen, flags, frameTime, 1000000);
}
}
void RadioConfig::radioSched(std::vector<int> sched)
{
// make sure we can pause the framer before we rewrite schedules to avoid
// any race conditions, for now I set tdd mode to 0
for (int i = 0; i < this->_radioNum; i++)
{
baStn[i]->writeSetting("TDD_MODE", "0");
// write schedule
for (int j = 0; j < 16; j++)
for(int k = 0; k < this->_symnum; k++) // symnum <= 256
{
baStn[i]->writeRegister("RFCORE", 116, j*256+k);
baStn[i]->writeRegister("RFCORE", 120, sched[k]);
}
baStn[i]->writeSetting("TDD_MODE", std::to_string(0x80000000));
}
}
RadioConfig::~RadioConfig(){}