bladerf_lib.c 14.9 KB
Newer Older
nikaeinn's avatar
nikaeinn committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*******************************************************************************
    OpenAirInterface 
    Copyright(c) 1999 - 2014 Eurecom

    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.


    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is 
    included in this distribution in the file called "COPYING". If not, 
    see <http://www.gnu.org/licenses/>.

   Contact Information
   OpenAirInterface Admin: openair_admin@eurecom.fr
   OpenAirInterface Tech : openair_tech@eurecom.fr
24
   OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
nikaeinn's avatar
nikaeinn committed
25
26
27
28
29
30
31
32
33
  
   Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE

 *******************************************************************************/

/** bladerf_lib.c
 *
 * Author: navid nikaein
 */
34
35
36
37
38
39
40


#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include "bladerf_lib.h"

nikaeinn's avatar
nikaeinn committed
41
42
43
44
45
46
47
48
#ifdef __SSE4_1__
#  include <smmintrin.h>
#endif
 
#ifdef __AVX2__
#  include <immintrin.h>
#endif

49
50
51
52
53
54
55
56
int num_devices=0;
/*These items configure the underlying asynch stream used by the the sync interface. 
 */

int trx_brf_init(openair0_device *openair0) {
  
}

57
 
nikaeinn's avatar
nikaeinn committed
58
openair0_timestamp trx_get_timestamp(openair0_device *device, bladerf_module module) {
59
  int status;
60
61
  struct bladerf_metadata meta;
  brf_state_t *brf = (brf_state_t*)device->priv;
nikaeinn's avatar
nikaeinn committed
62
  memset(&meta, 0, sizeof(meta));
63
  
nikaeinn's avatar
nikaeinn committed
64
65
66
67
68
  if ((status=bladerf_get_timestamp(brf->dev, module, &meta.timestamp)) != 0) {
    fprintf(stderr,"Failed to get current %s timestamp: %s\n",(module == BLADERF_MODULE_RX ) ? "RX" : "TX", bladerf_strerror(status));
    return -1; 
  } // else {printf("Current RX timestampe  0x%016"PRIx64"\n", meta.timestamp); }

69
  return meta.timestamp;
70
71
72
73
74
}


int trx_brf_start(openair0_device *openair0) {

75
  return 0;
76
77
}

navid's avatar
navid committed
78
79
80
81
82
83
static void trx_brf_stats(openair0_device *device){


}

static int trx_brf_write(openair0_device *device,openair0_timestamp ptimestamp, void **buff, int nsamps, int cc) {
84
  
nikaeinn's avatar
nikaeinn committed
85
  int status;
86
  brf_state_t *brf = (brf_state_t*)device->priv;
87
  /* BRF has only 1 rx/tx chaine : is it correct? */
nikaeinn's avatar
nikaeinn committed
88
  int16_t *samples = (int16_t*)buff[0];
89
  
nikaeinn's avatar
nikaeinn committed
90
91
92
93
94
95
96
  //memset(&brf->meta_tx, 0, sizeof(brf->meta_tx));
  // When  BLADERF_META_FLAG_TX_NOW is used the timestamp is not used, so one can't schedule a tx 
  if (brf->meta_tx.flags == 0 ) 
    brf->meta_tx.flags = (BLADERF_META_FLAG_TX_BURST_START);// | BLADERF_META_FLAG_TX_BURST_END);// |  BLADERF_META_FLAG_TX_NOW);
  
  
  brf->meta_tx.timestamp= (uint64_t) (ptimestamp); 
navid's avatar
navid committed
97
  status = bladerf_sync_tx(brf->dev, samples, (unsigned int) nsamps, &brf->meta_tx, 2*brf->tx_timeout_ms);
nikaeinn's avatar
nikaeinn committed
98
99
100
 
  if (brf->meta_tx.flags == BLADERF_META_FLAG_TX_BURST_START) 
    brf->meta_tx.flags =  BLADERF_META_FLAG_TX_UPDATE_TIMESTAMP;
101
  
nikaeinn's avatar
nikaeinn committed
102

103
  if (status != 0) {
nikaeinn's avatar
nikaeinn committed
104
    //fprintf(stderr,"Failed to TX sample: %s\n", bladerf_strerror(status));
105
    brf->num_tx_errors++;
106
    brf_error(status);
navid's avatar
navid committed
107
108
109
110
111
  } else if (brf->meta_tx.status & BLADERF_META_STATUS_UNDERRUN){
    /* libbladeRF does not report this status. It is here for future use. */ 
    fprintf(stderr, "TX Underrun detected. %u valid samples were read.\n",  brf->meta_tx.actual_count);
    brf->num_underflows++;
  } 
nikaeinn's avatar
nikaeinn committed
112
113
  //printf("Provided TX timestampe  %u, meta timestame %u\n", ptimestamp,brf->meta_tx.timestamp);
  
navid's avatar
navid committed
114
115
116
117
118
119
  //    printf("tx status %d \n",brf->meta_tx.status);
  brf->tx_current_ts=brf->meta_tx.timestamp;
  brf->tx_actual_nsamps+=brf->meta_tx.actual_count;
  brf->tx_nsamps+=nsamps;
  brf->tx_count++;
  
120

navid's avatar
navid committed
121
  return(0);
122
123
}

