blob: 404ef7598a5f72ad7bd4c81e6c38ffd9bf4a4cee [file] [log] [blame]
dburgessb3a0ca42011-10-12 07:44:40 +00001/*
2* Copyright 2008 Free Software Foundation, Inc.
3*
Martin Hauke066fd042019-10-13 19:08:00 +02004* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribution.
dburgessb3a0ca42011-10-12 07:44:40 +00005*
6* This use of this software may be subject to additional restrictions.
7* See the LEGAL file in the main directory for details.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13*/
14
15#ifndef __RADIO_DEVICE_H__
16#define __RADIO_DEVICE_H__
17
ttsouf60dafa2012-10-22 00:07:14 +000018#include <string>
Thomas Tsou204a9f12013-10-29 18:34:16 -040019#include <vector>
dburgessb3a0ca42011-10-12 07:44:40 +000020
Pau Espin Pedrole564f0f2018-04-24 18:43:51 +020021#include "GSMCommon.h"
Harald Welte24073142018-06-13 19:32:15 +020022#include "Logger.h"
Pau Espin Pedrole564f0f2018-04-24 18:43:51 +020023
Pau Espin Pedrolefac20b2018-02-21 14:59:19 +010024extern "C" {
25#include "config_defs.h"
Pau Espin Pedrol4456b6f2019-05-24 16:54:19 +020026#include "osmo_signal.h"
Pau Espin Pedrolefac20b2018-02-21 14:59:19 +010027}
28
dburgessb3a0ca42011-10-12 07:44:40 +000029#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
Alexander Chemerisf931cf22016-06-18 10:42:33 +030033#define GSMRATE (1625e3/6)
Tom Tsou76764272016-06-24 14:25:39 -070034#define MCBTS_SPACING 800000.0
Thomas Tsoucb69f082013-04-08 14:18:26 -040035
dburgessb3a0ca42011-10-12 07:44:40 +000036/** a 64-bit virtual timestamp for radio data */
37typedef unsigned long long TIMESTAMP;
38
39/** A class to handle a USRP rev 4, with a two RFX900 daughterboards */
40class RadioDevice {
41
42 public:
kurtis.heimerle380af32011-11-26 03:18:55 +000043 /* Available transport bus types */
Pau Espin Pedrolc7a0bf12018-04-25 12:17:10 +020044 enum TxWindowType { TX_WINDOW_USRP1, TX_WINDOW_FIXED, TX_WINDOW_LMS1 };
kurtis.heimerle380af32011-11-26 03:18:55 +000045
Thomas Tsoucb69f082013-04-08 14:18:26 -040046 /* Radio interface types */
Tom Tsou05c6feb2016-06-22 16:09:44 -070047 enum InterfaceType {
48 NORMAL,
49 RESAMP_64M,
50 RESAMP_100M,
Tom Tsou76764272016-06-24 14:25:39 -070051 MULTI_ARFCN,
Tom Tsou05c6feb2016-06-22 16:09:44 -070052 };
Thomas Tsoucb69f082013-04-08 14:18:26 -040053
Tom Tsou05c6feb2016-06-22 16:09:44 -070054 static RadioDevice *make(size_t tx_sps, size_t rx_sps, InterfaceType type,
Pau Espin Pedrol77ce99a2018-02-05 13:05:06 +010055 size_t chans = 1, double offset = 0.0,
56 const std::vector<std::string>& tx_paths = std::vector<std::string>(1, ""),
57 const std::vector<std::string>& rx_paths = std::vector<std::string>(1, ""));
kurtis.heimerl965e7572011-11-26 03:16:54 +000058
kurtis.heimerldb2aae52011-11-26 03:17:13 +000059 /** Initialize the USRP */
Tom Tsou2f3e60b2016-07-17 19:29:08 -070060 virtual int open(const std::string &args, int ref, bool swap_channels)=0;
dburgessb3a0ca42011-10-12 07:44:40 +000061
Thomas Tsou8c336792013-11-15 16:26:05 -050062 virtual ~RadioDevice() { }
63
dburgessb3a0ca42011-10-12 07:44:40 +000064 /** Start the USRP */
65 virtual bool start()=0;
66
67 /** Stop the USRP */
68 virtual bool stop()=0;
69
Thomas Tsou02d88d12013-04-05 15:36:30 -040070 /** Get the Tx window type */
71 virtual enum TxWindowType getWindowType()=0;
kurtis.heimerle380af32011-11-26 03:18:55 +000072
dburgessb3a0ca42011-10-12 07:44:40 +000073 /**
74 Read samples from the radio.
75 @param buf preallocated buf to contain read result
76 @param len number of samples desired
77 @param overrun Set if read buffer has been overrun, e.g. data not being read fast enough
78 @param timestamp The timestamp of the first samples to be read
79 @param underrun Set if radio does not have data to transmit, e.g. data not being sent fast enough
dburgessb3a0ca42011-10-12 07:44:40 +000080 @return The number of samples actually read
81 */
Thomas Tsou204a9f12013-10-29 18:34:16 -040082 virtual int readSamples(std::vector<short *> &bufs, int len, bool *overrun,
Pau Espin Pedrolf8c0c462020-03-12 19:08:46 +010083 TIMESTAMP timestamp = 0xffffffff, bool *underrun = 0) = 0;
dburgessb3a0ca42011-10-12 07:44:40 +000084 /**
85 Write samples to the radio.
86 @param buf Contains the data to be written.
87 @param len number of samples to write.
88 @param underrun Set if radio does not have data to transmit, e.g. data not being sent fast enough
89 @param timestamp The timestamp of the first sample of the data buffer.
dburgessb3a0ca42011-10-12 07:44:40 +000090 @return The number of samples actually written
91 */
Thomas Tsou204a9f12013-10-29 18:34:16 -040092 virtual int writeSamples(std::vector<short *> &bufs, int len, bool *underrun,
Pau Espin Pedroldfc6e5f2020-03-12 19:35:33 +010093 TIMESTAMP timestamp) = 0;
Thomas Tsou204a9f12013-10-29 18:34:16 -040094
dburgessb3a0ca42011-10-12 07:44:40 +000095 /** Update the alignment between the read and write timestamps */
96 virtual bool updateAlignment(TIMESTAMP timestamp)=0;
Thomas Tsou204a9f12013-10-29 18:34:16 -040097
dburgessb3a0ca42011-10-12 07:44:40 +000098 /** Set the transmitter frequency */
Thomas Tsou204a9f12013-10-29 18:34:16 -040099 virtual bool setTxFreq(double wFreq, size_t chan = 0) = 0;
dburgessb3a0ca42011-10-12 07:44:40 +0000100
101 /** Set the receiver frequency */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400102 virtual bool setRxFreq(double wFreq, size_t chan = 0) = 0;
dburgessb3a0ca42011-10-12 07:44:40 +0000103
104 /** Returns the starting write Timestamp*/
105 virtual TIMESTAMP initialWriteTimestamp(void)=0;
106
107 /** Returns the starting read Timestamp*/
108 virtual TIMESTAMP initialReadTimestamp(void)=0;
109
110 /** returns the full-scale transmit amplitude **/
111 virtual double fullScaleInputValue()=0;
112
113 /** returns the full-scale receive amplitude **/
114 virtual double fullScaleOutputValue()=0;
115
116 /** sets the receive chan gain, returns the gain setting **/
Thomas Tsou204a9f12013-10-29 18:34:16 -0400117 virtual double setRxGain(double dB, size_t chan = 0) = 0;
dburgessb3a0ca42011-10-12 07:44:40 +0000118
119 /** gets the current receive gain **/
Thomas Tsou204a9f12013-10-29 18:34:16 -0400120 virtual double getRxGain(size_t chan = 0) = 0;
dburgessb3a0ca42011-10-12 07:44:40 +0000121
122 /** return maximum Rx Gain **/
123 virtual double maxRxGain(void) = 0;
124
125 /** return minimum Rx Gain **/
126 virtual double minRxGain(void) = 0;
127
Pau Espin Pedrole91544d2020-10-13 17:03:37 +0200128 /** return base RSSI offset to apply for received samples **/
129 virtual double rssiOffset(size_t chan) = 0;
130
Pau Espin Pedrol0e09e7c2020-05-29 16:39:07 +0200131 /** returns the Nominal transmit output power of the transceiver in dBm, negative on error **/
132 virtual int getNominalTxPower(size_t chan = 0) = 0;
133
Pau Espin Pedrol77ce99a2018-02-05 13:05:06 +0100134 /** sets the RX path to use, returns true if successful and false otherwise */
135 virtual bool setRxAntenna(const std::string &ant, size_t chan = 0) = 0;
136
137 /** return the used RX path */
138 virtual std::string getRxAntenna(size_t chan = 0) = 0;
139
140 /** sets the RX path to use, returns true if successful and false otherwise */
141 virtual bool setTxAntenna(const std::string &ant, size_t chan = 0) = 0;
142
143 /** return the used RX path */
144 virtual std::string getTxAntenna(size_t chan = 0) = 0;
145
Pau Espin Pedrol0fc20d12018-04-24 17:48:52 +0200146 /** return whether user drives synchronization of Tx/Rx of USRP */
147 virtual bool requiresRadioAlign() = 0;
148
Pau Espin Pedrole564f0f2018-04-24 18:43:51 +0200149 /** Minimum latency that the device can achieve */
150 virtual GSM::Time minLatency() = 0;
151
dburgessb3a0ca42011-10-12 07:44:40 +0000152 /** Return internal status values */
Thomas Tsou204a9f12013-10-29 18:34:16 -0400153 virtual double getTxFreq(size_t chan = 0) = 0;
154 virtual double getRxFreq(size_t chan = 0) = 0;
dburgessb3a0ca42011-10-12 07:44:40 +0000155 virtual double getSampleRate()=0;
dburgessb3a0ca42011-10-12 07:44:40 +0000156
Pau Espin Pedrol5bd3d422020-06-19 18:11:54 +0200157 virtual double setPowerAttenuation(int atten, size_t chan) = 0;
158 virtual double getPowerAttenuation(size_t chan=0) = 0;
Pau Espin Pedrol992c9bd2020-06-08 13:44:24 +0200159
Harald Welte61707e82018-06-13 23:21:57 +0200160 protected:
161 size_t tx_sps, rx_sps;
162 InterfaceType iface;
163 size_t chans;
164 double lo_offset;
Harald Welte24073142018-06-13 19:32:15 +0200165 std::vector<std::string> tx_paths, rx_paths;
Pau Espin Pedrol4456b6f2019-05-24 16:54:19 +0200166 std::vector<struct device_counters> m_ctr;
Harald Welte61707e82018-06-13 23:21:57 +0200167
Pau Espin Pedrolee2ba192019-09-16 13:52:40 +0200168 RadioDevice(size_t tx_sps, size_t rx_sps, InterfaceType type, size_t chan_num, double offset,
Harald Welte61707e82018-06-13 23:21:57 +0200169 const std::vector<std::string>& tx_paths,
170 const std::vector<std::string>& rx_paths):
Pau Espin Pedrolee2ba192019-09-16 13:52:40 +0200171 tx_sps(tx_sps), rx_sps(rx_sps), iface(type), chans(chan_num), lo_offset(offset),
Eric5561f112022-07-19 21:18:21 +0200172 tx_paths(tx_paths), rx_paths(rx_paths), m_ctr(chans)
Pau Espin Pedrol4456b6f2019-05-24 16:54:19 +0200173 {
Pau Espin Pedrolee2ba192019-09-16 13:52:40 +0200174 if (iface == MULTI_ARFCN) {
175 LOGC(DDEV, INFO) << "Multi-ARFCN: "<< chan_num << " logical chans -> 1 physical chans";
176 chans = 1;
177 }
178
Pau Espin Pedrol4456b6f2019-05-24 16:54:19 +0200179 for (size_t i = 0; i < chans; i++) {
180 memset(&m_ctr[i], 0, sizeof(m_ctr[i]));
181 m_ctr[i].chan = i;
182 }
183 }
Harald Welte61707e82018-06-13 23:21:57 +0200184
Harald Welte24073142018-06-13 19:32:15 +0200185 bool set_antennas() {
186 unsigned int i;
187
188 for (i = 0; i < tx_paths.size(); i++) {
189 if (tx_paths[i] == "")
190 continue;
Vadim Yanitskiyb7c6f1e2020-09-11 18:03:56 +0700191 if (iface == MULTI_ARFCN && i > 0) {
192 LOGCHAN(i, DDEV, NOTICE) << "Not setting Tx antenna "
193 << tx_paths[i]
194 << " for a logical channel";
195 continue;
196 }
197
Pau Espin Pedrol77f33962019-08-26 17:11:12 +0200198 LOGCHAN(i, DDEV, DEBUG) << "Configuring Tx antenna " << tx_paths[i];
Harald Welte24073142018-06-13 19:32:15 +0200199 if (!setTxAntenna(tx_paths[i], i)) {
Pau Espin Pedrol77f33962019-08-26 17:11:12 +0200200 LOGCHAN(i, DDEV, ALERT) << "Failed configuring Tx antenna " << tx_paths[i];
Harald Welte24073142018-06-13 19:32:15 +0200201 return false;
202 }
203 }
204
205 for (i = 0; i < rx_paths.size(); i++) {
206 if (rx_paths[i] == "")
207 continue;
Vadim Yanitskiyb7c6f1e2020-09-11 18:03:56 +0700208 if (iface == MULTI_ARFCN && i > 0) {
209 LOGCHAN(i, DDEV, NOTICE) << "Not setting Rx antenna "
210 << rx_paths[i]
211 << " for a logical channel";
212 continue;
213 }
214
Pau Espin Pedrol77f33962019-08-26 17:11:12 +0200215 LOGCHAN(i, DDEV, DEBUG) << "Configuring Rx antenna " << rx_paths[i];
Harald Welte24073142018-06-13 19:32:15 +0200216 if (!setRxAntenna(rx_paths[i], i)) {
Pau Espin Pedrol77f33962019-08-26 17:11:12 +0200217 LOGCHAN(i, DDEV, ALERT) << "Failed configuring Rx antenna " << rx_paths[i];
Harald Welte24073142018-06-13 19:32:15 +0200218 return false;
219 }
220 }
221 LOG(INFO) << "Antennas configured successfully";
222 return true;
223 }
224
225
dburgessb3a0ca42011-10-12 07:44:40 +0000226};
227
228#endif