void retune(rtlsdr_dev_t *d, int freq) { uint8_t dump[BUFFER_DUMP]; int n_read; // // NB: time scan pass // struct timeval stop, start; // // // Record start time // gettimeofday(&start, NULL); rtlsdr_set_center_freq(d, (uint32_t)freq); /* wait for settling and flush buffer */ usleep(5000); rtlsdr_read_sync(d, &dump, BUFFER_DUMP, &n_read); if (n_read != BUFFER_DUMP) { fprintf(stderr, "Error: bad retune.\n");} // // Compute scan time // gettimeofday(&stop, NULL); // // long startTime = start.tv_sec * 1000000 + start.tv_usec; // long stopTime = stop.tv_sec * 1000000 + stop.tv_usec; // printf("Retune took %ld micros\n", stopTime - startTime); }
static void *dongle_f(void *arg) { struct dongle_struct *ds = arg; rtlsdr_dev_t *dev = NULL; fprintf(stderr, "Initializing %d\n", ds->id); #ifdef PURKKA1 CHECK1(rtlsdr_open(&dev, (ds->id + 1) % 3)); #define trigger_id 2 #else CHECK1(rtlsdr_open(&dev, ds->id)); #define trigger_id 0 #endif ds->dev = dev; CHECK1(rtlsdr_set_sample_rate(dev, samprate)); CHECK1(rtlsdr_set_dithering(dev, 0)); CHECK1(rtlsdr_set_center_freq(dev, frequency)); CHECK1(rtlsdr_set_tuner_gain_mode(dev, 1)); CHECK1(rtlsdr_set_tuner_gain(dev, gain)); CHECK1(rtlsdr_reset_buffer(dev)); fprintf(stderr, "Initialized %d\n", ds->id); donglesok++; for(;;) { int task; pthread_mutex_lock(&dongle_m); if(dongle_task == DONGLE_EXIT) break; sem_post(&dongle_sem); pthread_cond_wait(&dongle_c, &dongle_m); task = dongle_task; pthread_mutex_unlock(&dongle_m); if(task == DONGLE_READ) { int ret; int blocksize = ds->blocksize, n_read = 0; n_read = 0; errno = 0; CHECK2(ret = rtlsdr_read_sync(dev, ds->buffer, blocksize, &n_read)); if(ret < 0) { } else if(n_read < blocksize) { fprintf(stderr, "Short read %d: %d/%d\n", ds->id, n_read, blocksize); } else if(coherent_debug) { fprintf(stderr, "Read %d\n", ds->id); } } else if(task == DONGLE_EXIT) break; } donglesok--; err: fprintf(stderr, "Exiting %d\n", ds->id); if(dev) CHECK2(rtlsdr_close(dev)); sem_post(&dongle_sem); return NULL; }
void full_demod(struct fm_state *fm) { int i, sr, freq_next, hop = 0; // pthread_mutex_lock(&data_ready); static unsigned char tmpBuf[DEFAULT_BUF_LENGTH]; while(ringbuffer_is_empty((ringbuffer*)fm->buf)) { usleep(100000); } ringbuffer_read((ringbuffer*)fm->buf, tmpBuf); //fprintf(stderr, "data!\n"); rotate_90(tmpBuf, sizeof(tmpBuf)); if (fm->fir_enable) { low_pass_fir(fm, tmpBuf, sizeof(tmpBuf)); } else { low_pass(fm, tmpBuf, sizeof(tmpBuf)); } // pthread_mutex_unlock(&data_write); fm->mode_demod(fm); if (fm->mode_demod == &raw_demod) { fwrite(fm->signal2, 2, fm->signal2_len, fm->file); return; } sr = post_squelch(fm); if (!sr && fm->squelch_hits > fm->conseq_squelch) { if (fm->terminate_on_squelch) { fm->exit_flag = 1;} if (fm->freq_len == 1) { /* mute */ for (i=0; i<fm->signal_len; i++) { fm->signal2[i] = 0;} } else { hop = 1;} } if (fm->post_downsample > 1) { fm->signal2_len = low_pass_simple(fm->signal2, fm->signal2_len, fm->post_downsample);} if (fm->output_rate > 0) { low_pass_real(fm); } if (fm->deemph) { deemph_filter(fm);} if (fm->dc_block) { dc_block_filter(fm);} /* ignore under runs for now */ fwrite(fm->signal2, 2, fm->signal2_len, fm->file); if (hop && ringbuffer_is_empty((ringbuffer*)fm->buf)) { // Making sure the buffer is empty before tuning freq_next = (fm->freq_now + 1) % fm->freq_len; optimal_settings(fm, freq_next, 1); fm->squelch_hits = fm->conseq_squelch + 1; /* hair trigger */ /* wait for settling and flush buffer */ usleep(5000); rtlsdr_read_sync(dev, NULL, 4096, NULL); } }
void retune(rtlsdr_dev_t *d, int freq) { uint8_t dump[BUFFER_DUMP]; int n_read; rtlsdr_set_center_freq(d, (uint32_t)freq); /* wait for settling and flush buffer */ usleep(5000); rtlsdr_read_sync(d, &dump, BUFFER_DUMP, &n_read); if (n_read != BUFFER_DUMP) { fprintf(stderr, "Error: bad retune.\n");} }
void full_demod(struct fm_state *fm) { uint8_t dump[BUFFER_DUMP]; int i, sr, freq_next, n_read, hop = 0; pthread_rwlock_wrlock(&data_rw); rotate_90(fm->buf, fm->buf_len); if (fm->fir_enable) { low_pass_fir(fm, fm->buf, fm->buf_len); } else { low_pass(fm, fm->buf, fm->buf_len); } pthread_rwlock_unlock(&data_rw); fm->mode_demod(fm); if (fm->mode_demod == &raw_demod) { fwrite(fm->signal2, 2, fm->signal2_len, fm->file); return; } sr = post_squelch(fm); if (!sr && fm->squelch_hits > fm->conseq_squelch) { if (fm->terminate_on_squelch) { fm->exit_flag = 1;} if (fm->freq_len == 1) { /* mute */ for (i=0; i<fm->signal_len; i++) { fm->signal2[i] = 0;} } else { hop = 1;} } if (fm->post_downsample > 1) { fm->signal2_len = low_pass_simple(fm->signal2, fm->signal2_len, fm->post_downsample);} if (fm->output_rate > 0) { low_pass_real(fm); } if (fm->deemph) { deemph_filter(fm);} if (fm->dc_block) { dc_block_filter(fm);} /* ignore under runs for now */ fwrite(fm->signal2, 2, fm->signal2_len, fm->file); if (hop) { freq_next = (fm->freq_now + 1) % fm->freq_len; optimal_settings(fm, freq_next, 1); fm->squelch_hits = fm->conseq_squelch + 1; /* hair trigger */ /* wait for settling and flush buffer */ usleep(5000); rtlsdr_read_sync(dev, &dump, BUFFER_DUMP, &n_read); if (n_read != BUFFER_DUMP) { fprintf(stderr, "Error: bad retune.\n");} } }
static void sync_read(unsigned char *buf, uint32_t len, struct fm_state *fm) { int r, n_read; r = rtlsdr_read_sync(dev, buf, len, &n_read); if (r < 0) { fprintf(stderr, "WARNING: sync read failed.\n"); return; } pthread_rwlock_wrlock(&data_rw); memcpy(fm->buf, buf, len); fm->buf_len = len; pthread_rwlock_unlock(&data_rw); safe_cond_signal(&data_ready, &data_mutex); //full_demod(fm); }
void scanner(void) { int i, j, j2, n_read, offset, bin_e, bin_len, buf_len, ds, ds_p; int32_t w; struct tuning_state *ts; int16_t *fft_buf; bin_e = tunes[0].bin_e; bin_len = 1 << bin_e; buf_len = tunes[0].buf_len; for (i=0; i<tune_count; i++) { if (do_exit >= 2) {return;} ts = &tunes[i]; fft_buf = ts->fft_buf; regain(dev, ts->gain); rerate(dev, ts->rate); retune(dev, ts->freq); rtlsdr_read_sync(dev, ts->buf8, buf_len, &n_read); if (n_read != buf_len) { fprintf(stderr, "Error: dropped samples.\n");} /* rms */ if (bin_len == 1) { rms_power(ts); continue; } /* prep for fft */ for (j=0; j<buf_len; j++) { fft_buf[j] = (int16_t)ts->buf8[j] - 127; } ds = ts->downsample; ds_p = ts->downsample_passes; if (ds_p) { /* recursive */ for (j=0; j < ds_p; j++) { downsample_iq(fft_buf, buf_len >> j); } /* droop compensation */ if (ts->comp_fir_size == 9 && ds_p <= CIC_TABLE_MAX) { generic_fir(fft_buf, buf_len >> j, cic_9_tables[ds_p]); generic_fir(fft_buf+1, (buf_len >> j)-1, cic_9_tables[ds_p]); } } else if (ds > 1) { /* boxcar */
void sdr_work(struct rtlsdrstruct* sdr) { //if the size of the data read off the SDR is too large then the demod function //takes too long which makes the output audio low quality int x = rtlsdr_read_sync(sdr->device, sdr->buffer, 1 * 1024, &sdr->receivesize); // usleep(1000); if (x < 0) { printf("Samples read: %d\n", sdr->receivesize); printf("Error reading from SDR\n"); exit(0); } // if (sdr->receivesize == 0) { // printf("ERROR reading data off SDR, # Samples read: %d\n", sdr->receivesize); // } #if SDR_WRITE == 0 printf("sdr->receivesize = %d\n", sdr->receivesize); // printf("Sampling rate set to %d\n", rtlsdr_get_sample_rate(sdr->device)); fwrite(sdr->buffer, sizeof(uint8_t), sdr->receivesize, sdr->filewrite); #endif }
void full_demod(unsigned char *buf, uint32_t len, struct fm_state *fm) { int sr, freq_next; rotate_90(buf, len); if (fm->fir_enable) { low_pass_fir(fm, buf, len); } else { low_pass(fm, buf, len); } fm_demod(fm); sr = post_squelch(fm); if (fm->post_downsample > 1) { fm->signal_len = low_pass_simple(fm->signal2, fm->signal_len/2, fm->post_downsample)*2;} /* ignore under runs for now */ fwrite(fm->signal2, 2, fm->signal_len/2, fm->file); if (fm->freq_len > 1 && !sr && fm->squelch_hits > CONSEQ_SQUELCH) { freq_next = (fm->freq_now + 1) % fm->freq_len; optimal_settings(fm, freq_next, 1); fm->squelch_hits = CONSEQ_SQUELCH + 1; /* hair trigger */ /* wait for settling and dump buffer */ usleep(5000); rtlsdr_read_sync(dev, NULL, 4096, NULL); } }
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) { #ifndef _WIN32 struct sigaction sigact; #endif int n_read; int r, opt; int i, tuner_benchmark = 0; int sync_mode = 0; uint8_t *buffer; uint32_t dev_index = 0; uint32_t samp_rate = DEFAULT_SAMPLE_RATE; uint32_t out_block_size = DEFAULT_BUF_LENGTH; int device_count; int count; int gains[100]; int real_rate; int64_t ns; while ((opt = getopt(argc, argv, "d:s:b:tpS::")) != -1) { switch (opt) { case 'd': dev_index = atoi(optarg); break; case 's': samp_rate = (uint32_t)atof(optarg); break; case 'b': out_block_size = (uint32_t)atof(optarg); break; case 't': tuner_benchmark = 1; break; case 'p': ppm_benchmark = PPM_DURATION; break; case 'S': sync_mode = 1; break; 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)); device_count = rtlsdr_get_device_count(); if (!device_count) { fprintf(stderr, "No supported devices found.\n"); exit(1); } fprintf(stderr, "Found %d device(s):\n", device_count); for (i = 0; i < device_count; i++) fprintf(stderr, " %d: %s\n", i, rtlsdr_get_device_name(i)); fprintf(stderr, "\n"); fprintf(stderr, "Using device %d: %s\n", dev_index, rtlsdr_get_device_name(dev_index)); r = rtlsdr_open(&dev, 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 */ r = rtlsdr_set_sample_rate(dev, samp_rate); if (r < 0) fprintf(stderr, "WARNING: Failed to set sample rate.\n"); if (tuner_benchmark) { if (rtlsdr_get_tuner_type(dev) == RTLSDR_TUNER_E4000) e4k_benchmark(); else fprintf(stderr, "No E4000 tuner found, aborting.\n"); goto exit; } /* Enable test mode */ r = rtlsdr_set_testmode(dev, 1); /* Reset endpoint before we start reading from it (mandatory) */ r = rtlsdr_reset_buffer(dev); if (r < 0) fprintf(stderr, "WARNING: Failed to reset buffers.\n"); if (ppm_benchmark && !sync_mode) { fprintf(stderr, "Reporting PPM error measurement every %i seconds...\n", ppm_benchmark); fprintf(stderr, "Press ^C after a few minutes.\n"); #ifdef __APPLE__ gettimeofday(&tv, NULL); ppm_recent.tv_sec = tv.tv_sec; ppm_recent.tv_nsec = tv.tv_usec*1000; ppm_start.tv_sec = tv.tv_sec; ppm_start.tv_nsec = tv.tv_usec*1000; #elif __unix__ clock_gettime(CLOCK_REALTIME, &ppm_recent); clock_gettime(CLOCK_REALTIME, &ppm_start); #endif } if (!ppm_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"); 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; } } } else { fprintf(stderr, "Reading samples in async mode...\n"); r = rtlsdr_read_async(dev, rtlsdr_callback, NULL, DEFAULT_ASYNC_BUF_NUMBER, out_block_size); } if (do_exit) { fprintf(stderr, "\nUser cancel, exiting...\n"); if (ppm_benchmark) { #ifndef _WIN32 ns = 1000000000L * (int64_t)(ppm_recent.tv_sec - ppm_start.tv_sec); ns += (int64_t)(ppm_recent.tv_nsec - ppm_start.tv_nsec); real_rate = (int)(ppm_total * 1000000000L / ns); printf("Cumulative PPM error: %i\n", (int)round((double)(1000000 * (real_rate - (int)samp_rate)) / (double)samp_rate)); #endif } } 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; #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; #endif char *out_filename = NULL; char *in_filename = NULL; FILE *in_file; int n_read; int r = 0, opt; int i, gain = 0; int sync_mode = 0; int ppm_error = 0; struct dm_state* demod; uint32_t dev_index = 0; int frequency_current = 0; uint32_t out_block_size = DEFAULT_BUF_LENGTH; int device_count; char vendor[256], product[256], serial[256]; int have_opt_R = 0; setbuf(stdout, NULL); setbuf(stderr, NULL); demod = malloc(sizeof (struct dm_state)); memset(demod, 0, sizeof (struct dm_state)); /* initialize tables */ baseband_init(); r_device devices[] = { #define DECL(name) name, DEVICES #undef DECL }; num_r_devices = sizeof(devices)/sizeof(*devices); demod->level_limit = DEFAULT_LEVEL_LIMIT; while ((opt = getopt(argc, argv, "x:z:p:DtaAqm:r:l:d:f:g:s:b:n:SR:F:C:T:UW")) != -1) { switch (opt) { case 'd': dev_index = atoi(optarg); break; case 'f': if (frequencies < MAX_PROTOCOLS) frequency[frequencies++] = (uint32_t) atof(optarg); else fprintf(stderr, "Max number of frequencies reached %d\n", MAX_PROTOCOLS); break; case 'g': gain = (int) (atof(optarg) * 10); /* tenths of a dB */ break; case 'p': ppm_error = atoi(optarg); break; case 's': samp_rate = (uint32_t) atof(optarg); break; case 'b': out_block_size = (uint32_t) atof(optarg); break; case 'l': demod->level_limit = (uint32_t) atof(optarg); break; case 'n': bytes_to_read = (uint32_t) atof(optarg) * 2; break; case 'a': demod->analyze = 1; break; case 'A': demod->analyze_pulses = 1; break; case 'r': in_filename = optarg; break; case 't': demod->signal_grabber = 1; break; case 'm': demod->debug_mode = atoi(optarg); break; case 'S': sync_mode = 1; break; case 'D': debug_output++; break; case 'z': override_short = atoi(optarg); break; case 'x': override_long = atoi(optarg); break; case 'R': if (!have_opt_R) { for (i = 0; i < num_r_devices; i++) { devices[i].disabled = 1; } have_opt_R = 1; } i = atoi(optarg); if (i > num_r_devices) { fprintf(stderr, "Remote device number specified larger than number of devices\n\n"); usage(devices); } devices[i - 1].disabled = 0; break; case 'q': quiet_mode = 1; break; case 'F': if (strcmp(optarg, "json") == 0) { add_json_output(); } else if (strcmp(optarg, "csv") == 0) { add_csv_output(determine_csv_fields(devices, num_r_devices)); } else if (strcmp(optarg, "kv") == 0) { add_kv_output(); } else { fprintf(stderr, "Invalid output format %s\n", optarg); usage(devices); } break; case 'C': if (strcmp(optarg, "native") == 0) { conversion_mode = CONVERT_NATIVE; } else if (strcmp(optarg, "si") == 0) { conversion_mode = CONVERT_SI; } else if (strcmp(optarg, "customary") == 0) { conversion_mode = CONVERT_CUSTOMARY; } else { fprintf(stderr, "Invalid conversion mode %s\n", optarg); usage(devices); } break; case 'U': #if !defined(__MINGW32__) utc_mode = setenv("TZ", "UTC", 1); if(utc_mode != 0) fprintf(stderr, "Unable to set TZ to UTC; error code: %d\n", utc_mode); #endif break; case 'W': overwrite_mode = 1; break; case 'T': time(&stop_time); duration = atoi(optarg); if (duration < 1) { fprintf(stderr, "Duration '%s' was not positive integer; will continue indefinitely\n", optarg); } else { stop_time += duration; } break; default: usage(devices); break; } } if (argc <= optind - 1) { usage(devices); } else { out_filename = argv[optind]; } if (!output_handler) { add_kv_output(); } for (i = 0; i < num_r_devices; i++) { if (!devices[i].disabled) { register_protocol(demod, &devices[i]); if(devices[i].modulation >= FSK_DEMOD_MIN_VAL) { demod->enable_FM_demod = 1; } } } 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; } if (!in_filename) { device_count = rtlsdr_get_device_count(); if (!device_count) { fprintf(stderr, "No supported devices found.\n"); if (!in_filename) exit(1); } if (!quiet_mode) { fprintf(stderr, "Found %d device(s):\n", device_count); for (i = 0; i < device_count; i++) { rtlsdr_get_device_usb_strings(i, vendor, product, serial); fprintf(stderr, " %d: %s, %s, SN: %s\n", i, vendor, product, serial); } fprintf(stderr, "\n"); fprintf(stderr, "Using device %d: %s\n", dev_index, rtlsdr_get_device_name(dev_index)); } r = rtlsdr_open(&dev, 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 */ r = rtlsdr_set_sample_rate(dev, samp_rate); if (r < 0) fprintf(stderr, "WARNING: Failed to set sample rate.\n"); else fprintf(stderr, "Sample rate set to %d.\n", rtlsdr_get_sample_rate(dev)); // Unfortunately, doesn't return real rate fprintf(stderr, "Bit detection level set to %d.\n", demod->level_limit); if (0 == gain) { /* Enable automatic gain */ r = rtlsdr_set_tuner_gain_mode(dev, 0); if (r < 0) fprintf(stderr, "WARNING: Failed to enable automatic gain.\n"); else fprintf(stderr, "Tuner gain set to Auto.\n"); } else { /* Enable manual gain */ r = rtlsdr_set_tuner_gain_mode(dev, 1); if (r < 0) fprintf(stderr, "WARNING: Failed to enable manual gain.\n"); /* Set the tuner gain */ r = rtlsdr_set_tuner_gain(dev, gain); if (r < 0) fprintf(stderr, "WARNING: Failed to set tuner gain.\n"); else fprintf(stderr, "Tuner gain set to %f dB.\n", gain / 10.0); } r = rtlsdr_set_freq_correction(dev, ppm_error); } if (out_filename) { if (strcmp(out_filename, "-") == 0) { /* Write samples to stdout */ demod->out_file = stdout; #ifdef _WIN32 _setmode(_fileno(stdin), _O_BINARY); #endif } else { if (access(out_filename, F_OK) == 0 && !overwrite_mode) { fprintf(stderr, "Output file %s already exists, exiting\n", out_filename); goto out; } demod->out_file = fopen(out_filename, "wb"); if (!demod->out_file) { fprintf(stderr, "Failed to open %s\n", out_filename); goto out; } } } if (demod->signal_grabber) demod->sg_buf = malloc(SIGNAL_GRABBER_BUFFER); if (in_filename) { int i = 0; unsigned char test_mode_buf[DEFAULT_BUF_LENGTH]; float test_mode_float_buf[DEFAULT_BUF_LENGTH]; if (strcmp(in_filename, "-") == 0) { /* read samples from stdin */ in_file = stdin; in_filename = "<stdin>"; } else { in_file = fopen(in_filename, "rb"); if (!in_file) { fprintf(stderr, "Opening file: %s failed!\n", in_filename); goto out; } } fprintf(stderr, "Test mode active. Reading samples from file: %s\n", in_filename); // Essential information (not quiet) if (!quiet_mode) { fprintf(stderr, "Input format: %s\n", (demod->debug_mode == 3) ? "cf32" : "uint8"); } sample_file_pos = 0.0; int n_read, cf32_tmp; do { if (demod->debug_mode == 3) { n_read = fread(test_mode_float_buf, sizeof(float), 131072, in_file); for(int n = 0; n < n_read; n++) { cf32_tmp = test_mode_float_buf[n]*127 + 127; if (cf32_tmp < 0) cf32_tmp = 0; else if (cf32_tmp > 255) cf32_tmp = 255; test_mode_buf[n] = (uint8_t)cf32_tmp; } } else { n_read = fread(test_mode_buf, 1, 131072, in_file); } if (n_read == 0) break; // rtlsdr_callback() will Segmentation Fault with len=0 rtlsdr_callback(test_mode_buf, n_read, demod); i++; sample_file_pos = (float)i * n_read / samp_rate; } while (n_read != 0); // Call a last time with cleared samples to ensure EOP detection memset(test_mode_buf, 128, DEFAULT_BUF_LENGTH); // 128 is 0 in unsigned data rtlsdr_callback(test_mode_buf, 131072, demod); // Why the magic value 131072? //Always classify a signal at the end of the file classify_signal(); if (!quiet_mode) { fprintf(stderr, "Test mode file issued %d packets\n", i); } exit(0); } /* Reset endpoint before we start reading from it (mandatory) */ r = rtlsdr_reset_buffer(dev); if (r < 0) fprintf(stderr, "WARNING: Failed to reset buffers.\n"); if (sync_mode) { if (!demod->out_file) { fprintf(stderr, "Specify an output file for sync mode.\n"); exit(0); } fprintf(stderr, "Reading samples in sync mode...\n"); uint8_t *buffer = malloc(out_block_size * sizeof (uint8_t)); time_t timestamp; 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, demod->out_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 (duration > 0) { time(×tamp); if (timestamp >= stop_time) { do_exit = 1; fprintf(stderr, "Time expired, exiting!\n"); } } if (bytes_to_read > 0) bytes_to_read -= n_read; } free(buffer); } else { if (frequencies == 0) { frequency[0] = DEFAULT_FREQUENCY; frequencies = 1; } else { time(&rawtime_old); } if (!quiet_mode) { fprintf(stderr, "Reading samples in async mode...\n"); } while (!do_exit) { /* Set the frequency */ r = rtlsdr_set_center_freq(dev, frequency[frequency_current]); if (r < 0) fprintf(stderr, "WARNING: Failed to set center freq.\n"); else fprintf(stderr, "Tuned to %u Hz.\n", rtlsdr_get_center_freq(dev)); r = rtlsdr_read_async(dev, rtlsdr_callback, (void *) demod, DEFAULT_ASYNC_BUF_NUMBER, out_block_size); do_exit_async = 0; frequency_current++; if (frequency_current > frequencies - 1) frequency_current = 0; } } if (do_exit) fprintf(stderr, "\nUser cancel, exiting...\n"); else fprintf(stderr, "\nLibrary error %d, exiting...\n", r); if (demod->out_file && (demod->out_file != stdout)) fclose(demod->out_file); for (i = 0; i < demod->r_dev_num; i++) free(demod->r_devs[i]); if (demod->signal_grabber) free(demod->sg_buf); free(demod); rtlsdr_close(dev); out: for (output_handler_t *output = output_handler; output; output = output->next) { if (output->aux_free) { output->aux_free(output->aux); } } return r >= 0 ? r : -r; }
void vspectra(void) { int i, j, k, kk, num, numm, i4, maxi, r; int m, mm, blsiz, blsiz2, nsam, n_read; double avsig, av, max, min, noise, wid; uint8_t *bufferRead = malloc((NSAM) * sizeof(uint8_t)); static double vspec[NSPEC]; static int wtt[NSPEC]; static double re[NSPEC * 2], am[NSPEC * 2]; double smax; fftwf_plan p0; float *reamin0, *reamout0; blsiz = NSPEC * 2; blsiz2 = blsiz / 2; d1.bw = 2.4; // fixed 2.4 for TV dongle 10 MHz for ADC card if (d1.fbw == 0.0) d1.fbw = 2.0; // use bandwidth default if not set in srt.cat d1.f1 = 0.5 - (d1.fbw / d1.bw) * 0.5; d1.f2 = 0.5 + (d1.fbw / d1.bw) * 0.5; d1.fc = (d1.f1 + d1.f2) * 0.5; d1.lofreq = 0; // not used but needs to be set to zero to flag the use of the dongle d1.efflofreq = d1.freq - d1.bw * 0.5; if (!d1.fftsim) { fft_init(blsiz2, &p0, &reamin0, &reamout0); } num = d1.nblk; //was 20 // was 100 nsam = NSAM; d1.nsam = NSAM * num; avsig = 0; numm = 0; smax = 0; max = -1e99; min = 1e99; for (i = 0; i < blsiz2; i++) vspec[i] = 0.0; for (k = 0; k < num; k++) { if (!d1.radiosim) // Read the raw data from the RTL Dongle r = rtlsdr_read_sync(dev, bufferRead, nsam, &n_read); else { av = 5.0; if (d1.elnow < 5.0) av = av * (d1.tsys + d1.tcal) / d1.tsys; if (strstr(soutrack, "Sun")) { av = sqrt(d1.eloff * d1.eloff + d1.azoff * d1.azoff * cos(d1.elnow * PI / 180.0) * cos(d1.elnow * PI / 180.0) + 1e-6); if (av > d1.beamw) av = d1.beamw; av = 5.0 + 25.0 * cos(av * PI * 0.5 / d1.beamw) * cos(av * PI * 0.5 / d1.beamw); } for (i = 0; i < nsam; i++) bufferRead[i] = (uint8_t) (sqrt(av) * gauss() + 127.397 + 0.5 + 0 * sin(2.0 * PI * 0.5 * (i / 2) / d1.bw)); // simulate data } // for(i=0;i<nsam;i+=0x10000) printf("%d %f\n",i,(double)(bufferRead[i]-127.397)); for (kk = 0; kk < nsam / blsiz; kk++) { if (d1.fftsim) for (i = 0; i < blsiz2; i++) { re[i] = (double) (bufferRead[2 * i + kk * blsiz] - 127.397); am[i] = (double) (bufferRead[2 * i + 1 + kk * blsiz] - 127.397); if (re[i] > smax) smax = re[i]; } else for (i = 0; i < blsiz2; i++) { reamin0[2 * i] = (float) (bufferRead[2 * i + kk * blsiz] - 127.397); reamin0[2 * i + 1] = (float) (bufferRead[2 * i + 1 + kk * blsiz] - 127.397); if (reamin0[2 * i] > smax) smax = reamin0[2 * i]; } if (d1.fftsim) Four(re, am, blsiz2); else { cfft(&p0); for (i = 0; i < blsiz2; i++) { re[i] = reamout0[2 * i]; am[i] = reamout0[2 * i + 1]; } } // for(i = 0; i < blsiz2; i++) if(re[i] > max) max=re[i]; // for(i = 0; i < blsiz2; i++) if(re[i] < min) min=re[i]; for (i = 0; i < blsiz2; i++) { if (i < blsiz2 / 2) j = i + blsiz2 / 2; else j = i - blsiz2 / 2; vspec[j] += re[i] * re[i] + am[i] * am[i]; numm++; } } } // printf("max %f min %f\n",max,min); max = av = 0; maxi = 0; for (i = 0; i < blsiz2; i++) wtt[i] = 1; if (numm > 0) { if (d1.nfreq == blsiz2) { for (i = 0; i < blsiz2; i++) { if (i > 10) spec[i] = vspec[i] / (double) numm; else spec[i] = 0; } } else { m = blsiz2 / d1.nfreq; for (i = 0; i < d1.nrfi; i++) { i4 = (d1.rfi[i] - d1.freq + d1.bw * 0.5) * blsiz2 / d1.bw + 0.5; // index of rfi MHz wid = 0.5 * d1.rfiwid[i] / (d1.bw / NSPEC); for (j = -wid; j <= wid; j++) if ((i4 + j) >= 0 && (i4 + j) < blsiz2) wtt[i4 + j] = 0; } for (j = 0; j < d1.nfreq; j++) { av = mm = 0; for (i = j * m - m / 2; i <= j * m + m / 2; i++) { if (i > 10 && i < blsiz2 && wtt[i]) { // wtt=0 removal of spurs av += vspec[i] / (double) numm; if (vspec[i] > max) { max = vspec[i]; maxi = i; } mm++; } } if (mm > 0) spec[j] = av / mm; else { spec[j] = 0; if (j > 10) printf("check RFI settings in srt.cat data deleted at %8.3f\n", j * d1.bw / d1.nfreq + d1.freq - d1.bw * 0.5); } } max = max / (double) numm; noise = spec[maxi / m] * sqrt(2.0 * blsiz2 / (double) d1.nsam); if (max > spec[maxi / m] + d1.rfisigma * noise && d1.printout) // rfisigma sigma printf("check for RFI at %8.4f MHz max %5.0e av %5.0e smax %5.0f %3.0f sigma\n", maxi * d1.bw / blsiz2 + d1.freq - d1.bw * 0.5, max, spec[maxi / m], smax, (max - spec[maxi / m]) / noise); } } d1.smax = smax; if (!d1.fftsim) fft_free(&p0, &reamin0, &reamout0); free(bufferRead); }
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; }
// 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 main(int argc, char **argv) { #ifndef _WIN32 struct sigaction sigact; #endif char *filename = NULL; int n_read; int r, opt; int i, gain = 0; int sync_mode = 0; FILE *file; uint8_t *buffer; uint32_t dev_index = 0; uint32_t udp_port = 6666; uint32_t frequency = 100000000; uint32_t samp_rate = DEFAULT_SAMPLE_RATE; uint32_t out_block_size = DEFAULT_BUF_LENGTH; int device_count; char vendor[256], product[256], serial[256]; while ((opt = getopt(argc, argv, "d:p:f:g:s:b:n:S::")) != -1) { switch (opt) { case 'd': dev_index = atoi(optarg); break; case 'p': udp_port = atoi(optarg); break; case 'f': frequency = (uint32_t)atof(optarg); break; case 'g': gain = (int)(atof(optarg) * 10); /* tenths of a dB */ break; case 's': samp_rate = (uint32_t)atof(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)); device_count = rtlsdr_get_device_count(); if (!device_count) { fprintf(stderr, "No supported devices found.\n"); exit(1); } fprintf(stderr, "Found %d device(s):\n", device_count); for (i = 0; i < device_count; i++) { rtlsdr_get_device_usb_strings(i, vendor, product, serial); fprintf(stderr, " %d: %s, %s, SN: %s\n", i, vendor, product, serial); } fprintf(stderr, "\n"); fprintf(stderr, "Using device %d: %s\n", dev_index, rtlsdr_get_device_name(dev_index)); //-------------------------------------------------- fd = socket(AF_INET,SOCK_DGRAM,0); if(fd==-1) { perror("socket"); exit(-1); } fprintf(stderr, "create socket OK!\n"); //create an send address addr.sin_family = AF_INET; addr.sin_port = htons(udp_port); addr.sin_addr.s_addr=inet_addr("127.0.0.1"); fprintf(stderr, "127.0.0.1:%u\n", udp_port); //-------------------------------------------------- r = rtlsdr_open(&dev, 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 */ r = rtlsdr_set_sample_rate(dev, samp_rate); if (r < 0) fprintf(stderr, "WARNING: Failed to set sample rate.\n"); /* Set the frequency */ r = rtlsdr_set_center_freq(dev, frequency); if (r < 0) fprintf(stderr, "WARNING: Failed to set center freq.\n"); else fprintf(stderr, "Tuned to %u Hz.\n", frequency); if (0 == gain) { /* Enable automatic gain */ r = rtlsdr_set_tuner_gain_mode(dev, 0); if (r < 0) fprintf(stderr, "WARNING: Failed to enable automatic gain.\n"); } else { /* Enable manual gain */ r = rtlsdr_set_tuner_gain_mode(dev, 1); if (r < 0) fprintf(stderr, "WARNING: Failed to enable manual gain.\n"); /* Set the tuner gain */ r = rtlsdr_set_tuner_gain(dev, gain); if (r < 0) fprintf(stderr, "WARNING: Failed to set tuner gain.\n"); else fprintf(stderr, "Tuner gain set to %f dB.\n", gain/10.0); } 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) */ r = rtlsdr_reset_buffer(dev); if (r < 0) fprintf(stderr, "WARNING: Failed to reset buffers.\n"); 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, DEFAULT_ASYNC_BUF_NUMBER, 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); close(fd); out: 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; }
void scanner(void) { int i, j, j2, f, n_read, offset, bin_e, bin_len, buf_len, ds, ds_p; int32_t w; struct tuning_state *ts; bin_e = tunes[0].bin_e; bin_len = 1 << bin_e; buf_len = tunes[0].buf_len; for (i=0; i<tune_count; i++) { if (do_exit >= 2) {return;} ts = &tunes[i]; f = (int)rtlsdr_get_center_freq(dev); if (f != ts->freq) { retune(dev, ts->freq);} rtlsdr_read_sync(dev, ts->buf8, buf_len, &n_read); if (n_read != buf_len) { fprintf(stderr, "Error: dropped samples.\n");} /* rms */ if (bin_len == 1) { rms_power(ts); continue; } /* prep for fft */ for (j=0; j<buf_len; j++) { fft_buf[j] = (int16_t)ts->buf8[j] - 127; } ds = ts->downsample; ds_p = ts->downsample_passes; if (boxcar && ds > 1) { j=2, j2=0; while (j < buf_len) { fft_buf[j2] += fft_buf[j]; fft_buf[j2+1] += fft_buf[j+1]; fft_buf[j] = 0; fft_buf[j+1] = 0; j += 2; if (j % (ds*2) == 0) { j2 += 2;} } } else if (ds_p) { /* recursive */ for (j=0; j < ds_p; j++) { downsample_iq(fft_buf, buf_len >> j); } /* droop compensation */ if (comp_fir_size == 9 && ds_p <= CIC_TABLE_MAX) { generic_fir(fft_buf, buf_len >> j, cic_9_tables[ds_p]); generic_fir(fft_buf+1, (buf_len >> j)-1, cic_9_tables[ds_p]); } } remove_dc(fft_buf, buf_len / ds); remove_dc(fft_buf+1, (buf_len / ds) - 1); /* window function and fft */ for (offset=0; offset<(buf_len/ds); offset+=(2*bin_len)) { // todo, let rect skip this for (j=0; j<bin_len; j++) { w = (int32_t)fft_buf[offset+j*2]; w *= (int32_t)(window_coefs[j]); //w /= (int32_t)(ds); fft_buf[offset+j*2] = (int16_t)w; w = (int32_t)fft_buf[offset+j*2+1]; w *= (int32_t)(window_coefs[j]); //w /= (int32_t)(ds); fft_buf[offset+j*2+1] = (int16_t)w; } fix_fft(fft_buf+offset, bin_e); if (!peak_hold) { for (j=0; j<bin_len; j++) { ts->avg[j] += real_conj(fft_buf[offset+j*2], fft_buf[offset+j*2+1]); } } else { for (j=0; j<bin_len; j++) { ts->avg[j] = MAX(real_conj(fft_buf[offset+j*2], fft_buf[offset+j*2+1]), ts->avg[j]); } } ts->samples += ds; } }
void readData(int line_idx) { // this also works without the /2, the fft only needs to be drawn in the texture once then // I'm not sure if this is supposed to work like that, maybe ask some GL expert? // use /2 for now, maybe test later for performance if(line_idx == GLUT_BUFSIZE/2) { offset = 0.0f; line_idx = 0; } else offset = -(float)(line_idx)/(float)GLUT_BUFSIZE; // scale colors every full round of the buffer /* if(line_idx==100) { pwr_diff = pwr_max; fprintf(stderr, "pwr_diff reset to %.2f\n", pwr_diff); pwr_max = 0.0f; } */ uint32_t out_block_size = DEFAULT_BUF_LENGTH; int n_read; int r = rtlsdr_read_sync(dev, buffer, out_block_size, &n_read); if (r < 0) { fprintf(stderr, "WARNING: sync read failed.\n"); return; } if ((uint32_t)n_read < out_block_size) { fprintf(stderr, "Short read, samples lost, exiting!\n"); return; } // calculate fft of buffer uint32_t N = out_block_size/2; int i; for(i = 0 ; i < N ; i++) { fftw_in[i][0] = (buffer[i*2] -127) * 0.008; // adc is 8 bits, map (0,255) to (-1,1) fftw_in[i][1] = (buffer[i*2 +1] -127) * 0.008; } fftw_execute(fftw_p); //fprintf(stderr, "%d\n", n_read); //fprintf(stderr, "%3d: %d %d %d %d %d %d %d %d %d %d\n", line_idx, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9] ); //fprintf(stderr, "%3d: %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f\n", line_idx, fftw_in[0][0], fftw_in[0][1], fftw_in[1][0], fftw_in[1][1], fftw_in[2][0], fftw_in[2][1], fftw_in[3][0], fftw_in[3][1], fftw_in[4][0], fftw_in[4][1] ); //fprintf(stderr, "%3d: %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f\n", line_idx, fftw_out[0][0], fftw_out[0][1], fftw_out[1][0], fftw_out[1][1], fftw_out[2][0], fftw_out[2][1], fftw_out[3][0], fftw_out[3][1], fftw_out[4][0], fftw_out[4][1] ); // put fft on screen // x = index of pixel on screen, n_avg is number of fft bins that have to be averaged in one pixel int n_avg = N / GLUT_BUFSIZE; float pwr, color_idx, color_blue, color_green, color_red; int x, p; for(x = 0 ; x < GLUT_BUFSIZE ; x++) { pwr = 0.0f; for(p = 0 ; p < n_avg ; p++) pwr += (fftw_out[(x*n_avg) +p][0] * fftw_out[(x*n_avg) +p][0]) + (fftw_out[(x*n_avg) +p][1] * fftw_out[(x*n_avg) +p][1]); pwr /= (n_avg * (N/2)); // scale colors to power in spectrum if(pwr > pwr_max) pwr_max = pwr; color_idx = pwr/pwr_diff; //color_idx = (float)x/(float)GLUT_BUFSIZE; if(color_idx < 1) { //color_blue = (sin((color_idx * 3.1415f) + 1.5708) +1)/2; //color_green = sin(color_idx * 3.1415f); //color_red = (sin((color_idx * 3.1415f) - 1.5708) +1)/2; color_blue = exp( -((color_idx - 0.1) / .3) * ((color_idx - 0.1) / .3) ); color_green = exp( -((color_idx - 0.35) / .5) * ((color_idx - 0.35) / .5) ); color_red = exp( -((color_idx - .95) / .3) * ((color_idx - .95) / .3) ); } else { color_blue = 0.0f; color_green = 0.0f; color_red = 1.0f; } // negative frequencies are in [N/2,N] and positive in [0,N/2] int xN; if(x < (GLUT_BUFSIZE/2)) xN = x + GLUT_BUFSIZE/2; else xN = x - GLUT_BUFSIZE/2; texture[xN][GLUT_BUFSIZE-line_idx-1][0] = color_red; texture[xN][GLUT_BUFSIZE-line_idx-1][1] = color_green; texture[xN][GLUT_BUFSIZE-line_idx-1][2] = color_blue; // when using line_idx == GLUT_BUFSIZE/2 in the first if statement the fft should be drawn twice texture[xN][(GLUT_BUFSIZE/2)-line_idx-1][0] = color_red; texture[xN][(GLUT_BUFSIZE/2)-line_idx-1][1] = color_green; texture[xN][(GLUT_BUFSIZE/2)-line_idx-1][2] = color_blue; } //fprintf(stderr, "%.2f\n", pwr_max); glutPostRedisplay(); glutTimerFunc(0,readData,++line_idx); }