bladerf_lib.c 13.9 KB
Newer Older
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
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 41 42 43 44 45 46 47 48


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

int num_devices=0;
/*These items configure the underlying asynch stream used by the the sync interface. 
 */

int trx_brf_init(openair0_device *openair0) {
  
}

49 50
 
openair0_timestamp trx_get_timestamp(openair0_device *device) {
51
  int status;
52 53
  struct bladerf_metadata meta;
  brf_state_t *brf = (brf_state_t*)device->priv;
54
  
55 56
  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));
57
  } else {
58
    printf("Current TX timestampe  0x%016"PRIx64"\n", meta.timestamp);
59
  }
60
  return meta.timestamp;
61 62 63 64 65
}


int trx_brf_start(openair0_device *openair0) {

66
  return 0;
67 68
}

navid's avatar
navid committed
69 70 71 72 73 74
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) {
75
  
navid's avatar
navid committed
76
  int status, i;
77
  brf_state_t *brf = (brf_state_t*)device->priv;
78
  /* BRF has only 1 rx/tx chaine : is it correct? */
79 80
  void *samples = (void*)buff[0];
  
navid's avatar
navid committed
81 82 83 84 85 86 87 88
  //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);
89 90
  
  if (status != 0) {
navid's avatar
navid committed
91
    fprintf(stderr,"Failed to TX sample: %s\n", bladerf_strerror(status));
92
    brf->num_tx_errors++;
93
    brf_error(status);
navid's avatar
navid committed
94 95 96 97 98 99 100 101 102 103 104
  } 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++;
  
105

navid's avatar
navid committed
106
  return(0);
107 108
}

109
static int trx_brf_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
110
  int status, ret;
111
  
112
  unsigned int i;
113 114 115 116
  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
117
 
118
  brf->meta_rx.flags |= BLADERF_META_FLAG_RX_NOW;
navid's avatar
navid committed
119
  status = bladerf_sync_rx(brf->dev, samples, (unsigned int) nsamps, &brf->meta_rx, 2*brf->rx_timeout_ms);
120 121
  
  if (status != 0) {
122 123 124 125
    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
126
    fprintf(stderr, "RX overrun (%d) is detected. t=0x%"PRIu64". Got %u samples. nsymps %d\n", 
127 128
	    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
129 130 131 132 133 134 135
  }
  //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++;
  
136 137 138 139
  
  *ptimestamp = brf->meta_rx.timestamp;
  
  return brf->meta_rx.actual_count;
140 141 142 143 144 145

}

int trx_brf_end(openair0_device *device) {

  int status;
146
  brf_state_t *brf = (brf_state_t*)device->priv;
147
  // Disable RX module, shutting down our underlying RX stream
148
  if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_RX, false))  != 0) {
149 150
    fprintf(stderr, "Failed to disable RX module: %s\n", bladerf_strerror(status));
  }
151
  if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_TX, false))  != 0) {
152 153
    fprintf(stderr, "Failed to disable TX module: %s\n",  bladerf_strerror(status));
  }
154
  bladerf_close(brf->dev);
155 156 157
  return 0;
}

158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187

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);

}

188
int device_init(openair0_device *device, openair0_config_t *openair0_cfg, char *cfgfile) {
189 190 191 192

  int status;
  int card=0;
  
193 194
  brf_state_t *brf = (brf_state_t*)malloc(sizeof(brf_state_t));
  memset(brf, 0, sizeof(brf_state_t));
195
  // init required params for BRF
navid's avatar
navid committed
196 197 198 199 200
   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;
201
   brf->sample_rate=(unsigned int)openair0_cfg[card].sample_rate;
navid's avatar
navid committed
202

203
   
navid's avatar
navid committed
204 205
   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);
206 207

  if ((status=bladerf_open(&brf->dev, "")) != 0 ) {
208 209 210
    fprintf(stderr,"Failed to open brf device: %s\n",bladerf_strerror(status));
    brf_error(status);
  }
211 212 213 214 215 216 217 218 219
  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);
  }
220
  // RX
221 222
  // Example of CLI output: RX Frequency: 2539999999Hz
  
223
  if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg[card].rx_freq[0])) != 0){
224 225
    fprintf(stderr,"Failed to set RX frequency: %s\n",bladerf_strerror(status));
    brf_error(status);
226 227 228 229 230
  } 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){
231 232
    fprintf(stderr,"Failed to set RX sample rate: %s\n", bladerf_strerror(status));
    brf_error(status);
233 234 235 236
  }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){
237 238
    fprintf(stderr,"Failed to set RX bandwidth: %s\n", bladerf_strerror(status));
    brf_error(status);
239 240 241 242
  }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) {
243 244
    fprintf(stderr,"Failed to set RX gain: %s\n",bladerf_strerror(status));
    brf_error(status);
245 246
  } else 
    printf("[BRF] set RX gain to %f\n",openair0_cfg[card].rx_gain[0]);
