Post Go back to editing

Pluto SDR transmitting Data samples from file using C

Hello,

     I want to create a standalone C application for pluto SDR that reads samples( transmit signal) from a text/bin file (which is inside pluto) and loads into Tx buffer and transmit it. I had seen other questions/pages where a .mat file or txt file loaded and tranistted through iio-oscilloscope application. Is it possible to do so with C program i,e to read file and load the values directly to the buffer (i.e without converting string to int/floats). 

 Also if it is not possible and if i convert the samples from string to floats what must be the data type of the tx_buf? If it should be integer how do i create say a lookup table ? Like for example creating sine wave in a microcontroller using DAC that uses some lookup tables. 

Thank you.

Regards,

Bharat



Adding one more clarification
[edited by: bharathvikram at 1:33 PM (GMT -4) on 28 Jul 2021]
  • Can you elaborate more on your usecase regarding the datatype? Does USB OTG support for Pluto help your usecase - https://wiki.analog.com/university/tools/pluto/devs/usb_otg

    - Srikanth

  • Hey,

        I want to transmit a FMCW signal. I used python program with python ADI libraries to transmit and receive this signal. Now I want to make a standalone application that runs on pluto directly. Instead of using C program to generate FMCW signal, I want to use signal generated in python, load this into a file (.txt or .bin) and place it in pluto. Then C program that reads this file and sends the sample to the tx buffer. Since python will give me float values can i directly write these into Tx buffer, as we do it in python, making Tx_buffer as a float variable ? 

    Python Code :

       fmcw_array = chirp(t,0,0.001,2e6,method='linear')

       // SDR set up ..

       sdr.tx_cyclic_buffer = True 
       sdr.tx(fmcw_array)

    where FMCW array looks shown in picture. I want this to be stored in a  file and transmitted using C. So what will be the data type of the Tx buffer? Since Tx side uses DAC should i send integer values instead of float? or how to format the below values for transmission in C?

    Thank you,

    Reagrds,

    Bharat

  • Hey,

        I guess I found solution for the problem. I have attached the C code, binary file for the signal and python code to get the signal samples to send. It is working but I didn't know how to set cyclic buffer so i used while(1) loop. I hope it is correct and if anyone can verify it it would be great. I modified one of the example c program to do this. 

    #include <iio.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    #define MAX_SIZE 1000000
    
    int main(void)
    {
        struct iio_context *ctx;
        struct iio_device  *dev_phy;
        struct iio_device  *tx;
        struct iio_channel *ch;
        struct iio_channel *ch_tx_lo;
        struct iio_channel *tx0_i;
        struct iio_channel *tx0_q;
        struct iio_buffer  *txbuf;
        ssize_t ret;
        int indx;
        ssize_t nbytes_tx;
        char *p_dat, *p_end;
        ptrdiff_t p_inc;
        FILE *fp;
        int linect = 0;
        char buf[128];
    
    
        // ctx = iio_create_default_context();
        ctx = iio_create_context_from_uri("local:");
        dev_phy = iio_context_find_device(ctx, "ad9361-phy");
        ch = iio_device_find_channel(dev_phy, "voltage0", true);
        ch_tx_lo =iio_device_find_channel(dev_phy, "altvoltage1", true);
        tx = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc");
        tx0_i = iio_device_find_channel(tx, "voltage0", true);
        tx0_q = iio_device_find_channel(tx, "voltage1", true);
    
        ret = iio_channel_attr_write(ch, "sampling_frequency", "5000");
        if (ret<0)
            printf("Writing sampling_frequency failed");
        ret = iio_channel_attr_write(ch, "rf_bandwidth", "2000000");
        if (ret<0)
            printf("Writing rf_bandwidth failed");
        ret = iio_channel_attr_write(ch, "hardwaregain", "-10");
        if (ret<0)
            printf("Writing hardwaregain failed");
        iio_channel_enable(tx0_i);
        iio_channel_enable(tx0_q);
        ret = iio_channel_attr_write(ch_tx_lo,"frequency","2421000000");
    
    
        // Read data in
        int *i_data = (int*) malloc(sizeof(int)* MAX_SIZE);
        int *q_data = (int*) malloc(sizeof(int)* MAX_SIZE);
    
        fp = fopen("fmcw_2.bin", "r");
        if(fp == NULL) {
            fprintf(stderr,"Cannot open file for reading");
            exit(EXIT_FAILURE);
        }
        while( fgets(buf,sizeof(buf),fp) != NULL ) {
            sscanf(buf,"%d %d", &i_data[linect], &q_data[linect]);
            printf("Set %d - 1st: %d, 2nd: %d\n", linect, i_data[linect], q_data[linect]);
            linect++;
            if ((linect+1)>=MAX_SIZE) {
                fprintf(stderr,"Max data size exceeded");
                exit(EXIT_FAILURE);
            }
    
        }
        fclose(fp);
    
    
        // Create buffer
        txbuf = iio_device_create_buffer(tx, linect, true);
        if (!txbuf) {
            fprintf(stderr,"Could not create TX buffer");
            exit(EXIT_FAILURE);
        }
        // Fill buffer
        p_inc = iio_buffer_step(txbuf);
        p_end = iio_buffer_end(txbuf);
        indx = 0;
        for (p_dat = (char *)iio_buffer_first(txbuf, tx0_i); p_dat < p_end;
             p_dat += p_inc) {
            ((int16_t*)p_dat)[0] = i_data[indx]; // Real (I)
            indx++;
        }
        indx = 0;
        for (p_dat = (char *)iio_buffer_first(txbuf, tx0_q); p_dat < p_end;
             p_dat += p_inc) {
            ((int16_t*)p_dat)[0] = q_data[indx]; // Imag (Q)
            indx++;
        }
        nbytes_tx = iio_buffer_push(txbuf);
        if (nbytes_tx < 0) {
            fprintf(stderr,"Error pushing buf %d\n", (int) nbytes_tx);
            exit(EXIT_FAILURE);
        }
    
    
        while (1)
            sleep(30);
    
        iio_context_destroy(ctx);
        return EXIT_SUCCESS;
    
    
    }
      I     Q
    16384 -32596
     16383 -17069
     16383 -17257
     16383 -13225
     16383 -12878
     16383 -10778
     16383 -10337
     16382 -8953
     16381 -8506
     16380 -7473
     16378 -7040
     16376 -6210
     16373 -5793
     16369 -5090
     16364 -4688
     16357 -4070
     16350 -3681
     16340 -3122
     16329 -2743
     16316 -2226
     16301 -1854
     16283 -1369
     16262 -1001
     16239 -538
     16212 -173
     16182 272
     16148 636
     16109 1071
     16066 1435
     16019 1861
     15966 2226
     15908 2646
     15844 3014
     15774 3430
     15697 3800
     15613 4213
     15522 4586
     15423 4998
     15316 5373
     15201 5784
     15077 6162
     14943 6572
     14800 6953
     14646 7362
     14482 7743
     14307 8151
     14121 8532
     13923 8938
     13713 9319
     13490 9720
     13254 10099
     13006 10495
     12743 10870
     12467 11260
     12177 11628
     11872 12009
     11553 12369

      

    fmcw_array = chirp(t,0,0.001,2e6,method='linear')
    array_samp = hilbert(fmcw_array)
    #array_samp = array_samp.astype(np.complex64)
    
    fmcw_waveform = np.array([])
    fmcw_waveform=np.append(fmcw_waveform,array_samp)
    fmcw_waveform *=2**14
    fmcw_waveform=fmcw_waveform.astype(np.complex64)
    fmcw_waveform=np.int_(fmcw_waveform.real) + (np.int_(fmcw_waveform.imag))*1J
    fmcw_waveform.tofile("fmcwsamples.iq")
    
    

  • Passing the Boolean value of true as the third argument of iio_device_create_buffer() should take care of setting up cyclic buffers. Using either an instrument or Pluto in RF loopback mode with a transmit power set low, if you pull samples on the receive side, you should see that the waveform repeats continuously.