SDRPLAY linux commandline tools?

Add useful snippets of code or links to entire SDR projects.
0815
Posts: 45
Joined: Sat Jan 30, 2016 3:07 pm

Re: SDRPLAY linux commandline tools?

Post by 0815 » Wed Mar 16, 2016 8:34 pm

and it worked for the uint_8 version..... is the 16 signed or unsigned?
Last edited by 0815 on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason

sdrplay
Posts: 978
Joined: Wed Jan 07, 2015 7:58 am

Re: SDRPLAY linux commandline tools?

Post by sdrplay » Wed Mar 16, 2016 8:42 pm

it's signed (short)

Best regards,

SDRplay Support
Last edited by sdrplay on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason

Sasan
Posts: 124
Joined: Sat Jun 27, 2015 1:15 am
Location: Berlin

Re: SDRPLAY linux commandline tools?

Post by Sasan » Wed Mar 16, 2016 9:24 pm

"-r" switch in sox is for "sample rate". Changing it does not affect the output that much (I've tested with 250ksps, 1.536msps and 2msps, although I've saved samples with 1.536msps)
Here's the command I use for recording I/Q:

Code: Select all

./rawIQ -f 88000000 -s 1536000 -n 10000000 out_16bit.raw
Then, I either convert it directly to the Gqrx format (with the small rtl2gqrx16 utility), or first do some post processing on it with sox, then convert to Gqrx format.
I've also tested both "int16_t" and "uint16_t" as the data type for "buffer" variable.
With all these trial and errors and combinations, the best thing I've reached is a file which plays like in "speed mode" (it's completely audible and without noise, so we've a very small error)
I think the error lies in the format conversion (by the way, Gqrx format is GNURadio's standard "file sink" format)
I've changed the original source from this:

Code: Select all

  int byte1, byte2;  
  float _Complex fc;
  const size_t fc_size = sizeof(fc);
  FILE *infile,*outfile;
  const float scale = 1.0/128.0;
  ........
  while ((byte1=fgetc(infile)) != EOF){
    if ((byte2=fgetc(infile)) == EOF){
      exit(0);
    }
    fc = scale*(byte1-127) + I*scale*(byte2-127);
    fwrite(&fc,fc_size,1,outfile);
  }
to this:

Code: Select all

  int byte1, byte2, byte3, byte4;  
  float _Complex fc;
  const size_t fc_size = sizeof(fc) ;
  FILE *infile,*outfile;
  const float scale = 1.0/32768.0;
  ........
  while ((byte1=fgetc(infile)) != EOF){
    if ((byte2=fgetc(infile)) == EOF){
      exit(0);
    }
    if ((byte3=fgetc(infile)) == EOF){
      exit(0);
    }
    if ((byte4=fgetc(infile)) == EOF){
      exit(0);
    }
    byte1 = (byte2 << 8) + byte1;
    byte3 = (byte4 << 8) + byte3;
    fc = scale*(byte1-32767) + I*scale*(byte3-32767);[/b]
    fwrite(&fc,fc_size,1,outfile);
  }
Any ideas?
Thanks
Last edited by Sasan on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason
DF2HF, NM9A, EP2C

sdrplay
Posts: 978
Joined: Wed Jan 07, 2015 7:58 am

Re: SDRPLAY linux commandline tools?

Post by sdrplay » Wed Mar 16, 2016 10:22 pm

For 16bit output the 2nd parameter in the fwrite statement should be a 2 otherwise it's only writing 8 bits of the buffer value.

Best regards,

SDRplay Support
Last edited by sdrplay on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason

Sasan
Posts: 124
Joined: Sat Jun 27, 2015 1:15 am
Location: Berlin

Re: SDRPLAY linux commandline tools?

Post by Sasan » Wed Mar 16, 2016 10:40 pm

sdrplay wrote:For 16bit output the 2nd parameter in the fwrite statement should be a 2 otherwise it's only writing 8 bits of the buffer value.

Best regards,

SDRplay Support
Thank you very much.
This solves the problem and I can open the raw recorded file in Gqrx and play it without any problems.
Last edited by Sasan on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason
DF2HF, NM9A, EP2C

Bill_C
Posts: 3
Joined: Tue Mar 15, 2016 1:38 am

Re: SDRPLAY linux commandline tools?

Post by Bill_C » Thu Mar 17, 2016 4:36 am

Previously I reported that the rawIQ.c code from 0815 worked fine. With further testing it seems I lose a few samples sometimes. This can have a very detrimental effort when calculating the power spectrum of a narrowband signal (such as a beacon), although it depends of the specific parameter values.

I returned to the rawIQ code originally posted by SDRplay Support. I was getting segmentation faults - but that was simply due to the mallocs only requesting 2 bytes for each I and Q buffer! After fixing that, initial testing seems to work with continuous collection and no missed samples. I'm not sure why 0815 version behaves differently - the code is almost the same.

BTW, looking at the spectra I've collected, it seems that the bandwidth parameter is scaled as the sampling rate reduces. For example with "./rawIQ -g 30 -f 432.5 -b 0.2 -s 0.3" the actual signal bandwidth is about 10% of the requested 200kHz. This is probably due to some decimation operations, but I could not find much about it in the Mirics_SDR_API_Specification.
Last edited by Bill_C on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason

sdrplay
Posts: 978
Joined: Wed Jan 07, 2015 7:58 am

Re: SDRPLAY linux commandline tools?

Post by sdrplay » Thu Mar 17, 2016 7:18 am

In the code I posted -b is not used and the bandwidth is fixed at 1.536MHz - using -s of anything less than 2 is not a valid state so this maybe why you are getting strange buffer sizes being malloc'd?

The code was an example and needs more work to be robust.

I'm happy to update the github repository with any updated versions of code (please send to software@sdrplay.com with a small readme describing the changes)

Best regards,

SDRplay Support
Last edited by sdrplay on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason

0815
Posts: 45
Joined: Sat Jan 30, 2016 3:07 pm

Re: SDRPLAY linux commandline tools?

Post by 0815 » Thu Mar 17, 2016 6:36 pm

enclosed the tested 16 bit code - works for me now!
availiable options:

-f frequecy in Hz
-s samplerate
-g gain
filename a "-" dumps to stdout

please post feedback - thx


Use the standard makefile, posted before

Code: Select all

/*
 * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver
 * Copyright (C) 2012 by Steve Markgraf <steve@steve-m.de>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdint.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#ifndef _WIN32
#include <unistd.h>
#include "mirsdrapi-rsp.h"
#else
#include <windows.h>
#include <io.h>
#include <fcntl.h>
#include "getopt/getopt.h"
#include "mir_sdr.h"
#endif

#define DEFAULT_SAMPLE_RATE     2048000
#define DEFAULT_BUF_LENGTH      (336 * 2) // (16 * 16384)
#define MINIMAL_BUF_LENGTH      672 // 512
#define MAXIMAL_BUF_LENGTH      (256 * 16384)

static int do_exit = 0;
static uint32_t bytes_to_read = 0;

short *ibuf;
short *qbuf;
unsigned int firstSample;
int samplesPerPacket, grChanged, fsChanged, rfChanged;

double atofs(char *s)
/* standard suffixes */
{
    char last;
    int len;
    double suff = 1.0;
    len = strlen(s);
    last = s[len-1];
    s[len-1] = '\0';
    switch (last) {
        case 'g':
        case 'G':
            suff *= 1e3;
        case 'm':
        case 'M':
            suff *= 1e3;
        case 'k':
        case 'K':
            suff *= 1e3;
            suff *= atof(s);
            s[len-1] = last;
            return suff;
    }
    s[len-1] = last;
    return atof(s);
}

void usage(void)
{
    fprintf(stderr,
        "rawIQ [16BIT], an I/Q recorder) for SDRplay RSP receivers\n\n"
        "Usage:\t -f frequency_to_tune_to [Hz]\n"
        "\t[-s samplerate (default: 2048000 Hz)]\n"
        "\t[-g gain (default: 50)]\n"
        "\t[-ppm correct ppm errorvalue\n"
//        "\t[-n number of samples to read (default: 0, infinite)]\n"
        "\tfilename (a '-' dumps samples to stdout)\n\n");
    exit(1);
}

#ifdef _WIN32
BOOL WINAPI
sighandler(int signum)
{
    if (CTRL_C_EVENT == signum) {
        fprintf(stderr, "Signal caught, exiting!\n");
        do_exit = 1;
        rtlsdr_cancel_async(dev);
        return TRUE;
    }
    return FALSE;
}
#else
static void sighandler(int signum)
{
    fprintf(stderr, "Signal caught, exiting!\n");
    do_exit = 1;
    mir_sdr_Uninit();
}
#endif


int main(int argc, char **argv)
{
#ifndef _WIN32
    struct sigaction sigact;
#endif

    char *filename = NULL;
    int n_read;
    mir_sdr_ErrT r;
    int opt;
    int gain = 50;
    int ppm_error = 0;
    FILE *file;
    short *buffer;
    uint32_t frequency = 100000000;
    uint32_t samp_rate = DEFAULT_SAMPLE_RATE;
    uint32_t out_block_size = DEFAULT_BUF_LENGTH;
    int i, j;

    while ((opt = getopt(argc, argv, "d:f:g:s:b:n:p:S")) != -1) {
        switch (opt) {
        case 'f':
            frequency = (uint32_t)atofs(optarg);
            break;
        case 'g':
            gain = (int)atof(optarg);
            break;
        case 's':
            samp_rate = (uint32_t)atofs(optarg);
            break;
        default:
            usage();
            break;
    }
}

    if (argc <= optind) {
        usage();
    } else {
        filename = argv[optind];
    }

    if(out_block_size < MINIMAL_BUF_LENGTH ||
       out_block_size > MAXIMAL_BUF_LENGTH ){
        fprintf(stderr,
            "Output block size wrong value, falling back to default\n");
        fprintf(stderr,
            "Minimal length: %u\n", MINIMAL_BUF_LENGTH);
        fprintf(stderr,
            "Maximal length: %u\n", MAXIMAL_BUF_LENGTH);
        out_block_size = DEFAULT_BUF_LENGTH;
    }

    buffer = malloc(DEFAULT_BUF_LENGTH  * sizeof(short));
	

    r = mir_sdr_Init(40, 2.0, 100.00, mir_sdr_BW_1_536, mir_sdr_IF_Zero,
                        &samplesPerPacket);
    if (r != mir_sdr_Success) {
        fprintf(stderr, "Failed to open SDRplay RSP device.\n");
        exit(1);
    }
    mir_sdr_Uninit();
#ifndef _WIN32
    sigact.sa_handler = sighandler;
    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = 0;
    sigaction(SIGINT, &sigact, NULL);
    sigaction(SIGTERM, &sigact, NULL);
    sigaction(SIGQUIT, &sigact, NULL);
    sigaction(SIGPIPE, &sigact, NULL);
#else
    SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE );
#endif

    if(strcmp(filename, "-") == 0) { /* Write samples to stdout */
        file = stdout;
#ifdef _WIN32
        _setmode(_fileno(stdin), _O_BINARY);
#endif
    } else {
        file = fopen(filename, "wb");
        if (!file) {
            fprintf(stderr, "Failed to open %s\n", filename);
            goto out;
        }
    }

    r = mir_sdr_Init((78-gain), (samp_rate/1e6), ((frequency+ppm_error)/1e6),
                       mir_sdr_BW_1_536, mir_sdr_IF_Zero, &samplesPerPacket );

    mir_sdr_SetDcMode(4,0);
    mir_sdr_SetDcTrackTime(63);

    ibuf = malloc(samplesPerPacket * sizeof(short));
    qbuf = malloc(samplesPerPacket * sizeof(short));

    fprintf(stderr, "Writing samples...\n");
    while (!do_exit) {
        r = mir_sdr_ReadPacket(ibuf, qbuf, &firstSample, &grChanged, &rfChanged,
                            &fsChanged);
        if (r != mir_sdr_Success) {
            fprintf(stderr, "WARNING: ReadPacket failed.\n");
            break;
        }

        j = 0;
	
	for (i=0; i < samplesPerPacket; i++)
        {
            buffer[j++] = ibuf[i];
            buffer[j++] = qbuf[i];
        }	

        n_read = (samplesPerPacket * 2);

        if ((bytes_to_read > 0) && (bytes_to_read <= (uint32_t)n_read)) {
            n_read = bytes_to_read;
            do_exit = 1;
        }

        if (fwrite(buffer, 2, n_read, file) != (size_t)n_read) {
            fprintf(stderr, "Short write FILE, samples lost, exiting!\n"); break;
        }

        if ((uint32_t)n_read < (uint32_t)n_read) {
            fprintf(stderr, "Short read, samples lost, exiting!\n");
            break;
        }

        if (bytes_to_read > 0)
            bytes_to_read -= n_read;
    }

    if (do_exit)
        fprintf(stderr, "\nUser cancel, exiting...\n");
    else
        fprintf(stderr, "\nLibrary error %d, exiting...\n", r);

    if (file != stdout)
        fclose(file);

    mir_sdr_Uninit();
    free (buffer);
out:
    return r >= 0 ? r : -r;
}
Last edited by 0815 on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason

