libbladeRF
2.5.0
Nuand bladeRF library
|
This interface gives the API user full control over the stream and buffer management, at the cost of added complexity.
These functions are either thread-safe or may be used in a thread-safe manner (per the details noted in the function description).
Typedefs | |
typedef void *(* | bladerf_stream_cb) (struct bladerf *dev, struct bladerf_stream *stream, struct bladerf_metadata *meta, void *samples, size_t num_samples, void *user_data) |
Macros | |
#define | BLADERF_STREAM_SHUTDOWN (NULL) |
#define | BLADERF_STREAM_NO_DATA ((void *)(-1)) |
Functions | |
API_EXPORT int CALL_CONV | bladerf_init_stream (struct bladerf_stream **stream, struct bladerf *dev, bladerf_stream_cb callback, void ***buffers, size_t num_buffers, bladerf_format format, size_t samples_per_buffer, size_t num_transfers, void *user_data) |
API_EXPORT int CALL_CONV | bladerf_stream (struct bladerf_stream *stream, bladerf_channel_layout layout) |
API_EXPORT int CALL_CONV | bladerf_submit_stream_buffer (struct bladerf_stream *stream, void *buffer, unsigned int timeout_ms) |
API_EXPORT int CALL_CONV | bladerf_submit_stream_buffer_nb (struct bladerf_stream *stream, void *buffer) |
API_EXPORT void CALL_CONV | bladerf_deinit_stream (struct bladerf_stream *stream) |
API_EXPORT int CALL_CONV | bladerf_set_stream_timeout (struct bladerf *dev, bladerf_direction dir, unsigned int timeout) |
API_EXPORT int CALL_CONV | bladerf_get_stream_timeout (struct bladerf *dev, bladerf_direction dir, unsigned int *timeout) |
typedef void*(* bladerf_stream_cb) (struct bladerf *dev, struct bladerf_stream *stream, struct bladerf_metadata *meta, void *samples, size_t num_samples, void *user_data) |
This typedef represents a callback function that is executed in response to this interface's asynchronous events.
Stream callbacks must not block or perform long-running operations. Otherwise, timeouts may occur. If this cannot be guaranteed, consider returning BLADERF_STREAM_NO_DATA in callbacks and later submit a buffer using bladerf_submit_stream_buffer(). However, callbacks should always take a single approach of returning buffers or returning BLADERF_STREAM_NO_DATA and submitting buffers later – but not both.
When running in a full-duplex mode of operation with simultaneous TX and RX stream threads, be aware that one stream's callback may occur in the context of another stream's thread. The API user is responsible for ensuring their callbacks are thread safe. For example, when managing access to sample buffers, the caller must ensure that if one thread is processing samples in a buffer, that this buffer is not returned via the callback's return value.
As of libbladeRF v0.15.0, is guaranteed that only one callback from a stream will occur at a time. (i.e., a second TX callback will not fire while one is currently being handled.) To achieve this, while a callback is executing, a per-stream lock is held. It is important to consider this when thinking about the order of lock acquisitions both in the callbacks, and the code surrounding bladerf_submit_stream_buffer().
For both RX and TX, the stream callback receives:
For TX callbacks:
For RX callbacks:
num_samples
in size, BLADERF_STREAM_SHUTDOWN, or BLADERF_STREAM_NO_DATA. Definition at line 2892 of file libbladeRF.h.
#define BLADERF_STREAM_NO_DATA ((void *)(-1)) |
Use this value in a stream callback to indicate that no buffer is being provided. In this case, buffers are expected to be provided via bladerf_submit_stream_buffer().
Definition at line 2840 of file libbladeRF.h.
#define BLADERF_STREAM_SHUTDOWN (NULL) |
Use this as a return value in callbacks or as the buffer parameter to bladerf_submit_stream_buffer() to shutdown a stream.
Definition at line 2833 of file libbladeRF.h.
API_EXPORT void CALL_CONV bladerf_deinit_stream | ( | struct bladerf_stream * | stream | ) |
Deinitialize and deallocate stream resources.
stream | Stream to deinitialize. This function does nothing if stream is NULL . |
API_EXPORT int CALL_CONV bladerf_get_stream_timeout | ( | struct bladerf * | dev, |
bladerf_direction | dir, | ||
unsigned int * | timeout | ||
) |
Get transfer timeout in milliseconds
dev | Device handle | |
[in] | dir | Stream direction |
[out] | timeout | On success, updated with current transfer timeout value. Undefined on failure. |
API_EXPORT int CALL_CONV bladerf_init_stream | ( | struct bladerf_stream ** | stream, |
struct bladerf * | dev, | ||
bladerf_stream_cb | callback, | ||
void *** | buffers, | ||
size_t | num_buffers, | ||
bladerf_format | format, | ||
size_t | samples_per_buffer, | ||
size_t | num_transfers, | ||
void * | user_data | ||
) |
Initialize a stream for use with asynchronous routines.
This function will internally allocate data buffers, which will be provided to the API user in callback functions.
The buffers
output parameter populates a pointer to the list of allocated buffers. This allows the API user to implement a buffer management scheme to best suit his or her specific use case.
Generally, one will want to set the buffers
parameter to a value larger than the num_transfers
parameter, and keep track of which buffers are currently "in-flight", versus those available for use.
For example, for a transmit stream, modulated data can be actively written into free buffers while transfers of other buffers are occurring. Once a buffer has been filled with data, it can be marked 'in-flight' and be returned in a successive callback to transmit.
The choice of values for the num_transfers
and buffer_size
should be made based upon the desired samplerate, and the stream timeout value specified via bladerf_set_stream_timeout(), which defaults to 1 second.
For a given sample rate, the below relationship must be upheld to transmit or receive data without timeouts or dropped data.
\[ Sample\ Rate > \frac{\#\ Transfers}{Timeout} \times Buffer\ Size \]
...where Sample Rate is in samples per second, and Timeout is in seconds.
To account for general system overhead, it is recommended to multiply the righthand side by 1.1 to 1.25.
While increasing the number of buffers available provides additional elasticity, be aware that it also increases latency.
[out] | stream | Upon success, this will be updated to contain a stream handle (i.e., address) |
dev | Device to associate with the stream | |
[in] | callback | Callback routine to handle asynchronous events |
[out] | buffers | This will be updated to point to a dynamically allocated array of buffer pointers. |
[in] | num_buffers | Number of buffers to allocate and return. This value must >= the num_transfers parameter. |
[in] | format | Sample data format |
[in] | samples_per_buffer | Size of allocated buffers, in units of samples Note that the physical size of the buffer is a function of this and the format parameter. |
[in] | num_transfers | Maximum number of transfers that may be in-flight simultaneously. This must be <= the num_buffers parameter. |
[in] | user_data | Caller-provided data that will be provided in stream callbacks |
API_EXPORT int CALL_CONV bladerf_set_stream_timeout | ( | struct bladerf * | dev, |
bladerf_direction | dir, | ||
unsigned int | timeout | ||
) |
Set stream transfer timeout in milliseconds
dev | Device handle | |
[in] | dir | Stream direction |
[in] | timeout | Timeout in milliseconds |
API_EXPORT int CALL_CONV bladerf_stream | ( | struct bladerf_stream * | stream, |
bladerf_channel_layout | layout | ||
) |
Begin running a stream. This call will block until the stream completes.
Only 1 RX stream and 1 TX stream may be running at a time. Attempting to call bladerf_stream() with more than one stream will yield unexpected (and most likely undesirable) results.
stream | A stream handle that has been successfully been initialized via bladerf_init_stream() | |
[in] | layout | Stream direction and channel layout |
API_EXPORT int CALL_CONV bladerf_submit_stream_buffer | ( | struct bladerf_stream * | stream, |
void * | buffer, | ||
unsigned int | timeout_ms | ||
) |
Submit a buffer to a stream from outside of a stream callback function. Use this only when returning BLADERF_STREAM_NO_DATA from callbacks. Do not use this function if the associated callback functions will be returning buffers for submission.
This call may block if the device is not ready to submit a buffer for transfer. Use the timeout_ms
to place an upper limit on the time this function can block.
To safely submit buffers from outside the stream callback flow, this function internally acquires a per-stream lock (the same one that is held during the execution of a stream callback). Therefore, it is important to be aware of locks that may be held while making this call, especially those acquired during execution of the associated stream callback function. (i.e., be wary of the order of lock acquisitions, including the internal per-stream lock.)
stream | Stream to submit buffer to | |
[in,out] | buffer | Buffer to fill (RX) or containing data (TX). This buffer is assumed to be the size specified in the associated bladerf_init_stream() call. |
[in] | timeout_ms | Milliseconds to timeout in, if this call blocks. 0 implies an "infinite" wait. |
API_EXPORT int CALL_CONV bladerf_submit_stream_buffer_nb | ( | struct bladerf_stream * | stream, |
void * | buffer | ||
) |
This is a non-blocking variant of bladerf_submit_stream_buffer(). All of the caveats and important notes from bladerf_submit_stream_buffer() apply.
In the event that this call would need to block in order to submit a buffer, it returns BLADERF_ERR_WOULD_BLOCK. In this case, the caller could either wait and try again or defer buffer submission to the asynchronous callback.
stream | Stream to submit buffer to | |
[in,out] | buffer | Buffer to fill (RX) or containing data (TX). This buffer is assumed to be the size specified in the associated bladerf_init_stream() call. |