This example libiio program is meant to exercise the features of IIO functionality on the ADRV9009.
#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(); \
} \
}
enum iodev { RX, TX };
struct stream_cfg {
long long lo_hz;
};
static char tmpstr[64];
static bool stop;
static void shutdown()
{
printf("* Destroying buffers\n");
printf("* Disabling streaming channels\n");
printf("* Destroying context\n");
exit(0);
}
static void handle_sig(int sig)
{
printf("Waiting for process to finish... Got signal %d\n", sig);
stop = true;
}
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)
{
}
static long long rd_ch_lli(
struct iio_channel *chn,
const char* what)
{
long long val;
printf("\t %s: %lld\n", what, val);
return val;
}
#if 0
static void wr_ch_str(
struct iio_channel *chn,
const char* what,
const char* str)
{
}
#endif
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;
}
{
switch (d) {
default: IIO_ENSURE(0); return false;
}
}
{
*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;
}
{
switch (d) {
case RX: *chn =
iio_device_find_channel(get_adrv9009_phy(ctx), get_ch_name(
"voltage", chid),
false);
return *chn != NULL;
case TX: *chn =
iio_device_find_channel(get_adrv9009_phy(ctx), get_ch_name(
"voltage", chid),
true);
return *chn != NULL;
default: IIO_ENSURE(0); return false;
}
}
{
}
bool cfg_adrv9009_streaming_ch(
struct iio_context *ctx,
struct stream_cfg *cfg,
int chid)
{
printf("* Acquiring ADRV9009 phy channel %d\n", chid);
if (!get_phy_chan(ctx, 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(ctx, &chn)) { return false; }
wr_ch_lli(chn, "frequency", cfg->lo_hz);
return true;
}
int main (__notused int argc, __notused char **argv)
{
size_t nrx = 0;
size_t ntx = 0;
struct stream_cfg trxcfg;
signal(SIGINT, handle_sig);
trxcfg.lo_hz = GHZ(2.5);
printf("* Acquiring IIO context\n");
printf("* Acquiring ADRV9009 streaming devices\n");
IIO_ENSURE(get_adrv9009_stream_dev(ctx, TX, &tx) && "No tx dev found");
IIO_ENSURE(get_adrv9009_stream_dev(ctx, RX, &rx) && "No rx dev found");
printf("* Configuring ADRV9009 for streaming\n");
IIO_ENSURE(cfg_adrv9009_streaming_ch(ctx, &trxcfg, 0) && "TRX device not found");
printf("* Initializing ADRV9009 IIO streaming channels\n");
IIO_ENSURE(get_adrv9009_stream_ch(ctx, RX, rx, 0, 'i', &rx0_i) && "RX chan i not found");
IIO_ENSURE(get_adrv9009_stream_ch(ctx, RX, rx, 0, 'q', &rx0_q) && "RX chan q not found");
IIO_ENSURE(get_adrv9009_stream_ch(ctx, TX, tx, 0, 0, &tx0_i) && "TX chan i not found");
IIO_ENSURE(get_adrv9009_stream_ch(ctx, TX, tx, 1, 0, &tx0_q) && "TX chan q not found");
printf("* Enabling IIO streaming channels\n");
printf("* Creating non-cyclic IIO buffers with 1 MiS\n");
if (!rxbuf) {
perror("Could not create RX buffer");
shutdown();
}
if (!txbuf) {
perror("Could not create TX buffer");
shutdown();
}
printf("* Starting IO streaming (press CTRL+C to cancel)\n");
while (!stop)
{
ssize_t nbytes_rx, nbytes_tx;
char *p_dat, *p_end;
ptrdiff_t p_inc;
if (nbytes_tx < 0) { printf("Error pushing buf %d\n", (int) nbytes_tx); shutdown(); }
if (nbytes_rx < 0) { printf("Error refilling buf %d\n",(int) nbytes_rx); shutdown(); }
const int16_t i = ((int16_t*)p_dat)[0];
const int16_t q = ((int16_t*)p_dat)[1];
((int16_t*)p_dat)[0] = q;
((int16_t*)p_dat)[1] = i;
}
((int16_t*)p_dat)[0] = 0 << 2;
((int16_t*)p_dat)[1] = 0 << 2;
}
printf("\tRX %8.2f MSmp, TX %8.2f MSmp\n", nrx/1e6, ntx/1e6);
}
shutdown();
return 0;
}