Post Go back to editing

gnuplot yields double buffer size when plotting using libiio

Category: Hardware
Product Number: pluto

Hi all,

Im using C to plot a real time simple receive stream via libiio for ADALM pluto, it has dual receive enabled.  The plotting is done in real time and live using GNUplot as i need everything to be written in C for a project.  The code below strictly follows the C tutorial in libiio for receive from ADI.  However, despite defining the buffer size to be 4096, the x axis in the resulting plot demonstrates double that (> 8000) exactly.  Does it have to do with the fact that im summing up the I (in phase) components of both channels? or does it have to do with int_16t? 

My question is:  how do i get gnuplot to plot the IQ samples (for a single channel or both whatever), whereby the x axis reflects the correct buffer size.

Sincerely,

Abdalla

#include <stdio.h>
#include <iio.h>
#include <math.h>
#include <unistd.h>
#include <sys/wait.h>
#include <pthread.h>
#include <time.h>
#include <signal.h>
#include <complex.h>
#include <liquid/liquid.h>

// Below routing computes FFT

int receive(struct iio_context *ctx)
{
struct iio_device *dev;
struct iio_channel *rx0_i, *rx0_q, *rx1_i, *rx1_q;
struct iio_buffer *rxbuf;
struct iio_channels_mask *rxmask;
struct iio_stream *rxstream;

int64_t last_ts = 0;

dev = iio_context_find_device(ctx, "cf-ad9361-lpc");
rx0_i = iio_device_find_channel(dev, "voltage0", 0);
rx0_q = iio_device_find_channel(dev, "voltage1", 0);
rx1_i = iio_device_find_channel(dev, "voltage2", 0);
rx1_q = iio_device_find_channel(dev, "voltage3", 0);

iio_channel_enable(rx0_i);
iio_channel_enable(rx0_q);
iio_channel_enable(rx1_i);
iio_channel_enable(rx1_q);

rxbuf = iio_device_create_buffer(dev, 4096, false);
if (!rxbuf) {
perror("Could not create RX buffer for chan 0");
return -1;
}

FILE *pipe_gp = popen("gnuplot -persistent", "w");

fprintf(pipe_gp, "set term qt persistent'\n");
fprintf(pipe_gp, "set xlabel 'Time'\n");
fprintf(pipe_gp, "set ylabel 'I Value'\n");
fprintf(pipe_gp, "set title 'Real-Time Plot'\n");
fprintf(pipe_gp, "set grid\n");
int flags = 0;

while (true) {
void *p_dat, *p_end, *t_dat;
int64_t now_ts;
ptrdiff_t p_inc;
p_inc = iio_buffer_step(rxbuf);
p_end = iio_buffer_end(rxbuf);

// p_inc = iio_device_get_sample_size(dev);
// p_end = iio_block_end(rxblock);

for (p_dat = iio_buffer_first(rxbuf, rx0_i); p_dat < p_end; p_dat += p_inc, t_dat += p_inc) {
const int16_t i = ((int16_t*)p_dat)[0]; // Real (I)
const int16_t q = ((int16_t*)p_dat)[1]; // Imag (Q)
const int16_t i1 = ((int16_t*)p_dat)[2]; // Real (I)
const int16_t q2 = ((int16_t*)p_dat)[3]; // Imag (Q)
const int16_t IQ = i + i1;

fprintf(pipe_gp, "plot '-' with lines\n"); // Set up the initial plot
fprintf(pipe_gp, "%d\n", IQ);

}
iio_buffer_refill(rxbuf);
fprintf(pipe_gp, "e\n"); // Send 'e' to gnuplot to flush the plot
fflush(pipe_gp);
usleep(10000);
fprintf(pipe_gp, "replot\n");

}

fclose(pipe_gp);
iio_buffer_destroy(rxbuf);
return 0;
}


int main (int argc, char **argv)
{
struct iio_context *ctx;
struct iio_device *phy;

ctx = iio_create_context_from_uri("ip:pluto.local");

phy = iio_context_find_device(ctx, "ad9361-phy");

iio_channel_attr_write_longlong(
iio_device_find_channel(phy, "altvoltage0", true),
"frequency",
2400000000); /* RX LO frequency 2.4GHz */

iio_channel_attr_write_longlong(
iio_device_find_channel(phy, "voltage0", false),
"sampling_frequency",
5000000); /* RX baseband rate 5 MSPS */

receive(ctx);
iio_context_destroy(ctx);

return 0;
}

// For multiple devices, use multiple threads.