static int init_streams(struct repeater *repeater, struct repeater_config *config) { int status; /* TODO Until we can provide NULL to the init stream call to indicate that * we want to use user-probveded buffers, we'll just allocate and not * use some dummy buffers for TX */ void **dummy; status = bladerf_init_stream(&repeater->rx_stream, repeater->device, rx_stream_callback, &repeater->buf_mgmt.samples, config->num_buffers, BLADERF_FORMAT_SC16_Q12, config->samples_per_buffer, config->num_transfers, repeater); if (status < 0) { fprintf(stderr, "Failed to initialize RX stream: %s\n", bladerf_strerror(status)); return status; } else { repeater->buf_mgmt.rx_idx = 0; } status = bladerf_init_stream(&repeater->tx_stream, repeater->device, tx_stream_callback, &dummy, config->num_buffers, BLADERF_FORMAT_SC16_Q12, config->samples_per_buffer, config->num_transfers, repeater); if (status < 0) { fprintf(stderr, "Failed to initialize TX stream: %s\n", bladerf_strerror(status)); return status; } else { repeater->buf_mgmt.tx_idx = 0; } repeater->buf_mgmt.num_buffers = config->num_buffers; return 0; }
int setup_tx_stream(struct bladerf* dev, struct bladerf_stream** stream, struct bladerf_stream_data* stream_data) { int status; stream_data->next_buffer = 0; stream_data->module = BLADERF_MODULE_TX; printf("%-50s", "Initialising TX data stream... "); fflush(stdout); status = bladerf_init_stream(stream, dev, stream_cb, &stream_data->buffers, stream_data->num_buffers, BLADERF_FORMAT_SC16_Q12, stream_data->samples_per_buffer, stream_data->num_transfers, stream_data); if(status) { printf(KRED "Failed: %s" KNRM "\n", bladerf_strerror(status)); bladerf_close(dev); return 1; } fill_tx_buffers(stream_data); printf(KGRN "OK" KNRM "\n"); return 0; }
static int init_streams(struct repeater *repeater, struct repeater_config *config) { int status; status = bladerf_init_stream(&repeater->rx_stream, repeater->device, rx_stream_callback, &repeater->buf_mgmt.samples, config->num_buffers, BLADERF_FORMAT_SC16_Q11, config->samples_per_buffer, config->num_transfers, repeater); if (status < 0) { fprintf(stderr, "Failed to initialize RX stream: %s\r\n", bladerf_strerror(status)); return status; } else { repeater->buf_mgmt.rx_idx = 0; } status = bladerf_init_stream(&repeater->tx_stream, repeater->device, tx_stream_callback, NULL, config->num_buffers, BLADERF_FORMAT_SC16_Q11, config->samples_per_buffer, config->num_transfers, repeater); if (status < 0) { fprintf(stderr, "Failed to initialize TX stream: %s\r\n", bladerf_strerror(status)); return status; } else { repeater->buf_mgmt.tx_idx = 0; } repeater->buf_mgmt.num_buffers = config->num_buffers; return 0; }
void *rx_task(void *cli_state_arg) { int status = 0; unsigned char requests; enum rxtx_state task_state; struct cli_state *cli_state = (struct cli_state *) cli_state_arg; struct rxtx_data *rx = cli_state->rx; struct rx_params *rx_params = rx->params; struct rx_callback_data cb_data; task_state = rxtx_get_state(rx); assert(task_state == RXTX_STATE_INIT); set_last_error(&rx->last_error, ETYPE_BLADERF, 0); requests = 0; while (task_state != RXTX_STATE_SHUTDOWN) { switch (task_state) { case RXTX_STATE_INIT: rxtx_set_state(rx, RXTX_STATE_IDLE); break; case RXTX_STATE_IDLE: rxtx_task_exec_idle(rx, &requests); break; case RXTX_STATE_START: { /* This should be set to an appropriate value upon * encountering an error condition */ enum error_type err_type = ETYPE_BUG; /* Clear the last error */ set_last_error(&rx->last_error, ETYPE_ERRNO, 0); /* Set up count of samples to receive */ pthread_mutex_lock(&rx->param_lock); cb_data.samples_left = rx_params->n_samples; pthread_mutex_unlock(&rx->param_lock); cb_data.rx = rx; cb_data.inf = cb_data.samples_left == 0; /* Choose the callback appropriate for the desired file type */ pthread_mutex_lock(&rx->file_mgmt.file_meta_lock); switch (rx->file_mgmt.format) { case RXTX_FMT_CSV_SC16Q12: cb_data.write_samples = rx_write_csv_sc16q12; break; case RXTX_FMT_BIN_SC16Q12: cb_data.write_samples = rx_write_bin_sc16q12; break; default: status = CMD_RET_INVPARAM; set_last_error(&rx->last_error, ETYPE_CLI, status); rxtx_set_state(rx, RXTX_STATE_IDLE); } /* Open the specified file */ if (status == 0) { assert(rx->file_mgmt.path); } pthread_mutex_unlock(&rx->file_mgmt.file_meta_lock); /* Set up the reception stream and buffer information */ if (status == 0) { pthread_mutex_lock(&rx->data_mgmt.lock); rx->data_mgmt.next_idx = 0; status = bladerf_init_stream(&rx->data_mgmt.stream, cli_state->dev, rx_callback, &rx->data_mgmt.buffers, rx->data_mgmt.num_buffers, BLADERF_FORMAT_SC16_Q12, rx->data_mgmt.samples_per_buffer, rx->data_mgmt.num_transfers, &cb_data); if (status < 0) { err_type = ETYPE_BLADERF; } pthread_mutex_unlock(&rx->data_mgmt.lock); } if (status == 0) { rxtx_set_state(rx, RXTX_STATE_RUNNING); } else { bladerf_deinit_stream(rx->data_mgmt.stream); rx->data_mgmt.stream = NULL; set_last_error(&rx->last_error, err_type, status); rxtx_set_state(rx, RXTX_STATE_IDLE); } } break; case RXTX_STATE_RUNNING: rxtx_task_exec_running(rx, cli_state); break; case RXTX_STATE_STOP: rxtx_task_exec_stop(rx, &requests); break; case RXTX_STATE_SHUTDOWN: break; default: /* Bug - can only get here with a corrupted value */ assert(0); } task_state = rxtx_get_state(rx); } return NULL; }
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; }
/* 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; }
int sync_worker_init(struct bladerf_sync *s) { int status = 0; s->worker = (struct sync_worker*) calloc(1, sizeof(*s->worker)); if (s->worker == NULL) { status = BLADERF_ERR_MEM; goto worker_init_out; } s->worker->state = SYNC_WORKER_STATE_STARTUP; s->worker->err_code = 0; s->worker->cb = s->stream_config.module == BLADERF_MODULE_RX ? rx_callback : tx_callback; status = bladerf_init_stream(&s->worker->stream, s->dev, s->worker->cb, &s->buf_mgmt.buffers, s->buf_mgmt.num_buffers, s->stream_config.format, s->stream_config.samples_per_buffer, s->stream_config.num_xfers, s); if (status != 0) { log_debug("%s worker: Failed to init stream: %s\n", MODULE_STR(s), bladerf_strerror(status)); goto worker_init_out; } status = pthread_mutex_init(&s->worker->state_lock, NULL); if (status != 0) { status = BLADERF_ERR_UNEXPECTED; goto worker_init_out; } status = pthread_cond_init(&s->worker->state_changed, NULL); if (status != 0) { status = BLADERF_ERR_UNEXPECTED; goto worker_init_out; } status = pthread_mutex_init(&s->worker->request_lock, NULL); if (status != 0) { status = BLADERF_ERR_UNEXPECTED; goto worker_init_out; } status = pthread_cond_init(&s->worker->requests_pending, NULL); if (status != 0) { status = BLADERF_ERR_UNEXPECTED; goto worker_init_out; } status = pthread_create(&s->worker->thread, NULL, sync_worker_task, s); if (status != 0) { status = BLADERF_ERR_UNEXPECTED; goto worker_init_out; } /* Wait until the worker thread has initialized and is ready to go */ status = sync_worker_wait_for_state(s->worker, SYNC_WORKER_STATE_IDLE, 1000); if (status != 0) { status = BLADERF_ERR_TIMEOUT; goto worker_init_out; } worker_init_out: if (status != 0) { free(s->worker); s->worker = NULL; } return status; }
void *tx_task(void *cli_state_arg) { int status = 0; 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; struct tx_params *tx_params = tx->params; struct tx_callback_data cb_data; /* 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); /* Set up repeat and delay parameters for this run */ cb_data.tx = tx; cb_data.delay = 0; cb_data.done = false; pthread_mutex_lock(&tx->param_lock); cb_data.repeats_left = tx_params->repeat; pthread_mutex_unlock(&tx->param_lock); if (cb_data.repeats_left == 0) { cb_data.repeat_inf = true; } else { cb_data.repeat_inf = false; } /* Bug catcher */ pthread_mutex_lock(&tx->file_mgmt.file_meta_lock); assert(tx->file_mgmt.file != NULL); pthread_mutex_unlock(&tx->file_mgmt.file_meta_lock); /* Initialize the stream */ status = bladerf_init_stream(&tx->data_mgmt.stream, cli_state->dev, tx_callback, &tx->data_mgmt.buffers, tx->data_mgmt.num_buffers, BLADERF_FORMAT_SC16_Q11, tx->data_mgmt.samples_per_buffer, tx->data_mgmt.num_transfers, &cb_data); if (status < 0) { err_type = ETYPE_BLADERF; } if (status == 0) { rxtx_set_state(tx, RXTX_STATE_RUNNING); } else { bladerf_deinit_stream(tx->data_mgmt.stream); tx->data_mgmt.stream = NULL; set_last_error(&tx->last_error, err_type, status); rxtx_set_state(tx, RXTX_STATE_IDLE); } } break; case RXTX_STATE_RUNNING: rxtx_task_exec_running(tx, cli_state); 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; }