124
static int trx_brf_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
nikaeinn's avatar
nikaeinn committed
125
126

  int status=0;
127
128
129
  brf_state_t *brf = (brf_state_t*)device->priv;
  
  // BRF has only one rx/tx chain
nikaeinn's avatar
nikaeinn committed
130
131
132
  int16_t *samples = (int16_t*)buff[0];
  
  brf->meta_rx.flags = BLADERF_META_FLAG_RX_NOW;
navid's avatar
navid committed
133
  status = bladerf_sync_rx(brf->dev, samples, (unsigned int) nsamps, &brf->meta_rx, 2*brf->rx_timeout_ms);
134
  
nikaeinn's avatar
nikaeinn committed
135
136
  //printf("Current RX timestampe  %u, nsamps %u, actual %u, cc %d\n",  brf->meta_rx.timestamp, nsamps, brf->meta_rx.actual_count, cc);
   
137
  if (status != 0) {
138
139
140
141
    fprintf(stderr, "RX failed: %s\n", bladerf_strerror(status)); 
    brf->num_rx_errors++;
  } else if ( brf->meta_rx.status & BLADERF_META_STATUS_OVERRUN) {
    brf->num_overflows++;
nikaeinn's avatar
nikaeinn committed
142
    fprintf(stderr, "RX overrun (%d) is detected. t=%u. Got %u samples. nsymps %d\n", 
143
	    brf->num_overflows,brf->meta_rx.timestamp,  brf->meta_rx.actual_count, nsamps);
nikaeinn's avatar
nikaeinn committed
144
145
  } 
  //printf("Current RX timestampe  %u\n",  brf->meta_rx.timestamp);
navid's avatar
navid committed
146
147
148
149
150
151
  //printf("[BRF] (buff %p) ts=0x%"PRIu64" %s\n",samples, brf->meta_rx.timestamp,bladerf_strerror(status));
  brf->rx_current_ts=brf->meta_rx.timestamp;
  brf->rx_actual_nsamps+=brf->meta_rx.actual_count;
  brf->rx_nsamps+=nsamps;
  brf->rx_count++;
  
152
153
  
  *ptimestamp = brf->meta_rx.timestamp;
nikaeinn's avatar
nikaeinn committed
154
 
155
  return brf->meta_rx.actual_count;
156
157
158
159
160
161

}

int trx_brf_end(openair0_device *device) {

  int status;
162
  brf_state_t *brf = (brf_state_t*)device->priv;
163
  // Disable RX module, shutting down our underlying RX stream
164
  if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_RX, false))  != 0) {
165
166
    fprintf(stderr, "Failed to disable RX module: %s\n", bladerf_strerror(status));
  }
167
  if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_TX, false))  != 0) {
168
169
    fprintf(stderr, "Failed to disable TX module: %s\n",  bladerf_strerror(status));
  }
170
  bladerf_close(brf->dev);
171
172
173
  return 0;
}

174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203

int trx_brf_get_stats(openair0_device* device) {

  return(0);

}

int trx_brf_reset_stats(openair0_device* device) {

  return(0);

}

