bladerf_lib.c 15.6 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"

41
42
43
44
45
/** @addtogroup _BLADERF_PHY_RF_INTERFACE_
 * @{
 */

//! Number of BladeRF devices 
46
int num_devices=0;
47

48
49
50
/*These items configure the underlying asynch stream used by the the sync interface. 
 */

51
52
53
54
/*! \brief BladeRF Init function (not used at the moment)
 * \param device RF frontend parameters set by application
 */
int trx_brf_init(openair0_device *device) {
55
56
57
  
}

58
59
60
/*! \brief get current timestamp
 *\param device the hardware to use 
 */
61
openair0_timestamp trx_get_timestamp(openair0_device *device) {
62
  int status;
63
64
  struct bladerf_metadata meta;
  brf_state_t *brf = (brf_state_t*)device->priv;
65
  
66
67
  if ((status=bladerf_get_timestamp(brf->dev, BLADERF_MODULE_TX, &meta.timestamp)) != 0) {
    fprintf(stderr,"Failed to get current RX timestamp: %s\n",bladerf_strerror(status));
68
  } else {
69
    printf("Current TX timestampe  0x%016"PRIx64"\n", meta.timestamp);
70
  }
71
  return meta.timestamp;
72
73
}

74
75
76
77
/*! \brief Start BladeRF
 *\param device the hardware to use 
 */
int trx_brf_start(openair0_device *device) {
78

79
  return 0;
80
81
}

82
83
84
/*! \brief Get BladeRF stats
 *\param device the hardware to use 
 */
navid's avatar
navid committed
85
86
87
88
89
static void trx_brf_stats(openair0_device *device){


}

90
91
92
93
94
95
96
/*! \brief Called to send samples to the BladeRF RF target
      @param device pointer to the device structure specific to the RF hardware target
      @param timestamp The timestamp at whicch the first sample MUST be sent 
      @param buff Buffer which holds the samples
      @param nsamps number of samples to be sent
      @param cc index of the component carrier
*/ 
navid's avatar
navid committed
97
static int trx_brf_write(openair0_device *device,openair0_timestamp ptimestamp, void **buff, int nsamps, int cc) {
98
  
navid's avatar
navid committed
99
  int status, i;
100
  brf_state_t *brf = (brf_state_t*)device->priv;
101
  /* BRF has only 1 rx/tx chaine : is it correct? */
102
103
  void *samples = (void*)buff[0];
  
navid's avatar
navid committed
104
105
106
107
108
109
110
111
  //brf->meta_tx.flags &= ~BLADERF_META_FLAG_TX_NOW;
  brf->meta_tx.flags = BLADERF_META_FLAG_TX_BURST_START | 
    BLADERF_META_FLAG_TX_NOW | 
                       BLADERF_META_FLAG_TX_BURST_END;

  brf->meta_tx.timestamp= (uint64_t) ptimestamp;

  status = bladerf_sync_tx(brf->dev, samples, (unsigned int) nsamps, &brf->meta_tx, 2*brf->tx_timeout_ms);
112
113
  
  if (status != 0) {
navid's avatar
navid committed
114
    fprintf(stderr,"Failed to TX sample: %s\n", bladerf_strerror(status));
115
    brf->num_tx_errors++;
116
    brf_error(status);
navid's avatar
navid committed
117
118
119
120
121
122
123
124
125
126
127
  } 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++;
  } 
  //    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++;
  
128

navid's avatar
navid committed
129
  return(0);
130
131
}

132
133
134
135
136
137
138
139
140
141
/*! \brief Receive samples from hardware.
 * Read \ref nsamps samples from each channel to buffers. buff[0] is the array for
 * the first channel. *ptimestamp is the time at which the first sample
 * was received.
 * \param device the hardware to use
 * \param[out] ptimestamp the time at which the first sample was received.
 * \param[out] buff An array of pointers to buffers for received samples. The buffers must be large enough to hold the number of samples \ref nsamps.
 * \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte.
 * \param cc  Index of component carrier
*/
142
static int trx_brf_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
143
  int status, ret;
144
  
145
  unsigned int i;
146
147
148
149
  brf_state_t *brf = (brf_state_t*)device->priv;
  
  // BRF has only one rx/tx chain
  void *samples = (void*)buff[0];
navid's avatar
navid committed
150
 
151
  brf->meta_rx.flags |= BLADERF_META_FLAG_RX_NOW;
navid's avatar
navid committed
152
  status = bladerf_sync_rx(brf->dev, samples, (unsigned int) nsamps, &brf->meta_rx, 2*brf->rx_timeout_ms);
