/** * Initialize synchronous interface */ static int radio_init_sync(struct bladerf *dev) { int status; const unsigned int num_buffers = 64; const unsigned int buffer_size = SYNC_BUFFER_SIZE; /* Must be a multiple of 1024 */ const unsigned int num_transfers = 16; const unsigned int timeout_ms = 3500; /* Configure both the device's RX and TX modules for use with the synchronous * interface. SC16 Q11 samples with metadata are used. */ status = bladerf_sync_config(dev, BLADERF_MODULE_RX, BLADERF_FORMAT_SC16_Q11_META, num_buffers, buffer_size, num_transfers, timeout_ms); if (status != 0) { fprintf(stderr, "Failed to configure RX sync interface: %s\n", bladerf_strerror(status)); return status; } status = bladerf_sync_config(dev, BLADERF_MODULE_TX, BLADERF_FORMAT_SC16_Q11_META, num_buffers, buffer_size, num_transfers, timeout_ms); if (status != 0) { fprintf(stderr, "Failed to configure TX sync interface: %s\n", bladerf_strerror(status)); } return status; }
static inline int dummy_tx(struct bladerf *dev) { int status; const unsigned int buf_len = CAL_BUF_LEN; uint16_t *buf = (uint16_t*) calloc(2 * buf_len, sizeof(buf[0])); if (buf == NULL) { return BLADERF_ERR_MEM; } status = bladerf_sync_config(dev, BLADERF_MODULE_TX, BLADERF_FORMAT_SC16_Q11, CAL_NUM_BUFS, buf_len, CAL_NUM_XFERS, CAL_TIMEOUT); if (status != 0) { goto error; } status = bladerf_sync_tx(dev, buf, buf_len, NULL, CAL_TIMEOUT); error: free(buf); return status; }
bool Bladerf1Output::openDevice() { if (m_dev != 0) { closeDevice(); } int res; m_sampleSourceFifo.resize(m_settings.m_devSampleRate/(1<<(m_settings.m_log2Interp <= 4 ? m_settings.m_log2Interp : 4))); if (m_deviceAPI->getSourceBuddies().size() > 0) { DeviceSourceAPI *sourceBuddy = m_deviceAPI->getSourceBuddies()[0]; DeviceBladeRF1Params *buddySharedParams = (DeviceBladeRF1Params *) sourceBuddy->getBuddySharedPtr(); if (buddySharedParams == 0) { qCritical("BladerfOutput::start: could not get shared parameters from buddy"); return false; } if (buddySharedParams->m_dev == 0) // device is not opened by buddy { qCritical("BladerfOutput::start: could not get BladeRF handle from buddy"); return false; } m_sharedParams = *(buddySharedParams); // copy parameters from buddy m_dev = m_sharedParams.m_dev; // get BladeRF handle } else { if (!DeviceBladeRF1::open_bladerf(&m_dev, qPrintable(m_deviceAPI->getSampleSinkSerial()))) { qCritical("BladerfOutput::start: could not open BladeRF %s", qPrintable(m_deviceAPI->getSampleSinkSerial())); return false; } m_sharedParams.m_dev = m_dev; } // TODO: adjust USB transfer data according to sample rate if ((res = bladerf_sync_config(m_dev, BLADERF_TX_X1, BLADERF_FORMAT_SC16_Q11, 64, 8192, 32, 10000)) < 0) { qCritical("BladerfOutput::start: bladerf_sync_config with return code %d", res); return false; } if ((res = bladerf_enable_module(m_dev, BLADERF_MODULE_TX, true)) < 0) { qCritical("BladerfOutput::start: bladerf_enable_module with return code %d", res); return false; } return true; }
int rf_blade_start_rx_stream(void *h) { int status; rf_blade_handler_t *handler = (rf_blade_handler_t*) h; /* Configure the device's RX module for use with the sync interface. * SC16 Q11 samples *with* metadata are used. */ uint32_t buffer_size_rx = ms_buffer_size_rx*(handler->rx_rate/1000/1024); status = bladerf_sync_config(handler->dev, BLADERF_MODULE_RX, BLADERF_FORMAT_SC16_Q11_META, num_buffers, buffer_size_rx, num_transfers, timeout_ms); if (status != 0) { fprintf(stderr, "Failed to configure RX sync interface: %s\n", bladerf_strerror(status)); return status; } status = bladerf_sync_config(handler->dev, BLADERF_MODULE_TX, BLADERF_FORMAT_SC16_Q11_META, num_buffers, buffer_size_tx, num_transfers, timeout_ms); if (status != 0) { fprintf(stderr, "Failed to configure TX sync interface: %s\n", bladerf_strerror(status)); return status; } status = bladerf_enable_module(handler->dev, BLADERF_MODULE_RX, true); if (status != 0) { fprintf(stderr, "Failed to enable RX module: %s\n", bladerf_strerror(status)); return status; } status = bladerf_enable_module(handler->dev, BLADERF_MODULE_TX, true); if (status != 0) { fprintf(stderr, "Failed to enable TX module: %s\n", bladerf_strerror(status)); return status; } handler->rx_stream_enabled = true; return 0; }
/** [sync_init] */ static int init_sync(struct bladerf *dev) { int status; /* These items configure the underlying asynch stream used by the sync * interface. The "buffer" here refers to those used internally by worker * threads, not the user's sample buffers. * * It is important to remember that TX buffers will not be submitted to * the hardware until `buffer_size` samples are provided via the * bladerf_sync_tx call. Similarly, samples will not be available to * RX via bladerf_sync_rx() until a block of `buffer_size` samples has been * received. */ const unsigned int num_buffers = 16; const unsigned int buffer_size = 8192; /* Must be a multiple of 1024 */ const unsigned int num_transfers = 8; const unsigned int timeout_ms = 3500; /* Configure both the device's x1 RX and TX channels for use with the * synchronous * interface. SC16 Q11 samples *without* metadata are used. */ status = bladerf_sync_config(dev, BLADERF_RX_X1, BLADERF_FORMAT_SC16_Q11, num_buffers, buffer_size, num_transfers, timeout_ms); if (status != 0) { fprintf(stderr, "Failed to configure RX sync interface: %s\n", bladerf_strerror(status)); return status; } status = bladerf_sync_config(dev, BLADERF_TX_X1, BLADERF_FORMAT_SC16_Q11, num_buffers, buffer_size, num_transfers, timeout_ms); if (status != 0) { fprintf(stderr, "Failed to configure TX sync interface: %s\n", bladerf_strerror(status)); } return status; }
int rf_blade_start_tx_stream(void *h) { int status; rf_blade_handler_t *handler = (rf_blade_handler_t*) h; status = bladerf_sync_config(handler->dev, BLADERF_MODULE_TX, BLADERF_FORMAT_SC16_Q11_META, num_buffers, buffer_size_tx, num_transfers, timeout_ms); if (status != 0) { fprintf(stderr, "Failed to configure TX sync interface: %s\n", bladerf_strerror(status)); return status; } status = bladerf_enable_module(handler->dev, BLADERF_MODULE_TX, true); if (status != 0) { fprintf(stderr, "Failed to enable TX module: %s\n", bladerf_strerror(status)); return status; } handler->tx_stream_enabled = true; return 0; }
int main(int argc, char *argv[]) { sim_t s; char *devstr = NULL; int c; int result; double duration; datetime_t t0; if (argc<3) { usage(); exit(1); } s.opt.navfile[0] = 0; s.opt.umfile[0] = 0; s.opt.g0.week = -1; s.opt.g0.sec = 0.0; s.opt.iduration = USER_MOTION_SIZE; s.opt.verb = TRUE; s.opt.nmeaGGA = FALSE; s.opt.staticLocationMode = TRUE; // default user motion s.opt.llh[0] = 35.274016 / R2D; s.opt.llh[1] = 137.013765 / R2D; s.opt.llh[2] = 100.0; while ((result=getopt(argc,argv,"e:u:g:l:t:d:"))!=-1) { switch (result) { case 'e': strcpy(s.opt.navfile, optarg); break; case 'u': strcpy(s.opt.umfile, optarg); s.opt.nmeaGGA = FALSE; s.opt.staticLocationMode = FALSE; break; case 'g': strcpy(s.opt.umfile, optarg); s.opt.nmeaGGA = TRUE; s.opt.staticLocationMode = FALSE; break; case 'l': // Static geodetic coordinates input mode // Added by [email protected] s.opt.nmeaGGA = FALSE; s.opt.staticLocationMode = TRUE; sscanf(optarg,"%lf,%lf,%lf",&s.opt.llh[0],&s.opt.llh[1],&s.opt.llh[2]); s.opt.llh[0] /= R2D; // convert to RAD s.opt.llh[1] /= R2D; // convert to RAD break; case 't': sscanf(optarg, "%d/%d/%d,%d:%d:%lf", &t0.y, &t0.m, &t0.d, &t0.hh, &t0.mm, &t0.sec); if (t0.y<=1980 || t0.m<1 || t0.m>12 || t0.d<1 || t0.d>31 || t0.hh<0 || t0.hh>23 || t0.mm<0 || t0.mm>59 || t0.sec<0.0 || t0.sec>=60.0) { printf("ERROR: Invalid date and time.\n"); exit(1); } t0.sec = floor(t0.sec); date2gps(&t0, &s.opt.g0); break; case 'd': duration = atof(optarg); if (duration<0.0 || duration>((double)USER_MOTION_SIZE)/10.0) { printf("ERROR: Invalid duration.\n"); exit(1); } s.opt.iduration = (int)(duration*10.0+0.5); break; case ':': case '?': usage(); exit(1); default: break; } } if (s.opt.navfile[0]==0) { printf("ERROR: GPS ephemeris file is not specified.\n"); exit(1); } if (s.opt.umfile[0]==0 && !s.opt.staticLocationMode) { printf("ERROR: User motion file / NMEA GGA stream is not specified.\n"); printf("You may use -l to specify the static location directly.\n"); exit(1); } // Initialize simulator init_sim(&s); // Allocate TX buffer to hold each block of samples to transmit. s.tx.buffer = (int16_t *)malloc(SAMPLES_PER_BUFFER * sizeof(int16_t) * 2); // for 16-bit I and Q samples if (s.tx.buffer == NULL) { fprintf(stderr, "Failed to allocate TX buffer.\n"); goto out; } // Allocate FIFOs to hold 0.1 seconds of I/Q samples each. s.fifo = (int16_t *)malloc(FIFO_LENGTH * sizeof(int16_t) * 2); // for 16-bit I and Q samples if (s.fifo == NULL) { fprintf(stderr, "Failed to allocate I/Q sample buffer.\n"); goto out; } // Initializing device. printf("Opening and initializing device...\n"); s.status = bladerf_open(&s.tx.dev, devstr); if (s.status != 0) { fprintf(stderr, "Failed to open device: %s\n", bladerf_strerror(s.status)); goto out; } s.status = bladerf_set_frequency(s.tx.dev, BLADERF_MODULE_TX, TX_FREQUENCY); if (s.status != 0) { fprintf(stderr, "Faield to set TX frequency: %s\n", bladerf_strerror(s.status)); goto out; } else { printf("TX frequency: %u Hz\n", TX_FREQUENCY); } s.status = bladerf_set_sample_rate(s.tx.dev, BLADERF_MODULE_TX, TX_SAMPLERATE, NULL); if (s.status != 0) { fprintf(stderr, "Failed to set TX sample rate: %s\n", bladerf_strerror(s.status)); goto out; } else { printf("TX sample rate: %u sps\n", TX_SAMPLERATE); } s.status = bladerf_set_bandwidth(s.tx.dev, BLADERF_MODULE_TX, TX_BANDWIDTH, NULL); if (s.status != 0) { fprintf(stderr, "Failed to set TX bandwidth: %s\n", bladerf_strerror(s.status)); goto out; } else { printf("TX bandwidth: %u Hz\n", TX_BANDWIDTH); } s.status = bladerf_set_txvga1(s.tx.dev, TX_VGA1); if (s.status != 0) { fprintf(stderr, "Failed to set TX VGA1 gain: %s\n", bladerf_strerror(s.status)); goto out; } else { printf("TX VGA1 gain: %d dB\n", TX_VGA1); } s.status = bladerf_set_txvga2(s.tx.dev, TX_VGA2); if (s.status != 0) { fprintf(stderr, "Failed to set TX VGA2 gain: %s\n", bladerf_strerror(s.status)); goto out; } else { printf("TX VGA2 gain: %d dB\n", TX_VGA2); } // Start GPS task. s.status = start_gps_task(&s); if (s.status < 0) { fprintf(stderr, "Failed to start GPS task.\n"); goto out; } else printf("Creating GPS task...\n"); // Wait until GPS task is initialized pthread_mutex_lock(&(s.tx.lock)); while (!s.gps.ready) pthread_cond_wait(&(s.gps.initialization_done), &(s.tx.lock)); pthread_mutex_unlock(&(s.tx.lock)); // Fillfull the FIFO. if (is_fifo_write_ready(&s)) pthread_cond_signal(&(s.fifo_write_ready)); // Configure the TX module for use with the synchronous interface. s.status = bladerf_sync_config(s.tx.dev, BLADERF_MODULE_TX, BLADERF_FORMAT_SC16_Q11, NUM_BUFFERS, SAMPLES_PER_BUFFER, NUM_TRANSFERS, TIMEOUT_MS); if (s.status != 0) { fprintf(stderr, "Failed to configure TX sync interface: %s\n", bladerf_strerror(s.status)); goto out; } // We must always enable the modules *after* calling bladerf_sync_config(). s.status = bladerf_enable_module(s.tx.dev, BLADERF_MODULE_TX, true); if (s.status != 0) { fprintf(stderr, "Failed to enable TX module: %s\n", bladerf_strerror(s.status)); goto out; } // Start TX task s.status = start_tx_task(&s); if (s.status < 0) { fprintf(stderr, "Failed to start TX task.\n"); goto out; } else printf("Creating TX task...\n"); // Running... printf("Running...\n"); printf("Press 'q' to exit.\n"); while (1) { c = _getch(); if (c=='q') break; } // // TODO: Cleaning up the threads properly. // printf("\nDone!\n"); // Disable TX module, shutting down our underlying TX stream. s.status = bladerf_enable_module(s.tx.dev, BLADERF_MODULE_TX, false); if (s.status != 0) { fprintf(stderr, "Failed to disable TX module: %s\n", bladerf_strerror(s.status)); } out: // Free up resources if (s.tx.buffer != NULL) free(s.tx.buffer); if (s.fifo != NULL) free(s.fifo); printf("Closing device...\n"); bladerf_close(s.tx.dev); return(0); }
/** [example_snippet] */ int sync_rx_example(struct bladerf *dev) { int status, ret; bool done = false; /* "User" samples buffers and their associated sizes, in units of samples. * Recall that one sample = two int16_t values. */ int16_t *rx_samples = NULL; int16_t *tx_samples = NULL; const unsigned int samples_len = 10000; /* May be any (reasonable) size */ /* These items configure the underlying asynch stream used by the sync * interface. The "buffer" here refers to those used internally by worker * threads, not the `samples` buffer above. */ const unsigned int num_buffers = 16; const unsigned int buffer_size = 8192; /* Must be a multiple of 1024 */ const unsigned int num_transfers = 8; const unsigned int timeout_ms = 3500; /* Allocate a buffer to store received samples in */ rx_samples = malloc(samples_len * 2 * sizeof(int16_t)); if (rx_samples == NULL) { perror("malloc"); return BLADERF_ERR_MEM; } /* Allocate a buffer to prepare transmit data in */ tx_samples = malloc(samples_len * 2 * sizeof(int16_t)); if (tx_samples == NULL) { perror("malloc"); free(rx_samples); return BLADERF_ERR_MEM; } /* Configure both the device's RX and TX modules for use with the synchronous * interface. SC16 Q11 samples *without* metadata are used. */ status = bladerf_sync_config(dev, BLADERF_MODULE_RX, BLADERF_FORMAT_SC16_Q11, num_buffers, buffer_size, num_transfers, timeout_ms); if (status != 0) { fprintf(stderr, "Failed to configure RX sync interface: %s\n", bladerf_strerror(status)); goto out; } status = bladerf_sync_config(dev, BLADERF_MODULE_TX, BLADERF_FORMAT_SC16_Q11, num_buffers, buffer_size, num_transfers, timeout_ms); if (status != 0) { fprintf(stderr, "Failed to configure TX sync interface: %s\n", bladerf_strerror(status)); goto out; } /* We must always enable the modules *after* calling bladerf_sync_config(), * and *before* attempting to RX or TX samples. */ status = bladerf_enable_module(dev, BLADERF_MODULE_RX, true); if (status != 0) { fprintf(stderr, "Failed to enable RX module: %s\n", bladerf_strerror(status)); goto out; } status = bladerf_enable_module(dev, BLADERF_MODULE_TX, true); if (status != 0) { fprintf(stderr, "Failed to enable RX module: %s\n", bladerf_strerror(status)); goto out; } /* Receive samples and do work on them and then transmit a response. * * Note we transmit more than `buffer_size` samples to ensure that our * samples are written to the FPGA. (The samples are sent when the * synchronous interface's internal buffer of `buffer_size` samples is * filled.) This is generally not nececssary if you are continuously * streaming TX data. Otherwise, you may need to zero-pad your TX data to * achieve this. */ while (status == 0 && !done) { status = bladerf_sync_rx(dev, rx_samples, samples_len, NULL, 5000); if (status == 0) { done = do_work(rx_samples, samples_len, tx_samples, samples_len); if (!done) { status = bladerf_sync_tx(dev, tx_samples, samples_len, NULL, 5000); if (status != 0) { fprintf(stderr, "Failed to TX samples: %s\n", bladerf_strerror(status)); } } } else { fprintf(stderr, "Failed to RX samples: %s\n", bladerf_strerror(status)); } } if (status == 0) { /* Wait a few seconds for any remaining TX samples to finish */ usleep(2000000); } out: ret = status; /* Disable RX module, shutting down our underlying RX stream */ status = bladerf_enable_module(dev, BLADERF_MODULE_RX, false); if (status != 0) { fprintf(stderr, "Failed to disable RX module: %s\n", bladerf_strerror(status)); } /* Disable TX module, shutting down our underlying TX stream */ status = bladerf_enable_module(dev, BLADERF_MODULE_TX, false); if (status != 0) { fprintf(stderr, "Failed to disable TX module: %s\n", bladerf_strerror(status)); } /* Free up our resources */ free(rx_samples); free(tx_samples); return ret; }
// Open BladeRF device. BladeRFSource::BladeRFSource(const char *serial) : m_dev(0), m_sampleRate(1000000), m_actualSampleRate(1000000), m_frequency(300000000), m_minFrequency(300000000), m_bandwidth(1500000), m_actualBandwidth(1500000), m_lnaGain(3), m_vga1Gain(6), m_vga2Gain(5), m_thread(0) { int status; struct bladerf_devinfo info; bladerf_init_devinfo(&info); if (serial != 0) { strncpy(info.serial, serial, BLADERF_SERIAL_LENGTH - 1); info.serial[BLADERF_SERIAL_LENGTH - 1] = '\0'; } status = bladerf_open_with_devinfo(&m_dev, &info); if (status == BLADERF_ERR_NODEV) { std::ostringstream err_ostr; err_ostr << "No devices available with serial=" << serial; m_error = err_ostr.str(); m_dev = 0; } else if (status != 0) { std::ostringstream err_ostr; err_ostr << "Failed to open device with serial=" << serial; m_error = err_ostr.str(); m_dev = 0; } else { int fpga_loaded = bladerf_is_fpga_configured(m_dev); if (fpga_loaded < 0) { std::ostringstream err_ostr; err_ostr << "Failed to check FPGA state: " << bladerf_strerror(fpga_loaded); m_error = err_ostr.str(); m_dev = 0; } else if (fpga_loaded == 0) { m_error = "The device's FPGA is not loaded."; m_dev = 0; } else { if ((status = bladerf_sync_config(m_dev, BLADERF_MODULE_RX, BLADERF_FORMAT_SC16_Q11, 64, 8192, 32, 10000)) < 0) { std::ostringstream err_ostr; err_ostr << "bladerf_sync_config failed with return code " << status; m_error = err_ostr.str(); m_dev = 0; } else { if ((status = bladerf_enable_module(m_dev, BLADERF_MODULE_RX, true)) < 0) { std::ostringstream err_ostr; err_ostr << "bladerf_enable_module failed with return code " << status; m_error = err_ostr.str(); m_dev = 0; } else { if (bladerf_expansion_attach(m_dev, BLADERF_XB_200) == 0) { std::cerr << "BladeRFSource::BladeRFSource: Attached XB200 extension" << std::endl; if ((status = bladerf_xb200_set_path(m_dev, BLADERF_MODULE_RX, BLADERF_XB200_MIX)) != 0) { std::cerr << "BladeRFSource::BladeRFSource: bladerf_xb200_set_path failed with return code " << status << std::endl; } else { if ((status = bladerf_xb200_set_filterbank(m_dev, BLADERF_MODULE_RX, BLADERF_XB200_AUTO_1DB)) != 0) { std::cerr << "BladeRFSource::BladeRFSource: bladerf_xb200_set_filterbank failed with return code " << status << std::endl; } else { std::cerr << "BladeRFSource::BladeRFSource: XB200 configured. Min freq set to 100kHz" << std::endl; m_minFrequency = 100000; } } } } } } } std::ostringstream lgains_ostr; for (int g: m_lnaGains) { lgains_ostr << g << " "; } m_lnaGainsStr = lgains_ostr.str(); std::ostringstream v1gains_ostr; for (int g: m_vga1Gains) { v1gains_ostr << g << " "; } m_vga1GainsStr = v1gains_ostr.str(); std::ostringstream v2gains_ostr; for (int g: m_vga2Gains) { v2gains_ostr << g << " "; } m_vga2GainsStr = v2gains_ostr.str(); std::ostringstream bw_ostr; for (int b: m_halfbw) { bw_ostr << 2*b << " "; } m_bwfiltStr = bw_ostr.str(); m_this = this; }
void *tx_task(void *cli_state_arg) { int status = 0; int disable_status; unsigned char requests; enum rxtx_state task_state; struct cli_state *cli_state = (struct cli_state *) cli_state_arg; struct rxtx_data *tx = cli_state->tx; MUTEX *dev_lock = &cli_state->dev_lock; /* We expect to be in the IDLE state when this is kicked off. We could * also get into the shutdown state if the program exits before we * finish up initialization */ task_state = rxtx_get_state(tx); assert(task_state == RXTX_STATE_INIT); set_last_error(&tx->last_error, ETYPE_BLADERF, 0); requests = 0; while (task_state != RXTX_STATE_SHUTDOWN) { task_state = rxtx_get_state(tx); switch (task_state) { case RXTX_STATE_INIT: rxtx_set_state(tx, RXTX_STATE_IDLE); break; case RXTX_STATE_IDLE: rxtx_task_exec_idle(tx, &requests); break; case RXTX_STATE_START: { enum error_type err_type = ETYPE_BUG; /* Clear out the last error */ set_last_error(&tx->last_error, ETYPE_ERRNO, 0); /* Bug catcher */ MUTEX_LOCK(&tx->file_mgmt.file_meta_lock); assert(tx->file_mgmt.file != NULL); MUTEX_UNLOCK(&tx->file_mgmt.file_meta_lock); /* Initialize the TX synchronous data configuration */ status = bladerf_sync_config(cli_state->dev, BLADERF_MODULE_TX, BLADERF_FORMAT_SC16_Q11, tx->data_mgmt.num_buffers, tx->data_mgmt.samples_per_buffer, tx->data_mgmt.num_transfers, tx->data_mgmt.timeout_ms); if (status < 0) { err_type = ETYPE_BLADERF; } if (status == 0) { rxtx_set_state(tx, RXTX_STATE_RUNNING); } else { set_last_error(&tx->last_error, err_type, status); rxtx_set_state(tx, RXTX_STATE_IDLE); } } break; case RXTX_STATE_RUNNING: MUTEX_LOCK(dev_lock); status = bladerf_enable_module(cli_state->dev, tx->module, true); MUTEX_UNLOCK(dev_lock); if (status < 0) { set_last_error(&tx->last_error, ETYPE_BLADERF, status); } else { status = tx_task_exec_running(tx, cli_state); if (status < 0) { set_last_error(&tx->last_error, ETYPE_BLADERF, status); } MUTEX_LOCK(dev_lock); disable_status = bladerf_enable_module(cli_state->dev, tx->module, false); MUTEX_UNLOCK(dev_lock); if (status == 0 && disable_status < 0) { set_last_error( &tx->last_error, ETYPE_BLADERF, disable_status); } } rxtx_set_state(tx, RXTX_STATE_STOP); break; case RXTX_STATE_STOP: rxtx_task_exec_stop(tx, &requests); break; case RXTX_STATE_SHUTDOWN: break; default: /* Bug */ assert(0); rxtx_set_state(tx, RXTX_STATE_IDLE); } } return NULL; }
int calibrate_dc_rx(struct cli_state *s, int16_t *dc_i, int16_t *dc_q, int16_t *avg_i, int16_t *avg_q) { int status; int16_t *samples = NULL; int16_t dc_i0, dc_q0, dc_i1, dc_q1; int16_t avg_i0, avg_q0, avg_i1, avg_q1; int16_t test_i[7], test_q[7]; int16_t tmp_i, tmp_q, min_i, min_q; unsigned int min_i_idx, min_q_idx, n; samples = (int16_t*) malloc(CAL_BUF_LEN * 2 * sizeof(samples[0])); if (samples == NULL) { status = BLADERF_ERR_MEM;; goto out; } /* Ensure old samples are flushed */ status = bladerf_enable_module(s->dev, BLADERF_MODULE_RX, false); if (status != 0) { goto out; } status = bladerf_sync_config(s->dev, BLADERF_MODULE_RX, BLADERF_FORMAT_SC16_Q11, CAL_NUM_BUFS, CAL_BUF_LEN, CAL_NUM_XFERS, CAL_TIMEOUT); if (status != 0) { goto out; } status = bladerf_enable_module(s->dev, BLADERF_MODULE_RX, true); if (status != 0) { goto out; } dc_i0 = dc_q0 = -512; dc_i1 = dc_q1 = 512; /* Get an initial set of sample points */ status = set_rx_dc(s->dev, dc_i0, dc_q0); if (status != 0) { goto out; } status = rx_avg(s->dev, samples, &avg_i0, &avg_q0); if (status != 0) { goto out; } status = set_rx_dc(s->dev, dc_i1, dc_q1); if (status != 0) { goto out; } status = rx_avg(s->dev, samples, &avg_i1, &avg_q1); if (status != 0) { goto out; } status = interpolate(dc_i0, dc_i1, avg_i0, avg_i1, dc_i); if (status != 0) { cli_err(s, "Error", "RX I values appear to be stuck @ %d\n", avg_i0); goto out; } status = interpolate(dc_q0, dc_q1, avg_q0, avg_q1, dc_q); if (status != 0) { cli_err(s, "Error", "RX Q values appear to be stuck @ %d\n", avg_q0); goto out; } test_i[0] = *dc_i; test_i[1] = test_i[0] + 96; test_i[2] = test_i[0] + 64; test_i[3] = test_i[0] + 32; test_i[4] = test_i[0] - 32; test_i[5] = test_i[0] - 64; test_i[6] = test_i[0] - 96; test_q[0] = *dc_q; test_q[1] = test_q[0] + 96; test_q[2] = test_q[0] + 64; test_q[3] = test_q[0] + 32; test_q[4] = test_q[0] - 32; test_q[5] = test_q[0] - 64; test_q[6] = test_q[0] - 96; min_i_idx = min_q_idx = 0; min_i = min_q = INT16_MAX; for (n = 0; n < 7; n++) { if (test_i[n] > CAL_DC_MAX) { test_i[n] = CAL_DC_MAX; } else if (test_i[n] < CAL_DC_MIN) { test_i[n] = CAL_DC_MIN; } if (test_q[n] > CAL_DC_MAX) { test_q[n] = CAL_DC_MAX; } else if (test_q[n] < CAL_DC_MIN) { test_q[n] = CAL_DC_MIN; } /* See where we're at now... */ status = set_rx_dc(s->dev, test_i[n], test_q[n]); if (status != 0) { goto out; } status = rx_avg(s->dev, samples, &tmp_i, &tmp_q); if (status != 0) { goto out; } if (abs(tmp_i) < abs(min_i)) { min_i = tmp_i; min_i_idx = n; } if (abs(tmp_q) < abs(min_q)) { min_q = tmp_q; min_q_idx = n; } } *dc_i = test_i[min_i_idx]; *dc_q = test_q[min_q_idx]; if (avg_i) { *avg_i = min_i; } if (avg_q) { *avg_q = min_q; } status = set_rx_dc(s->dev, *dc_i, *dc_q); if (status != 0) { goto out; } out: free(samples); return status; }
int calibrate_dc_tx(struct cli_state *s, int16_t *dc_i, int16_t *dc_q, float *error_i, float *error_q) { int retval, status; unsigned int rx_freq, tx_freq; int16_t *rx_samples = NULL; struct cal_tx_task tx_task; struct point p0, p1, p2, p3; struct point result; status = bladerf_get_frequency(s->dev, BLADERF_MODULE_RX, &rx_freq); if (status != 0) { return status; } status = bladerf_get_frequency(s->dev, BLADERF_MODULE_TX, &tx_freq); if (status != 0) { return status; } rx_samples = (int16_t*) malloc(CAL_BUF_LEN * 2 * sizeof(rx_samples[0])); if (rx_samples == NULL) { return BLADERF_ERR_MEM; } status = init_tx_task(s, &tx_task); if (status != 0) { goto out; } status = bladerf_set_frequency(s->dev, BLADERF_MODULE_TX, rx_freq + (CAL_SAMPLERATE / 4)); if (status != 0) { goto out; } if (tx_freq < UPPER_BAND) { status = bladerf_set_loopback(s->dev, BLADERF_LB_RF_LNA1); } else { status = bladerf_set_loopback(s->dev, BLADERF_LB_RF_LNA2); } if (status != 0) { goto out; } /* Ensure old samples are flushed */ status = bladerf_enable_module(s->dev, BLADERF_MODULE_RX, false); if (status != 0) { goto out; } status = bladerf_enable_module(s->dev, BLADERF_MODULE_TX, false); if (status != 0) { goto out; } status = bladerf_sync_config(s->dev, BLADERF_MODULE_RX, BLADERF_FORMAT_SC16_Q11, CAL_NUM_BUFS, CAL_BUF_LEN, CAL_NUM_XFERS, CAL_TIMEOUT); if (status != 0) { goto out; } status = bladerf_sync_config(s->dev, BLADERF_MODULE_TX, BLADERF_FORMAT_SC16_Q11, CAL_NUM_BUFS, CAL_BUF_LEN, CAL_NUM_XFERS, CAL_TIMEOUT); if (status != 0) { goto out; } status = bladerf_enable_module(s->dev, BLADERF_MODULE_RX, true); if (status != 0) { goto out; } status = bladerf_enable_module(s->dev, BLADERF_MODULE_TX, true); if (status != 0) { goto out; } status = start_tx_task(&tx_task); if (status != 0) { goto out; } /* Sample the results of 4 points, which should yield 2 intersecting lines, * for 4 different DC offset settings of the I channel */ p0.x = -2048; p1.x = -512; p2.x = 512; p3.x = 2048; status = rx_avg_magnitude(s->dev, rx_samples, (int16_t) p0.x, 0, &p0.y); if (status != 0) { goto out; } status = rx_avg_magnitude(s->dev, rx_samples, (int16_t) p1.x, 0, &p1.y); if (status != 0) { goto out; } status = rx_avg_magnitude(s->dev, rx_samples, (int16_t) p2.x, 0, &p2.y); if (status != 0) { goto out; } status = rx_avg_magnitude(s->dev, rx_samples, (int16_t) p3.x, 0, &p3.y); if (status != 0) { goto out; } status = intersection(s, &p0, &p1, &p2, &p3, &result); if (status != 0) { goto out; } if (result.x < CAL_DC_MIN || result.x > CAL_DC_MAX) { cli_err(s, "Error", "Obtained out-of-range TX I DC cal value (%f).\n", result.x); status = BLADERF_ERR_UNEXPECTED; goto out; } *dc_i = (int16_t) (result.x + 0.5); *error_i = result.y; status = set_tx_dc(s->dev, *dc_i, 0); if (status != 0) { goto out; } /* Repeat for the Q channel */ status = rx_avg_magnitude(s->dev, rx_samples, *dc_i, (int16_t) p0.x, &p0.y); if (status != 0) { goto out; } status = rx_avg_magnitude(s->dev, rx_samples, *dc_i, (int16_t) p1.x, &p1.y); if (status != 0) { goto out; } status = rx_avg_magnitude(s->dev, rx_samples, *dc_i, (int16_t) p2.x, &p2.y); if (status != 0) { goto out; } status = rx_avg_magnitude(s->dev, rx_samples, *dc_i, (int16_t) p3.x, &p3.y); if (status != 0) { goto out; } status = intersection(s, &p0, &p1, &p2, &p3, &result); if (status != 0) { goto out; } *dc_q = (int16_t) (result.x + 0.5); *error_q = result.y; status = set_tx_dc(s->dev, *dc_i, *dc_q); out: retval = status; status = stop_tx_task(&tx_task); retval = first_error(retval, status); free(rx_samples); free(tx_task.samples); status = bladerf_enable_module(s->dev, BLADERF_MODULE_TX, false); retval = first_error(retval, status); /* Restore RX frequency */ status = bladerf_set_frequency(s->dev, BLADERF_MODULE_TX, tx_freq); retval = first_error(retval, status); return retval; }
static inline int setup_device(struct test *t) { int status; struct bladerf *dev = t->dev; #if !DISABLE_RX_LOOPBACK status = bladerf_set_loopback(dev, BLADERF_LB_BB_TXVGA1_RXVGA2); if (status != 0) { fprintf(stderr, "Failed to set loopback mode: %s\n", bladerf_strerror(status)); return status; } #endif status = bladerf_set_lna_gain(dev, BLADERF_LNA_GAIN_MAX); if (status != 0) { fprintf(stderr, "Failed to set LNA gain value: %s\n", bladerf_strerror(status)); return status; } status = bladerf_set_rxvga1(dev, 30); if (status != 0) { fprintf(stderr, "Failed to set RXVGA1 value: %s\n", bladerf_strerror(status)); return status; } status = bladerf_set_rxvga2(dev, 10); if (status != 0) { fprintf(stderr, "Failed to set RXVGA2 value: %s\n", bladerf_strerror(status)); return status; } status = bladerf_set_txvga1(dev, -10); if (status != 0) { fprintf(stderr, "Failed to set TXVGA1 value: %s\n", bladerf_strerror(status)); return status; } status = bladerf_set_txvga2(dev, BLADERF_TXVGA2_GAIN_MIN); if (status != 0) { fprintf(stderr, "Failed to set TXVGA2 value: %s\n", bladerf_strerror(status)); return status; } status = bladerf_sync_config(t->dev, BLADERF_MODULE_RX, BLADERF_FORMAT_SC16_Q11_META, t->params->num_buffers, t->params->buf_size, t->params->num_xfers, t->params->timeout_ms); if (status != 0) { fprintf(stderr, "Failed to configure RX stream: %s\n", bladerf_strerror(status)); return status; } status = bladerf_enable_module(t->dev, BLADERF_MODULE_RX, true); if (status != 0) { fprintf(stderr, "Failed to enable RX module: %s\n", bladerf_strerror(status)); return status; } status = bladerf_sync_config(t->dev, BLADERF_MODULE_TX, BLADERF_FORMAT_SC16_Q11_META, t->params->num_buffers, t->params->buf_size, t->params->num_xfers, t->params->timeout_ms); if (status != 0) { fprintf(stderr, "Failed to configure TX stream: %s\n", bladerf_strerror(status)); return status; } status = bladerf_enable_module(t->dev, BLADERF_MODULE_TX, true); if (status != 0) { fprintf(stderr, "Failed to enable RX module: %s\n", bladerf_strerror(status)); return status; } return status; }
/** [tx_meta_init] */ int16_t * init(struct bladerf *dev, int16_t num_samples) { int status = -1; /* "User" buffer that we store our modulated samples in, and its * associated size, in units of samples. Recall that for the * SC16Q11 format (native to the ADCs), one sample = two int16_t values. * * When using the bladerf_sync_* functions, the buffer size isn't * restricted to multiples of any particular size. * * The value for `num_samples` has no major restrictions here, while the * `buffer_size` below must be a multiple of 1024. */ int16_t *samples; /* These items configure the underlying asynch stream used by the the sync * interface. The "buffer" here refers to those used internally by worker * threads, not the `samples` buffer above. */ const unsigned int num_buffers = 32; const unsigned int buffer_size = 2048; const unsigned int num_transfers = 16; const unsigned int timeout_ms = 1000; samples = malloc(num_samples * 2 * sizeof(int16_t)); if (samples == NULL) { perror("malloc"); goto error; } /** [sync_config] */ /* Configure the device's TX module for use with the sync interface. * SC16 Q11 samples *with* metadata are used. */ status = bladerf_sync_config(dev, BLADERF_MODULE_TX, BLADERF_FORMAT_SC16_Q11_META, num_buffers, buffer_size, num_transfers, timeout_ms); if (status != 0) { fprintf(stderr, "Failed to configure TX sync interface: %s\n", bladerf_strerror(status)); goto error; } /** [sync_config] */ /* We must always enable the TX module *after* calling * bladerf_sync_config(), and *before* attempting to TX samples via * bladerf_sync_tx(). */ status = bladerf_enable_module(dev, BLADERF_MODULE_TX, true); if (status != 0) { fprintf(stderr, "Failed to enable TX module: %s\n", bladerf_strerror(status)); goto error; } status = 0; error: if (status != 0) { free(samples); samples = NULL; } return samples; }
//! Do any initialization required void BladeRfTxComponent::initialize() { // Set up the input DataBuffer inBuf_ = castToType< complex<float> >(inputBuffers.at(0)); // Initialize raw sample vector to some multiple of block size rawSampleBuffer_.data.resize(128 * BLADERF_SAMPLE_BLOCK_SIZE); // Set up the BladeRF try { // Create the device LOG(LINFO) << "Trying to open device " << deviceName_x; int ret = bladerf_open(&device_, deviceName_x.c_str()); if (ret != 0) { throw IrisException("Failed to open bladeRF device!"); } // Check whether FPGA is configured yet if (bladerf_is_fpga_configured(device_) != 1 ) { // try to load FPGA image if (not fpgaImage_x.empty()) { ret = bladerf_load_fpga(device_, fpgaImage_x.c_str()); if (ret != 0) { throw IrisException("Failed to load FPGA to bladeRF!"); } else { LOG(LINFO) << "FPGA image successfully loaded."; } } else { throw IrisException("BladeRF FPGA is not configured and no FPGA image given!"); } } // Print some information about device struct bladerf_version version; if (bladerf_fw_version(device_, &version) == 0) { LOG(LINFO) << "Using FW " << version.describe; } if (bladerf_fpga_version(device_, &version) == 0) { LOG(LINFO) << "Using FPGA " << version.describe; } if (bladerf_is_fpga_configured(device_) != 1 ) { throw IrisException("BladeRF FPGA is not configured!"); } // setting up sync config ret = bladerf_sync_config(device_, BLADERF_MODULE_TX, BLADERF_FORMAT_SC16_Q11, BLADERF_DEFAULT_STREAM_BUFFERS, BLADERF_DEFAULT_STREAM_SAMPLES, BLADERF_DEFAULT_STREAM_XFERS, BLADERF_SYNC_TIMEOUT_MS); if (ret != 0) { throw IrisException("Couldn't enable BladeRF Tx sync handle!"); LOG(LERROR) << bladerf_strerror(ret); } // Turn on transmitter ret = bladerf_enable_module(device_, BLADERF_MODULE_TX, true); if ( ret != 0 ) { throw IrisException("Couldn't enable BladeRF Tx module!"); } // Set sample rate uint32_t actualValue; ret = bladerf_set_sample_rate(device_, BLADERF_MODULE_TX, (uint32_t)rate_x, &actualValue); if (ret != 0) { throw IrisException("Failed to set sample rate!"); } LOG(LINFO) << "Actual Tx sample rate is: " << actualValue << " Hz"; // Set center frequency ret = bladerf_set_frequency(device_, BLADERF_MODULE_TX, frequency_x); if (ret != 0) { throw IrisException("Failed to set center frequency!"); } bladerf_get_frequency(device_, BLADERF_MODULE_TX, &actualValue); LOG(LINFO) << "Actual Tx center frequency is: " << actualValue << " Hz"; // Set bandwidth ret = bladerf_set_bandwidth(device_, BLADERF_MODULE_TX, bw_x, &actualValue); if (ret != 0) { throw IrisException("Failed to set receive bandwidth!"); } LOG(LINFO) << "Actual Tx bandwidth is " << actualValue << " Hz"; // Set VGA1 gain int actualGain; ret = bladerf_set_txvga1(device_, vga1Gain_x); if (ret != 0) { throw IrisException("Failed to set VGA1 gain!"); } bladerf_get_txvga1(device_, &actualGain); LOG(LINFO) << "Actual VGA1 gain is " << actualGain << " dB"; // Set VGA2 gain ret = bladerf_set_txvga2(device_, vga2Gain_x); if (ret != 0) { throw IrisException("Failed to set VGA2 gain!"); } bladerf_get_txvga2(device_, &actualGain); LOG(LINFO) << "Actual VGA2 gain is " << actualGain << " dB"; } catch(const boost::exception &e) { throw IrisException(boost::diagnostic_information(e)); } catch(std::exception& e) { throw IrisException(e.what()); } }
/* We've found that running samples through the LMS6 tends to be required * for the TX LPF calibration to converge */ static inline int tx_lpf_dummy_tx(struct bladerf *dev) { int status; int retval = 0; struct bladerf_metadata meta; int16_t zero_sample[] = { 0, 0 }; bladerf_loopback loopback_backup; struct bladerf_rational_rate sample_rate_backup; memset(&meta, 0, sizeof(meta)); status = bladerf_get_loopback(dev, &loopback_backup); if (status != 0) { return status; } status = bladerf_get_rational_sample_rate(dev, BLADERF_MODULE_TX, &sample_rate_backup); if (status != 0) { return status; } status = bladerf_set_loopback(dev, BLADERF_LB_BB_TXVGA1_RXVGA2); if (status != 0) { goto out; } status = bladerf_set_sample_rate(dev, BLADERF_MODULE_TX, 3000000, NULL); if (status != 0) { goto out; } status = bladerf_sync_config(dev, BLADERF_MODULE_TX, BLADERF_FORMAT_SC16_Q11_META, 64, 16384, 16, 1000); if (status != 0) { goto out; } status = bladerf_enable_module(dev, BLADERF_MODULE_TX, true); if (status != 0) { goto out; } meta.flags = BLADERF_META_FLAG_TX_BURST_START | BLADERF_META_FLAG_TX_BURST_END | BLADERF_META_FLAG_TX_NOW; status = bladerf_sync_tx(dev, zero_sample, 1, &meta, 2000); if (status != 0) { goto out; } out: status = bladerf_enable_module(dev, BLADERF_MODULE_TX, false); if (status != 0 && retval == 0) { retval = status; } status = bladerf_set_rational_sample_rate(dev, BLADERF_MODULE_TX, &sample_rate_backup, NULL); if (status != 0 && retval == 0) { retval = status; } status = bladerf_set_loopback(dev, loopback_backup); if (status != 0 && retval == 0) { retval = status; } return retval; }
int main(int argc, char *argv[]) { sim_t s; char *devstr = NULL; int c; // Initialize structures init_sim(&s); // Allocate TX buffer to hold each block of samples to transmit. s.tx.buffer = (int16_t *)malloc(SAMPLES_PER_BUFFER * sizeof(int16_t) * 2); // for 16-bit I and Q samples if (s.tx.buffer == NULL) { fprintf(stderr, "Failed to allocate TX buffer.\n"); goto out; } // Allocate FIFOs to hold 0.1 seconds of I/Q samples each. s.fifo = (int16_t *)malloc(FIFO_LENGTH * sizeof(int16_t) * 2); // for 16-bit I and Q samples if (s.fifo == NULL) { fprintf(stderr, "Failed to allocate I/Q sample buffer.\n"); goto out; } // Initializing device. printf("Opening and initializing device...\n"); s.status = bladerf_open(&s.tx.dev, devstr); if (s.status != 0) { fprintf(stderr, "Failed to open device: %s\n", bladerf_strerror(s.status)); goto out; } s.status = bladerf_set_frequency(s.tx.dev, BLADERF_MODULE_TX, TX_FREQUENCY); if (s.status != 0) { fprintf(stderr, "Faield to set TX frequency: %s\n", bladerf_strerror(s.status)); goto out; } else { printf("TX frequency: %u Hz\n", TX_FREQUENCY); } s.status = bladerf_set_sample_rate(s.tx.dev, BLADERF_MODULE_TX, TX_SAMPLERATE, NULL); if (s.status != 0) { fprintf(stderr, "Failed to set TX sample rate: %s\n", bladerf_strerror(s.status)); goto out; } else { printf("TX sample rate: %u sps\n", TX_SAMPLERATE); } s.status = bladerf_set_bandwidth(s.tx.dev, BLADERF_MODULE_TX, TX_BANDWIDTH, NULL); if (s.status != 0) { fprintf(stderr, "Failed to set TX bandwidth: %s\n", bladerf_strerror(s.status)); goto out; } else { printf("TX bandwidth: %u Hz\n", TX_BANDWIDTH); } s.status = bladerf_set_txvga1(s.tx.dev, TX_VGA1); if (s.status != 0) { fprintf(stderr, "Failed to set TX VGA1 gain: %s\n", bladerf_strerror(s.status)); goto out; } else { printf("TX VGA1 gain: %d dB\n", TX_VGA1); } s.status = bladerf_set_txvga2(s.tx.dev, TX_VGA2); if (s.status != 0) { fprintf(stderr, "Failed to set TX VGA2 gain: %s\n", bladerf_strerror(s.status)); goto out; } else { printf("TX VGA2 gain: %d dB\n", TX_VGA2); } // Start GPS task. s.status = start_gps_task(&s); if (s.status < 0) { fprintf(stderr, "Failed to start GPS task.\n"); goto out; } else printf("Creating GPS task...\n"); // Wait until GPS task is initialized pthread_mutex_lock(&(s.tx.lock)); while (!s.gps.ready) pthread_cond_wait(&(s.gps.initialization_done), &(s.tx.lock)); pthread_mutex_unlock(&(s.tx.lock)); // Fillfull the FIFO. if (is_fifo_write_ready(&s)) pthread_cond_signal(&(s.fifo_write_ready)); // Configure the TX module for use with the synchronous interface. s.status = bladerf_sync_config(s.tx.dev, BLADERF_MODULE_TX, BLADERF_FORMAT_SC16_Q11, NUM_BUFFERS, SAMPLES_PER_BUFFER, NUM_TRANSFERS, TIMEOUT_MS); if (s.status != 0) { fprintf(stderr, "Failed to configure TX sync interface: %s\n", bladerf_strerror(s.status)); goto out; } // We must always enable the modules *after* calling bladerf_sync_config(). s.status = bladerf_enable_module(s.tx.dev, BLADERF_MODULE_TX, true); if (s.status != 0) { fprintf(stderr, "Failed to enable TX module: %s\n", bladerf_strerror(s.status)); goto out; } // Start TX task s.status = start_tx_task(&s); if (s.status < 0) { fprintf(stderr, "Failed to start TX task.\n"); goto out; } else printf("Creating TX task...\n"); // Running... printf("Running...\n"); printf("Press 'q' to exit.\n"); while (1) { c = _getch(); if (c=='q') break; } // // TODO: Cleaning up the threads properly. // printf("\nDone!\n"); // Disable TX module, shutting down our underlying TX stream. s.status = bladerf_enable_module(s.tx.dev, BLADERF_MODULE_TX, false); if (s.status != 0) { fprintf(stderr, "Failed to disable TX module: %s\n", bladerf_strerror(s.status)); } out: // Free up resources if (s.tx.buffer != NULL) free(s.tx.buffer); if (s.fifo != NULL) free(s.fifo); printf("Closing device...\n"); bladerf_close(s.tx.dev); return(0); }