int rtlsdr_verbose_direct_sampling(rtlsdr_dev_t *dev, int on) { int r; r = rtlsdr_set_direct_sampling(dev, on); if (r != 0) { fprintf(stderr, "WARNING: Failed to set direct sampling mode.\n"); return r; } if (on == 0) { fprintf(stderr, "Direct sampling mode disabled.\n");} if (on == 1) { fprintf(stderr, "Enabled direct sampling mode, input 1/I.\n");} if (on == 2) { fprintf(stderr, "Enabled direct sampling mode, input 2/Q.\n");} return r; }
int rtlsdr_open2(rtlsdr_dev_t **out_dev, int fd, const char * devicePath) { int r; rtlsdr_dev_t *dev = NULL; libusb_device *device = NULL; uint8_t reg; dev = malloc(sizeof(rtlsdr_dev_t)); if (NULL == dev) return -ENOMEM; memset(dev, 0, sizeof(rtlsdr_dev_t)); memcpy(dev->fir, fir_default, sizeof(fir_default)); int status = libusb_init(&dev->ctx); if (status != LIBUSB_SUCCESS) return status; else if (dev->ctx == NULL) return LIBUSB_ERROR_OTHER; dev->dev_lost = 1; device = libusb_get_device2(dev->ctx, devicePath); if (!device) { r = -1; goto err; } r = libusb_open2(device, &dev->devh, fd); if (libusb_kernel_driver_active(dev->devh, 0) == 1) { dev->driver_active = 1; #ifdef DETACH_KERNEL_DRIVER if (!libusb_detach_kernel_driver(dev->devh, 0)) { fprintf(stderr, "Detached kernel driver\n"); } else { fprintf(stderr, "Detaching kernel driver failed!"); goto err; } #else LOGI("ERROR: \nKernel driver is active, or device is " "claimed by second instance of librtlsdr." "\nIn the first case, please either detach" " or blacklist the kernel module\n" "(dvb_usb_rtl28xxu), or enable automatic" " detaching at compile time.\n\n"); #endif } r = libusb_claim_interface(dev->devh, 0); if (r < 0) { LOGI("ERROR: usb_claim_interface error %d\n", r); goto err; } dev->rtl_xtal = DEF_RTL_XTAL_FREQ; /* perform a dummy write, if it fails, reset the device */ if (rtlsdr_write_reg(dev, USBB, USB_SYSCTL, 0x09, 1) < 0) { LOGI("ERROR: Resetting device...\n"); libusb_reset_device(dev->devh); } rtlsdr_init_baseband(dev); dev->dev_lost = 0; /* Probe tuners */ rtlsdr_set_i2c_repeater(dev, 1); reg = rtlsdr_i2c_read_reg(dev, E4K_I2C_ADDR, E4K_CHECK_ADDR); if (reg == E4K_CHECK_VAL) { LOGI("ERROR: Found Elonics E4000 tuner\n"); dev->tuner_type = RTLSDR_TUNER_E4000; goto found; } reg = rtlsdr_i2c_read_reg(dev, FC0013_I2C_ADDR, FC0013_CHECK_ADDR); if (reg == FC0013_CHECK_VAL) { LOGI("ERROR: Found Fitipower FC0013 tuner\n"); dev->tuner_type = RTLSDR_TUNER_FC0013; goto found; } reg = rtlsdr_i2c_read_reg(dev, R820T_I2C_ADDR, R82XX_CHECK_ADDR); if (reg == R82XX_CHECK_VAL) { LOGI("ERROR: Found Rafael Micro R820T tuner\n"); dev->tuner_type = RTLSDR_TUNER_R820T; goto found; } reg = rtlsdr_i2c_read_reg(dev, R828D_I2C_ADDR, R82XX_CHECK_ADDR); if (reg == R82XX_CHECK_VAL) { LOGI("ERROR: Found Rafael Micro R828D tuner\n"); dev->tuner_type = RTLSDR_TUNER_R828D; goto found; } /* initialise GPIOs */ rtlsdr_set_gpio_output(dev, 5); /* reset tuner before probing */ rtlsdr_set_gpio_bit(dev, 5, 1); rtlsdr_set_gpio_bit(dev, 5, 0); reg = rtlsdr_i2c_read_reg(dev, FC2580_I2C_ADDR, FC2580_CHECK_ADDR); if ((reg & 0x7f) == FC2580_CHECK_VAL) { LOGI("ERROR: Found FCI 2580 tuner\n"); dev->tuner_type = RTLSDR_TUNER_FC2580; goto found; } reg = rtlsdr_i2c_read_reg(dev, FC0012_I2C_ADDR, FC0012_CHECK_ADDR); if (reg == FC0012_CHECK_VAL) { LOGI("ERROR: Found Fitipower FC0012 tuner\n"); rtlsdr_set_gpio_output(dev, 6); dev->tuner_type = RTLSDR_TUNER_FC0012; goto found; } found: /* use the rtl clock value by default */ dev->tun_xtal = dev->rtl_xtal; dev->tuner = &tuners[dev->tuner_type]; switch (dev->tuner_type) { case RTLSDR_TUNER_R828D: dev->tun_xtal = R828D_XTAL_FREQ; case RTLSDR_TUNER_R820T: /* disable Zero-IF mode */ rtlsdr_demod_write_reg(dev, 1, 0xb1, 0x1a, 1); /* only enable In-phase ADC input */ rtlsdr_demod_write_reg(dev, 0, 0x08, 0x4d, 1); /* the R82XX use 3.57 MHz IF for the DVB-T 6 MHz mode, and * 4.57 MHz for the 8 MHz mode */ rtlsdr_set_if_freq(dev, R82XX_IF_FREQ); /* enable spectrum inversion */ rtlsdr_demod_write_reg(dev, 1, 0x15, 0x01, 1); break; case RTLSDR_TUNER_UNKNOWN: LOGI("ERROR: No supported tuner found\n"); rtlsdr_set_direct_sampling(dev, 1); break; default: break; } if (dev->tuner->init) r = dev->tuner->init(dev); rtlsdr_set_i2c_repeater(dev, 0); *out_dev = dev; return 0; err: if (dev) { if (dev->ctx) libusb_exit(dev->ctx); free(dev); } return r; }
int rtlsdr_open2(rtlsdr_dev_t **out_dev, uint32_t index, int fd) { int r; int i; libusb_device **list; rtlsdr_dev_t *dev = NULL; libusb_device *device = NULL; uint32_t device_count = 0; struct libusb_device_descriptor dd; uint8_t reg; ssize_t cnt; dev = malloc(sizeof(rtlsdr_dev_t)); if (NULL == dev) return -ENOMEM; memset(dev, 0, sizeof(rtlsdr_dev_t)); libusb_init(&dev->ctx); cnt = libusb_get_device_list(dev->ctx, &list); for (i = 0; i < cnt; i++) { device = list[i]; libusb_get_device_descriptor(list[i], &dd); if (find_known_device(dd.idVendor, dd.idProduct)) { device_count++; } if (index == device_count - 1) break; device = NULL; } if (!device) { r = -1; goto err; } r = libusb_open2(device, &dev->devh, fd); if (r < 0) { libusb_free_device_list(list, 1); fprintf(stderr, "usb_open error %d\n", r); goto err; } libusb_free_device_list(list, 1); r = libusb_claim_interface(dev->devh, 0); if (r < 0) { fprintf(stderr, "usb_claim_interface error %d\n", r); goto err; } dev->rtl_xtal = DEF_RTL_XTAL_FREQ; rtlsdr_init_baseband(dev); /* Probe tuners */ rtlsdr_set_i2c_repeater(dev, 1); reg = rtlsdr_i2c_read_reg(dev, E4K_I2C_ADDR, E4K_CHECK_ADDR); if (reg == E4K_CHECK_VAL) { fprintf(stderr, "Found Elonics E4000 tuner\n"); dev->tuner_type = RTLSDR_TUNER_E4000; goto found; } reg = rtlsdr_i2c_read_reg(dev, FC0013_I2C_ADDR, FC0013_CHECK_ADDR); if (reg == FC0013_CHECK_VAL) { fprintf(stderr, "Found Fitipower FC0013 tuner\n"); dev->tuner_type = RTLSDR_TUNER_FC0013; goto found; } reg = rtlsdr_i2c_read_reg(dev, R820T_I2C_ADDR, R820T_CHECK_ADDR); if (reg == R820T_CHECK_VAL) { fprintf(stderr, "Found Rafael Micro R820T tuner\n"); dev->tuner_type = RTLSDR_TUNER_R820T; /* disable Zero-IF mode */ rtlsdr_demod_write_reg(dev, 1, 0xb1, 0x1a, 1); /* only enable In-phase ADC input */ rtlsdr_demod_write_reg(dev, 0, 0x08, 0x4d, 1); /* the R820T uses 3.57 MHz IF for the DVB-T 6 MHz mode, and * 4.57 MHz for the 8 MHz mode */ rtlsdr_set_if_freq(dev, R820T_IF_FREQ); /* enable spectrum inversion */ rtlsdr_demod_write_reg(dev, 1, 0x15, 0x01, 1); goto found; } /* initialise GPIOs */ rtlsdr_set_gpio_output(dev, 5); /* reset tuner before probing */ rtlsdr_set_gpio_bit(dev, 5, 1); rtlsdr_set_gpio_bit(dev, 5, 0); reg = rtlsdr_i2c_read_reg(dev, FC2580_I2C_ADDR, FC2580_CHECK_ADDR); if ((reg & 0x7f) == FC2580_CHECK_VAL) { fprintf(stderr, "Found FCI 2580 tuner\n"); dev->tuner_type = RTLSDR_TUNER_FC2580; goto found; } reg = rtlsdr_i2c_read_reg(dev, FC0012_I2C_ADDR, FC0012_CHECK_ADDR); if (reg == FC0012_CHECK_VAL) { fprintf(stderr, "Found Fitipower FC0012 tuner\n"); rtlsdr_set_gpio_output(dev, 6); dev->tuner_type = RTLSDR_TUNER_FC0012; goto found; } found: if (dev->tuner_type == RTLSDR_TUNER_UNKNOWN) { fprintf(stderr, "No supported tuner found\n"); rtlsdr_set_direct_sampling(dev, 1); } dev->tuner = &tuners[dev->tuner_type]; dev->tun_xtal = dev->rtl_xtal; /* use the rtl clock value by default */ if (dev->tuner->init) r = dev->tuner->init(dev); rtlsdr_set_i2c_repeater(dev, 0); *out_dev = dev; return 0; err: if (dev) { if (dev->ctx) libusb_exit(dev->ctx); free(dev); } return r; }
int main(int argc, char** argv) { uint32_t opt; int32_t rtl_result; int32_t rtl_count; char rtl_vendor[256], rtl_product[256], rtl_serial[256]; initrx_options(); initDecoder_options(); /* RX buffer allocation */ rx_state.iSamples=malloc(sizeof(float)*SIGNAL_LENGHT*SIGNAL_SAMPLE_RATE); rx_state.qSamples=malloc(sizeof(float)*SIGNAL_LENGHT*SIGNAL_SAMPLE_RATE); /* Stop condition setup */ rx_state.exit_flag = false; rx_state.decode_flag = false; uint32_t nLoop = 0; if (argc <= 1) usage(); while ((opt = getopt(argc, argv, "f:c:l:g:a:o:p:u:d:n:i:H:Q:S")) != -1) { switch (opt) { case 'f': // Frequency rx_options.dialfreq = (uint32_t)atofs(optarg); break; case 'c': // Callsign sprintf(dec_options.rcall, "%.12s", optarg); break; case 'l': // Locator / Grid sprintf(dec_options.rloc, "%.6s", optarg); break; case 'g': // Small signal amplifier gain rx_options.gain = atoi(optarg); if (rx_options.gain < 0) rx_options.gain = 0; if (rx_options.gain > 49) rx_options.gain = 49; rx_options.gain *= 10; break; case 'a': // Auto gain rx_options.autogain = atoi(optarg); if (rx_options.autogain < 0) rx_options.autogain = 0; if (rx_options.autogain > 1) rx_options.autogain = 1; break; case 'o': // Fine frequency correction rx_options.shift = atoi(optarg); break; case 'p': rx_options.ppm = atoi(optarg); break; case 'u': // Upconverter frequency rx_options.upconverter = (uint32_t)atofs(optarg); break; case 'd': // Direct Sampling rx_options.directsampling = (uint32_t)atofs(optarg); break; case 'n': // Stop after n iterations rx_options.maxloop = (uint32_t)atofs(optarg); break; case 'i': // Select the device to use rx_options.device = (uint32_t)atofs(optarg); break; case 'H': // Decoder option, use a hastable dec_options.usehashtable = 1; break; case 'Q': // Decoder option, faster dec_options.quickmode = 1; break; case 'S': // Decoder option, single pass mode (same as original wsprd) dec_options.subtraction = 0; dec_options.npasses = 1; break; default: usage(); break; } } if (rx_options.dialfreq == 0) { fprintf(stderr, "Please specify a dial frequency.\n"); fprintf(stderr, " --help for usage...\n"); exit(1); } if (dec_options.rcall[0] == 0) { fprintf(stderr, "Please specify your callsign.\n"); fprintf(stderr, " --help for usage...\n"); exit(1); } if (dec_options.rloc[0] == 0) { fprintf(stderr, "Please specify your locator.\n"); fprintf(stderr, " --help for usage...\n"); exit(1); } /* Calcule shift offset */ rx_options.realfreq = rx_options.dialfreq + rx_options.shift + rx_options.upconverter; /* Store the frequency used for the decoder */ dec_options.freq = rx_options.dialfreq; /* If something goes wrong... */ signal(SIGINT, &sigint_callback_handler); signal(SIGTERM, &sigint_callback_handler); signal(SIGILL, &sigint_callback_handler); signal(SIGFPE, &sigint_callback_handler); signal(SIGSEGV, &sigint_callback_handler); signal(SIGABRT, &sigint_callback_handler); /* Init & parameter the device */ rtl_count = rtlsdr_get_device_count(); if (!rtl_count) { fprintf(stderr, "No supported devices found\n"); return EXIT_FAILURE; } fprintf(stderr, "Found %d device(s):\n", rtl_count); for (uint32_t i=0; i<rtl_count; i++) { rtlsdr_get_device_usb_strings(i, rtl_vendor, rtl_product, rtl_serial); fprintf(stderr, " %d: %s, %s, SN: %s\n", i, rtl_vendor, rtl_product, rtl_serial); } fprintf(stderr, "\nUsing device %d: %s\n", rx_options.device, rtlsdr_get_device_name(rx_options.device)); rtl_result = rtlsdr_open(&rtl_device, rx_options.device); if (rtl_result < 0) { fprintf(stderr, "ERROR: Failed to open rtlsdr device #%d.\n", rx_options.device); return EXIT_FAILURE; } if (rx_options.directsampling) { rtl_result = rtlsdr_set_direct_sampling(rtl_device, rx_options.directsampling); if (rtl_result < 0) { fprintf(stderr, "ERROR: Failed to set direct sampling\n"); rtlsdr_close(rtl_device); return EXIT_FAILURE; } } rtl_result = rtlsdr_set_sample_rate(rtl_device, SAMPLING_RATE); if (rtl_result < 0) { fprintf(stderr, "ERROR: Failed to set sample rate\n"); rtlsdr_close(rtl_device); return EXIT_FAILURE; } rtl_result = rtlsdr_set_tuner_gain_mode(rtl_device, 1); if (rtl_result < 0) { fprintf(stderr, "ERROR: Failed to enable manual gain\n"); rtlsdr_close(rtl_device); return EXIT_FAILURE; } if (rx_options.autogain) { rtl_result = rtlsdr_set_tuner_gain_mode(rtl_device, 0); if (rtl_result != 0) { fprintf(stderr, "ERROR: Failed to set tuner gain\n"); rtlsdr_close(rtl_device); return EXIT_FAILURE; } } else { rtl_result = rtlsdr_set_tuner_gain(rtl_device, rx_options.gain); if (rtl_result != 0) { fprintf(stderr, "ERROR: Failed to set tuner gain\n"); rtlsdr_close(rtl_device); return EXIT_FAILURE; } } if (rx_options.ppm != 0) { rtl_result = rtlsdr_set_freq_correction(rtl_device, rx_options.ppm); if (rtl_result < 0) { fprintf(stderr, "ERROR: Failed to set ppm error\n"); rtlsdr_close(rtl_device); return EXIT_FAILURE; } } rtl_result = rtlsdr_set_center_freq(rtl_device, rx_options.realfreq + FS4_RATE + 1500); if (rtl_result < 0) { fprintf(stderr, "ERROR: Failed to set frequency\n"); rtlsdr_close(rtl_device); return EXIT_FAILURE; } rtl_result = rtlsdr_reset_buffer(rtl_device); if (rtl_result < 0) { fprintf(stderr, "ERROR: Failed to reset buffers.\n"); rtlsdr_close(rtl_device); return EXIT_FAILURE; } /* Print used parameter */ time_t rawtime; time ( &rawtime ); struct tm *gtm = gmtime(&rawtime); printf("\nStarting rtlsdr-wsprd (%04d-%02d-%02d, %02d:%02dz) -- Version 0.2\n", gtm->tm_year + 1900, gtm->tm_mon + 1, gtm->tm_mday, gtm->tm_hour, gtm->tm_min); printf(" Callsign : %s\n", dec_options.rcall); printf(" Locator : %s\n", dec_options.rloc); printf(" Dial freq. : %d Hz\n", rx_options.dialfreq); printf(" Real freq. : %d Hz\n", rx_options.realfreq); printf(" PPM factor : %d\n", rx_options.ppm); if(rx_options.autogain) printf(" Auto gain : enable\n"); else printf(" Gain : %d dB\n", rx_options.gain/10); /* Time alignment stuff */ struct timeval lTime; gettimeofday(&lTime, NULL); uint32_t sec = lTime.tv_sec % 120; uint32_t usec = sec * 1000000 + lTime.tv_usec; uint32_t uwait = 120000000 - usec; printf("Wait for time sync (start in %d sec)\n\n", uwait/1000000); /* Prepare a low priority param for the decoder thread */ struct sched_param param; pthread_attr_init(&dec.tattr); pthread_attr_setschedpolicy(&dec.tattr, SCHED_RR); pthread_attr_getschedparam(&dec.tattr, ¶m); param.sched_priority = 90; // = sched_get_priority_min(); pthread_attr_setschedparam(&dec.tattr, ¶m); /* Create a thread and stuff for separate decoding Info : https://computing.llnl.gov/tutorials/pthreads/ */ pthread_rwlock_init(&dec.rw, NULL); pthread_cond_init(&dec.ready_cond, NULL); pthread_mutex_init(&dec.ready_mutex, NULL); pthread_create(&dongle.thread, NULL, rtlsdr_rx, NULL); pthread_create(&dec.thread, &dec.tattr, wsprDecoder, NULL); /* Main loop : Wait, read, decode */ while (!rx_state.exit_flag && !(rx_options.maxloop && (nLoop >= rx_options.maxloop))) { /* Wait for time Sync on 2 mins */ gettimeofday(&lTime, NULL); sec = lTime.tv_sec % 120; usec = sec * 1000000 + lTime.tv_usec; uwait = 120000000 - usec + 10000; // Adding 10ms, to be sure to reach this next minute usleep(uwait); //printf("SYNC! RX started\n"); /* Use the Store the date at the begin of the frame */ time ( &rawtime ); gtm = gmtime(&rawtime); sprintf(rx_options.date,"%02d%02d%02d", gtm->tm_year - 100, gtm->tm_mon + 1, gtm->tm_mday); sprintf(rx_options.uttime,"%02d%02d", gtm->tm_hour, gtm->tm_min); /* Start to store the samples */ initSampleStorage(); while( (rx_state.exit_flag == false) && (rx_state.iqIndex < (SIGNAL_LENGHT * SIGNAL_SAMPLE_RATE) ) ) { usleep(250000); } nLoop++; } /* Stop the RX and free the blocking function */ rtlsdr_cancel_async(rtl_device); /* Close the RTL device */ rtlsdr_close(rtl_device); printf("Bye!\n"); /* Wait the thread join (send a signal before to terminate the job) */ pthread_mutex_lock(&dec.ready_mutex); pthread_cond_signal(&dec.ready_cond); pthread_mutex_unlock(&dec.ready_mutex); pthread_join(dec.thread, NULL); pthread_join(dongle.thread, NULL); /* Destroy the lock/cond/thread */ pthread_rwlock_destroy(&dec.rw); pthread_cond_destroy(&dec.ready_cond); pthread_mutex_destroy(&dec.ready_mutex); pthread_exit(NULL); return EXIT_SUCCESS; }