int trx_brf_stop(openair0_device* device) {

  return(0);

}

int trx_brf_set_freq(openair0_device* device) {

  return(0);

}
int trx_brf_set_gains(openair0_device* device) {

  return(0);

}

navid's avatar
navid committed
204
int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg) {
205
206
207
208

  int status;
  int card=0;
  
209
210
  brf_state_t *brf = (brf_state_t*)malloc(sizeof(brf_state_t));
  memset(brf, 0, sizeof(brf_state_t));
211
212
  // init required params for [97448.145250] lte-softmodem-n[20648]: segfault at 0 ip           (null) sp 00007fff220167b8 error 14 in lte-softmodem-nos1[400000+3bc000]

nikaeinn's avatar
nikaeinn committed
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
  //  The number of buffers to use in the underlying data stream
  brf->num_buffers   = 128;
  // the size of the underlying stream buffers, in samples
  brf->buffer_size   = (unsigned int) openair0_cfg[card].samples_per_packet;//*sizeof(int32_t); // buffer size = 4096 for sample_len of 1024
  brf->num_transfers = 16;
  brf->rx_timeout_ms = 0;  
  brf->tx_timeout_ms = 0;
  brf->sample_rate=(unsigned int)openair0_cfg[card].sample_rate;

  memset(&brf->meta_rx, 0, sizeof(brf->meta_rx));
  memset(&brf->meta_tx, 0, sizeof(brf->meta_tx));

  printf("\n[BRF] sampling_rate %d, num_buffers %d,  buffer_size %d, num transfer %d, timeout_ms (rx %d, tx %d)\n", 
	 brf->sample_rate, brf->num_buffers, brf->buffer_size,brf->num_transfers, brf->rx_timeout_ms, brf->tx_timeout_ms);
  
228
  if ((status=bladerf_open(&brf->dev, "")) != 0 ) {
229
230
231
    fprintf(stderr,"Failed to open brf device: %s\n",bladerf_strerror(status));
    brf_error(status);
  }
232
233
234
235
236
237
238
239
240
  printf("[BRF] init dev %p\n", brf->dev);
  switch(bladerf_device_speed(brf->dev)){
  case BLADERF_DEVICE_SPEED_SUPER:
    printf("[BRF] Device operates at max speed\n");
    break;
  default:
    printf("[BRF] Device does not operates at max speed, change the USB port\n");
    brf_error(BLADERF_ERR_UNSUPPORTED);
  }
nikaeinn's avatar
nikaeinn committed
241
  // RX  
242
243
  // Example of CLI output: RX Frequency: 2539999999Hz
  
244
  if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg[card].rx_freq[0])) != 0){
245
246
    fprintf(stderr,"Failed to set RX frequency: %s\n",bladerf_strerror(status));
    brf_error(status);
247
  } else 
nikaeinn's avatar
nikaeinn committed
248
    printf("[BRF] set RX frequency to %u\n",(unsigned int)openair0_cfg[card].rx_freq[0]);
249
  
nikaeinn's avatar
nikaeinn committed
250
251
  unsigned int actual_value=0;
  if ((status=bladerf_set_sample_rate(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg[card].sample_rate, &actual_value)) != 0){
252
253
    fprintf(stderr,"Failed to set RX sample rate: %s\n", bladerf_strerror(status));
    brf_error(status);
nikaeinn's avatar
nikaeinn committed
254
255
  }else  
    printf("[BRF] set RX sample rate to %u, %u\n", (unsigned int) openair0_cfg[card].sample_rate, actual_value);
256
 
nikaeinn's avatar
nikaeinn committed
257

258
  if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg[card].rx_bw*2, &actual_value)) != 0){
259
260
    fprintf(stderr,"Failed to set RX bandwidth: %s\n", bladerf_strerror(status));
    brf_error(status);
261
  }else 
262
    printf("[BRF] set RX bandwidth to %u, %u\n",(unsigned int)openair0_cfg[card].rx_bw*2, actual_value);
263
264
 
  if ((status=bladerf_set_gain(brf->dev, BLADERF_MODULE_RX, (int) openair0_cfg[card].rx_gain[0])) != 0) {
265
266
    fprintf(stderr,"Failed to set RX gain: %s\n",bladerf_strerror(status));
    brf_error(status);
267
  } else 