153
154
  
  if (status != 0) {
155
156
157
158
    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++;
navid's avatar
navid committed
159
    fprintf(stderr, "RX overrun (%d) is detected. t=0x%"PRIu64". Got %u samples. nsymps %d\n", 
160
161
	    brf->num_overflows,brf->meta_rx.timestamp,  brf->meta_rx.actual_count, nsamps);
    //brf->meta_rx.timestamp=(unsigned int)(nsamps-brf->meta_rx.actual_count);
navid's avatar
navid committed
162
163
164
165
166
167
168
  }
  //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++;
  
169
170
171
172
  
  *ptimestamp = brf->meta_rx.timestamp;
  
  return brf->meta_rx.actual_count;
173
174
175

}

176
177
178
/*! \brief Terminate operation of the BladeRF transceiver -- free all associated resources 
 * \param device the hardware to use
 */
179
180
181
int trx_brf_end(openair0_device *device) {

  int status;
182
  brf_state_t *brf = (brf_state_t*)device->priv;
183
  // Disable RX module, shutting down our underlying RX stream
184
  if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_RX, false))  != 0) {
185
186
    fprintf(stderr, "Failed to disable RX module: %s\n", bladerf_strerror(status));
  }
187
  if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_TX, false))  != 0) {
188
189
    fprintf(stderr, "Failed to disable TX module: %s\n",  bladerf_strerror(status));
  }
190
  bladerf_close(brf->dev);
191
192
193
  return 0;
}

194
195
196
197
/*! \brief print the BladeRF statistics  
* \param device the hardware to use
* \returns  0 on success
*/
198
199
200
201
202
203
int trx_brf_get_stats(openair0_device* device) {

  return(0);

}

204
205
206
207
/*! \brief Reset the BladeRF statistics  
* \param device the hardware to use
* \returns  0 on success
*/
208
209
210
211
212
213
int trx_brf_reset_stats(openair0_device* device) {

  return(0);

}

214
215
216
/*! \brief Stop USRP
 * \param device the hardware to use
 */
217
218
219
220
221
222
int trx_brf_stop(openair0_device* device) {

  return(0);

}

223
224
225
226
/*! \brief Set frequencies (TX/RX)
 * \param device the hardware to use
 * \returns 0 in success 
 */
227
228
229
230
231
int trx_brf_set_freq(openair0_device* device) {

  return(0);

}
232
233
234
235
236

/*! \brief Set Gains (TX/RX)
 * \param device the hardware to use
 * \returns 0 in success 
 */
237
238
239
240
241
242
int trx_brf_set_gains(openair0_device* device) {

  return(0);

}

243
244
245
246
/*! \brief Initialize Openair BLADERF target. It returns 0 if OK 
 * \param device the hardware to use
 * \param openair0_cfg RF frontend parameters set by application
 */
navid's avatar
navid committed
247
int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg) {
248
249
250
251

  int status;
  int card=0;
  
252
253
  brf_state_t *brf = (brf_state_t*)malloc(sizeof(brf_state_t));
  memset(brf, 0, sizeof(brf_state_t));
nikaeinn's avatar
nikaeinn committed
254
  // init required params for BRF
navid's avatar
navid committed
255
256
257
258
259
   brf->num_buffers   = 128;
   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;
260
   brf->sample_rate=(unsigned int)openair0_cfg[card].sample_rate;
navid's avatar
navid committed
261

262
   
navid's avatar
navid committed
263
264
   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);
265
266

  if ((status=bladerf_open(&brf->dev, "")) != 0 ) {
267
268
269
    fprintf(stderr,"Failed to open brf device: %s\n",bladerf_strerror(status));
    brf_error(status);
  }
270
271
272
273
274
275
276
277
278
  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);
  }
279
  // RX
280
281
  // Example of CLI output: RX Frequency: 2539999999Hz
  
282
  if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg[card].rx_freq[0])) != 0){
283
284
    fprintf(stderr,"Failed to set RX frequency: %s\n",bladerf_strerror(status));
    brf_error(status);
285
286
287
288
289
  } else 
    printf("[BRF] set RX frequency to %f\n",openair0_cfg[card].rx_freq[0]);
  
 
  if ((status=bladerf_set_sample_rate(brf->dev, BLADERF_MODULE_RX, (unsigned int)openair0_cfg[card].sample_rate, NULL)) != 0){
290
291
    fprintf(stderr,"Failed to set RX sample rate: %s\n", bladerf_strerror(status));
    brf_error(status);
292
293
294
295
  }else 
    printf("[BRF] set RX sample rate to %f\n",openair0_cfg[card].sample_rate);
 
  if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg[card].rx_bw, NULL)) != 0){
296
297
    fprintf(stderr,"Failed to set RX bandwidth: %s\n", bladerf_strerror(status));
    brf_error(status);
298
299
300
301
  }else 
    printf("[BRF] set RX bandwidth to %f\n",openair0_cfg[card].rx_bw);
 
  if ((status=bladerf_set_gain(brf->dev, BLADERF_MODULE_RX, (int) openair0_cfg[card].rx_gain[0])) != 0) {
302
303
    fprintf(stderr,"Failed to set RX gain: %s\n",bladerf_strerror(status));
    brf_error(status);
304
305
  } else 
    printf("[BRF] set RX gain to %f\n",openair0_cfg[card].rx_gain[0]);