247 248 249

  /* Configure the device's RX module for use with the sync interface.
   * SC16 Q11 samples *with* metadata are used. */
navid's avatar
navid committed
250
  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 ) {
251 252
    fprintf(stderr,"Failed to configure RX sync interface: %s\n", bladerf_strerror(status));
     brf_error(status);
253 254 255
  }else 
    printf("[BRF] configured Rx for sync interface \n");
  
256 257
   /* We must always enable the RX module after calling bladerf_sync_config(), and 
    * before  attempting to RX samples via  bladerf_sync_rx(). */
258
  if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_RX, true)) != 0) {
259 260
    fprintf(stderr,"Failed to enable RX module: %s\n", bladerf_strerror(status));
    brf_error(status);
261 262 263
  }else 
    printf("[BRF] RX module enabled \n");
  
264
  // TX
265
  if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_TX, (unsigned int) openair0_cfg[card].tx_freq[0])) != 0){
266 267
    fprintf(stderr,"Failed to set TX frequency: %s\n",bladerf_strerror(status));
    brf_error(status);
268 269 270 271
  }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){
272 273
    fprintf(stderr,"Failed to set TX sample rate: %s\n", bladerf_strerror(status));
    brf_error(status);
274 275 276 277
  }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){
278 279
    fprintf(stderr, "Failed to set RX bandwidth: %s\n", bladerf_strerror(status));
    brf_error(status);
280 281 282 283
  }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) {
284 285
    fprintf(stderr,"Failed to set TX gain: %s\n",bladerf_strerror(status));
    brf_error(status);
286 287 288
  }else 
    printf("[BRF] set the Tx gain to %f \n", openair0_cfg[card].tx_gain[0]);

289 290 291

  /* Configure the device's TX module for use with the sync interface.
   * SC16 Q11 samples *with* metadata are used. */
navid's avatar
navid committed
292
  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 ) {
293 294
    fprintf(stderr,"Failed to configure TX sync interface: %s\n", bladerf_strerror(status));
     brf_error(status);
295 296
  }else 
    printf("[BRF] configured tx for sync interface \n");
297 298 299

   /* We must always enable the TX module after calling bladerf_sync_config(), and 
    * before  attempting to TX samples via  bladerf_sync_tx(). */
300
  if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_TX, true)) != 0) {
301 302
    fprintf(stderr,"Failed to enable TX module: %s\n", bladerf_strerror(status));
    brf_error(status);
303
  } else 
navid's avatar
navid committed
304
    printf("[BRF] TX module enabled \n");
305
 
306 307 308
  bladerf_log_set_verbosity(get_brf_log_level(openair0_cfg[card].log_level));
  
  printf("BLADERF: Initializing openair0_device\n");
309
  device->priv           = brf; 
310
  device->Mod_id         = num_devices++;
311
  device->type             = BLADERF_DEV; 
312 313 314 315
  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;
316 317 318 319 320
  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;
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345

  if(brf->sample_rate==30.72e6) {
    openair0_cfg->tx_delay = 8;
    openair0_cfg->tx_forward_nsamps = 175;
    brf->tx_forward_nsamps  = 175;
  }
  if(brf->sample_rate==15.36e6) {
    openair0_cfg->tx_delay = 5;
    openair0_cfg->tx_forward_nsamps = 95;
    brf->tx_forward_nsamps = 95;
  }
  if(brf->sample_rate==7.68e6) {
    openair0_cfg->tx_delay = 8;
    openair0_cfg->tx_forward_nsamps = 0;
    brf->tx_forward_nsamps = 0;
  }
  if(brf->sample_rate==1.92e6) {
    openair0_cfg->tx_delay = 8;
    openair0_cfg->tx_forward_nsamps = 40;
    brf->tx_forward_nsamps = 40;
  }
  
  openair0_cfg->iq_txshift= 0;
  openair0_cfg->iq_rxrescale = 15;

346
  memcpy((void*)&device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t));
347 348

  return 0;
349 350
}

351
int brf_error(int status) {
352
  
navid's avatar
navid committed
353
  //exit(-1);
354
  //return 1; // or status error code
355 356
}

357

358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384

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;
  }
}
385 386 387
int get_brf_log_level(int log_level){

  int level=BLADERF_LOG_LEVEL_INFO;
navid's avatar
navid committed
388
  //return  BLADERF_LOG_LEVEL_DEBUG;
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
  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;
}