void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { struct bladerf *dev; bladerf_loopback lp; int ret; long long *ip; int *lp_ptr; if (nrhs < 2) return; ip = (long long *)mxGetPr(prhs[0]); lp_ptr = (int *)mxGetPr(prhs[1]); dev = (struct bladerf *)*ip; lp = (bladerf_loopback)*(double *)mxGetData(prhs[1]); ret = bladerf_set_loopback(dev, lp); if (nlhs >= 1) { plhs[0] = mxCreateNumericMatrix(1,1,mxINT64_CLASS,mxREAL); ip = (long long *)mxGetData(plhs[0]); *ip = 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; }
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; }
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; }
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; }
int radio_init_and_configure(struct bladerf *dev, struct radio_params *params) { struct module_config config; int status; #ifdef DEBUG_MODE bladerf_log_set_verbosity(BLADERF_LOG_LEVEL_DEBUG); #endif //Configure TX parameters config.module = BLADERF_MODULE_TX; config.frequency = params->tx_freq; config.bandwidth = BLADERF_BANDWIDTH; config.samplerate = BLADERF_SAMPLE_RATE; config.vga1 = params->tx_vga1_gain; config.vga2 = params->tx_vga2_gain; status = radio_configure_module(dev, &config); if (status != 0){ fprintf(stderr, "Couldn't configure TX module: %s\n", bladerf_strerror(status)); return status; } //Configure RX parameters config.module = BLADERF_MODULE_RX; config.frequency = params->rx_freq; config.bandwidth = BLADERF_BANDWIDTH; config.samplerate = BLADERF_SAMPLE_RATE; config.rx_lna = params->rx_lna_gain; config.vga1 = params->rx_vga1_gain; config.vga2 = params->rx_vga2_gain; status = radio_configure_module(dev, &config); if (status != 0){ fprintf(stderr, "Couldn't configure RX module: %s\n", bladerf_strerror(status)); return status; } //Unset loopback status = bladerf_set_loopback(dev, BLADERF_LB_NONE); if (status != 0){ fprintf(stderr, "Couldn't set loopback: %s", bladerf_strerror(status)); return status; } //Initialize synchronous interface status = radio_init_sync(dev); if (status != 0){ fprintf(stderr, "Couldn't initialize synchronous interface: %s\n", bladerf_strerror(status)); return status; } //Enable tx module status = bladerf_enable_module(dev, BLADERF_MODULE_TX, true); if (status != 0){ fprintf(stderr, "Couldn't enable TX module: %s\n", bladerf_strerror(status)); return status; } //Enable rx module status = bladerf_enable_module(dev, BLADERF_MODULE_RX, true); if (status != 0){ fprintf(stderr, "Couldn't enable RX module: %s\n", bladerf_strerror(status)); return status; } return 0; }
/* 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; }
/* 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; FILE *write_check; 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); /* This operation may take a bit of time, so let's make sure we * actually have write access before kicking things off. Note that * access is checked later when the file is actually written. */ write_check = fopen(filename, "wb"); if (write_check == NULL) { if (errno == EACCES) { return BLADERF_ERR_PERMISSION; } else { return BLADERF_ERR_IO; } } else { fclose(write_check); /* Not much we care to do if this fails. Throw away the return value * to make this explicit to our static analysis tools */ (void) remove(filename); } 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; }