blob: f5e5232ad821cca48fdf938bdf027c251b5a9500 [file] [log] [blame]
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +02001/*
2 * Device support for Ettus Research UHD driver
3 *
4 * Copyright 2010,2011 Free Software Foundation, Inc.
5 * Copyright (C) 2015 Ettus Research LLC
6 * Copyright 2019 sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
7 *
8 * Author: Tom Tsou <tom.tsou@ettus.com>
9 *
Pau Espin Pedrol21d03d32019-07-22 12:05:52 +020010 * SPDX-License-Identifier: AGPL-3.0+
11 *
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +020012 * This program is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Affero General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Affero General Public License for more details.
21 *
22 * You should have received a copy of the GNU Affero General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * See the COPYING file in the main directory for details.
25 */
26
27#pragma once
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
Ericc0f78a32023-05-12 13:00:14 +020033#include "bandmanager.h"
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +020034#include "radioDevice.h"
35#include "smpl_buf.h"
36
37#include <uhd/version.hpp>
38#include <uhd/property_tree.hpp>
39#include <uhd/usrp/multi_usrp.hpp>
40
Pau Espin Pedrol056ce132020-06-08 12:13:11 +020041extern "C" {
42#include <osmocom/gsm/gsm_utils.h>
43}
44
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +020045
46enum uhd_dev_type {
47 USRP1,
48 USRP2,
49 B100,
50 B200,
51 B210,
52 B2XX_MCBTS,
53 E1XX,
54 E3XX,
55 X3XX,
56 UMTRX,
57 LIMESDR,
58};
59
Pau Espin Pedrole91544d2020-10-13 17:03:37 +020060struct dev_band_desc {
61 /* Maximum UHD Tx Gain which can be set/used without distorting the
62 output signal, and the resulting real output power measured when that
63 gain is used. Correct measured values only provided for B210 so far. */
64 double nom_uhd_tx_gain; /* dB */
65 double nom_out_tx_power; /* dBm */
66 /* Factor used to infer base real RSSI offset on the Rx path based on current
67 configured RxGain. The resulting rssiOffset is added to the per burst
68 calculated energy in upper layers. These values were empirically
69 found and may change based on multiple factors, see OS#4468.
70 rssiOffset = rxGain + rxgain2rssioffset_rel;
71 */
72 double rxgain2rssioffset_rel; /* dB */
73};
Pau Espin Pedrol056ce132020-06-08 12:13:11 +020074
Ericc0f78a32023-05-12 13:00:14 +020075struct dev_desc {
76 unsigned channels;
77 double mcr;
78 double rate;
79 double offset;
80 std::string desc_str;
81};
82
83using dev_key = std::tuple<uhd_dev_type, int, int>;
84using dev_band_key = std::tuple<uhd_dev_type, enum gsm_band>;
85using power_map_t = std::map<dev_band_key, dev_band_desc>;
86using dev_map_t = std::map<dev_key, dev_desc>;
87
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +020088/*
89 uhd_device - UHD implementation of the Device interface. Timestamped samples
90 are sent to and received from the device. An intermediate buffer
91 on the receive side collects and aligns packets of samples.
92 Events and errors such as underruns are reported asynchronously
93 by the device and received in a separate thread.
94*/
Ericc0f78a32023-05-12 13:00:14 +020095class uhd_device : public RadioDevice, public band_manager<power_map_t, dev_map_t> {
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +020096public:
Eric19e134a2023-05-10 23:50:38 +020097 uhd_device(InterfaceType iface, const struct trx_cfg *cfg);
98 ~uhd_device();
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +020099
Eric19e134a2023-05-10 23:50:38 +0200100 int open();
101 bool start();
102 bool stop();
103 bool restart();
104 enum TxWindowType getWindowType()
105 {
106 return tx_window;
107 }
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +0200108
109 int readSamples(std::vector<short *> &bufs, int len, bool *overrun,
Pau Espin Pedrolf8c0c462020-03-12 19:08:46 +0100110 TIMESTAMP timestamp, bool *underrun);
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +0200111
112 int writeSamples(std::vector<short *> &bufs, int len, bool *underrun,
Pau Espin Pedroldfc6e5f2020-03-12 19:35:33 +0100113 TIMESTAMP timestamp);
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +0200114
115 bool updateAlignment(TIMESTAMP timestamp);
116
117 bool setTxFreq(double wFreq, size_t chan);
118 bool setRxFreq(double wFreq, size_t chan);
119
120 TIMESTAMP initialWriteTimestamp();
121 TIMESTAMP initialReadTimestamp();
122
123 double fullScaleInputValue();
124 double fullScaleOutputValue();
125
126 double setRxGain(double db, size_t chan);
127 double getRxGain(size_t chan);
128 double maxRxGain(void) { return rx_gain_max; }
129 double minRxGain(void) { return rx_gain_min; }
Pau Espin Pedrole91544d2020-10-13 17:03:37 +0200130 double rssiOffset(size_t chan);
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +0200131
Pau Espin Pedrolb899c192020-06-08 14:49:33 +0200132 double setPowerAttenuation(int atten, size_t chan);
133 double getPowerAttenuation(size_t chan = 0);
134
Pau Espin Pedrol0e09e7c2020-05-29 16:39:07 +0200135 int getNominalTxPower(size_t chan = 0);
136
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +0200137 double getTxFreq(size_t chan);
138 double getRxFreq(size_t chan);
139 double getRxFreq();
140
141 bool setRxAntenna(const std::string &ant, size_t chan);
142 std::string getRxAntenna(size_t chan);
143 bool setTxAntenna(const std::string &ant, size_t chan);
144 std::string getTxAntenna(size_t chan);
145
146 bool requiresRadioAlign();
147
148 GSM::Time minLatency();
149
150 inline double getSampleRate() { return tx_rate; }
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +0200151
152 /** Receive and process asynchronous message
153 @return true if message received or false on timeout or error
154 */
155 bool recv_async_msg();
156
157 enum err_code {
158 ERROR_TIMING = -1,
159 ERROR_TIMEOUT = -2,
160 ERROR_UNRECOVERABLE = -3,
161 ERROR_UNHANDLED = -4,
162 };
163
Eric Wild1e17c4f2020-03-24 17:19:27 +0100164protected:
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +0200165 uhd::usrp::multi_usrp::sptr usrp_dev;
166 uhd::tx_streamer::sptr tx_stream;
167 uhd::rx_streamer::sptr rx_stream;
168 enum TxWindowType tx_window;
169 enum uhd_dev_type dev_type;
170
171 double tx_rate, rx_rate;
172
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +0200173 double rx_gain_min, rx_gain_max;
174
175 std::vector<double> tx_gains, rx_gains;
176 std::vector<double> tx_freqs, rx_freqs;
177 size_t tx_spp, rx_spp;
178
179 bool started;
180 bool aligned;
181
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +0200182 size_t drop_cnt;
183 uhd::time_spec_t prev_ts;
184
185 TIMESTAMP ts_initial, ts_offset;
186 std::vector<smpl_buf *> rx_buffers;
Pau Espin Pedrolef192d32019-04-30 18:51:00 +0200187 /* Sample buffers used to receive samples from UHD: */
188 std::vector<std::vector<short> > pkt_bufs;
189 /* Used to call UHD API: Buffer pointer of each elem in pkt_ptrs will
190 point to corresponding buffer of vector pkt_bufs. */
191 std::vector<short *> pkt_ptrs;
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +0200192
193 void init_gains();
194 void set_channels(bool swap);
195 void set_rates();
196 bool parse_dev_type();
197 bool flush_recv(size_t num_pkts);
198 int check_rx_md_err(uhd::rx_metadata_t &md, ssize_t num_smpls);
199
200 std::string str_code(uhd::rx_metadata_t metadata);
201 std::string str_code(uhd::async_metadata_t metadata);
202
203 uhd::tune_request_t select_freq(double wFreq, size_t chan, bool tx);
204 bool set_freq(double freq, size_t chan, bool tx);
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +0200205
206 Thread *async_event_thrd;
Pau Espin Pedrol7bef2342019-04-29 17:23:21 +0200207};