306
307
308

  /* Configure the device's RX module for use with the sync interface.
   * SC16 Q11 samples *with* metadata are used. */
navid's avatar
navid committed
309
  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 ) {
310
311
    fprintf(stderr,"Failed to configure RX sync interface: %s\n", bladerf_strerror(status));
     brf_error(status);
312
313
314
  }else 
    printf("[BRF] configured Rx for sync interface \n");
  
315
316
   /* We must always enable the RX module after calling bladerf_sync_config(), and 
    * before  attempting to RX samples via  bladerf_sync_rx(). */
317
  if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_RX, true)) != 0) {
318
319
    fprintf(stderr,"Failed to enable RX module: %s\n", bladerf_strerror(status));
    brf_error(status);
320
321
322
  }else 
    printf("[BRF] RX module enabled \n");
  
323
  // TX
324
  if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_TX, (unsigned int) openair0_cfg[card].tx_freq[0])) != 0){
325
326
    fprintf(stderr,"Failed to set TX frequency: %s\n",bladerf_strerror(status));
    brf_error(status);
327
328
329
330
  }else 
    printf("[BRF] set Tx Frequenct to %f \n", openair0_cfg[card].tx_freq[0]);

  if ((status=bladerf_set_sample_rate(brf->dev, BLADERF_MODULE_TX, (unsigned int) openair0_cfg[card].sample_rate, NULL)) != 0){
331
332
    fprintf(stderr,"Failed to set TX sample rate: %s\n", bladerf_strerror(status));
    brf_error(status);
333
334
335
336
  }else 
    printf("[BRF] set Tx sampling rate to %f \n", openair0_cfg[card].sample_rate);

  if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_TX,(unsigned int)openair0_cfg[card].tx_bw, NULL)) != 0){
337
338
    fprintf(stderr, "Failed to set RX bandwidth: %s\n", bladerf_strerror(status));
    brf_error(status);
339
340
341
342
  }else 
    printf("[BRF] set Tx sampling ratebandwidth to %f \n", openair0_cfg[card].tx_bw);

  if ((status=bladerf_set_gain(brf->dev, BLADERF_MODULE_TX, (int)openair0_cfg[card].tx_gain[0])) != 0) {
343
344
    fprintf(stderr,"Failed to set TX gain: %s\n",bladerf_strerror(status));
    brf_error(status);
345
346
347
  }else 
    printf("[BRF] set the Tx gain to %f \n", openair0_cfg[card].tx_gain[0]);

348
349
350

  /* Configure the device's TX module for use with the sync interface.
   * SC16 Q11 samples *with* metadata are used. */
navid's avatar
navid committed
351
  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 ) {
352
353
    fprintf(stderr,"Failed to configure TX sync interface: %s\n", bladerf_strerror(status));
     brf_error(status);
354
355
  }else 
    printf("[BRF] configured tx for sync interface \n");
356
357
358

   /* We must always enable the TX module after calling bladerf_sync_config(), and 
    * before  attempting to TX samples via  bladerf_sync_tx(). */
359
  if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_TX, true)) != 0) {
360
361
    fprintf(stderr,"Failed to enable TX module: %s\n", bladerf_strerror(status));
    brf_error(status);
362
  } else 
navid's avatar
navid committed
363
    printf("[BRF] TX module enabled \n");
nikaeinn's avatar
nikaeinn committed
364
 
365
366
367
  bladerf_log_set_verbosity(get_brf_log_level(openair0_cfg[card].log_level));
  
  printf("BLADERF: Initializing openair0_device\n");
368
  device->priv           = brf; 
369
370
371
372
373
  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;
374
375
376
377
378
  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;
379
  memcpy((void*)&device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t));
380
381

  return 0;
382
383
}

384
385
386
/*! \brief bladeRF error report 
 * \param status 
 */
387
int brf_error(int status) {
388
  
navid's avatar
navid committed
389
  //exit(-1);
390
  //return 1; // or status error code
391
392
}

393

394
395
396
/*! \brief Open BladeRF from serial port
 * \param serial name of serial port on which to open BladeRF device
 */
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
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;
  }
}
423
424
425
426

/*! \brief Get BladeRF log level
 * \param log_level log level
 */
427
428
429
int get_brf_log_level(int log_level){

  int level=BLADERF_LOG_LEVEL_INFO;
navid's avatar
navid committed
430
  //return  BLADERF_LOG_LEVEL_DEBUG;
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
  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;
}
455
/*@}*/