Post Go back to editing

OOK Modulation at 2MHz sample rate

Category: Software
Product Number: ADALM-PLUTO- Rev.C
Software Version: v0.39

Hi,

I try to setup a OOK (On-Off Keying) modulation with my PlutoSDR but I face some issues.

I want to generate a signal with a carrier of 868 MHz and a datarate of 2Mbaud.

I finally succed to generate a signal but i'm a bit disturbing by the rise/fall time between bit.

  • The carrier frequency is OK (868 MHz)

  • My 100 bits paquet take 50us to be send at 2Mbits/s which is also OK

  • The time between each bit i have 500ns wich is also ok (2Mbits/s)

  • The rise/fall time is about 250ns

I find that the rise/fall time are very long.
I expected something much shorter.

I use the following C code with libiio and libad9361 to drive the device.
Right now this code only generate a sequence of 100 bit "01010101..." and convert it to IQ sample data to send it every ms.

There is a better way to generate the signal to have a much shorter rise/fall time ?

#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>

#include <iio.h>
#include <ad9361.h>

#define SAMPLES_CNT 100 // Number of bit in my bitstream

#define TX_LO_FREQ      868000000   // 868 MHz
#define TX_SAMPLERATE   2000000     // 2 MHz
#define TX_GAIN         -1          // -1 dB
#define TX_RF_BANDWIDTH 2000000     // 2 MHz

int main(int argc, char **argv)
{
    // Create context and search phy device
    struct iio_context* ctx = iio_create_context_from_uri("ip:pluto.local");
    struct iio_device* dev_phy = iio_context_find_device(ctx, "ad9361-phy");

    // Search TX device
    struct iio_device* dev_tx = iio_context_find_device(ctx, "cf-ad9361-dds-core-lpc");

    // Create IQ channels
    struct iio_channel* ch_txi = iio_device_find_channel(dev_tx, "voltage0", true);
    struct iio_channel* ch_txq = iio_device_find_channel(dev_tx, "voltage1", true);

    // Enable channels
    iio_channel_enable(ch_txi);
    iio_channel_enable(ch_txq);

    //Create nonclyclic TX IQ buffer
    struct iio_buffer* buf_tx = iio_device_create_buffer(dev_tx, SAMPLES_CNT, false);

    // Set TX LO frequency
    iio_channel_attr_write_longlong( iio_device_find_channel(dev_phy, "altvoltage1", true), "frequency", TX_LO_FREQ);

    // Set TX sample rate
    ad9361_set_bb_rate(dev_phy, TX_SAMPLERATE);

    // Set TX Gain
    iio_channel_attr_write_double( iio_device_find_channel(dev_phy, "voltage0", true), "hardwaregain", TX_GAIN);

    // Set TX RF filter bandwidth
    iio_channel_attr_write_longlong( iio_device_find_channel(dev_phy, "voltage0", true), "rf_bandwidth", TX_RF_BANDWIDTH);

    // Enable TX
    iio_channel_attr_write_bool( iio_device_find_channel(dev_phy, "altvoltage1", true), "powerdown", false);
   
    // Delay
    sleep(1);

    // IQ data buffer init (see buffer init for array size explanation)
    int16_t data_iq[SAMPLES_CNT*2];

    // Generate simple OOK signal equivalent to '0101010101...' bitstream
    for (int i = 0; i < SAMPLES_CNT; i++)
    {
        if(i % 2 == 0)
        {
            data_iq[2 * i]     = 2047;  // I component
            data_iq[2 * i + 1] = 2047;  // Q component
        }
        else
        {
            data_iq[2 * i]     = 0;  // I component
            data_iq[2 * i + 1] = 0;  // Q component
        }
    }

    // Send signal periodically
    while(1)
    {
        // Get pointer to iio buffer start
        int16_t* samples = (int16_t*) iio_buffer_start(buf_tx);

        // Copy IQ data to IIO buffer
        for (size_t i = 0; i < SAMPLES_CNT*2; i++)
            samples[i] = data_iq[i] << 4;  

        // Send data
        iio_buffer_push(buf_tx);

        // Sleep 1ms
        usleep(1000);
    }

    return EXIT_SUCCESS;
}

Thread Notes