0815
Posts: 45
Joined: Sat Jan 30, 2016 3:07 pm

Re: SDRPLAY linux commandline tools?

Post by 0815 » Thu Mar 17, 2016 7:07 pm

but about the adsb mode, i did

Code: Select all

buffer[j++] = (unsigned char) (ibuf[i] >> 8 + 127);
            buffer[j++] = (unsigned char) (qbuf[i] >> 8 + 127);
and the compiler complains:

Code: Select all

rawIQ.c:232:13: warning: right shift count >= width of type [enabled by default]
             buffer[j++] = (unsigned char) (ibuf[i] >> 8 + 127);
             ^
rawIQ.c:232:13: warning: suggest parentheses around ‘+’ inside ‘>>’ [-Wparentheses]
rawIQ.c:233:13: warning: right shift count >= width of type [enabled by default]
             buffer[j++] = (unsigned char) (qbuf[i] >> 8 + 127);
             ^
rawIQ.c:233:13: warning: suggest parentheses around ‘+’ inside ‘>>’ [-Wparentheses]
Last edited by 0815 on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason

Sasan
Posts: 124
Joined: Sat Jun 27, 2015 1:15 am
Location: Berlin

Re: SDRPLAY linux commandline tools?

Post by Sasan » Thu Mar 17, 2016 9:30 pm

@0815:
I compiled your code on OS X 10.11.3 and it works (gcc: Apple LLVM version 7.0.2 (clang-700.1.81) )
About the warnings: as the compiler itself suggests, you should use parentheses around the shift operation:

Code: Select all

 
            buffer[j++] = (unsigned char) ((ibuf[i] >> 8) + 127);
            buffer[j++] = (unsigned char) ((qbuf[i] >> 8) + 127);
 
Last edited by Sasan on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason
DF2HF, NM9A, EP2C

Post Reply