Having issues with the site, hardware, source code, or any other issues?

Moderator: robert.ghilduta

nipunamr
Posts: 21
Joined: Sat Sep 08, 2018 2:05 pm

How do I get "BLADERF_FORMAT_SC16_Q11_META" I&Q samples using "bladeRF-cli" program? This format is described in the API. However, it doesn't say how to force the I&Q samples to be written in this format.

Thanks

bglod
Posts: 201
Joined: Thu Jun 18, 2015 6:10 pm

They are in this format by default. You can make it explicit with the following command:

Code: Select all

rx config format=bin

Or, similarly for TX:

Code: Select all

tx config format=bin

Electrical Engineer
Nuand, LLC.

nipunamr
Posts: 21
Joined: Sat Sep 08, 2018 2:05 pm

No, my understanding is that "bin" gives me " BLADERF_FORMAT_SC16_Q11" format NOT " BLADERF_FORMAT_SC16_Q11_META" format. I was looking at the libbladeRF.h and they have defined both of these formats. Is there a way I can get to the "META" format? I want to get access to the META format since it gives me the needed timestamps.

see below for the "META" format after the SC16_Q11 format (this is a section in libbladeRF.h")

typedef enum {
/**
* Signed, Complex 16-bit Q11. This is the native format of the DAC data.
*
* Values in the range [-2048, 2048) are used to represent [-1.0, 1.0).
* Note that the lower bound here is inclusive, and the upper bound is
* exclusive. Ensure that provided samples stay within [-2048, 2047].
*
* Samples consist of interleaved IQ value pairs, with I being the first
* value in the pair. Each value in the pair is a right-aligned,
* little-endian int16_t. The FPGA ensures that these values are
* sign-extended.
*
* <pre>
* .--------------.--------------.
* | Bits 31...16 | Bits 15...0 |
* +--------------+--------------+
* | Q[15..0] | I[15..0] |
* ----------------------------
* </pre>
*
* When using this format the minimum required buffer size, in bytes, is:
*
* \f$* buffer\_size\_min = (2 \times num\_samples \times num\_channels \times * sizeof(int16\_t)) * \f$
*
* For example, to hold 2048 samples for one channel, a buffer must be at
* least 8192 bytes large.
*
* When a multi-channel ::bladerf_channel_layout is selected, samples
* will be interleaved per channel. For example, with ::BLADERF_RX_X2
* or ::BLADERF_TX_X2 (x2 MIMO), the buffer is structured like:
*
* <pre>
* .-------------.--------------.--------------.------------------.
* | Byte offset | Bits 31...16 | Bits 15...0 | Description |
* +-------------+--------------+--------------+------------------+
* | 0x00 | Q0[0] | I0[0] | Ch 0, sample 0 |
* | 0x04 | Q1[0] | I1[0] | Ch 1, sample 0 |
* | 0x08 | Q0[1] | I0[1] | Ch 0, sample 1 |
* | 0x0c | Q1[1] | I1[1] | Ch 1, sample 1 |
* | ... | ... | ... | ... |
* | 0xxx | Q0[n] | I0[n] | Ch 0, sample n |
* | 0xxx | Q1[n] | I1[n] | Ch 1, sample n |
* -----------------------------------------------------------
* </pre>
*
* Per the buffer_size_min formula above, 2048 samples for two channels
* will generate 4096 total samples, and require at least 16384 bytes.
*
* Implementors may use the interleaved buffers directly, or may use
* if contiguous blocks of samples are desired.
*/

/**
* This format is the same as the ::BLADERF_FORMAT_SC16_Q11 format, except
* the first 4 samples in every <i>block*</i> of samples are replaced with
* metadata organized as follows. All fields are little-endian byte order.
*
* <pre>
* .-------------.------------.----------------------------------.
* | Byte offset | Type | Description |
* +-------------+------------+----------------------------------+
* | 0x00 | uint32_t | Reserved |
* | 0x04 | uint64_t | 64-bit Timestamp |
* | 0x0c | uint32_t | BLADERF_META_FLAG_* flags |
* | 0x10..end | | Payload |
* -----------------------------------------------------------
* </pre>
*
* <i>*</i>The number of samples in a <i>block</i> is dependent upon
* the USB speed being used:
* - USB 2.0 Hi-Speed: 256 samples
* - USB 3.0 SuperSpeed: 512 samples
*
* above details are entirely transparent; the caller need not be concerned
* with these details. These functions take care of packing/unpacking the
* metadata into/from the underlying stream and convey this information
*
* However, when using the \ref FN_STREAMING_ASYNC interface, the user is
* responsible for manually packing/unpacking the above metadata into/from
* their samples.
*
* @see The src/streaming/metadata.h header in the libbladeRF codebase.
*/

bglod
Posts: 201
Joined: Thu Jun 18, 2015 6:10 pm

Gotcha, sorry. The META stuff is ignored in the CLI, but you might be able to enable it with a few modifications. Take a look at host/utilities/bladeRF-cli/src/cmd/rx.c.

Line 221 shows bladerf_sync_rx() with the metadata pointer parameter set to NULL:

Electrical Engineer
Nuand, LLC.

nipunamr
Posts: 21
Joined: Sat Sep 08, 2018 2:05 pm

Thanks for the reply. I am now trying to understand the "bladeRF-cli" and I found the function that handles each command but I can't find where it's defined. I tried to use VS2017 as well as a content search on the folder. I am looking for where "int (*exec)(struct cli_state *s, int argc, char **argv)" is defined (implemented). It's in cmd.c file and I see that it's declared in the cmd struct as a function pointer. But where is it implemented?

See below for the releavant excerpts from "cmd.c" file

struct cmd {
const char **names;
int (*exec)(struct cli_state *s, int argc, char **argv);
const char *desc;
const char *help;
bool requires_device;
bool requires_fpga;
bool allow_while_streaming;
};

if (ret == 0) {
/* Commands own the device handle while they're executing.
* This is needed to prevent races on the device handle
* while the RX/TX make any necessary control calls while
* starting up or finishing up a stream() call*/
MUTEX_LOCK(&s->dev_lock);
ret = cmd->exec(s, argc, argv);
MUTEX_UNLOCK(&s->dev_lock);
}

Thanks

nipunamr
Posts: 21
Joined: Sat Sep 08, 2018 2:05 pm

I think I understand what you are doing. I read "ADDING_COMMANDS.txt" and it seems you are converting "exec" to whatever command ("rx", "tx", etc) by the pre-processor (I have never done that before). Is that correct?

I think I need to understand "rx.c" so that I can get the timestamps with the samples.

Thanks

bglod
Posts: 201
Joined: Thu Jun 18, 2015 6:10 pm

Yes, that's what's happening.
Electrical Engineer
Nuand, LLC.

nipunamr
Posts: 21
Joined: Sat Sep 08, 2018 2:05 pm

I am looking for the function that writes the samples during "rx" mode. I understand it's a function pointer and dynamically selects which function to call. Specifically, here's the line,

status = write_samples(rx, samples, to_write); //rx.c line 232

So, when we do "rx start", can you point me to the IMPLEMENTATION of write_samples function that's get called. I can't find it?

Thanks

nipunamr
Posts: 21
Joined: Sat Sep 08, 2018 2:05 pm

I did figure out that the function it's calling is "static int rx_write_bin_sc16q11(...)" using function pointers (It's hard to follow the function pointers since you are dynamically changing it). I am now trying to read the timestamp. I added the following code in "static int rx_task_exec_running(...)" in the rx.c file.

....
....
status = bladerf_sync_rx(s->dev, samples, samples_per_buffer, metaInformation, timeout_ms); //changed NULL to metaInformation

seems that metaInformation variable is still NULL. I did a printf to verify it.

if (metaInformation != NULL)
{
printf("metaInformation is NOT NULL\n");
testTimestamp = metaInformation->timestamp;
}
else
{
printf("metaInformation is NULL\n");
}

It comes out that "metaInformation is NULL". Any ideas on how to fix it?

Thanks