This example libiio program is meant to exercise the features of IIO functionality on the ADRV9009.
#include "iiostream-common.h"
#include <errno.h>
#include <iio/iio-debug.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#define MHZ(x) ((long long)(x*1000000.0 + .5))
#define GHZ(x) ((long long)(x*1000000000.0 + .5))
#define IIO_ENSURE(expr) { \
if (!(expr)) { \
(void) fprintf(stderr, "assertion failed (%s:%d)\n", __FILE__, __LINE__); \
(void) abort(); \
} \
}
#define BLOCK_SIZE (1024 * 1024)
enum iodev { RX, TX };
struct stream_cfg {
long long lo_hz;
};
static char tmpstr[64];
static struct iio_stream *rxstream = NULL;
static struct iio_stream *txstream = NULL;
static struct iio_channels_mask *rxmask = NULL;
static struct iio_channels_mask *txmask = NULL;
static void cleanup(void)
{
printf("* Destroying streams\n");
printf("* Destroying channel masks\n");
printf("* Destroying context\n");
}
static void shutdown(void)
{
cleanup();
exit(1);
}
static void handle_sig(int sig)
{
printf("Waiting for process to finish... Got signal %d\n", sig);
stop_stream();
}
static void errchk(int v, const char* what) {
if (v < 0) { fprintf(stderr, "Error %d writing to channel \"%s\"\nvalue may not be supported.\n", v, what); shutdown(); }
}
static void wr_ch_lli(
struct iio_channel *chn,
const char* what,
long long val)
{
errchk(attr ? iio_attr_write_longlong(attr, val) : -ENOENT, what);
}
static long long rd_ch_lli(
struct iio_channel *chn,
const char* what)
{
long long val = 0;
errchk(attr ? iio_attr_read_longlong(attr, &val) : -ENOENT, what);
printf("\t %s: %lld\n", what, val);
return val;
}
static char* get_ch_name_mod(const char* type, int id, char modify)
{
snprintf(tmpstr, sizeof(tmpstr), "%s%d_%c", type, id, modify);
return tmpstr;
}
static char* get_ch_name(const char* type, int id)
{
snprintf(tmpstr, sizeof(tmpstr), "%s%d", type, id);
return tmpstr;
}
{
IIO_ENSURE(dev && "No adrv9009-phy found");
return dev;
}
static bool get_adrv9009_stream_dev(
enum iodev d,
struct iio_device **dev)
{
switch (d) {
default: IIO_ENSURE(0); return false;
}
}
static bool get_adrv9009_stream_ch(
enum iodev d,
struct iio_device *dev,
int chid,
char modify,
struct iio_channel **chn)
{
*chn =
iio_device_find_channel(dev, modify ? get_ch_name_mod(
"voltage", chid, modify) : get_ch_name(
"voltage", chid), d == TX);
if (!*chn)
*chn =
iio_device_find_channel(dev, modify ? get_ch_name_mod(
"voltage", chid, modify) : get_ch_name(
"voltage", chid), d == TX);
return *chn != NULL;
}
static bool get_phy_chan(
enum iodev d,
int chid,
struct iio_channel **chn)
{
switch (d) {
case RX: *chn =
iio_device_find_channel(get_adrv9009_phy(), get_ch_name(
"voltage", chid),
false);
return *chn != NULL;
case TX: *chn =
iio_device_find_channel(get_adrv9009_phy(), get_ch_name(
"voltage", chid),
true);
return *chn != NULL;
default: IIO_ENSURE(0); return false;
}
}
{
}
bool cfg_adrv9009_streaming_ch(struct stream_cfg *cfg, int chid)
{
printf("* Acquiring ADRV9009 phy channel %d\n", chid);
if (!get_phy_chan(true, chid, &chn)) { return false; }
rd_ch_lli(chn, "rf_bandwidth");
rd_ch_lli(chn, "sampling_frequency");
printf("* Acquiring ADRV9009 TRX lo channel\n");
if (!get_lo_chan(&chn)) { return false; }
wr_ch_lli(chn, "frequency", cfg->lo_hz);
return true;
}
int main (int argc, char **argv)
{
size_t rx_sample_sz, tx_sample_sz;
struct stream_cfg trxcfg;
int err;
signal(SIGINT, handle_sig);
trxcfg.lo_hz = GHZ(2.5);
printf("* Acquiring IIO context\n");
if (argc == 1) {
err = iio_err(ctx);
IIO_ENSURE(!err && "No context");
} else if (argc == 2) {
err = iio_err(ctx);
IIO_ENSURE(!err && "No context");
}
printf("* Acquiring ADRV9009 streaming devices\n");
IIO_ENSURE(get_adrv9009_stream_dev(TX, &tx) && "No tx dev found");
IIO_ENSURE(get_adrv9009_stream_dev(RX, &rx) && "No rx dev found");
printf("* Configuring ADRV9009 for streaming\n");
IIO_ENSURE(cfg_adrv9009_streaming_ch(&trxcfg, 0) && "TRX device not found");
printf("* Initializing ADRV9009 IIO streaming channels\n");
IIO_ENSURE(get_adrv9009_stream_ch(RX, rx, 0, 'i', &rx0_i) && "RX chan i not found");
IIO_ENSURE(get_adrv9009_stream_ch(RX, rx, 0, 'q', &rx0_q) && "RX chan q not found");
IIO_ENSURE(get_adrv9009_stream_ch(TX, tx, 0, 0, &tx0_i) && "TX chan i not found");
IIO_ENSURE(get_adrv9009_stream_ch(TX, tx, 1, 0, &tx0_q) && "TX chan q not found");
if (!rxmask) {
fprintf(stderr, "Unable to alloc RX channels mask\n");
shutdown();
}
if (!txmask) {
fprintf(stderr, "Unable to alloc TX channels mask\n");
shutdown();
}
printf("* Enabling IIO streaming channels\n");
printf("* Creating non-cyclic IIO buffers with 1 MiS\n");
if (!rxbuf) {
ctx_perror(ctx, -ENODEV, "Could not get RX buffer");
shutdown();
}
if (!txbuf) {
ctx_perror(ctx, -ENODEV, "Could not get TX buffer");
shutdown();
}
if (iio_err(rxstream)) {
rxstream = NULL;
ctx_perror(ctx, iio_err(rxstream), "Could not create RX stream");
shutdown();
}
if (iio_err(txstream)) {
txstream = NULL;
ctx_perror(ctx, iio_err(txstream), "Could not create TX stream");
shutdown();
}
rx_sample_sz = iio_device_get_sample_size(rx, rxmask);
tx_sample_sz = iio_device_get_sample_size(tx, txmask);
printf("* Starting IO streaming (press CTRL+C to cancel)\n");
stream(rx_sample_sz, tx_sample_sz, BLOCK_SIZE,
rxstream, txstream, rx0_i, tx0_i);
cleanup();
return 0;
}
void iio_channel_enable(const struct iio_channel *chn, struct iio_channels_mask *mask)
Enable the given channel.
Definition channel.c:444
const struct iio_attr * iio_channel_find_attr(const struct iio_channel *chn, const char *name)
Try to find a channel-specific attribute by its name.
Definition channel.c:392
struct iio_device * iio_context_find_device(const struct iio_context *ctx, const char *name)
Try to find a device structure by its ID, label or name.
Definition compat.c:710
struct iio_context * iio_create_context(const struct iio_context_params *params, const char *uri)
Create a context from a URI description.
Definition context.c:716
void iio_context_destroy(struct iio_context *ctx)
Destroy the given context.
Definition compat.c:434
unsigned int iio_context_get_devices_count(const struct iio_context *ctx)
Enumerate the devices found in the given context.
Definition compat.c:698
struct iio_channels_mask * iio_create_channels_mask(unsigned int nb_channels)
Create a new empty channels mask.
Definition mask.c:14
void iio_channels_mask_destroy(struct iio_channels_mask *mask)
Destroy a channels mask.
Definition mask.c:40
struct iio_buffer * iio_device_get_buffer(const struct iio_device *dev, unsigned int index)
Get the buffer present at the given index.
Definition device.c:254
struct iio_channel * iio_device_find_channel(const struct iio_device *dev, const char *name, bool output)
Try to find a channel structure by its ID, label or name.
Definition compat.c:969
unsigned int iio_device_get_channels_count(const struct iio_device *dev)
Enumerate the channels of the given device.
Definition compat.c:857
void iio_stream_destroy(struct iio_stream *stream)
Destroy the given stream object.
Definition stream.c:86
struct iio_stream * iio_buffer_create_stream(struct iio_buffer *buffer, size_t nb_blocks, size_t samples_count, struct iio_channels_mask *mask)
Create a iio_stream object for the given iio_buffer.
Definition stream.c:26
Structure holding meta-data for an attribute.
Definition iio-backend.h:83
An input or output buffer, used to read or write samples.
Represents an input or output channel of a device.
Contains the representation of an IIO context.
Represents a device in the IIO context.