bladerf_lib.c 13.2 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
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);

}

navid's avatar
navid committed
188
int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg) {
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));
nikaeinn's avatar
nikaeinn committed
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");
nikaeinn's avatar
nikaeinn committed
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
311
312
313
314
  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;
315
316
317
318
319
  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;
320
  memcpy((void*)&device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t));
321
322

  return 0;
323
324
}

325
int brf_error(int status) {
326
  
navid's avatar
navid committed
327
  //exit(-1);
328
  //return 1; // or status error code
329
330
}

331

332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358

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;
  }
}
359
360
361
int get_brf_log_level(int log_level){

  int level=BLADERF_LOG_LEVEL_INFO;
navid's avatar
navid committed
362
  //return  BLADERF_LOG_LEVEL_DEBUG;
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
  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;
}