int encode_field(char *ptr, int len, int *idx, const char *field, const char *val) { int vlen, flen, tlen; flen = (int)strlen(field); vlen = (int)strlen(val); tlen = flen + vlen + 1; if (tlen >= 256 || *idx + tlen >= len) return BLADERF_ERR_MEM; ptr[*idx] = flen + vlen; strcpy(&ptr[*idx + 1], field); strcpy(&ptr[*idx + 1 + flen], val); *(unsigned short *)(&ptr[*idx + tlen ]) = HOST_TO_LE16(crc16mp(0, &ptr[*idx ], tlen)); *idx += tlen + 2; return 0; }
/** * Peform adjustments on received samples before writing them out: * (1) Mask off FPGA markers * (2) Convert little-endian samples to host endianness, if needed. * * @param buff Sample buffer * @param n Number of samples */ static inline void sc16q12_sample_fixup(int16_t *buf, size_t n) { size_t i; for (i = 0; i < n; i++) { /* I - Mask off the marker and sign extend */ *buf &= (*buf) & 0x0fff; if (*buf & 0x800) { *buf |= 0xf000; } *buf = LE16_TO_HOST(*buf); buf++; /* Q - Mask off the marker and sign extend */ *buf = HOST_TO_LE16(*buf) & 0x0fff; if (*buf & 0x800) { *buf |= 0xf000; } *buf = LE16_TO_HOST(*buf); buf++; } }
/* 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; }
/* * n - # samples * fmt - binle or binbe * in - Is this data being TX'd (RX'd assumed otherwise) */ static void c16_sample_fixup(int16_t *buff, size_t n, enum rxtx_fmt fmt, bool tx) { size_t i; /* For each sample, we need to: * (1) Convert to appropriate endianness * (2, RX only) Mask and sign-extend. * FIXME this will soon be done in libbladeRF * * The 4 permutations are unrolled here intentionally, to keep * the amount of massaging on these samples to a minimum... */ if (tx) { if (fmt == RXTX_FMT_BINLE_C16) { for (i = 0; i < n; i++) { /* I - Correct sign extension is assumed */ *buff = (HOST_TO_LE16(*buff) & 0x0fff); buff++; /* Q - Correct sign extention is assumed*/ *buff = (HOST_TO_LE16(*buff) & 0x0fff); buff++; } } else { for (i = 0; i < n; i++) { /* I - Correct sign extension is assumed */ *buff = (HOST_TO_BE16(*buff) & 0x0fff); buff++; /* Q - Correct sign extention is assumed*/ *buff = (HOST_TO_BE16(*buff) & 0x0fff); buff++; } } } else { if (fmt == RXTX_FMT_CSV_C16) { fmt = RXTX_FMT_BINHOST_C16; } if (fmt == RXTX_FMT_BINLE_C16) { for (i = 0; i < n; i++) { /* I - Mask off the marker and sign extend */ *buff = HOST_TO_LE16(*buff) & 0x0fff; if (*buff & 0x800) { *buff |= 0xf000; } buff++; /* Q - Mask off the marker and sign extend */ *buff = HOST_TO_LE16(*buff) & 0x0fff; if (*buff & 0x800) { *buff |= 0xf000; } buff++; } } else { for (i = 0; i < n; i++) { /* I - Mask off the marker and sign extend */ *buff = HOST_TO_BE16(*buff) & 0x0fff; if (*buff & 0x800) { *buff |= 0xf000; } buff++; /* Q - Mask off the marker and sign extend */ *buff = HOST_TO_BE16(*buff) & 0x0fff; if (*buff & 0x800) { *buff |= 0xf000; } buff++; } } } }
/* 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; }