pothosware / SoapyPlutoSDR

Soapy SDR plugin for PlutoSDR
https://github.com/pothosware/SoapyPlutoSDR/wiki
GNU Lesser General Public License v2.1
53 stars 22 forks source link

Tx samples Correct format #64

Closed Mas313 closed 2 weeks ago

Mas313 commented 1 month ago

Hi I am having trouble transmitting with plutosdr with specified formats like CF32 and CS 16 . Although I was able to send some pulses using CU8 format but those were values like 127 -127 , more here https://github.com/pothosware/SoapyPlutoSDR/issues/63.

I have gausian filtered data that has been accumulated (integrated). Now trying to transmit the data results in no transmisssion, verified through 'SdrSharp'. I want to know what values the soapysdr library expects for pluto to be. When using complex float or 16 bit integer, What is the range of values the data should fit in?. Also I have seen example of narrow band fm transmitter where CF32 format is used and the samples values are stored in a variable and assigned to void buffer like this

float buff;
--- fill buff samples from wave file
void *buffs={buff}

Now transmission is done with writestream function. Here I assume that wave file already had scaled samples so no scaling was done and wave file transmitted successfully. But it seems strange that CF32 format was specified but samples were stored in float (not complex float) and it did transmit. Besides this the main question is what are the ranges the data should fit in for float and 16 bit integer samples. Thanks

zuckschwerdt commented 1 month ago

Integer formats always expect the maximum signed range, for 16 bit that would be 2^15-1 = 32767 to -2^15 = -32768. For float formats the range is normalized to +/-1.0.

The Pluto uses 12 bits but the transfer is 16 bits, so CU8 would leave some dynamic range unused, CS16 could be optimal and CF32 is wasting (USB) bandwith and needs to be converted anyway. See https://github.com/pothosware/SoapyPlutoSDR/blob/master/PlutoSDR_Streaming.cpp#L649

Note that complex float is just two channels (I/Q) interleaved floats. If you read from a stereo wave file that maps to the two stereo channels (left/right).

Mas313 commented 1 month ago

I did following but no luck, pluto not transmitting anything. I converted double to int16_t and changed soapy format to CS16. Any sugegstions please,

 for (int i = 0; i < num_samples; i++) {
        // Scale floating-point sample to signed 16-bit integer range (-32768 to 32767)
        outI[i] = (int16_t)(I[i] * 32767);
        outQ[i] = (int16_t)(Q[i] * 32767);
    }
//values assigned to complex int16_t buffer like this
for (int  a=0; a< num_samples; a++){
buf.real( outI[i]  );
buf.imag( outQ[i] );
}
void *buffs[]={buf};

Thanks

zuckschwerdt commented 1 month ago

Write your buffers to .cf32 and .cs16 files. Then open with https://triq.org/pdv/ to verify the data. E.g.

    int fd = open("foo.cs16", O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd < 0) {
        perror("open()");
        exit(1);
    }
    int r = write(fd, buf, num_samples * sizeof(int16_t) * 2);
    printf("Wrote: %d bytes\n", r);
    close(fd);
Mas313 commented 1 month ago

Thanks for the reply. I have attached the results i cannot understood. First screen shot is of file containing I & Q int16_t samples interleaved in a buffer.
Second screenshot is of complex int16_t buffer with values stores as

buf.real( outI[i]  );
buf.imag( outQ[i] );

I am producing zero IF signals so the SDR Fc should have no offset. I dont see any spectrum in any case. cs16InterleavedComlpexIQ CS16comlplexVariable

zuckschwerdt commented 1 month ago

both files look empty. somehow your data is not present in the original or much too quiet (too small numbers).

zuckschwerdt commented 1 month ago

Try this to fill your complex float buffer. You'll get a pure tone at +10 kHz and a (-27 dB) noise background.

    for (int i = 0; i < num_samples; i +=1) {
        float ni = rand() / (float)RAND_MAX * 0.1f - 0.05f;
        float nq = rand() / (float)RAND_MAX * 0.1f - 0.05f;
        float ph = i / 3.0;
        buf[i] = ni + cosf(ph) + nq + sinf(ph) * I;
    }
Mas313 commented 1 month ago

I have implemented your code and stores file as

int main()
{
    int num_samples=10000;

    complex float buf[num_samples];

    for (int i = 0; i < num_samples; i +=1) {
        float ni = rand() / (float)RAND_MAX * 0.1f - 0.05f;
        float nq = rand() / (float)RAND_MAX * 0.1f - 0.05f;
        float ph = i / 3.0;
        buf[i] = ni + cosf(ph) + nq + sinf(ph) * I;
    }

    int fd = open("Tone.cf32", O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd < 0) {
        perror("open()");
        exit(1);
    }
    int r = write(fd, buf, num_samples * sizeof(float) * 2);
    printf("Wrote: %d bytes\n", r);
    close(fd);

    return 0;
}

