int enable(struct bladerf* dev, bool enabled) { int status; if(enabled) printf("%-50s", "Enabling TX... "); else printf("%-50s", "Disabling TX... "); fflush(stdout); status = bladerf_enable_module(dev, BLADERF_MODULE_TX, enabled); if(status) { printf(KRED "Failed: %s" KNRM "\n", bladerf_strerror(status)); bladerf_close(dev); return 1; } printf(KGRN "OK" KNRM "\n"); if(enabled) printf("%-50s", "Enabling RX... "); else printf("%-50s", "Disabling RX... "); fflush(stdout); status = bladerf_enable_module(dev, BLADERF_MODULE_RX, enabled); if(status) { printf(KRED "Failed: %s" KNRM "\n", bladerf_strerror(status)); bladerf_close(dev); return 1; } printf(KGRN "OK" KNRM "\n"); return 0; }
int bladerf_init_device(struct bladerf *dev) { unsigned int actual; uint32_t val; /* Readback the GPIO values to see if they are default or already set */ bladerf_config_gpio_read( dev, &val ); if (val == 0) { log_verbose( "Default GPIO value found - initializing device\n" ); /* Set the GPIO pins to enable the LMS and select the low band */ bladerf_config_gpio_write( dev, 0x57 ); /* Set the internal LMS register to enable RX and TX */ bladerf_lms_write( dev, 0x05, 0x3e ); /* LMS FAQ: Improve TX spurious emission performance */ bladerf_lms_write( dev, 0x47, 0x40 ); /* LMS FAQ: Improve ADC performance */ bladerf_lms_write( dev, 0x59, 0x29 ); /* LMS FAQ: Common mode voltage for ADC */ bladerf_lms_write( dev, 0x64, 0x36 ); /* LMS FAQ: Higher LNA Gain */ bladerf_lms_write( dev, 0x79, 0x37 ); /* FPGA workaround: Set IQ polarity for RX */ bladerf_lms_write( dev, 0x5a, 0xa0 ); /* Set a default saplerate */ bladerf_set_sample_rate( dev, BLADERF_MODULE_TX, 1000000, &actual ); bladerf_set_sample_rate( dev, BLADERF_MODULE_RX, 1000000, &actual ); /* Enable TX and RX */ bladerf_enable_module( dev, BLADERF_MODULE_TX, false ); bladerf_enable_module( dev, BLADERF_MODULE_RX, false ); /* Set a default frequency of 1GHz */ bladerf_set_frequency( dev, BLADERF_MODULE_TX, 1000000000 ); bladerf_set_frequency( dev, BLADERF_MODULE_RX, 1000000000 ); /* Set the calibrated VCTCXO DAC value */ bladerf_dac_write( dev, dev->dac_trim ); } /* TODO: Read this return from the SPI calls */ return 0; }
void rxtx_task_exec_stop(struct rxtx_data *rxtx, unsigned char *requests, struct bladerf *dev) { int status; *requests = rxtx_get_requests(rxtx, RXTX_TASK_REQ_STOP | RXTX_TASK_REQ_SHUTDOWN); pthread_mutex_lock(&rxtx->data_mgmt.lock); bladerf_deinit_stream(rxtx->data_mgmt.stream); rxtx->data_mgmt.stream = NULL; pthread_mutex_unlock(&rxtx->data_mgmt.lock); pthread_mutex_lock(&rxtx->file_mgmt.file_lock); if (rxtx->file_mgmt.file != NULL) { fclose(rxtx->file_mgmt.file); rxtx->file_mgmt.file = NULL; } pthread_mutex_unlock(&rxtx->file_mgmt.file_lock); if (*requests & RXTX_TASK_REQ_SHUTDOWN) { rxtx_set_state(rxtx, RXTX_STATE_SHUTDOWN); } else { rxtx_set_state(rxtx, RXTX_STATE_IDLE); } status = bladerf_enable_module(dev, rxtx->module, false); if (status < 0) { set_last_error(&rxtx->last_error, ETYPE_BLADERF, status); } *requests = 0; rxtx_release_wait(rxtx); }
void Bladerf1Output::closeDevice() { int res; if (m_dev == 0) { // was never open return; } if ((res = bladerf_enable_module(m_dev, BLADERF_MODULE_TX, false)) < 0) { qCritical("BladerfOutput::closeDevice: bladerf_enable_module with return code %d", res); } if (m_deviceAPI->getSourceBuddies().size() == 0) { qDebug("BladerfOutput::closeDevice: closing device since Rx side is not open"); if (m_dev != 0) // close BladeRF { bladerf_close(m_dev); } } m_sharedParams.m_dev = 0; m_dev = 0; }
int rf_blade_stop_rx_stream(void *h) { rf_blade_handler_t *handler = (rf_blade_handler_t*) h; int status = bladerf_enable_module(handler->dev, BLADERF_MODULE_RX, false); 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, false); if (status != 0) { fprintf(stderr, "Failed to enable TX module: %s\n", bladerf_strerror(status)); return status; } handler->rx_stream_enabled = false; handler->tx_stream_enabled = false; return 0; }
BladeRfTxComponent::~BladeRfTxComponent() { if (device_) { if (bladerf_enable_module(device_, BLADERF_MODULE_TX, false) != 0) LOG(LERROR) << "Couldn't shutdown BladeRF Tx module!"; bladerf_close(device_); } }
void radio_stop(struct bladerf *dev) { int status; if (dev == NULL){ return; } //Disable tx module status = bladerf_enable_module(dev, BLADERF_MODULE_TX, false); if (status != 0){ fprintf(stderr, "Couldn't disable TX module: %s\n", bladerf_strerror(status)); } //Disable rx module status = bladerf_enable_module(dev, BLADERF_MODULE_RX, false); if (status != 0){ fprintf(stderr, "Couldn't disable RX module: %s\n", bladerf_strerror(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; }
static void deinit(struct repeater *repeater) { if (repeater->device) { if (repeater->rx_stream) { bladerf_deinit_stream(repeater->rx_stream); } if (repeater->tx_stream) { bladerf_deinit_stream(repeater->tx_stream); } bladerf_enable_module(repeater->device, BLADERF_MODULE_RX, false); bladerf_enable_module(repeater->device, BLADERF_MODULE_TX, false); bladerf_close(repeater->device); repeater->device = NULL; } }
int main(int argc, char *argv[]) { int status = 0; struct bladerf *dev = NULL; struct bladerf_devinfo dev_info; /* Initialize the information used to identify the desired device * to all wildcard (i.e., "any device") values */ bladerf_init_devinfo(&dev_info); /* Request a device with the provided serial number. * Invalid strings should simply fail to match a device. */ if (argc >= 2) { fprintf(stdout, "dev_info.serial: %s", dev_info.serial); strncpy(dev_info.serial, argv[1], sizeof(dev_info.serial) - 1); } status = bladerf_open_with_devinfo(&dev, &dev_info); if (status != 0) { fprintf(stderr, "Unable to open device: %s\n", bladerf_strerror(status)); return 1; } /* A quick check that this works is to watch LO leakage on a VSA */ status = bladerf_enable_module(dev, BLADERF_MODULE_TX, true); if (status != 0) { fprintf(stderr, "Failed to enable TX module: %s\n", bladerf_strerror(status)); return status; } status = example(dev, BLADERF_MODULE_TX); bladerf_enable_module(dev, BLADERF_MODULE_TX, false); bladerf_close(dev); return status; }
/** [tx_meta_deinit] */ void deinit(struct bladerf *dev, int16_t *samples) { printf("\nDeinitalizing device.\n"); /* Disable TX module, shutting down our underlying TX stream */ int status = bladerf_enable_module(dev, BLADERF_MODULE_TX, false); if (status != 0) { fprintf(stderr, "Failed to disable TX module: %s\n", bladerf_strerror(status)); } /* Deinitialize and free resources */ free(samples); bladerf_close(dev); }
static int tx_start_init(struct cli_state *s) { int status = CMD_RET_UNKNOWN; enum rxtx_state state; switch(s->rxtx_data->tx.common.file_fmt) { case RXTX_FMT_CSV_C16: status = tx_csv_to_c16(s); if (status < 0) return status; printf("\nConverted CSV file to binary file. Using %s\n", s->rxtx_data->tx.common.file_path); printf("Note that this program will not delete the temporary file.\n\n"); /* Fall through - if we hit this line we're now using * a temporary binary file */ case RXTX_FMT_BINLE_C16: case RXTX_FMT_BINBE_C16: s->rxtx_data->tx.read_samples = rxtx_read_bin_c16; break; /* This shouldn't happen...*/ default: assert(0); return CMD_RET_UNKNOWN; } status = bladerf_enable_module(s->dev, BLADERF_MODULE_TX, true); if (status >= 0) { set_state(&s->rxtx_data->tx.common, RXTX_STATE_RUNNING, true); /* Don't expect to poll here long... replace with cond var? */ while ((state = get_state(&s->rxtx_data->tx.common)) == RXTX_STATE_IDLE) { usleep(100000); } if (state == RXTX_STATE_RUNNING) { status = 0; } } return status; }
static int rx_start_init(struct cli_state *s) { enum rxtx_state state; int status = CMD_RET_UNKNOWN; struct rx_cfg *rx = &s->rxtx_data->rx; switch(s->rxtx_data->rx.common.file_fmt) { case RXTX_FMT_CSV_C16: rx->write_samples = rxtx_write_csv_c16; break; case RXTX_FMT_BINLE_C16: case RXTX_FMT_BINBE_C16: rx->write_samples = rxtx_write_bin_c16; break; /* This shouldn't happen...*/ default: assert(0); return CMD_RET_UNKNOWN; } status = bladerf_enable_module(s->dev, BLADERF_MODULE_RX, true); if (status >= 0) { set_state(&rx->common, RXTX_STATE_RUNNING, true); while ((state = get_state(&rx->common)) == RXTX_STATE_IDLE) { usleep(100000); } if (state == RXTX_STATE_RUNNING) { status = 0; } } 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); }
static int run(struct bladerf *dev, struct app_params *p, int16_t *samples, const struct test_case *t) { int status, status_out; struct bladerf_metadata meta; uint64_t timestamp; unsigned int gap; uint32_t counter; uint64_t tscount_diff; unsigned int i; bool suppress_overrun_msg = false; unsigned int overruns = 0; bool prev_iter_overrun = false; /* Clear out metadata and request that we just received any available * samples, with the timestamp filled in for us */ memset(&meta, 0, sizeof(meta)); meta.flags = BLADERF_META_FLAG_RX_NOW; status = enable_counter_mode(dev, true); if (status != 0) { goto out; } status = perform_sync_init(dev, BLADERF_MODULE_RX, 0, p); if (status != 0) { goto out; } /* Initial read to get a starting timestamp, and counter value */ gap = get_gap(p, t); status = bladerf_sync_rx(dev, samples, gap, &meta, p->timeout_ms); if (status != 0) { fprintf(stderr, "Intial RX failed: %s\n", bladerf_strerror(status)); goto out; } counter = extract_counter_val((uint8_t*) samples); timestamp = meta.timestamp; assert(timestamp >= (uint64_t) counter); tscount_diff = timestamp - (uint64_t) counter; if (t->gap != 0) { printf("\nTest Case: Read size=%"PRIu64" samples, %u iterations\n", t->gap, t->iterations); } else { printf("\nTest Case: Random read size, %u iterations\n", t->iterations); } printf("--------------------------------------------------------\n"); assert((timestamp - tscount_diff) <= UINT32_MAX); status = check_data(samples, &meta, UINT64_MAX, (uint32_t) (timestamp - tscount_diff), meta.actual_count, &suppress_overrun_msg); if (status == DETECTED_OVERRUN) { overruns++; status = 0; } printf("Timestamp-counter diff: %"PRIu64"\n", tscount_diff); printf("Initial timestamp: 0x%016"PRIx64"\n", meta.timestamp); printf("Intital counter value: 0x%08"PRIx32"\n", counter); printf("Initial status: 0x%08"PRIu32"\n", meta.status); for (i = 0; i < t->iterations && status == 0; i++) { timestamp = meta.timestamp + gap; gap = get_gap(p, t); status = bladerf_sync_rx(dev, samples, gap, &meta, p->timeout_ms); if (status != 0) { fprintf(stderr, "RX %u failed: %s\n", i, bladerf_strerror(status)); goto out; } /* If an overrun occured on the previous iteration, we don't know what * the timestamp will actually be on this iteration. */ if (prev_iter_overrun) { timestamp = meta.timestamp; } status = check_data(samples, &meta, timestamp, (uint32_t) (timestamp - tscount_diff), gap, &suppress_overrun_msg); if (status == DETECTED_OVERRUN) { overruns++; status = 0; prev_iter_overrun = true; } } if (status != 0) { printf("Test failed due to errors.\n"); } else if (overruns != 0) { printf("Test failed due to %u overruns.\n", overruns); status = -1; } else { printf("Test passed.\n"); } out: status_out = bladerf_enable_module(dev, BLADERF_MODULE_RX, false); if (status_out != 0) { fprintf(stderr, "Failed to disable RX module: %s\n", bladerf_strerror(status)); } status = first_error(status, status_out); status_out = enable_counter_mode(dev, false); status = first_error(status, status_out); return status; }
int main(int argc, char *argv[]) { int status; unsigned int actual; struct bladerf *dev; struct bladerf_stream *stream; struct test_data test_data; bool conv_ok; if (argc != 4 && argc != 5) { fprintf(stderr, "Usage: %s [tx|rx] <samples per buffer> <# buffers> [# samples]\n", argv[0]); return EXIT_FAILURE; } if (strcasecmp(argv[1], "rx") == 0 ) { test_data.module = BLADERF_MODULE_RX ; } else if (strcasecmp(argv[1], "tx") == 0 ) { test_data.module = BLADERF_MODULE_TX; } else { fprintf(stderr, "Invalid module: %s\n", argv[1]); return EXIT_FAILURE; } test_data.idx = 0; test_data.fout = NULL; test_data.samples_per_buffer = str2int(argv[2], 1, INT_MAX, &conv_ok); if (!conv_ok) { fprintf(stderr, "Invalid samples per buffer value: %s\n", argv[2]); return EXIT_FAILURE; } test_data.num_buffers = str2int(argv[3], 1, INT_MAX, &conv_ok); if (!conv_ok) { fprintf(stderr, "Invalid # buffers: %s\n", argv[3]); return EXIT_FAILURE; } if(test_data.module == BLADERF_MODULE_RX && argc == 5) { test_data.samples_left = str2int(argv[4], 1, INT_MAX, &conv_ok); if(!conv_ok) { fprintf(stderr, "Invalid number of samples: %s\n", argv[4]); return EXIT_FAILURE; } } if (signal(SIGINT, handler) == SIG_ERR || signal(SIGTERM, handler) == SIG_ERR) { fprintf(stderr, "Failed to set up signal handler\n"); return EXIT_FAILURE; } status = bladerf_open(&dev, NULL); if (status < 0) { fprintf(stderr, "Failed to open device: %s\n", bladerf_strerror(status)); return EXIT_FAILURE; } status = bladerf_is_fpga_configured(dev); if (status < 0) { fprintf(stderr, "Failed to determine FPGA state: %s\n", bladerf_strerror(status)); return EXIT_FAILURE; } else if (status == 0) { fprintf(stderr, "Error: FPGA is not loaded.\n"); bladerf_close(dev); return EXIT_FAILURE; } if (!status) { status = bladerf_set_frequency(dev, test_data.module, 1000000000); if (status < 0) { fprintf(stderr, "Failed to set frequency: %s\n", bladerf_strerror(status)); bladerf_close(dev); return EXIT_FAILURE; } } if (!status) { status = bladerf_set_sample_rate(dev, test_data.module, 40000000, &actual); if (status < 0) { fprintf(stderr, "Failed to set sample rate: %s\n", bladerf_strerror(status)); bladerf_close(dev); return EXIT_FAILURE; } } /* Initialize the stream */ status = bladerf_init_stream( &stream, dev, stream_callback, &test_data.buffers, test_data.num_buffers, BLADERF_FORMAT_SC16_Q12, test_data.samples_per_buffer, test_data.num_buffers, &test_data ) ; /* Populate buffers with test data */ if( test_data.module == BLADERF_MODULE_TX ) { if (populate_test_data(&test_data) ) { fprintf(stderr, "Failed to populated test data\n"); bladerf_deinit_stream(stream); bladerf_close(dev); return EXIT_FAILURE; } } else { /* Open up file we'll read test data to */ test_data.fout = fopen( "samples.txt", "w" ); if (!test_data.fout) { fprintf(stderr, "Failed to open samples.txt: %s\n", strerror(errno)); bladerf_deinit_stream(stream); bladerf_close(dev); return EXIT_FAILURE; } } status = bladerf_enable_module(dev, test_data.module, true); if (status < 0) { fprintf(stderr, "Failed to enable module: %s\n", bladerf_strerror(status)); } if (!status) { /* Start stream and stay there until we kill the stream */ status = bladerf_stream(stream, test_data.module); if (status < 0) { fprintf(stderr, "Stream error: %s\n", bladerf_strerror(status)); } } status = bladerf_enable_module(dev, test_data.module, false); if (status < 0) { fprintf(stderr, "Failed to enable module: %s\n", bladerf_strerror(status)); } bladerf_deinit_stream(stream); bladerf_close(dev); if (test_data.fout) { fclose(test_data.fout); } return 0; }
int sync_rx_example(struct bladerf *dev) { int status, ret; bool done = false; bool have_tx_data = false; /** [user_buffers] */ /* "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 */ /* Allocate a buffer to store received samples in */ rx_samples = malloc(samples_len * 2 * 1 * 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 * 1 * sizeof(int16_t)); if (tx_samples == NULL) { perror("malloc"); free(rx_samples); return BLADERF_ERR_MEM; } /** [user_buffers] */ /* Initialize synch interface on RX and TX */ status = init_sync(dev); if (status != 0) { goto out; } /** [enable_modules] */ status = bladerf_enable_module(dev, BLADERF_RX, true); if (status != 0) { fprintf(stderr, "Failed to enable RX: %s\n", bladerf_strerror(status)); goto out; } status = bladerf_enable_module(dev, BLADERF_TX, true); if (status != 0) { fprintf(stderr, "Failed to enable TX: %s\n", bladerf_strerror(status)); goto out; } /** [enable_modules] */ /** [rxtx_loop] */ while (status == 0 && !done) { /* Receive samples */ status = bladerf_sync_rx(dev, rx_samples, samples_len, NULL, 5000); if (status == 0) { /* Process these samples, and potentially produce a response * to transmit */ done = do_work(rx_samples, samples_len, &have_tx_data, tx_samples, samples_len); if (!done && have_tx_data) { /* Transmit a response */ 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 * reaching the RF front-end */ usleep(2000000); } /** [rxtx_loop] */ out: ret = status; /** [disable_modules] */ /* Disable RX, shutting down our underlying RX stream */ status = bladerf_enable_module(dev, BLADERF_RX, false); if (status != 0) { fprintf(stderr, "Failed to disable RX: %s\n", bladerf_strerror(status)); } /* Disable TX, shutting down our underlying TX stream */ status = bladerf_enable_module(dev, BLADERF_TX, false); if (status != 0) { fprintf(stderr, "Failed to disable TX: %s\n", bladerf_strerror(status)); } /* Free up our resources */ free(rx_samples); free(tx_samples); /** [disable_modules] */ return ret; }
int calibrate_dc(struct cli_state *s, unsigned int ops) { int retval = 0; int status = BLADERF_ERR_UNEXPECTED; struct settings rx_settings, tx_settings; bladerf_loopback loopback; int16_t dc_i, dc_q; if (IS_RX_CAL(ops)) { status = backup_and_update_settings(s->dev, BLADERF_MODULE_RX, &rx_settings); if (status != 0) { s->last_lib_error = status; return CLI_RET_LIBBLADERF; } } if (IS_TX_CAL(ops)) { status = backup_and_update_settings(s->dev, BLADERF_MODULE_TX, &tx_settings); if (status != 0) { s->last_lib_error = status; return CLI_RET_LIBBLADERF; } } status = bladerf_get_loopback(s->dev, &loopback); if (status != 0) { s->last_lib_error = status; return CLI_RET_LIBBLADERF; } if (IS_RX_CAL(ops)) { status = set_rx_dc(s->dev, 0, 0); if (status != 0) { goto error; } status = bladerf_enable_module(s->dev, BLADERF_MODULE_RX, true); if (status != 0) { goto error; } } if (IS_TX_CAL(ops)) { status = bladerf_enable_module(s->dev, BLADERF_MODULE_RX, true); if (status != 0) { goto error; } status = bladerf_set_loopback(s->dev, BLADERF_LB_BB_TXVGA1_RXVGA2); if (status != 0) { goto error; } status = bladerf_enable_module(s->dev, BLADERF_MODULE_TX, true); if (status != 0) { goto error; } status = dummy_tx(s->dev); if (status != 0) { goto error; } status = bladerf_enable_module(s->dev, BLADERF_MODULE_TX, false); if (status != 0) { goto error; } } status = bladerf_set_loopback(s->dev, BLADERF_LB_NONE); if (status != 0) { goto error; } putchar('\n'); if (IS_CAL(CAL_DC_LMS_TUNING, ops)) { printf(" Calibrating LMS LPF tuning module...\n"); status = bladerf_calibrate_dc(s->dev, BLADERF_DC_CAL_LPF_TUNING); if (status != 0) { goto error; } else { struct bladerf_lms_dc_cals dc_cals; status = bladerf_lms_get_dc_cals(s->dev, &dc_cals); if (status != 0) { goto error; } printf(" LPF tuning module: %d\n\n", dc_cals.lpf_tuning); } } if (IS_CAL(CAL_DC_LMS_TXLPF, ops)) { printf(" Calibrating LMS TX LPF modules...\n"); status = bladerf_calibrate_dc(s->dev, BLADERF_DC_CAL_TX_LPF); if (status != 0) { goto error; } else { struct bladerf_lms_dc_cals dc_cals; status = bladerf_lms_get_dc_cals(s->dev, &dc_cals); if (status != 0) { goto error; } printf(" TX LPF I filter: %d\n", dc_cals.tx_lpf_i); printf(" TX LPF Q filter: %d\n\n", dc_cals.tx_lpf_q); } } if (IS_CAL(CAL_DC_LMS_RXLPF, ops)) { printf(" Calibrating LMS RX LPF modules...\n"); status = bladerf_calibrate_dc(s->dev, BLADERF_DC_CAL_RX_LPF); if (status != 0) { goto error; } else { struct bladerf_lms_dc_cals dc_cals; status = bladerf_lms_get_dc_cals(s->dev, &dc_cals); if (status != 0) { goto error; } printf(" RX LPF I filter: %d\n", dc_cals.rx_lpf_i); printf(" RX LPF Q filter: %d\n\n", dc_cals.rx_lpf_q); } } if (IS_CAL(CAL_DC_LMS_RXVGA2, ops)) { printf(" Calibrating LMS RXVGA2 modules...\n"); status = bladerf_calibrate_dc(s->dev, BLADERF_DC_CAL_RXVGA2); if (status != 0) { goto error; } else { struct bladerf_lms_dc_cals dc_cals; status = bladerf_lms_get_dc_cals(s->dev, &dc_cals); if (status != 0) { goto error; } printf(" RX VGA2 DC reference module: %d\n", dc_cals.dc_ref); printf(" RX VGA2 stage 1, I channel: %d\n", dc_cals.rxvga2a_i); printf(" RX VGA2 stage 1, Q channel: %d\n", dc_cals.rxvga2a_q); printf(" RX VGA2 stage 2, I channel: %d\n", dc_cals.rxvga2b_i); printf(" RX VGA2 stage 2, Q channel: %d\n\n", dc_cals.rxvga2b_q); } } if (IS_CAL(CAL_DC_AUTO_RX, ops)) { int16_t avg_i, avg_q; status = calibrate_dc_rx(s, &dc_i, &dc_q, &avg_i, &avg_q); if (status != 0) { goto error; } else { printf(" RX DC I Setting = %d, error ~= %d\n", dc_i, avg_i); printf(" RX DC Q Setting = %d, error ~= %d\n\n", dc_q, avg_q); } } if (IS_CAL(CAL_DC_AUTO_TX, ops)) { float error_i, error_q; status = calibrate_dc_tx(s, &dc_i, &dc_q, &error_i, &error_q); if (status != 0) { goto error; } else { printf(" TX DC I Setting = %d, error ~= %f\n", dc_i, error_i); printf(" TX DC Q Setting = %d, error ~= %f\n\n", dc_q, error_q); } } error: retval = status; if (IS_RX_CAL(ops)) { status = restore_settings(s->dev, BLADERF_MODULE_RX, &rx_settings); retval = first_error(retval, status); } if (IS_TX_CAL(ops)) { status = restore_settings(s->dev, BLADERF_MODULE_TX, &tx_settings); retval = first_error(retval, status); } status = bladerf_enable_module(s->dev, BLADERF_MODULE_RX, false); retval = first_error(retval, status); status = bladerf_enable_module(s->dev, BLADERF_MODULE_TX, false); retval = first_error(retval, status); status = bladerf_set_loopback(s->dev, loopback); retval = first_error(retval, status); if (retval != 0) { s->last_lib_error = retval; retval = CLI_RET_LIBBLADERF; } return retval; }
/* See libbladeRF's dc_cal_table.c for the packed table data format */ int calibrate_dc_gen_tbl(struct cli_state *s, bladerf_module module, const char *filename, unsigned int f_low, unsigned f_inc, unsigned int f_high) { int retval, status; size_t off; struct bladerf_lms_dc_cals lms_dc_cals; unsigned int f; struct settings settings; bladerf_loopback loopback_backup; struct bladerf_image *image = NULL; const uint16_t magic = HOST_TO_LE16(0x1ab1); const uint32_t reserved = HOST_TO_LE32(0x00000000); const uint32_t tbl_version = HOST_TO_LE32(0x00000001); const size_t lms_data_size = 10; /* 10 uint8_t register values */ const uint32_t n_frequencies = (f_high - f_low) / f_inc + 1; const uint32_t n_frequencies_le = HOST_TO_LE32(n_frequencies); const size_t entry_size = sizeof(uint32_t) + /* Frequency */ 2 * sizeof(int16_t); /* DC I and Q valus */ const size_t table_size = n_frequencies * entry_size; const size_t data_size = sizeof(magic) + sizeof(reserved) + sizeof(tbl_version) + sizeof(n_frequencies_le) + lms_data_size + table_size; assert(data_size <= UINT_MAX); status = backup_and_update_settings(s->dev, module, &settings); if (status != 0) { return status; } status = bladerf_get_loopback(s->dev, &loopback_backup); if (status != 0) { return status; } status = bladerf_lms_get_dc_cals(s->dev, &lms_dc_cals); if (status != 0) { goto out; } if (module == BLADERF_MODULE_RX) { image = bladerf_alloc_image(BLADERF_IMAGE_TYPE_RX_DC_CAL, 0xffffffff, (unsigned int) data_size); } else { image = bladerf_alloc_image(BLADERF_IMAGE_TYPE_TX_DC_CAL, 0xffffffff, (unsigned int) data_size); } if (image == NULL) { status = BLADERF_ERR_MEM; goto out; } status = bladerf_get_serial(s->dev, image->serial); if (status != 0) { goto out; } if (module == BLADERF_MODULE_RX) { status = bladerf_set_loopback(s->dev, BLADERF_LB_NONE); if (status != 0) { goto out; } } off = 0; memcpy(&image->data[off], &magic, sizeof(magic)); off += sizeof(magic); memcpy(&image->data[off], &reserved, sizeof(reserved)); off += sizeof(reserved); memcpy(&image->data[off], &tbl_version, sizeof(tbl_version)); off += sizeof(tbl_version); memcpy(&image->data[off], &n_frequencies_le, sizeof(n_frequencies_le)); off += sizeof(n_frequencies_le); image->data[off++] = (uint8_t)lms_dc_cals.lpf_tuning; image->data[off++] = (uint8_t)lms_dc_cals.tx_lpf_i; image->data[off++] = (uint8_t)lms_dc_cals.tx_lpf_q; image->data[off++] = (uint8_t)lms_dc_cals.rx_lpf_i; image->data[off++] = (uint8_t)lms_dc_cals.rx_lpf_q; image->data[off++] = (uint8_t)lms_dc_cals.dc_ref; image->data[off++] = (uint8_t)lms_dc_cals.rxvga2a_i; image->data[off++] = (uint8_t)lms_dc_cals.rxvga2a_q; image->data[off++] = (uint8_t)lms_dc_cals.rxvga2b_i; image->data[off++] = (uint8_t)lms_dc_cals.rxvga2b_q; putchar('\n'); for (f = f_low; f <= f_high; f += f_inc) { const uint32_t frequency = HOST_TO_LE32((uint32_t)f); int16_t dc_i, dc_q; printf(" Calibrating @ %u Hz...", f); status = bladerf_set_frequency(s->dev, module, f); if (status != 0) { goto out; } if (module == BLADERF_MODULE_RX) { int16_t error_i, error_q; status = calibrate_dc_rx(s, &dc_i, &dc_q, &error_i, &error_q); printf(" I=%-4d (avg: %-4d), Q=%-4d (avg: %-4d)\r", dc_i, error_i, dc_q, error_q); } else { float error_i, error_q; status = calibrate_dc_tx(s, &dc_i, &dc_q, &error_i, &error_q); printf(" I=%-4d (avg: %3.3f), Q=%-4d (avg: %3.3f)\r", dc_i, error_i, dc_q, error_q); } if (status != 0) { goto out; } fflush(stdout); dc_i = HOST_TO_LE16(dc_i); dc_q = HOST_TO_LE16(dc_q); memcpy(&image->data[off], &frequency, sizeof(frequency)); off += sizeof(frequency); memcpy(&image->data[off], &dc_i, sizeof(dc_i)); off += sizeof(dc_i); memcpy(&image->data[off], &dc_q, sizeof(dc_q)); off += sizeof(dc_q); } status = bladerf_image_write(image, filename); printf("\n Done.\n\n"); out: retval = status; if (module == BLADERF_MODULE_RX) { status = bladerf_set_loopback(s->dev, loopback_backup); retval = first_error(retval, status); } status = bladerf_enable_module(s->dev, BLADERF_MODULE_RX, false); retval = first_error(retval, status); status = restore_settings(s->dev, module, &settings); retval = first_error(retval, status); bladerf_free_image(image); return retval; }
/* FIXME Clean up this function up. It's very unreadable. * Suggestions include moving to switch() and possibly adding some * intermediary states. (More smaller, simpler states); */ static void *rx_task(void *arg) { int lib_ret, write_ret; enum rxtx_state state, prev_state; struct cli_state *s = (struct cli_state *) arg; struct rx_cfg *rx = &s->rxtx_data->rx; unsigned int n_samples_left = 0; bool inf = false; size_t to_write = 0; /* We expect to be in the IDLE state when this task is kicked off */ state = prev_state = get_state(&rx->common); assert(state == RXTX_STATE_IDLE || state == RXTX_STATE_SHUTDOWN); while (state != RXTX_STATE_SHUTDOWN) { if (state == RXTX_STATE_RUNNING) { /* Transitioning from IDLE/ERROR -> RUNNING */ if (prev_state == RXTX_STATE_IDLE || prev_state == RXTX_STATE_ERROR) { pthread_mutex_lock(&rx->common.param_lock); n_samples_left = rx->n_samples; pthread_mutex_unlock(&rx->common.param_lock); inf = n_samples_left == 0; /* Task owns file while running */ pthread_mutex_lock(&rx->common.file_lock); /* Flush out any old samples before recording any data */ /*lib_ret = bladerf_read_c16(s->dev, rx->common.buff, rx->common.buff_size / 2);*/ lib_ret = bladerf_rx( s->dev, BLADERF_FORMAT_SC16_Q12, rx->common.buff, rx->common.buff_size/2, NULL ); if (lib_ret < 0) { set_last_error(&rx->common.error, ETYPE_BLADERF, lib_ret); state = RXTX_STATE_ERROR; } } else { /*lib_ret = bladerf_read_c16(s->dev, rx->common.buff, rx->common.buff_size / 2);*/ lib_ret = bladerf_rx( s->dev, BLADERF_FORMAT_SC16_Q12, rx->common.buff, rx->common.buff_size/2, NULL ); if (lib_ret < 0) { set_last_error(&rx->common.error, ETYPE_BLADERF, lib_ret); state = RXTX_STATE_ERROR; } else { /* Bug catcher */ assert((size_t)lib_ret <= (rx->common.buff_size / 2)); if (!inf) { to_write = uint_min(n_samples_left, lib_ret); } else { to_write = rx->common.buff_size / 2; } write_ret = rx->write_samples(s, to_write); if (write_ret < 0) { /* write_samples will have set the last error info */ state = RXTX_STATE_ERROR; } else if (!inf) { n_samples_left -= to_write; if (n_samples_left == 0) { state = RXTX_STATE_IDLE; } } } } } if (state != RXTX_STATE_RUNNING && prev_state == RXTX_STATE_RUNNING) { /* Clean up as we transition from RUNNING -> <any other state> */ lib_ret = bladerf_enable_module(s->dev, BLADERF_MODULE_RX, false); close_samples_file(&rx->common, false); pthread_mutex_unlock(&rx->common.file_lock); if (lib_ret < 0) { set_last_error(&rx->common.error, ETYPE_BLADERF, lib_ret); state = RXTX_STATE_ERROR; } set_state(&rx->common, state, false); } prev_state = state; /* Wait here while if we're in the IDLE/ERROR states */ pthread_mutex_lock(&rx->common.task_lock); while (state == RXTX_STATE_IDLE || state == RXTX_STATE_ERROR) { pthread_cond_wait(&rx->common.task_state_changed, &rx->common.task_lock); state = rx->common.task_state; } state = rx->common.task_state; pthread_mutex_unlock(&rx->common.task_lock); } 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; }
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; }
/* Initialization and stuff */ int main(int argc, char **argv) { struct bladerf_devinfo *devs; struct sigaction sigact; struct devinfo_s device; int show_help = false; int n, ret; char ch; /* Set up default values, bandwidth and num_transfers * are automatically calculated later */ device.device_id = DEFAULT_DEVICE_ID; device.frequency = DEFAULT_FREQUENCY; device.samplerate = DEFAULT_SAMPLERATE; device.bandwidth = 0; device.txvga1 = DEFAULT_TXVGA1; device.txvga2 = DEFAULT_TXVGA2; device.buffers.gain = DEFAULT_GAIN; device.buffers.again = DEFAULT_AGAIN; device.buffers.num_buffers = DEFAULT_BUFFERS; device.buffers.num_samples = DEFAULT_SAMPLES; device.buffers.num_transfers = 0; device.buffers.pos = 0; /* Evaluate command line options */ while((ch = getopt(argc, argv, "hd:f:r:b:g:G:a:m:n:s:t:")) != -1) { switch(ch) { case 'd': device.device_id = optarg; break; case 'f': device.frequency = atoi(optarg); break; case 'r': device.samplerate = atoi(optarg); break; case 'b': device.bandwidth = atoi(optarg); break; case 'g': device.txvga1 = atoi(optarg); break; case 'G': device.txvga2 = atoi(optarg); break; case 'm': device.buffers.gain = atof(optarg); break; case 'a': device.buffers.again = atof(optarg); break; case 'n': device.buffers.num_buffers = atoi(optarg); break; case 's': device.buffers.num_samples = atoi(optarg); break; case 't': device.buffers.num_transfers = atoi(optarg); break; case 'h': default: show_help = true; } } /* Now calculate bandwidth and num_transfers if the user didn't * configure them manually */ if(device.bandwidth == 0) device.bandwidth = device.samplerate * 3 / 4; if(device.buffers.num_transfers == 0) device.buffers.num_transfers = device.buffers.num_buffers / 2; if(show_help) { usage(argv[0], &device); return EXIT_FAILURE; } argc -= optind; argv += optind; /* Allocate the float input buffer */ device.buffers.fbuf = malloc(device.buffers.num_samples * 2 * sizeof(float)); /* Set up signal handler to enable clean shutdowns */ sigact.sa_handler = sighandler; sigemptyset(&sigact.sa_mask); sigact.sa_flags = 0; sigaction(SIGINT, &sigact, NULL); sigaction(SIGTERM, &sigact, NULL); sigaction(SIGQUIT, &sigact, NULL); sigaction(SIGPIPE, &sigact, NULL); /* Look for devices attached */ ret = bladerf_get_device_list(&devs); if(ret < 1) { fprintf(stderr, "No devices found.\n"); return EXIT_FAILURE; } /* Print some information about all the devices */ for(n = 0; n < ret; n++) { fprintf(stderr, "Serial:\t%s\n" "USB bus:\t%i\n" "USB address:\t%i\n" "Instance:\t%i\n\n", devs[n].serial, devs[n].usb_bus, devs[n].usb_addr, devs[n].instance ); } /* the list is not needed any more */ bladerf_free_device_list(devs); /* Open a device by given device string */ ret = bladerf_open(&device.dev, device.device_id); if(ret != 0) { fprintf(stderr, "Error opening device %s: %s.\n", device.device_id, bladerf_strerror(ret)); goto out0; } else { fprintf(stderr, "Device \"%s\" opened successfully.\n", device.device_id); } /* Set the device parameters */ ret = bladerf_set_sample_rate(device.dev, BLADERF_MODULE_TX, device.samplerate, &device.samplerate); if(ret != 0) { fprintf(stderr, "Error setting sample rate to %i: %s.\n", device.samplerate, bladerf_strerror(ret)); goto out1; } else { fprintf(stderr, "Actual sample rate is %i.\n", device.samplerate); } ret = bladerf_set_frequency(device.dev, BLADERF_MODULE_TX, device.frequency); if(ret != 0) { fprintf(stderr, "Error setting frequency to %iHz: %s.\n", device.frequency, bladerf_strerror(ret)); goto out1; } else { fprintf(stderr, "Frequency set to %iHz.\n", device.frequency); } ret = bladerf_set_txvga1(device.dev, device.txvga1); if(ret != 0) { fprintf(stderr, "Error setting gain for txvga1: %s.\n", bladerf_strerror(ret)); goto out1; } ret = bladerf_set_txvga2(device.dev, device.txvga2); if(ret != 0) { fprintf(stderr, "Error setting gain for txvga2: %s.\n", bladerf_strerror(ret)); goto out1; } ret = bladerf_set_bandwidth(device.dev, BLADERF_MODULE_TX, device.bandwidth, &device.bandwidth); if(ret != 0) { fprintf(stderr, "Error setting LPF bandwidth: %s.\n", bladerf_strerror(ret)); goto out1; } else { fprintf(stderr, "Bandwidth set to %iHz.\n", device.bandwidth); } /* Set up the sample stream */ ret = bladerf_init_stream(&device.stream, device.dev, stream_callback, &device.buffers.sbuf, device.buffers.num_buffers, BLADERF_FORMAT_SC16_Q12, device.buffers.num_samples, device.buffers.num_transfers, &device.buffers); if(ret != 0) { fprintf(stderr, "Failed setting up stream: %s.\n", bladerf_strerror(ret)); goto out1; } /* Finally enable TX... */ ret = bladerf_enable_module(device.dev, BLADERF_MODULE_TX, true); if(ret != 0) { fprintf(stderr, "Error enabling TX module: %s.\n", bladerf_strerror(ret)); goto out1; } else { fprintf(stderr, "Successfully enabled TX module.\n"); } /* ...and start the stream. * Execution stops here until stream has finished. */ ret = bladerf_stream(device.stream, BLADERF_MODULE_TX); if(ret != 0) { fprintf(stderr, "Failed starting stream: %s.\n", bladerf_strerror(ret)); goto out2; } /* Cleanup the mess */ out2: bladerf_deinit_stream(device.stream); out1: ret = bladerf_enable_module(device.dev, BLADERF_MODULE_TX, false); if(ret != 0) { fprintf(stderr, "Error disabling TX module: %s.\n", bladerf_strerror(ret)); } else { fprintf(stderr, "Successfully disabled TX module.\n"); } bladerf_close(device.dev); fprintf(stderr, "Device closed.\n"); out0: return EXIT_SUCCESS; }
/** [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; }
/* FIXME Clean up this function up. It's very unreadable. * Suggestions include moving to switch() and possibly adding some * intermediary states. (More smaller, simpler states); */ static void *tx_task(void *arg) { enum rxtx_state state, prev_state; struct cli_state *s = (struct cli_state *) arg; struct tx_cfg *tx = &s->rxtx_data->tx; ssize_t read_ret; int lib_ret; unsigned int last_repeats_left; unsigned int repeats_left = 0; unsigned int repeat_delay = 0; bool repeats_inf = false; /* We expect to be in the IDLE state when this task is kicked off */ state = prev_state = get_state(&tx->common); assert(state == RXTX_STATE_IDLE || state == RXTX_STATE_SHUTDOWN); while (state != RXTX_STATE_SHUTDOWN) { if (state == RXTX_STATE_RUNNING) { /* Transitioning from IDLE/ERROR -> RUNNING */ if (prev_state == RXTX_STATE_IDLE || prev_state == RXTX_STATE_ERROR) { pthread_mutex_lock(&tx->common.param_lock); repeats_left = tx->repeat; repeat_delay = tx->repeat_delay; pthread_mutex_unlock(&tx->common.param_lock); repeats_inf = repeats_left == 0; /* Task owns the file while running */ pthread_mutex_lock(&tx->common.file_lock); } else { /* Fetch samples to write */ last_repeats_left = repeats_left; read_ret = tx->read_samples(s, &repeats_left); if (read_ret == (2 * LIBBLADERF_SAMPLE_BLOCK_SIZE) || read_ret == 0) { if (read_ret != 0) { /* lib_ret = bladerf_send_c16(s->dev, tx->common.buff, tx->common.buff_size / 2); */ lib_ret = bladerf_tx( s->dev, BLADERF_FORMAT_SC16_Q12, tx->common.buff, tx->common.buff_size/2, NULL ); if (lib_ret < 0) { set_last_error(&tx->common.error, ETYPE_BLADERF, lib_ret); state = RXTX_STATE_ERROR; } } if (repeats_inf || repeats_left != 0) { if (repeats_left != last_repeats_left && repeat_delay) { /* Currently seeing timeouts from the driver when * attempting to disable/enable TX here... * * FIXME re-enable this after driver issues are * resolved... */ #if 0 lib_ret = bladerf_enable_module(s->dev, TX, false); if (lib_ret < 0) { set_last_error(&tx->common.error, ETYPE_BLADERF, lib_ret); state = RXTX_STATE_ERROR; } else { #endif /* TODO replace with 0-send here for better * accuracy, as usleep isn't sufficient here */ usleep(repeat_delay); #if 0 lib_ret = bladerf_enable_module(s->dev, TX, true); if (lib_ret < 0) { set_last_error(&tx->common.error, ETYPE_BLADERF, lib_ret); state = RXTX_STATE_ERROR; } } #endif } } else { state = RXTX_STATE_IDLE; } } else { /* Reads of an in-between size are a bug */ assert(read_ret <= 0); /* read-samples will have filled out "last error" */ state = RXTX_STATE_ERROR; } } } /* Clean up as we transition from RUNNING -> <any other state> */ if (state != RXTX_STATE_RUNNING && prev_state == RXTX_STATE_RUNNING) { lib_ret = bladerf_enable_module(s->dev, BLADERF_MODULE_TX, false); close_samples_file(&tx->common, false); pthread_mutex_unlock(&tx->common.file_lock); if (lib_ret < 0) { set_last_error(&tx->common.error, ETYPE_BLADERF, lib_ret); state = RXTX_STATE_ERROR; } set_state(&tx->common, state, false); } prev_state = state; /* Wait here while if we're in the IDLE/ERROR states */ pthread_mutex_lock(&tx->common.task_lock); while (state == RXTX_STATE_IDLE || state == RXTX_STATE_ERROR) { pthread_cond_wait(&tx->common.task_state_changed, &tx->common.task_lock); state = tx->common.task_state; } state = tx->common.task_state; pthread_mutex_unlock(&tx->common.task_lock); } return NULL; }
int main(int argc, char *argv[]) { int status = 0; struct rc_config rc; struct cli_state *state; bool exit_immediately = false; /* If no actions are specified, just show the usage text and exit */ if (argc == 1) { usage(argv[0]); return 0; } init_rc_config(&rc); if (get_rc_config(argc, argv, &rc)) { return 1; } state = cli_state_create(); if (!state) { fprintf(stderr, "Failed to create state object\n"); return 1; } bladerf_log_set_verbosity(rc.verbosity); if (rc.show_help) { usage(argv[0]); exit_immediately = true; } else if (rc.show_version) { printf(BLADERF_CLI_VERSION "\n"); exit_immediately = true; } else if (rc.show_lib_version) { struct bladerf_version version; bladerf_version(&version); printf("%s\n", version.describe); exit_immediately = true; } else if (rc.probe) { status = cmd_handle(state, "probe"); exit_immediately = true; } if (!exit_immediately) { /* Conditionally performed items, depending on runtime config */ status = open_device(&rc, state, status); if (status) { fprintf(stderr, "Could not open device\n"); goto main__issues ; } status = flash_fw(&rc, state, status); if (status) { fprintf(stderr, "Could not flash firmware\n"); goto main__issues ; } status = load_fpga(&rc, state, status); if (status) { fprintf(stderr, "Could not load fpga\n"); goto main__issues ; } status = open_script(&rc, state, status); if (status) { fprintf(stderr, "Could not load scripts\n"); goto main__issues ; } main__issues: /* These items are no longer needed */ free(rc.device); rc.device = NULL; free(rc.fw_file); rc.fw_file = NULL; free(rc.fpga_file); rc.fpga_file = NULL; free(rc.script_file); rc.script_file = NULL; /* Drop into interactive mode or begin executing commands * from a script. If we're not requested to do either, exit cleanly */ if (rc.interactive_mode || state->script != NULL) { status = start_threads(state); if (status < 0) { fprintf(stderr, "Failed to kick off threads\n"); } else { status = interactive(state, !rc.interactive_mode); stop_threads(state); } } /* Ensure we exit with RX & TX disabled. * Can't do much about an error at this point anyway... */ if (state->dev && bladerf_is_fpga_configured(state->dev)) { bladerf_enable_module(state->dev, BLADERF_MODULE_TX, false); bladerf_enable_module(state->dev, BLADERF_MODULE_RX, false); } } cli_state_destroy(state); return status; }
int test_fn_loopback_onoff(struct bladerf *dev, struct app_params *p) { int status = 0; struct test test; pthread_t tx_thread; bool tx_started = false; #if !DISABLE_RX_LOOPBACK pthread_t rx_thread; bool rx_started = false; bool rx_ready = false; #endif test.dev = dev; test.params = p; test.num_bursts = 1000; test.stop = false; test.rx_ready = false; pthread_mutex_init(&test.lock, NULL); test.bursts = (struct burst *) malloc(test.num_bursts * sizeof(test.bursts[0])); if (test.bursts == NULL) { perror("malloc"); return -1; } else { fill_bursts(&test); } status = setup_device(&test); if (status != 0) { goto out; } printf("Starting bursts...\n"); #if !DISABLE_RX_LOOPBACK status = pthread_create(&rx_thread, NULL, rx_task, &test); if (status != 0) { fprintf(stderr, "Failed to start RX thread: %s\n", strerror(status)); goto out; } else { rx_started = true; } while (!rx_ready) { usleep(10000); pthread_mutex_lock(&test.lock); rx_ready = test.rx_ready; pthread_mutex_unlock(&test.lock); } #endif status = pthread_create(&tx_thread, NULL, tx_task, &test); if (status != 0) { fprintf(stderr, "Failed to start TX thread: %s\n", strerror(status)); goto out; } else { tx_started = true; } out: if (tx_started) { pthread_join(tx_thread, NULL); } #if !DISABLE_RX_LOOPBACK if (rx_started) { pthread_join(rx_thread, NULL); } #endif free(test.bursts); bladerf_enable_module(dev, BLADERF_MODULE_RX, false); bladerf_enable_module(dev, BLADERF_MODULE_TX, false); bladerf_set_loopback(dev, BLADERF_LB_NONE); 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; }