/* rtlsdr initialization ------------------------------------------------------- * search front end and initialization * args : none * return : int status 0:okay -1:failure *-----------------------------------------------------------------------------*/ extern int rtlsdr_init(void) { int ret,dev_index=0;; /* open rtlsdr */ dev_index=verbose_device_search("0"); ret=rtlsdr_open(&dev, (uint32_t)dev_index); if (ret<0) { SDRPRINTF("error: failed to open rtlsdr device #%d.\n",dev_index); return -1; } /* set configuration */ ret=rtlsdr_initconf(); if (ret<0) { SDRPRINTF("error: failed to initialize rtlsdr\n"); return -1; } return 0; }
// //========================================================================= // int main(int argc, char **argv) { int j; // Set sane defaults modesInitConfig(); signal(SIGINT, sigintHandler); // Define Ctrl/C handler (exit program) // Parse the command line options for (j = 1; j < argc; j++) { int more = j+1 < argc; // There are more arguments if (!strcmp(argv[j],"--device-index") && more) { #ifndef NORTLSDR Modes.dev_index = verbose_device_search(argv[++j]); #else assert(!"Compiled without librtlsdr support"); #endif } else if (!strcmp(argv[j],"--gain") && more) { Modes.gain = (int) (atof(argv[++j])*10); // Gain is in tens of DBs } else if (!strcmp(argv[j],"--enable-agc")) { Modes.enable_agc++; } else if (!strcmp(argv[j],"--freq") && more) { Modes.freq = (int) strtoll(argv[++j],NULL,10); } else if (!strcmp(argv[j],"--ifile") && more) { Modes.filename = strdup(argv[++j]); } else if (!strcmp(argv[j],"--fix")) { Modes.nfix_crc = 1; } else if (!strcmp(argv[j],"--no-fix")) { Modes.nfix_crc = 0; } else if (!strcmp(argv[j],"--no-crc-check")) { Modes.check_crc = 0; } else if (!strcmp(argv[j],"--phase-enhance")) { Modes.phase_enhance = 1; } else if (!strcmp(argv[j],"--raw")) { Modes.raw = 1; } else if (!strcmp(argv[j],"--net")) { Modes.net = 1; } else if (!strcmp(argv[j],"--modeac")) { Modes.mode_ac = 1; } else if (!strcmp(argv[j],"--net-beast")) { Modes.beast = 1; } else if (!strcmp(argv[j],"--net-only")) { Modes.net = 1; Modes.net_only = 1; } else if (!strcmp(argv[j],"--net-heartbeat") && more) { Modes.net_heartbeat_rate = atoi(argv[++j]) * 15; } else if (!strcmp(argv[j],"--net-ro-size") && more) { Modes.net_output_raw_size = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-ro-rate") && more) { Modes.net_output_raw_rate = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-ro-port") && more) { if (Modes.beast) // Required for legacy backward compatibility {Modes.net_output_beast_port = atoi(argv[++j]);;} else {Modes.net_output_raw_port = atoi(argv[++j]);} } else if (!strcmp(argv[j],"--net-ri-port") && more) { Modes.net_input_raw_port = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-bo-port") && more) { Modes.net_output_beast_port = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-bi-port") && more) { Modes.net_input_beast_port = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-bind-address") && more) { Modes.net_bind_address = strdup(argv[++j]); } else if (!strcmp(argv[j],"--net-http-port") && more) { Modes.net_http_port = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-sbs-port") && more) { Modes.net_output_sbs_port = atoi(argv[++j]); } else if (!strcmp(argv[j],"--net-buffer") && more) { Modes.net_sndbuf_size = atoi(argv[++j]); } else if (!strcmp(argv[j],"--onlyaddr")) { Modes.onlyaddr = 1; } else if (!strcmp(argv[j],"--metric")) { Modes.metric = 1; } else if (!strcmp(argv[j],"--aggressive")) { Modes.nfix_crc = MODES_MAX_BITERRORS; } else if (!strcmp(argv[j],"--interactive")) { Modes.interactive = 1; } else if (!strcmp(argv[j],"--interactive-rows") && more) { Modes.interactive_rows = atoi(argv[++j]); } else if (!strcmp(argv[j],"--interactive-ttl") && more) { Modes.interactive_display_ttl = atoi(argv[++j]); } else if (!strcmp(argv[j],"--lat") && more) { Modes.fUserLat = atof(argv[++j]); } else if (!strcmp(argv[j],"--lon") && more) { Modes.fUserLon = atof(argv[++j]); } else if (!strcmp(argv[j],"--debug") && more) { char *f = argv[++j]; while(*f) { switch(*f) { case 'D': Modes.debug |= MODES_DEBUG_DEMOD; break; case 'd': Modes.debug |= MODES_DEBUG_DEMODERR; break; case 'C': Modes.debug |= MODES_DEBUG_GOODCRC; break; case 'c': Modes.debug |= MODES_DEBUG_BADCRC; break; case 'p': Modes.debug |= MODES_DEBUG_NOPREAMBLE; break; case 'n': Modes.debug |= MODES_DEBUG_NET; break; case 'j': Modes.debug |= MODES_DEBUG_JS; break; default: fprintf(stderr, "Unknown debugging flag: %c\n", *f); exit(1); break; } f++; } } else if (!strcmp(argv[j],"--stats")) { Modes.stats = -1; } else if (!strcmp(argv[j],"--stats-every") && more) { Modes.stats = atoi(argv[++j]); } else if (!strcmp(argv[j],"--snip") && more) { snipMode(atoi(argv[++j])); exit(0); } else if (!strcmp(argv[j],"--help")) { showHelp(); exit(0); } else if (!strcmp(argv[j],"--ppm") && more) { Modes.ppm_error = atoi(argv[++j]); } else if (!strcmp(argv[j],"--quiet")) { Modes.quiet = 1; } else if (!strcmp(argv[j],"--mlat")) { Modes.mlat = 1; } else if (!strcmp(argv[j],"--interactive-rtl1090")) { Modes.interactive = 1; Modes.interactive_rtl1090 = 1; } else { fprintf(stderr, "Unknown or not enough arguments for option '%s'.\n\n", argv[j]); showHelp(); exit(1); } } #ifdef _WIN32 // Try to comply with the Copyright license conditions for binary distribution if (!Modes.quiet) {showCopyright();} #endif #ifndef _WIN32 // Setup for SIGWINCH for handling lines if (Modes.interactive) {signal(SIGWINCH, sigWinchCallback);} #endif // Initialization modesInit(); if (Modes.net_only) { fprintf(stderr,"Net-only mode, no RTL device or file open.\n"); } else if (Modes.filename == NULL) { #ifndef NORTLSDR modesInitRTLSDR(); #else assert(!"Compiled without librtlsdr support"); #endif } else { if (Modes.filename[0] == '-' && Modes.filename[1] == '\0') { Modes.fd = STDIN_FILENO; } else if ((Modes.fd = open(Modes.filename, #ifdef _WIN32 (O_RDONLY | O_BINARY) #else (O_RDONLY) #endif )) == -1) { perror("Opening data file"); exit(1); } } if (Modes.net) modesInitNet(); // If the user specifies --net-only, just run in order to serve network // clients without reading data from the RTL device while (Modes.net_only) { if (Modes.exit) exit(0); // If we exit net_only nothing further in main() backgroundTasks(); usleep(100000); } // Create the thread that will read the data from the device. pthread_create(&Modes.reader_thread, NULL, readerThreadEntryPoint, NULL); pthread_mutex_lock(&Modes.data_mutex); while (Modes.exit == 0) { if (Modes.iDataReady == 0) { pthread_cond_wait(&Modes.data_cond,&Modes.data_mutex); // This unlocks Modes.data_mutex, and waits for Modes.data_cond continue; // Once (Modes.data_cond) occurs, it locks Modes.data_mutex } // Modes.data_mutex is Locked, and (Modes.iDataReady != 0) if (Modes.iDataReady) { // Check we have new data, just in case!! Modes.iDataOut &= (MODES_ASYNC_BUF_NUMBER-1); // Just incase // Translate the next lot of I/Q samples into Modes.magnitude computeMagnitudeVector(Modes.pData[Modes.iDataOut]); Modes.stSystemTimeBlk = Modes.stSystemTimeRTL[Modes.iDataOut]; // Update the input buffer pointer queue Modes.iDataOut = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataOut + 1); Modes.iDataReady = (MODES_ASYNC_BUF_NUMBER-1) & (Modes.iDataIn - Modes.iDataOut); // If we lost some blocks, correct the timestamp if (Modes.iDataLost) { Modes.timestampBlk += (MODES_ASYNC_BUF_SAMPLES * 6 * Modes.iDataLost); Modes.stat_blocks_dropped += Modes.iDataLost; Modes.iDataLost = 0; } // It's safe to release the lock now pthread_cond_signal (&Modes.data_cond); pthread_mutex_unlock(&Modes.data_mutex); // Process data after releasing the lock, so that the capturing // thread can read data while we perform computationally expensive // stuff at the same time. detectModeS(Modes.magnitude, MODES_ASYNC_BUF_SAMPLES); // Update the timestamp ready for the next block Modes.timestampBlk += (MODES_ASYNC_BUF_SAMPLES*6); Modes.stat_blocks_processed++; } else { pthread_cond_signal (&Modes.data_cond); pthread_mutex_unlock(&Modes.data_mutex); } backgroundTasks(); pthread_mutex_lock(&Modes.data_mutex); } // If --stats were given, print statistics if (Modes.stats) { display_stats(); } if (Modes.filename == NULL && !Modes.net_only) { #ifndef NORTLSDR rtlsdr_cancel_async(Modes.dev); // Cancel rtlsdr_read_async will cause data input thread to terminate cleanly rtlsdr_close(Modes.dev); #endif } pthread_cond_destroy(&Modes.data_cond); // Thread cleanup pthread_mutex_destroy(&Modes.data_mutex); pthread_join(Modes.reader_thread,NULL); // Wait on reader thread exit #ifndef _WIN32 pthread_exit(0); #else return (0); #endif }
int main(int argc, char **argv) { #ifndef _WIN32 struct sigaction sigact; #endif int n_read, r, opt, i; int sync_mode = 0; uint8_t *buffer; int dev_index = 0; int dev_given = 0; uint32_t out_block_size = DEFAULT_BUF_LENGTH; int count; int gains[100]; while ((opt = getopt(argc, argv, "d:s:b:tp::Sh")) != -1) { switch (opt) { case 'd': dev_index = verbose_device_search(optarg); dev_given = 1; break; case 's': samp_rate = (uint32_t)atof(optarg); break; case 'b': out_block_size = (uint32_t)atof(optarg); break; case 't': test_mode = TUNER_BENCHMARK; break; case 'p': test_mode = PPM_BENCHMARK; if (optarg) ppm_duration = atoi(optarg); break; case 'S': sync_mode = 1; break; case 'h': default: usage(); break; } } 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(out_block_size * sizeof(uint8_t)); if (!dev_given) { dev_index = verbose_device_search("0"); } if (dev_index < 0) { exit(1); } r = rtlsdr_open(&dev, (uint32_t)dev_index); if (r < 0) { fprintf(stderr, "Failed to open rtlsdr device #%d.\n", dev_index); exit(1); } #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 count = rtlsdr_get_tuner_gains(dev, NULL); fprintf(stderr, "Supported gain values (%d): ", count); count = rtlsdr_get_tuner_gains(dev, gains); for (i = 0; i < count; i++) fprintf(stderr, "%.1f ", gains[i] / 10.0); fprintf(stderr, "\n"); /* Set the sample rate */ verbose_set_sample_rate(dev, samp_rate); if (test_mode == TUNER_BENCHMARK) { tuner_benchmark(); goto exit; } /* Enable test mode */ r = rtlsdr_set_testmode(dev, 1); /* Reset endpoint before we start reading from it (mandatory) */ verbose_reset_buffer(dev); if ((test_mode == PPM_BENCHMARK) && !sync_mode) { fprintf(stderr, "Reporting PPM error measurement every %i seconds...\n", ppm_duration); fprintf(stderr, "Press ^C after a few minutes.\n"); } if (test_mode == NO_BENCHMARK) { fprintf(stderr, "\nInfo: This tool will continuously" " read from the device, and report if\n" "samples get lost. If you observe no " "further output, everything is fine.\n\n"); } if (sync_mode) { fprintf(stderr, "Reading samples in sync mode...\n"); fprintf(stderr, "(Samples are being lost but not reported.)\n"); while (!do_exit) { r = rtlsdr_read_sync(dev, buffer, out_block_size, &n_read); if (r < 0) { fprintf(stderr, "WARNING: sync read failed.\n"); break; } if ((uint32_t)n_read < out_block_size) { fprintf(stderr, "Short read, samples lost, exiting!\n"); break; } underrun_test(buffer, n_read, 1); } } else { fprintf(stderr, "Reading samples in async mode...\n"); r = rtlsdr_read_async(dev, rtlsdr_callback, NULL, 0, out_block_size); } if (do_exit) { fprintf(stderr, "\nUser cancel, exiting...\n"); fprintf(stderr, "Samples per million lost (minimum): %i\n", (int)(1000000L * dropped_samples / total_samples)); } else fprintf(stderr, "\nLibrary error %d, exiting...\n", r); exit: rtlsdr_close(dev); free (buffer); return r >= 0 ? r : -r; }
int main(int argc, char **argv) { #ifndef WIN32 struct sigaction sigact; 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 signal(SIGINT, sighandler); signal(SIGTERM, sighandler); #endif int opt; struct rtl_ais_config config; rtl_ais_default_config(&config); config.host = strdup("127.0.0.1"); config.port = strdup("10110"); while ((opt = getopt(argc, argv, "l:r:s:o:EODd:g:p:RAP:h:nLS:?")) != -1) { switch (opt) { case 'l': config.left_freq = (int)atofs(optarg); break; case 'r': config.right_freq = (int)atofs(optarg); break; case 's': config.sample_rate = (int)atofs(optarg); break; case 'o': config.output_rate = (int)atofs(optarg); break; case 'E': config.edge = !config.edge; break; case 'D': config.dc_filter = !config.dc_filter; break; case 'O': config.oversample = !config.oversample; break; case 'd': config.dev_index = verbose_device_search(optarg); config.dev_given = 1; break; case 'g': config.gain = (int)(atof(optarg) * 10); break; case 'p': config.ppm_error = atoi(optarg); config.custom_ppm = 1; break; case 'R': config.rtl_agc=1; break; case 'A': config.use_internal_aisdecoder=0; break; case 'P': config.port=strdup(optarg); break; case 'h': config.host=strdup(optarg); break; case 'L': config.show_levels=1; break; case 'S': config.seconds_for_decoder_stats=atoi(optarg); break; case 'n': config.debug_nmea = 1; break; case '?': default: usage(); return 2; } } if (argc <= optind) { config.filename = "-"; } else { config.filename = argv[optind]; } if (config.edge) { fprintf(stderr, "Edge tuning enabled.\n"); } else { fprintf(stderr, "Edge tuning disabled.\n"); } if (config.dc_filter) { fprintf(stderr, "DC filter enabled.\n"); } else { fprintf(stderr, "DC filter disabled.\n"); } if (config.rtl_agc) { fprintf(stderr, "RTL AGC enabled.\n"); } else { fprintf(stderr, "RTL AGC disabled.\n"); } if (config.use_internal_aisdecoder) { fprintf(stderr, "Internal AIS decoder enabled.\n"); } else { fprintf(stderr, "Internal AIS decoder disabled.\n"); } struct rtl_ais_context *ctx = rtl_ais_start(&config); if(!ctx) { fprintf(stderr, "\nrtl_ais_start failed, exiting...\n"); exit(1); } // loop printing received ais messages to console while(!do_exit && rtl_ais_isactive(ctx)) { const char *str; while((str = rtl_ais_next_message(ctx))) puts(str); usleep(50000); } rtl_ais_cleanup(ctx); return 0; }
// // =============================== RTLSDR handling ========================== // int modesInitRTLSDR(void) { int j; int device_count, dev_index = 0; char vendor[256], product[256], serial[256]; if (Modes.dev_name) { if ( (dev_index = verbose_device_search(Modes.dev_name)) < 0 ) return -1; } device_count = rtlsdr_get_device_count(); if (!device_count) { fprintf(stderr, "No supported RTLSDR devices found.\n"); return -1; } fprintf(stderr, "Found %d device(s):\n", device_count); for (j = 0; j < device_count; j++) { rtlsdr_get_device_usb_strings(j, vendor, product, serial); fprintf(stderr, "%d: %s, %s, SN: %s %s\n", j, vendor, product, serial, (j == dev_index) ? "(currently selected)" : ""); } if (rtlsdr_open(&Modes.dev, dev_index) < 0) { fprintf(stderr, "Error opening the RTLSDR device: %s\n", strerror(errno)); return -1; } // Set gain, frequency, sample rate, and reset the device rtlsdr_set_tuner_gain_mode(Modes.dev, (Modes.gain == MODES_AUTO_GAIN) ? 0 : 1); if (Modes.gain != MODES_AUTO_GAIN) { int *gains; int numgains; numgains = rtlsdr_get_tuner_gains(Modes.dev, NULL); if (numgains <= 0) { fprintf(stderr, "Error getting tuner gains\n"); return -1; } gains = malloc(numgains * sizeof(int)); if (rtlsdr_get_tuner_gains(Modes.dev, gains) != numgains) { fprintf(stderr, "Error getting tuner gains\n"); free(gains); return -1; } if (Modes.gain == MODES_MAX_GAIN) { int highest = -1; int i; for (i = 0; i < numgains; ++i) { if (gains[i] > highest) highest = gains[i]; } Modes.gain = highest; fprintf(stderr, "Max available gain is: %.2f dB\n", Modes.gain/10.0); } else { int closest = -1; int i; for (i = 0; i < numgains; ++i) { if (closest == -1 || abs(gains[i] - Modes.gain) < abs(closest - Modes.gain)) closest = gains[i]; } if (closest != Modes.gain) { Modes.gain = closest; fprintf(stderr, "Closest available gain: %.2f dB\n", Modes.gain/10.0); } } free(gains); fprintf(stderr, "Setting gain to: %.2f dB\n", Modes.gain/10.0); if (rtlsdr_set_tuner_gain(Modes.dev, Modes.gain) < 0) { fprintf(stderr, "Error setting tuner gains\n"); return -1; } } else { fprintf(stderr, "Using automatic gain control.\n"); } rtlsdr_set_freq_correction(Modes.dev, Modes.ppm_error); if (Modes.enable_agc) rtlsdr_set_agc_mode(Modes.dev, 1); rtlsdr_set_center_freq(Modes.dev, Modes.freq); rtlsdr_set_sample_rate(Modes.dev, (unsigned)Modes.sample_rate); rtlsdr_reset_buffer(Modes.dev); fprintf(stderr, "Gain reported by device: %.2f dB\n", rtlsdr_get_tuner_gain(Modes.dev)/10.0); return 0; }
int main(){ printf("samplerate: %d\nbuflen:%d\n", SAMPLERATE, BUFLEN); rtlsdr_dev_t *dev = NULL; int devindex = verbose_device_search("0"); int r = rtlsdr_open(&dev, devindex); if(r){printf("err %d opening device\n", r);} verbose_set_sample_rate(dev, SAMPLERATE); verbose_set_frequency(dev, 90000000);//357000); //verbose_gain_set(dev, 496); verbose_gain_set(dev, 200); //verbose_auto_gain(dev); verbose_reset_buffer(dev); char *buf = calloc(BUFLEN,1); //char *buf = malloc((1<<16)*8);//[(1<<16)*8] = {0}; int howmany = 0; rtlsdr_read_sync(dev, buf, BUFLEN, &howmany); printf("read %d of %d\n", howmany, BUFLEN); FILE *testfile = fopen("test.dat", "w"); //fprintf(testfile, "[\n"); int i; for(i=0;i<howmany/2;i++){ fprintf(testfile, "%d %d\n", i, (int)((unsigned short*)buf)[i] - 0xffff/2); } fwrite(buf, 1, howmany,testfile); fclose(testfile); double *inbuf = calloc(BUFLEN/2, sizeof(double)); fftw_complex *outbuf = calloc(BUFLEN/2, sizeof(fftw_complex)); fftw_plan plan = fftw_plan_dft_r2c_1d(BUFLEN/2, inbuf, outbuf, FFTW_ESTIMATE); for(i=0;i<howmany/2;i++){ inbuf[i] = (double)((int)((unsigned short*)buf)[i] - 0xffff/2); } fftw_execute(plan); testfile = fopen("testdft.dat", "w"); for(i=1/*ignore first component (dc?)*/;i<howmany/2/2;i++){ fprintf(testfile, "%d %f\n", i, log10(abs(outbuf[i][0]))-log10(DBL_MAX));//this math is probably/definitely all wrong } fclose(testfile); //free(buf); #ifdef BIGDFT testfile = fopen("bigdft.dat", "w"); int freq; //for(freq=2000000;freq<1000000000;freq += 2048000){ //for(freq=80000000;freq<100000000;freq += SAMPLERATE/*BUFLEN/2*/){ for(freq=40000000;freq<1000000000;freq += SAMPLERATE/*BUFLEN/2*/){ verbose_set_frequency(dev, freq);//357000); verbose_reset_buffer(dev); rtlsdr_read_sync(dev, buf, BUFLEN, &howmany); for(i=0;i<howmany/2;i++){ inbuf[i] = (double)((int)((unsigned short*)buf)[i] - 0xffff/2); } fftw_execute(plan); for(i=1;i<howmany/2/2;i+= 1){//50){ //fprintf(testfile, "%d %f\n", i*(SAMPLERATE/(howmany/2/2))+freq, (outbuf[i][0]));//this math is probably/definitely all wrong fprintf(testfile, "%d %f\n", i*(SAMPLERATE/(howmany/2/2))+freq, log10(abs(outbuf[i][0]))-log10(DBL_MAX));//this math is probably/definitely all wrong } printf("%d\n", freq); } fclose(testfile); #endif rtlsdr_close(dev); return 0; }
int main(int argc, char **argv) { #ifndef _WIN32 struct sigaction sigact; #endif char *filename = NULL; int n_read; int r, opt; int gain = 0; int ppm_error = 0; int sync_mode = 0; FILE *file; uint8_t *buffer; int dev_index = 0; int dev_given = 0; uint32_t frequency = 100000000; uint32_t bandwidth = DEFAULT_BANDWIDTH; uint32_t samp_rate = DEFAULT_SAMPLE_RATE; uint32_t out_block_size = DEFAULT_BUF_LENGTH; while ((opt = getopt(argc, argv, "d:f:g:s:w:b:n:p:S")) != -1) { switch (opt) { case 'd': dev_index = verbose_device_search(optarg); dev_given = 1; break; case 'f': frequency = (uint32_t)atofs(optarg); break; case 'g': gain = (int)(atof(optarg) * 10); /* tenths of a dB */ break; case 's': samp_rate = (uint32_t)atofs(optarg); break; case 'w': bandwidth = (uint32_t)atofs(optarg); break; case 'p': ppm_error = atoi(optarg); break; case 'b': out_block_size = (uint32_t)atof(optarg); break; case 'n': bytes_to_read = (uint32_t)atof(optarg) * 2; break; case 'S': sync_mode = 1; 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(out_block_size * sizeof(uint8_t)); if (!dev_given) { dev_index = verbose_device_search("0"); } if (dev_index < 0) { exit(1); } r = rtlsdr_open(&dev, (uint32_t)dev_index); if (r < 0) { fprintf(stderr, "Failed to open rtlsdr device #%d.\n", dev_index); exit(1); } #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 /* Set the sample rate */ verbose_set_sample_rate(dev, samp_rate); /* Set the tuner bandwidth */ verbose_set_bandwidth(dev, bandwidth); /* Set the frequency */ verbose_set_frequency(dev, frequency); if (0 == gain) { /* Enable automatic gain */ verbose_auto_gain(dev); } else { /* Enable manual gain */ gain = nearest_gain(dev, gain); verbose_gain_set(dev, gain); } verbose_ppm_set(dev, ppm_error); 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; } } /* Reset endpoint before we start reading from it (mandatory) */ verbose_reset_buffer(dev); if (sync_mode) { fprintf(stderr, "Reading samples in sync mode...\n"); while (!do_exit) { r = rtlsdr_read_sync(dev, buffer, out_block_size, &n_read); if (r < 0) { fprintf(stderr, "WARNING: sync read failed.\n"); break; } if ((bytes_to_read > 0) && (bytes_to_read < (uint32_t)n_read)) { n_read = bytes_to_read; do_exit = 1; } if (fwrite(buffer, 1, n_read, file) != (size_t)n_read) { fprintf(stderr, "Short write, samples lost, exiting!\n"); break; } if ((uint32_t)n_read < out_block_size) { fprintf(stderr, "Short read, samples lost, exiting!\n"); break; } if (bytes_to_read > 0) bytes_to_read -= n_read; } } else { fprintf(stderr, "Reading samples in async mode...\n"); r = rtlsdr_read_async(dev, rtlsdr_callback, (void *)file, 0, out_block_size); } if (do_exit) fprintf(stderr, "\nUser cancel, exiting...\n"); else fprintf(stderr, "\nLibrary error %d, exiting...\n", r); if (file != stdout) fclose(file); rtlsdr_close(dev); free (buffer); out: return r >= 0 ? r : -r; }
int main(int argc, char **argv) { struct sigaction sigact; char *filename = NULL; int r, opt; int i, gain = AUTO_GAIN; /* tenths of a dB */ int dev_index = 0; int dev_given = 0; int ppm_error = 0; int custom_ppm = 0; int left_freq = 161975000; int right_freq = 162025000; int sample_rate = 12000; int output_rate = 48000; int dongle_freq, dongle_rate, delta; int edge = 0; pthread_cond_init(&ready, NULL); pthread_mutex_init(&ready_m, NULL); while ((opt = getopt(argc, argv, "l:r:s:o:EODd:g:p:h")) != -1) { switch (opt) { case 'l': left_freq = (int)atofs(optarg); break; case 'r': right_freq = (int)atofs(optarg); break; case 's': sample_rate = (int)atofs(optarg); break; case 'o': output_rate = (int)atofs(optarg); break; case 'E': edge = !edge; break; case 'D': dc_filter = !dc_filter; break; case 'O': oversample = !oversample; break; case 'd': dev_index = verbose_device_search(optarg); dev_given = 1; break; case 'g': gain = (int)(atof(optarg) * 10); break; case 'p': ppm_error = atoi(optarg); custom_ppm = 1; break; case 'h': default: usage(); return 2; } } if (argc <= optind) { filename = "-"; } else { filename = argv[optind]; } if (left_freq > right_freq) { usage(); return 2; } /* precompute rates */ dongle_freq = left_freq/2 + right_freq/2; if (edge) { dongle_freq -= sample_rate/2;} delta = right_freq - left_freq; if (delta > 1.2e6) { fprintf(stderr, "Frequencies may be at most 1.2MHz apart."); exit(1); } if (delta < 0) { fprintf(stderr, "Left channel must be lower than right channel."); exit(1); } i = (int)log2(2.4e6 / delta); dongle_rate = delta * (1<<i); both.rate_in = dongle_rate; both.rate_out = delta * 2; i = (int)log2(both.rate_in/both.rate_out); both.downsample_passes = i; both.downsample = 1 << i; left.rate_in = both.rate_out; i = (int)log2(left.rate_in / sample_rate); left.downsample_passes = i; left.downsample = 1 << i; left.rate_out = left.rate_in / left.downsample; right.rate_in = left.rate_in; right.rate_out = left.rate_out; right.downsample = left.downsample; right.downsample_passes = left.downsample_passes; if (left.rate_out > output_rate) { fprintf(stderr, "Channel bandwidth too high or output bandwidth too low."); exit(1); } stereo.rate = output_rate; if (edge) { fprintf(stderr, "Edge tuning enabled.\n"); } else { fprintf(stderr, "Edge tuning disabled.\n"); } if (dc_filter) { fprintf(stderr, "DC filter enabled.\n"); } else { fprintf(stderr, "DC filter disabled.\n"); } fprintf(stderr, "Buffer size: %0.2f mS\n", 1000 * (double)DEFAULT_BUF_LENGTH / (double)dongle_rate); fprintf(stderr, "Downsample factor: %i\n", both.downsample * left.downsample); fprintf(stderr, "Low pass: %i Hz\n", left.rate_out); fprintf(stderr, "Output: %i Hz\n", output_rate); /* precompute lengths */ both.len_in = DEFAULT_BUF_LENGTH; both.len_out = both.len_in / both.downsample; left.len_in = both.len_out; right.len_in = both.len_out; left.len_out = left.len_in / left.downsample; right.len_out = right.len_in / right.downsample; left_demod.buf_len = left.len_out; left_demod.result_len = left_demod.buf_len / 2; right_demod.buf_len = left_demod.buf_len; right_demod.result_len = left_demod.result_len; stereo.bl_len = (int)((long)(DEFAULT_BUF_LENGTH/2) * (long)output_rate / (long)dongle_rate); stereo.br_len = stereo.bl_len; stereo.result_len = stereo.br_len * 2; stereo.rate = output_rate; if (!dev_given) { dev_index = verbose_device_search("0"); } if (dev_index < 0) { exit(1); } downsample_init(&both); downsample_init(&left); downsample_init(&right); demod_init(&left_demod); demod_init(&right_demod); stereo_init(&stereo); r = rtlsdr_open(&dev, (uint32_t)dev_index); if (r < 0) { fprintf(stderr, "Failed to open rtlsdr device #%d.\n", dev_index); exit(1); } 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); if (strcmp(filename, "-") == 0) { /* Write samples to stdout */ file = stdout; setvbuf(stdout, NULL, _IONBF, 0); } else { file = fopen(filename, "wb"); if (!file) { fprintf(stderr, "Failed to open %s\n", filename); exit(1); } } /* Set the tuner gain */ if (gain == AUTO_GAIN) { verbose_auto_gain(dev); } else { gain = nearest_gain(dev, gain); verbose_gain_set(dev, gain); } if (!custom_ppm) { verbose_ppm_eeprom(dev, &ppm_error); } verbose_ppm_set(dev, ppm_error); //r = rtlsdr_set_agc_mode(dev, 1); /* Set the tuner frequency */ verbose_set_frequency(dev, dongle_freq); /* Set the sample rate */ verbose_set_sample_rate(dev, dongle_rate); /* Reset endpoint before we start reading from it (mandatory) */ verbose_reset_buffer(dev); pthread_create(&demod_thread, NULL, demod_thread_fn, (void *)(NULL)); rtlsdr_read_async(dev, rtlsdr_callback, (void *)(NULL), DEFAULT_ASYNC_BUF_NUMBER, DEFAULT_BUF_LENGTH); if (do_exit) { fprintf(stderr, "\nUser cancel, exiting...\n");} else { fprintf(stderr, "\nLibrary error %d, exiting...\n", r);} rtlsdr_cancel_async(dev); safe_cond_signal(&ready, &ready_m); pthread_cond_destroy(&ready); pthread_mutex_destroy(&ready_m); if (file != stdout) { fclose(file);} rtlsdr_close(dev); return r >= 0 ? r : -r; }
// main program int main (int argc, char **argv) { // command-line options int verbose = 1; int ppm_error = 0; int gain = 0; float rx_resamp_rate; float bandwidth = 800e3f; int r, n_read; uint32_t frequency = 100000000; uint32_t samp_rate = DEFAULT_SAMPLE_RATE; uint32_t out_block_size = DEFAULT_BUF_LENGTH; uint8_t *buffer; complex float *buffer_norm; int dev_index = 0; int dev_given = 0; struct sigaction sigact; normalizer_t *norm; float kf = 0.1f; // modulation factor liquid_freqdem_type type = LIQUID_FREQDEM_DELAYCONJ; // int d; while ((d = getopt(argc,argv,"hf:b:B:G:p:s:")) != EOF) { switch (d) { case 'h': usage(); return 0; case 'f': frequency = atof(optarg); break; case 'b': bandwidth = atof(optarg); break; case 'B': out_block_size = (uint32_t)atof(optarg); break; case 'G': gain = (int)(atof(optarg) * 10); break; case 'p': ppm_error = atoi(optarg); break; case 's': samp_rate = (uint32_t)atofs(optarg); break; case 'd': dev_index = verbose_device_search(optarg); dev_given = 1; break; default: usage(); return 1; } } if (!dev_given) { dev_index = verbose_device_search("0"); } if (dev_index < 0) { exit(1); } r = rtlsdr_open(&dev, (uint32_t)dev_index); if (r < 0) { fprintf(stderr, "Failed to open rtlsdr device #%d.\n", dev_index); exit(1); } 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); /* Set the sample rate */ verbose_set_sample_rate(dev, samp_rate); /* Set the frequency */ verbose_set_frequency(dev, frequency); if (0 == gain) { /* Enable automatic gain */ verbose_auto_gain(dev); } else { /* Enable manual gain */ gain = nearest_gain(dev, gain); verbose_gain_set(dev, gain); } verbose_ppm_set(dev, ppm_error); rx_resamp_rate = bandwidth/samp_rate; printf("frequency : %10.4f [MHz]\n", frequency*1e-6f); printf("bandwidth : %10.4f [kHz]\n", bandwidth*1e-3f); printf("sample rate : %10.4f kHz = %10.4f kHz * %8.6f\n", samp_rate * 1e-3f, bandwidth * 1e-3f, 1.0f / rx_resamp_rate); printf("verbosity : %s\n", (verbose?"enabled":"disabled")); unsigned int i,j; // add arbitrary resampling component msresamp_crcf resamp = msresamp_crcf_create(rx_resamp_rate, 60.0f); assert(resamp); //allocate recv buffer buffer = malloc(out_block_size * sizeof(uint8_t)); assert(buffer); buffer_norm = malloc(out_block_size * sizeof(complex float)); assert(buffer_norm); // create buffer for arbitrary resamper output int b_len = ((int)(out_block_size * rx_resamp_rate) + 64) >> 1; complex float buffer_resamp[b_len]; int16_t buffer_demod[b_len]; debug("resamp_buffer_len: %d\n", b_len); norm = normalizer_create(); verbose_reset_buffer(dev); freqdem dem = freqdem_create(kf,type); while (!do_exit) { // grab data from device r = rtlsdr_read_sync(dev, buffer, out_block_size, &n_read); if (r < 0) { fprintf(stderr, "WARNING: sync read failed.\n"); break; } if ((bytes_to_read > 0) && (bytes_to_read < (uint32_t)n_read)) { n_read = bytes_to_read; do_exit = 1; } // push data through arbitrary resampler and give to frame synchronizer // TODO : apply bandwidth-dependent gain for (i=0; i<n_read/2; i++) { // grab sample from usrp buffer buffer_norm[i] = normalizer_normalize(norm, *((uint16_t*)buffer+i)); } // push through resampler (one at a time) unsigned int nw; float demod; msresamp_crcf_execute(resamp, buffer_norm, n_read/2, buffer_resamp, &nw); for(j=0;j<nw;j++) { freqdem_demodulate(dem, buffer_resamp[j], &demod); buffer_demod[j] = to_int16(demod); } if (fwrite(buffer_demod, 2, nw, stdout) != (size_t)nw) { fprintf(stderr, "Short write, samples lost, exiting!\n"); break; } if ((uint32_t)n_read < out_block_size) { fprintf(stderr, "Short read, samples lost, exiting!\n"); break; } if (bytes_to_read > 0) bytes_to_read -= n_read; } // destroy objects freqdem_destroy(dem); normalizer_destroy(&norm); msresamp_crcf_destroy(resamp); rtlsdr_close(dev); free (buffer); return 0; }
// main program int main (int argc, char **argv) { // command-line options int verbose = 1; int ppm_error = 0; int gain = 0; unsigned int nfft = 64; float offset = -65.0f; float scale = 5.0f; float fft_rate = 10.0f; float rx_resamp_rate; float bandwidth = 800e3f; unsigned int logsize = 4096; char filename[256] = "rtl_asgram.dat"; int r, n_read; uint32_t frequency = 100000000; uint32_t samp_rate = DEFAULT_SAMPLE_RATE; uint32_t out_block_size = DEFAULT_BUF_LENGTH; uint8_t *buffer; int dev_index = 0; int dev_given = 0; struct sigaction sigact; normalizer_t *norm; // int d; while ((d = getopt(argc,argv,"hf:b:B:G:n:p:s:o:r:L:F:")) != EOF) { switch (d) { case 'h': usage(); return 0; case 'f': frequency = atof(optarg); break; case 'b': bandwidth = atof(optarg); break; case 'B': out_block_size = (uint32_t)atof(optarg); break; case 'G': gain = (int)(atof(optarg) * 10); break; case 'n': nfft = atoi(optarg); break; case 'o': offset = atof(optarg); break; case 'p': ppm_error = atoi(optarg); break; case 's': samp_rate = (uint32_t)atofs(optarg); break; case 'r': fft_rate = atof(optarg); break; case 'L': logsize = atoi(optarg); break; case 'F': strncpy(filename,optarg,255); break; case 'd': dev_index = verbose_device_search(optarg); dev_given = 1; break; default: usage(); return 1; } } // validate parameters if (fft_rate <= 0.0f || fft_rate > 100.0f) { fprintf(stderr,"error: %s, fft rate must be in (0, 100) Hz\n", argv[0]); exit(1); } if (!dev_given) { dev_index = verbose_device_search("0"); } if (dev_index < 0) { exit(1); } r = rtlsdr_open(&dev, (uint32_t)dev_index); if (r < 0) { fprintf(stderr, "Failed to open rtlsdr device #%d.\n", dev_index); exit(1); } 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); /* Set the sample rate */ verbose_set_sample_rate(dev, samp_rate); /* Set the frequency */ verbose_set_frequency(dev, frequency); if (0 == gain) { /* Enable automatic gain */ verbose_auto_gain(dev); } else { /* Enable manual gain */ gain = nearest_gain(dev, gain); verbose_gain_set(dev, gain); } verbose_ppm_set(dev, ppm_error); rx_resamp_rate = bandwidth/samp_rate; printf("frequency : %10.4f [MHz]\n", frequency*1e-6f); printf("bandwidth : %10.4f [kHz]\n", bandwidth*1e-3f); printf("sample rate : %10.4f kHz = %10.4f kHz * %8.6f\n", samp_rate * 1e-3f, bandwidth * 1e-3f, 1.0f / rx_resamp_rate); printf("verbosity : %s\n", (verbose?"enabled":"disabled")); unsigned int i; // add arbitrary resampling component msresamp_crcf resamp = msresamp_crcf_create(rx_resamp_rate, 60.0f); assert(resamp); // create buffer for sample logging windowcf log = windowcf_create(logsize); // create ASCII spectrogram object float maxval; float maxfreq; char ascii[nfft+1]; ascii[nfft] = '\0'; // append null character to end of string asgram q = asgram_create(nfft); asgram_set_scale(q, offset, scale); // assemble footer unsigned int footer_len = nfft + 16; char footer[footer_len+1]; for (i=0; i<footer_len; i++) footer[i] = ' '; footer[1] = '['; footer[nfft/2 + 3] = '+'; footer[nfft + 4] = ']'; sprintf(&footer[nfft+6], "%8.3f MHz", frequency*1e-6f); unsigned int msdelay = 1000 / fft_rate; // create/initialize Hamming window float w[nfft]; for (i=0; i<nfft; i++) w[i] = hamming(i,nfft); //allocate recv buffer buffer = malloc(out_block_size * sizeof(uint8_t)); assert(buffer); // create buffer for arbitrary resamper output int b_len = ((int)(out_block_size * rx_resamp_rate) + 64) >> 1; complex float buffer_resamp[b_len]; debug("resamp_buffer_len: %d", b_len); // timer to control asgram output timer t1 = timer_create(); timer_tic(t1); norm = normalizer_create(); verbose_reset_buffer(dev); while (!do_exit) { // grab data from device r = rtlsdr_read_sync(dev, buffer, out_block_size, &n_read); if (r < 0) { fprintf(stderr, "WARNING: sync read failed.\n"); break; } if ((bytes_to_read > 0) && (bytes_to_read < (uint32_t)n_read)) { n_read = bytes_to_read; do_exit = 1; } // push data through arbitrary resampler and give to frame synchronizer // TODO : apply bandwidth-dependent gain for (i=0; i<n_read/2; i++) { // grab sample from usrp buffer complex float rtlsdr_sample = normalizer_normalize(norm, *((uint16_t*)buffer+i)); // push through resampler (one at a time) unsigned int nw; msresamp_crcf_execute(resamp, &rtlsdr_sample, 1, buffer_resamp, &nw); // push resulting samples into asgram object asgram_push(q, buffer_resamp, nw); // write samples to log windowcf_write(log, buffer_resamp, nw); } if ((uint32_t)n_read < out_block_size) { fprintf(stderr, "Short read, samples lost, exiting!\n"); break; } if (bytes_to_read > 0) bytes_to_read -= n_read; if (timer_toc(t1) > msdelay*1e-3f) { // reset timer timer_tic(t1); // run the spectrogram asgram_execute(q, ascii, &maxval, &maxfreq); // print the spectrogram printf(" > %s < pk%5.1fdB [%5.2f]\n", ascii, maxval, maxfreq); printf("%s\r", footer); fflush(stdout); } } // try to write samples to file FILE * fid = fopen(filename,"w"); if (fid != NULL) { // write header fprintf(fid, "# %s : auto-generated file\n", filename); fprintf(fid, "#\n"); fprintf(fid, "# num_samples : %u\n", logsize); fprintf(fid, "# frequency : %12.8f MHz\n", frequency*1e-6f); fprintf(fid, "# bandwidth : %12.8f kHz\n", bandwidth*1e-3f); // save results to file complex float * rc; // read pointer windowcf_read(log, &rc); for (i=0; i<logsize; i++) fprintf(fid, "%12.4e %12.4e\n", crealf(rc[i]), cimagf(rc[i])); // close it up fclose(fid); printf("results written to '%s'\n", filename); } else { fprintf(stderr,"error: %s, could not open '%s' for writing\n", argv[0], filename); } // destroy objects normalizer_destroy(&norm); msresamp_crcf_destroy(resamp); windowcf_destroy(log); asgram_destroy(q); timer_destroy(t1); rtlsdr_close(dev); free (buffer); return 0; }
int start_the_radio(int device_index, long freq_hz, long output_SR, int gain_db10) { // post("inside start_the_radio()" ); // int err = 0; // tz for usage call int r; int dev_given = 0; // gets set on, if user passes in device index arg (-d) // int custom_ppm = 0; // gets set on, if users specifies freq correction arg (-p) char device_index_str[10] = "0"; // initialization dongle_init(&dongle); demod_init(&demod); output_init(&output); controller_init(&controller); buffer_init(); // tz reset index pointers // handle device index if(device_index != 0) { sprintf(device_index_str,"%d", device_index); dongle.dev_index = verbose_device_search(device_index_str); dev_given = 1; } // set gain // tz - note that when passing this param from Max/Pd it gets passed in // db * 10 format - so we don't need extra multiplier // this is done to allow setting to AUTOGAIN // dongle.gain = gain_db10 ; // set sample rate demod.rate_in = (uint32_t) output_SR; demod.rate_out = (uint32_t) output_SR; // set frequency controller.freqs[controller.freq_len] = (uint32_t) freq_hz; controller.freq_len++; // note: here is how dongle ppm error correction was set in rtl_fm // dongle.ppm_error = atoi(optarg); // custom_ppm = 1; // do initial setup // tz this was for resampling and can be removed output.rate = demod.rate_out; // tz this can get cleaned up too... // set buffer length - would need to increase if downsample rate increased // ACTUAL_BUF_LENGTH = DEFAULT_BUF_LENGTH; // if user specied a device number, use it - otherwise default to 0 if (!dev_given) { dongle.dev_index = verbose_device_search("0"); } if (dongle.dev_index < 0) { return(1); } // open device r = rtlsdr_open(&dongle.dev, (uint32_t)dongle.dev_index); if (r < 0) { // sprintf(errmesg, "Failed to open rtlsdr device #%d.\n", dongle.dev_index); sprintf(errmesg, "Failed to open rtlsdr device #%d.\n", dongle.dev_index); post(errmesg, 0); return(1); } set_tuner_gain(&dongle); // do freq error correction verbose_ppm_set(dongle.dev, dongle.ppm_error); //r = rtlsdr_set_testmode(dongle.dev, 1); /* Reset endpoint before we start reading from it (mandatory) */ verbose_reset_buffer(dongle.dev); // tz these threads all get running in parallel here // int errx; // for debugging - not really used now errx = pthread_create(&controller.thread, NULL, controller_thread_fn, (void *)(&controller)); usleep(100000); errx = pthread_create(&dongle.thread, NULL, dongle_thread_fn, (void *)(&dongle)); radio_running = 1; return(0); }