Got following TonefloatComplex

When i transmitted same data using following code i got multiple harmonics ( not 10 Khz offset to carrier) verified throgh SDR sharp on another PC. I used plutosdr using c as follows:

int delay=1000000;
double  carrier_frequency=800025000;
double  sampling_rate=2000000.0;
double  tx_gain=65.0;

int main()
{
    SoapySDRDevice *sdr = NULL;
        SoapySDRKwargs args = {};

    int num_samples=313;

    complex float buf[num_samples];

    for (int i = 0; i < num_samples; i +=1) {
        float ni = rand() / (float)RAND_MAX * 0.1f - 0.05f;
        float nq = rand() / (float)RAND_MAX * 0.1f - 0.05f;
        float ph = i / 3.0;
        buf[i] = ni + cosf(ph) + nq + sinf(ph) * I;
    }

    int fd = open("Tone.cf32", O_WRONLY | O_CREAT | O_TRUNC, 0644);
    if (fd < 0) {
        perror("open()");
        exit(1);
    }
    int r = write(fd, buf, num_samples * sizeof(float) * 2);
    printf("Wrote: %d bytes\n", r);
    close(fd);

    // Soapy Sending 

        SoapySDRKwargs_set(&args, "driver", "plutosdr");
        //SoapySDRDevice *sdr = SoapySDRDevice_make(&args);
        sdr = SoapySDRDevice_make(&args);
        SoapySDRKwargs_clear(&args);

        printf("After SoapySDRKwargs_clear(&args) \n");
        if (sdr == NULL)
        {
        printf("Errorr SoapySDRDevice_make fail: %s\n", SoapySDRDevice_lastError());
        return 1;
        }
        if (sdr == NULL) {
        fprintf(stderr, "Failed to create SoapySDR device\n");

        return 1;
        }

        // Set sample rate, center frequency, and gain 
        SoapySDRDevice_setSampleRate(sdr, SOAPY_SDR_TX, 0, sampling_rate);
        SoapySDRDevice_setFrequency(sdr, SOAPY_SDR_TX, 0, carrier_frequency, NULL);
        SoapySDRDevice_setGain(sdr, SOAPY_SDR_TX, 0, tx_gain);

        // Create TX stream
        printf(" Before: SoapySDRDevice_setupStream for Tx \n");// float 32 bit SOAPY_SDR_F32
        SoapySDRStream *txStream = SoapySDRDevice_setupStream(sdr,SOAPY_SDR_TX,SOAPY_SDR_CF32,NULL,0, NULL);

        if (txStream == NULL)
            {
            printf("setupStream fail: %s\n", SoapySDRDevice_lastError());
            SoapySDRDevice_unmake(sdr);
        exit(0);
            return EXIT_FAILURE;
            }
        printf(" After: SoapySDRDevice_setupStream \n");  

        int sres=SoapySDRDevice_activateStream(sdr, txStream, 0, 0, 0); //start streaming
        printf(" After calling--------  SoapySDRDevice_activateStream Tx sres=%d  \n",sres);
        getchar();

          int flags = 0;
            long long timeNs = 0;
         int loop=0;

        while(loop++<10){

             int numcount=num_samples; //num_samples*2; //j;
        int count=0;
        //while(numcount > 0){
        // printf("bEFORE void *buffs[] = {buffp} \n");
          const void *buffs[] = {buf}; // {buffp};
         // printf("AFTER void *buffs[] = {buffp} \n");
          if(sdr==NULL || txStream ==NULL ){
            printf("NULL " );
            exit(0);
          }
          printf("=====Writing with Buffer count=%d\n",numcount);
          int ret=SoapySDRDevice_writeStream(sdr, txStream, buffs, numcount, &flags, timeNs, 1000000);  
          if (ret <= 0){
             printf("writeStream Error ret %d\n",ret);
            exit(0);
          }
           if (ret > 0){
             printf("writeStream Ok ret %d\n",ret);
          }

        //}
            printf("-------------Complete One buffer transmitted with count= %d\n",count);
        usleep(delay);
}   

    return 0;
}
zuckschwerdt commented 1 month ago

Looks like a good transmission! The harmonics would be from the maxed out amplitude, you can try to scale the cos and sin down with e.g. 0.9 * This example shows that very likely your earlier input buffer did not contain good samples.