nikaeinn's avatar
nikaeinn committed
268
    printf("[BRF] set RX gain to %d\n",(int)openair0_cfg[card].rx_gain[0]);
269
270

  // TX
nikaeinn's avatar
nikaeinn committed
271
  
272
  if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_TX, (unsigned int) openair0_cfg[card].tx_freq[0])) != 0){
273
274
    fprintf(stderr,"Failed to set TX frequency: %s\n",bladerf_strerror(status));
    brf_error(status);
275
  }else 
nikaeinn's avatar
nikaeinn committed
276
    printf("[BRF] set TX Frequenct to %u\n", (unsigned int) openair0_cfg[card].tx_freq[0]);
277
278

  if ((status=bladerf_set_sample_rate(brf->dev, BLADERF_MODULE_TX, (unsigned int) openair0_cfg[card].sample_rate, NULL)) != 0){
279
280
    fprintf(stderr,"Failed to set TX sample rate: %s\n", bladerf_strerror(status));
    brf_error(status);
281
  }else 
nikaeinn's avatar
nikaeinn committed
282
    printf("[BRF] set TX sampling rate to %u \n", (unsigned int) openair0_cfg[card].sample_rate);
283

284
  if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_TX,(unsigned int)openair0_cfg[card].tx_bw*2, NULL)) != 0){
nikaeinn's avatar
nikaeinn committed
285
    fprintf(stderr, "Failed to set TX bandwidth: %s\n", bladerf_strerror(status));
286
    brf_error(status);
287
  }else 
288
    printf("[BRF] set TX bandwidth to %u \n", (unsigned int) openair0_cfg[card].tx_bw*2);
289

nikaeinn's avatar
nikaeinn committed
290
  if ((status=bladerf_set_gain(brf->dev, BLADERF_MODULE_TX, (int) openair0_cfg[card].tx_gain[0])) != 0) {
291
292
    fprintf(stderr,"Failed to set TX gain: %s\n",bladerf_strerror(status));
    brf_error(status);
293
  }else 
nikaeinn's avatar
nikaeinn committed
294
295
    printf("[BRF] set the TX gain to %d\n", (int)openair0_cfg[card].tx_gain[0]);
  
296

nikaeinn's avatar
nikaeinn committed
297
 /* Configure the device's TX module for use with the sync interface.
298
   * SC16 Q11 samples *with* metadata are used. */
navid's avatar
navid committed
299
  if ((status=bladerf_sync_config(brf->dev, BLADERF_MODULE_TX,BLADERF_FORMAT_SC16_Q11_META,brf->num_buffers,brf->buffer_size,brf->num_transfers,brf->tx_timeout_ms)) != 0 ) {
300
301
    fprintf(stderr,"Failed to configure TX sync interface: %s\n", bladerf_strerror(status));
     brf_error(status);
302
  }else 
nikaeinn's avatar
nikaeinn committed
303
304
305
306
307
308
309
310
311
312
    printf("[BRF] configured TX  sync interface \n");

/* Configure the device's RX module for use with the sync interface.
   * SC16 Q11 samples *with* metadata are used. */
  if ((status=bladerf_sync_config(brf->dev, BLADERF_MODULE_RX, BLADERF_FORMAT_SC16_Q11_META,brf->num_buffers,brf->buffer_size,brf->num_transfers,brf->rx_timeout_ms)) != 0 ) {
    fprintf(stderr,"Failed to configure RX sync interface: %s\n", bladerf_strerror(status));
    brf_error(status);
  }else 
    printf("[BRF] configured Rx sync interface \n");

313
314
315

   /* We must always enable the TX module after calling bladerf_sync_config(), and 
    * before  attempting to TX samples via  bladerf_sync_tx(). */
316
  if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_TX, true)) != 0) {
317
318
    fprintf(stderr,"Failed to enable TX module: %s\n", bladerf_strerror(status));
    brf_error(status);
319
  } else 
navid's avatar
navid committed
320
    printf("[BRF] TX module enabled \n");
nikaeinn's avatar
nikaeinn committed
321
 
