blob: 9db8bf0a4372613c3659f22af434d79106288312 [file] [log] [blame]
Ericb7253c62022-11-28 19:21:08 +01001#pragma once
2/*
3 * (C) 2022 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
4 * All Rights Reserved
5 *
6 * Author: Eric Wild <ewild@sysmocom.de>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#include "itrq.h"
24#include <atomic>
25#include <complex>
26#include <cstdint>
27#include <functional>
28#include <iostream>
29#include <cassert>
30#include <cstring>
31
32#include <libbladeRF.h>
33#include <Timeval.h>
34#include <unistd.h>
35
36const size_t BLADE_BUFFER_SIZE = 1024 * 1;
37const size_t BLADE_NUM_BUFFERS = 32 * 1;
38const size_t NUM_TRANSFERS = 16 * 2;
39const int SAMPLE_SCALE_FACTOR = 15; // actually 16 but sigproc complains about clipping..
40
41// see https://en.cppreference.com/w/cpp/language/parameter_pack "Brace-enclosed initializers" example
Eric2e6c3622023-05-02 14:34:49 +020042template <typename Arg, typename... Args>
43void expand_args(std::ostream &out, Arg &&arg, Args &&...args)
Ericb7253c62022-11-28 19:21:08 +010044{
45 out << '(' << std::forward<Arg>(arg);
46 (void)(int[]){ 0, (void((out << "," << std::forward<Args>(args))), 0)... };
47 out << ')' << std::endl;
48}
49
Eric2e6c3622023-05-02 14:34:49 +020050template <class R, class... Args>
51using RvalFunc = R (*)(Args...);
Ericb7253c62022-11-28 19:21:08 +010052
53template <class R, class... Args>
54R exec_and_check(RvalFunc<R, Args...> func, const char *fname, const char *finame, const char *funcname, int line,
55 Args... args)
56{
57 R rval = func(std::forward<Args>(args)...);
58 if (rval != 0) {
59 std::cerr << ((rval >= 0) ? "OK:" : bladerf_strerror(rval)) << ':' << finame << ':' << line << ':'
60 << funcname << ':' << fname;
61 expand_args(std::cerr, args...);
62 }
63 return rval;
64}
65
66// only macros can pass a func name string
67#define blade_check(func, ...) exec_and_check(func, #func, __FILE__, __FUNCTION__, __LINE__, __VA_ARGS__)
68
69#pragma pack(push, 1)
70using blade_sample_type = std::complex<int16_t>;
71enum class blade_speed_buffer_type { HS, SS };
Eric2e6c3622023-05-02 14:34:49 +020072template <blade_speed_buffer_type T>
73struct blade_usb_message {
Ericb7253c62022-11-28 19:21:08 +010074 uint32_t reserved;
75 uint64_t ts;
76 uint32_t meta_flags;
77 blade_sample_type d[(T == blade_speed_buffer_type::SS ? 512 : 256) - 4];
78};
79
80static_assert(sizeof(blade_usb_message<blade_speed_buffer_type::SS>) == 2048, "blade buffer mismatch!");
81static_assert(sizeof(blade_usb_message<blade_speed_buffer_type::HS>) == 1024, "blade buffer mismatch!");
Eric2e6c3622023-05-02 14:34:49 +020082template <unsigned int SZ, blade_speed_buffer_type T>
83struct blade_otw_buffer {
Ericb7253c62022-11-28 19:21:08 +010084 static_assert((SZ >= 2 && !(SZ % 2)), "min size is 2x usb buffer!");
85 blade_usb_message<T> m[SZ];
86 int actual_samples_per_msg()
87 {
88 return sizeof(blade_usb_message<T>::d) / sizeof(typeof(blade_usb_message<T>::d[0]));
89 }
90 int actual_samples_per_buffer()
91 {
92 return SZ * actual_samples_per_msg();
93 }
94 int samples_per_buffer()
95 {
96 return SZ * sizeof(blade_usb_message<T>) / sizeof(typeof(blade_usb_message<T>::d[0]));
97 }
98 int num_msgs_per_buffer()
99 {
100 return SZ;
101 }
102 auto get_first_ts()
103 {
104 return m[0].ts;
105 }
106 constexpr auto *getsampleoffset(int ofs)
107 {
108 auto full = ofs / actual_samples_per_msg();
109 auto rem = ofs % actual_samples_per_msg();
110 return &m[full].d[rem];
111 }
112 int readall(blade_sample_type *outaddr)
113 {
114 blade_sample_type *addr = outaddr;
115 for (unsigned int i = 0; i < SZ; i++) {
116 memcpy(addr, &m[i].d[0], actual_samples_per_msg() * sizeof(blade_sample_type));
117 addr += actual_samples_per_msg();
118 }
119 return actual_samples_per_buffer();
120 }
121 int read_n(blade_sample_type *outaddr, int start, int num)
122 {
123 assert((start + num) <= actual_samples_per_buffer());
124 assert(start >= 0);
125
126 if (!num)
127 return 0;
128
129 // which buffer?
130 int start_buf_idx = (start > 0) ? start / actual_samples_per_msg() : 0;
131 // offset from actual buffer start
132 auto start_offset_in_buf = (start - (start_buf_idx * actual_samples_per_msg()));
133 auto samp_rem_in_first_buf = actual_samples_per_msg() - start_offset_in_buf;
134 auto remaining_first_buf = num > samp_rem_in_first_buf ? samp_rem_in_first_buf : num;
135
136 memcpy(outaddr, &m[start_buf_idx].d[start_offset_in_buf],
137 remaining_first_buf * sizeof(blade_sample_type));
138 outaddr += remaining_first_buf;
139
140 auto remaining = num - remaining_first_buf;
141
142 if (!remaining)
143 return num;
144
145 start_buf_idx++;
146
147 auto rem_full_bufs = remaining / actual_samples_per_msg();
148 remaining -= rem_full_bufs * actual_samples_per_msg();
149
150 for (int i = 0; i < rem_full_bufs; i++) {
151 memcpy(outaddr, &m[start_buf_idx++].d[0], actual_samples_per_msg() * sizeof(blade_sample_type));
152 outaddr += actual_samples_per_msg();
153 }
154
155 if (remaining)
156 memcpy(outaddr, &m[start_buf_idx].d[0], remaining * sizeof(blade_sample_type));
157 return num;
158 }
159 int write_n_burst(blade_sample_type *in, int num, uint64_t first_ts)
160 {
161 assert(num <= actual_samples_per_buffer());
162 int len_rem = num;
163 for (unsigned int i = 0; i < SZ; i++) {
164 m[i] = {};
165 m[i].ts = first_ts + i * actual_samples_per_msg();
166 if (len_rem) {
167 int max_to_copy =
168 len_rem > actual_samples_per_msg() ? actual_samples_per_msg() : len_rem;
169 memcpy(&m[i].d[0], in, max_to_copy * sizeof(blade_sample_type));
170 len_rem -= max_to_copy;
171 in += actual_samples_per_msg();
172 }
173 }
174 return num;
175 }
176};
177#pragma pack(pop)
178
Eric2e6c3622023-05-02 14:34:49 +0200179template <unsigned int SZ, blade_speed_buffer_type T>
180struct blade_otw_buffer_helper {
Ericb7253c62022-11-28 19:21:08 +0100181 static_assert((SZ >= 1024 && ((SZ & (SZ - 1)) == 0)), "only buffer size multiples of 1024 allowed!");
182 static blade_otw_buffer<SZ / 512, T> x;
183};
184
185using dev_buf_t = typeof(blade_otw_buffer_helper<BLADE_BUFFER_SIZE, blade_speed_buffer_type::SS>::x);
186// using buf_in_use = blade_otw_buffer<2, blade_speed_buffer_type::SS>;
187using bh_fn_t = std::function<int(dev_buf_t *)>;
188
Eric2e6c3622023-05-02 14:34:49 +0200189template <typename T>
190struct blade_hw {
Ericb7253c62022-11-28 19:21:08 +0100191 struct bladerf *dev;
192 struct bladerf_stream *rx_stream;
193 struct bladerf_stream *tx_stream;
194 // using pkt2buf = blade_otw_buffer<2, blade_speed_buffer_type::SS>;
Ericc3e515a2023-05-08 12:56:56 +0200195 using tx_buf_q_type = spsc_cond_timeout<BLADE_NUM_BUFFERS, dev_buf_t *, true, false>;
Ericb7253c62022-11-28 19:21:08 +0100196 const unsigned int rxFullScale, txFullScale;
197 const int rxtxdelay;
198
199 float rxgain, txgain;
Eric40978042023-05-23 10:59:58 +0200200 static std::atomic<bool> stop_lower_threads_flag;
Ericc0f0a612023-05-02 15:34:19 +0200201 double rxfreq_cache, txfreq_cache;
Ericb7253c62022-11-28 19:21:08 +0100202
203 struct ms_trx_config {
204 int tx_freq;
205 int rx_freq;
206 int sample_rate;
207 int bandwidth;
208
209 public:
210 ms_trx_config() : tx_freq(881e6), rx_freq(926e6), sample_rate(((1625e3 / 6) * 4)), bandwidth(1e6)
211 {
212 }
213 } cfg;
214
215 struct buf_mgmt {
216 void **rx_samples;
217 void **tx_samples;
218 tx_buf_q_type bufptrqueue;
219
220 } buf_mgmt;
221
222 virtual ~blade_hw()
223 {
224 close_device();
225 }
Ericc0f0a612023-05-02 15:34:19 +0200226 blade_hw()
227 : rxFullScale(2047), txFullScale(2047), rxtxdelay(-60), rxgain(30), txgain(30), rxfreq_cache(0),
228 txfreq_cache(0)
Ericb7253c62022-11-28 19:21:08 +0100229 {
230 }
231
232 void close_device()
233 {
234 if (dev) {
235 if (tx_stream) {
236 bladerf_deinit_stream(tx_stream);
237 }
238
239 if (rx_stream) {
240 bladerf_deinit_stream(rx_stream);
241 }
242
243 bladerf_enable_module(dev, BLADERF_MODULE_RX, false);
244 bladerf_enable_module(dev, BLADERF_MODULE_TX, false);
245
246 bladerf_close(dev);
247 dev = NULL;
248 }
249 }
250
251 int init_device(bh_fn_t rxh, bh_fn_t txh)
252 {
253 struct bladerf_rational_rate rate = { 0, static_cast<uint64_t>((1625e3 * 4)) * 64, 6 * 64 }, actual;
254
255 bladerf_log_set_verbosity(BLADERF_LOG_LEVEL_DEBUG);
256 bladerf_set_usb_reset_on_open(true);
Ericb52650f2023-11-03 20:37:51 +0100257
Ericb7253c62022-11-28 19:21:08 +0100258 blade_check(bladerf_open, &dev, "");
259 if (!dev) {
260 std::cerr << "open failed, device missing?" << std::endl;
261 exit(0);
262 }
263 if (bladerf_device_speed(dev) != bladerf_dev_speed::BLADERF_DEVICE_SPEED_SUPER) {
264 std::cerr << "open failed, only superspeed (usb3) supported!" << std::endl;
265 return -1;
266 }
267
268 blade_check(bladerf_set_tuning_mode, dev, bladerf_tuning_mode::BLADERF_TUNING_MODE_FPGA);
269
270 bool is_locked;
271 blade_check(bladerf_set_pll_enable, dev, true);
Eric Wild3fc39b52024-03-18 16:16:17 +0100272 uint64_t refclock = 10000000UL;
273 blade_check(bladerf_set_pll_refclk, dev, refclock);
Ericb7253c62022-11-28 19:21:08 +0100274 for (int i = 0; i < 20; i++) {
275 usleep(50 * 1000);
276 bladerf_get_pll_lock_state(dev, &is_locked);
277
278 if (is_locked)
279 break;
280 }
281 if (!is_locked) {
282 std::cerr << "unable to lock refclk!" << std::endl;
283 return -1;
284 }
285
286 blade_check(bladerf_set_rational_sample_rate, dev, BLADERF_CHANNEL_RX(0), &rate, &actual);
287 blade_check(bladerf_set_rational_sample_rate, dev, BLADERF_CHANNEL_TX(0), &rate, &actual);
288
289 blade_check(bladerf_set_frequency, dev, BLADERF_CHANNEL_RX(0), (bladerf_frequency)cfg.rx_freq);
290 blade_check(bladerf_set_frequency, dev, BLADERF_CHANNEL_TX(0), (bladerf_frequency)cfg.tx_freq);
291
292 blade_check(bladerf_set_bandwidth, dev, BLADERF_CHANNEL_RX(0), (bladerf_bandwidth)cfg.bandwidth,
293 (bladerf_bandwidth *)NULL);
294 blade_check(bladerf_set_bandwidth, dev, BLADERF_CHANNEL_TX(0), (bladerf_bandwidth)cfg.bandwidth,
295 (bladerf_bandwidth *)NULL);
296
297 blade_check(bladerf_set_gain_mode, dev, BLADERF_CHANNEL_RX(0), BLADERF_GAIN_MGC);
Eric4b2b98b2023-05-02 15:22:05 +0200298 setRxGain(rxgain, 0);
299 setTxGain(txgain, 0);
Ericb7253c62022-11-28 19:21:08 +0100300 usleep(1000);
Ericb3157b92023-05-23 11:32:34 +0200301
302 bladerf_set_stream_timeout(dev, BLADERF_TX, 10);
303 bladerf_set_stream_timeout(dev, BLADERF_RX, 10);
304
Ericb7253c62022-11-28 19:21:08 +0100305 blade_check(bladerf_init_stream, &rx_stream, dev, getrxcb(rxh), &buf_mgmt.rx_samples, BLADE_NUM_BUFFERS,
306 BLADERF_FORMAT_SC16_Q11_META, BLADE_BUFFER_SIZE, NUM_TRANSFERS, (void *)this);
307
308 blade_check(bladerf_init_stream, &tx_stream, dev, gettxcb(txh), &buf_mgmt.tx_samples, BLADE_NUM_BUFFERS,
309 BLADERF_FORMAT_SC16_Q11_META, BLADE_BUFFER_SIZE, NUM_TRANSFERS, (void *)this);
310
311 for (unsigned int i = 0; i < BLADE_NUM_BUFFERS; i++) {
312 auto cur_buffer = reinterpret_cast<tx_buf_q_type::elem_t *>(buf_mgmt.tx_samples);
313 buf_mgmt.bufptrqueue.spsc_push(&cur_buffer[i]);
314 }
315
Ericb7253c62022-11-28 19:21:08 +0100316 return 0;
317 }
318
Ericb3157b92023-05-23 11:32:34 +0200319 void actually_enable_streams()
320 {
321 blade_check(bladerf_enable_module, dev, BLADERF_MODULE_RX, true);
322 usleep(1000);
323 blade_check(bladerf_enable_module, dev, BLADERF_MODULE_TX, true);
324 }
325
Ericb7253c62022-11-28 19:21:08 +0100326 bool tuneTx(double freq, size_t chan = 0)
327 {
Ericc0f0a612023-05-02 15:34:19 +0200328 if (txfreq_cache == freq)
329 return true;
Ericb7253c62022-11-28 19:21:08 +0100330 msleep(15);
331 blade_check(bladerf_set_frequency, dev, BLADERF_CHANNEL_TX(0), (bladerf_frequency)freq);
Ericc0f0a612023-05-02 15:34:19 +0200332 txfreq_cache = freq;
Ericb7253c62022-11-28 19:21:08 +0100333 msleep(15);
334 return true;
335 };
336 bool tuneRx(double freq, size_t chan = 0)
337 {
Ericc0f0a612023-05-02 15:34:19 +0200338 if (rxfreq_cache == freq)
339 return true;
Ericb7253c62022-11-28 19:21:08 +0100340 msleep(15);
341 blade_check(bladerf_set_frequency, dev, BLADERF_CHANNEL_RX(0), (bladerf_frequency)freq);
Ericc0f0a612023-05-02 15:34:19 +0200342 rxfreq_cache = freq;
Ericb7253c62022-11-28 19:21:08 +0100343 msleep(15);
344 return true;
345 };
346 bool tuneRxOffset(double offset, size_t chan = 0)
347 {
348 return true;
349 };
350
351 double setRxGain(double dB, size_t chan = 0)
352 {
353 rxgain = dB;
354 msleep(15);
355 blade_check(bladerf_set_gain, dev, BLADERF_CHANNEL_RX(0), (bladerf_gain)dB);
356 msleep(15);
357 return dB;
358 };
359 double setTxGain(double dB, size_t chan = 0)
360 {
361 txgain = dB;
362 msleep(15);
363 blade_check(bladerf_set_gain, dev, BLADERF_CHANNEL_TX(0), (bladerf_gain)dB);
364 msleep(15);
365 return dB;
366 };
367 int setPowerAttenuation(int atten, size_t chan = 0)
368 {
369 return atten;
370 };
371
372 static void check_timestamp(dev_buf_t *rcd)
373 {
374 static bool first = true;
375 static uint64_t last_ts;
376 if (first) {
377 first = false;
378 last_ts = rcd->m[0].ts;
379 } else if (last_ts + rcd->actual_samples_per_buffer() != rcd->m[0].ts) {
380 std::cerr << "RX Overrun!" << last_ts << " " << rcd->actual_samples_per_buffer() << " "
381 << last_ts + rcd->actual_samples_per_buffer() << " " << rcd->m[0].ts << std::endl;
382 last_ts = rcd->m[0].ts;
383 } else {
384 last_ts = rcd->m[0].ts;
385 }
386 }
387
388 bladerf_stream_cb getrxcb(bh_fn_t rxbh)
389 {
390 // C cb -> no capture!
391 static auto rxbhfn = rxbh;
392 return [](struct bladerf *dev, struct bladerf_stream *stream, struct bladerf_metadata *meta,
393 void *samples, size_t num_samples, void *user_data) -> void * {
394 // struct blade_hw *trx = (struct blade_hw *)user_data;
395 static int to_skip = 0;
396 dev_buf_t *rcd = (dev_buf_t *)samples;
397
Eric40978042023-05-23 10:59:58 +0200398 if (stop_lower_threads_flag)
Ericb7253c62022-11-28 19:21:08 +0100399 return BLADERF_STREAM_SHUTDOWN;
400
401 if (to_skip < 120) // prevents weird overflows on startup
402 to_skip++;
403 else {
404 check_timestamp(rcd);
405 rxbhfn(rcd);
406 }
407
408 return samples;
409 };
410 }
411 bladerf_stream_cb gettxcb(bh_fn_t txbh)
412 {
413 // C cb -> no capture!
414 static auto txbhfn = txbh;
415 return [](struct bladerf *dev, struct bladerf_stream *stream, struct bladerf_metadata *meta,
416 void *samples, size_t num_samples, void *user_data) -> void * {
417 struct blade_hw *trx = (struct blade_hw *)user_data;
418 auto ptr = reinterpret_cast<tx_buf_q_type::elem_t>(samples);
419
420 if (samples) // put buffer address back into queue, ready to be reused
421 trx->buf_mgmt.bufptrqueue.spsc_push(&ptr);
422
Eric40978042023-05-23 10:59:58 +0200423 if (stop_lower_threads_flag)
Ericb7253c62022-11-28 19:21:08 +0100424 return BLADERF_STREAM_SHUTDOWN;
425
426 return BLADERF_STREAM_NO_DATA;
427 };
428 }
429
430 auto get_rx_burst_handler_fn(bh_fn_t burst_handler)
431 {
Eric989fe752023-10-06 16:06:13 +0200432 using thist = decltype(this);
433 auto fn = [](void *args) -> void * {
434 thist t = reinterpret_cast<thist>(args);
Ericb3157b92023-05-23 11:32:34 +0200435 int status = 0;
Eric40978042023-05-23 10:59:58 +0200436 if (!stop_lower_threads_flag)
Eric989fe752023-10-06 16:06:13 +0200437 status = bladerf_stream(t->rx_stream, BLADERF_RX_X1);
Ericb7253c62022-11-28 19:21:08 +0100438 if (status < 0)
439 std::cerr << "rx stream error! " << bladerf_strerror(status) << std::endl;
440
441 return 0;
442 };
443 return fn;
444 }
445 auto get_tx_burst_handler_fn(bh_fn_t burst_handler)
446 {
Eric989fe752023-10-06 16:06:13 +0200447 using thist = decltype(this);
448 auto fn = [](void *args) -> void * {
449 thist t = reinterpret_cast<thist>(args);
Ericb3157b92023-05-23 11:32:34 +0200450 int status = 0;
Eric40978042023-05-23 10:59:58 +0200451 if (!stop_lower_threads_flag)
Eric989fe752023-10-06 16:06:13 +0200452 status = bladerf_stream(t->tx_stream, BLADERF_TX_X1);
Ericb7253c62022-11-28 19:21:08 +0100453 if (status < 0)
454 std::cerr << "rx stream error! " << bladerf_strerror(status) << std::endl;
455
456 return 0;
457 };
458 return fn;
459 }
460
461 void submit_burst_ts(blade_sample_type *buffer, int len, uint64_t ts)
462 {
Ericb7253c62022-11-28 19:21:08 +0100463 tx_buf_q_type::elem_t rcd;
464
Ericb3157b92023-05-23 11:32:34 +0200465 // exit by submitting a dummy buffer to assure the libbladerf stream mutex is happy (thread!)
466 if (!buffer) {
467 bladerf_submit_stream_buffer(tx_stream, (void *)BLADERF_STREAM_SHUTDOWN, 1000);
468 return;
469 }
470
471 //get empty bufer from list
Ericb7253c62022-11-28 19:21:08 +0100472 while (!buf_mgmt.bufptrqueue.spsc_pop(&rcd))
473 buf_mgmt.bufptrqueue.spsc_prep_pop();
474 assert(rcd != nullptr);
475
476 rcd->write_n_burst(buffer, len, ts + rxtxdelay); // blade xa4 specific delay!
477 blade_check(bladerf_submit_stream_buffer_nb, tx_stream, (void *)rcd);
478 }
479};