nikaeinn's avatar
nikaeinn committed
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
 /* We must always enable the RX module after calling bladerf_sync_config(), and 
    * before  attempting to RX samples via  bladerf_sync_rx(). */
  if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_RX, true)) != 0) {
    fprintf(stderr,"Failed to enable RX module: %s\n", bladerf_strerror(status));
    brf_error(status);
  }else 
    printf("[BRF] RX module enabled \n");

  // calibrate 
  /*  
 if ((status=bladerf_calibrate_dc(brf->dev, BLADERF_MODULE_TX)) != 0) {
    fprintf(stderr,"Failed to calibrate TX DC: %s\n", bladerf_strerror(status));
    brf_error(status);
  } else 
    printf("[BRF] TX module calibrated DC \n");
 
  if ((status=bladerf_calibrate_dc(brf->dev, BLADERF_MODULE_RX)) != 0) {
    fprintf(stderr,"Failed to calibrate RX DC: %s\n", bladerf_strerror(status));
    brf_error(status);
  }else 
    printf("[BRF] RX module calibrated DC \n");
  */

345
346
347
  bladerf_log_set_verbosity(get_brf_log_level(openair0_cfg[card].log_level));
  
  printf("BLADERF: Initializing openair0_device\n");
348
  device->priv           = brf; 
349
350
351
352
353
  device->Mod_id         = num_devices++;
  device->trx_start_func = trx_brf_start;
  device->trx_end_func   = trx_brf_end;
  device->trx_read_func  = trx_brf_read;
  device->trx_write_func = trx_brf_write;
354
355
356
357
358
  device->trx_get_stats_func   = trx_brf_get_stats;
  device->trx_reset_stats_func = trx_brf_reset_stats;
  device->trx_stop_func        = trx_brf_stop;
  device->trx_set_freq_func    = trx_brf_set_freq;
  device->trx_set_gains_func   = trx_brf_set_gains;
359
  memcpy((void*)&device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t));
360
361

  return 0;
362
363
}

364
int brf_error(int status) {
365
  
navid's avatar
navid committed
366
  //exit(-1);
367
  //return 1; // or status error code
368
369
}

370

371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397

struct bladerf * open_bladerf_from_serial(const char *serial) {

  int status;
  struct bladerf *dev;
  struct bladerf_devinfo info;
  /* Initialize all fields to "don't care" wildcard values.
   *
   * Immediately passing this to bladerf_open_with_devinfo() would cause
   * libbladeRF to open any device on any available backend. */
  bladerf_init_devinfo(&info);
  /* Specify the desired device's serial number, while leaving all other
   * fields in the info structure wildcard values */
  strncpy(info.serial, serial, BLADERF_SERIAL_LENGTH - 1);
  info.serial[BLADERF_SERIAL_LENGTH - 1] = '\0';
  status = bladerf_open_with_devinfo(&dev, &info);
  
  if (status == BLADERF_ERR_NODEV) {
    printf("No devices available with serial=%s\n", serial);
    return NULL;
  } else if (status != 0) {
    fprintf(stderr, "Failed to open device with serial=%s (%s)\n", serial, bladerf_strerror(status));
    return NULL;
  } else {
    return dev;
  }
}
398
399
400
int get_brf_log_level(int log_level){

  int level=BLADERF_LOG_LEVEL_INFO;
nikaeinn's avatar
nikaeinn committed
401
  return  BLADERF_LOG_LEVEL_DEBUG; // BLADERF_LOG_LEVEL_VERBOSE;// BLADERF_LOG_LEVEL_DEBUG; //
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
  switch(log_level) {
  case LOG_DEBUG:
    level=BLADERF_LOG_LEVEL_DEBUG;
    break;
  case LOG_INFO:
    level= BLADERF_LOG_LEVEL_INFO;
    break;
  case LOG_WARNING:
    level=BLADERF_LOG_LEVEL_WARNING;
    break;
  case LOG_ERR:
    level=BLADERF_LOG_LEVEL_ERROR;
    break;
  case LOG_CRIT:
    level=BLADERF_LOG_LEVEL_CRITICAL;
    break;
  case LOG_EMERG:
    level = BLADERF_LOG_LEVEL_SILENT;
    break;
  default:
    break;
  }
  return level;
}