|
|
|
@ -53,8 +53,13 @@ static int do_exit = 0; |
|
|
|
|
static rtlsdr_dev_t *dev = NULL; |
|
|
|
|
|
|
|
|
|
static int ppm_benchmark = 0; |
|
|
|
|
static int ppm_running = 0; |
|
|
|
|
static int64_t ppm_count = 0L; |
|
|
|
|
static int64_t ppm_total = 0L; |
|
|
|
|
uint32_t samp_rate = DEFAULT_SAMPLE_RATE; |
|
|
|
|
|
|
|
|
|
long total_samples; |
|
|
|
|
long dropped_samples; |
|
|
|
|
|
|
|
|
|
#ifndef _WIN32 |
|
|
|
|
static struct timespec ppm_start; |
|
|
|
@ -103,17 +108,15 @@ static void sighandler(int signum) |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) |
|
|
|
|
static void underrun_test(unsigned char *buf, uint32_t len, int mute) |
|
|
|
|
{ |
|
|
|
|
uint32_t i, lost = 0; |
|
|
|
|
int64_t ns; |
|
|
|
|
static uint8_t bcnt, uninit = 1; |
|
|
|
|
|
|
|
|
|
if (uninit) { |
|
|
|
|
bcnt = buf[0]; |
|
|
|
|
uninit = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) { |
|
|
|
|
if(bcnt != buf[i]) { |
|
|
|
|
lost += (buf[i] > bcnt) ? (buf[i] - bcnt) : (bcnt - buf[i]); |
|
|
|
@ -123,12 +126,43 @@ static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) |
|
|
|
|
bcnt++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
total_samples += (long)len; |
|
|
|
|
dropped_samples += (long)lost; |
|
|
|
|
if (mute) |
|
|
|
|
return; |
|
|
|
|
if (lost) |
|
|
|
|
printf("lost at least %d bytes\n", lost); |
|
|
|
|
|
|
|
|
|
if (!ppm_benchmark) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void ppm_clock_init(void) |
|
|
|
|
{ |
|
|
|
|
#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 |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int ppm_report(void) |
|
|
|
|
{ |
|
|
|
|
int real_rate; |
|
|
|
|
int64_t ns; |
|
|
|
|
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); |
|
|
|
|
return (int)round((double)(1000000 * (real_rate - (int)samp_rate)) / (double)samp_rate); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void ppm_test(uint32_t len) |
|
|
|
|
{ |
|
|
|
|
int64_t ns; |
|
|
|
|
|
|
|
|
|
ppm_count += (int64_t)len; |
|
|
|
|
#ifndef _WIN32 |
|
|
|
|
#ifndef __APPLE__ |
|
|
|
@ -141,7 +175,7 @@ static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) |
|
|
|
|
if (ppm_now.tv_sec - ppm_recent.tv_sec > PPM_DURATION) { |
|
|
|
|
ns = 1000000000L * (int64_t)(ppm_now.tv_sec - ppm_recent.tv_sec); |
|
|
|
|
ns += (int64_t)(ppm_now.tv_nsec - ppm_recent.tv_nsec); |
|
|
|
|
printf("real sample rate: %i\n", |
|
|
|
|
printf("real sample rate: %i", |
|
|
|
|
(int)((1000000000L * ppm_count / 2L) / ns)); |
|
|
|
|
#ifndef __APPLE__ |
|
|
|
|
clock_gettime(CLOCK_REALTIME, &ppm_recent); |
|
|
|
@ -152,10 +186,26 @@ static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) |
|
|
|
|
#endif |
|
|
|
|
ppm_total += ppm_count / 2L; |
|
|
|
|
ppm_count = 0L; |
|
|
|
|
printf(" cumulative ppm: %i\n", ppm_report()); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) |
|
|
|
|
{ |
|
|
|
|
underrun_test(buf, len, 0); |
|
|
|
|
|
|
|
|
|
if (ppm_benchmark && !ppm_running) { |
|
|
|
|
ppm_clock_init(); |
|
|
|
|
ppm_running = 1; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (ppm_benchmark) { |
|
|
|
|
ppm_test(len); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void e4k_benchmark(void) |
|
|
|
|
{ |
|
|
|
|
uint32_t freq, gap_start = 0, gap_end = 0; |
|
|
|
@ -214,12 +264,9 @@ int main(int argc, char **argv) |
|
|
|
|
uint8_t *buffer; |
|
|
|
|
int dev_index = 0; |
|
|
|
|
int dev_given = 0; |
|
|
|
|
uint32_t samp_rate = DEFAULT_SAMPLE_RATE; |
|
|
|
|
uint32_t out_block_size = DEFAULT_BUF_LENGTH; |
|
|
|
|
int count; |
|
|
|
|
int gains[100]; |
|
|
|
|
int real_rate; |
|
|
|
|
int64_t ns; |
|
|
|
|
|
|
|
|
|
while ((opt = getopt(argc, argv, "d:s:b:tpS::")) != -1) { |
|
|
|
|
switch (opt) { |
|
|
|
@ -314,16 +361,6 @@ int main(int argc, char **argv) |
|
|
|
|
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) { |
|
|
|
@ -335,6 +372,7 @@ int main(int argc, char **argv) |
|
|
|
|
|
|
|
|
|
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) { |
|
|
|
@ -346,6 +384,7 @@ int main(int argc, char **argv) |
|
|
|
|
fprintf(stderr, "Short read, samples lost, exiting!\n"); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
underrun_test(buffer, n_read, 1); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
fprintf(stderr, "Reading samples in async mode...\n"); |
|
|
|
@ -355,15 +394,12 @@ int main(int argc, char **argv) |
|
|
|
|
|
|
|
|
|
if (do_exit) { |
|
|
|
|
fprintf(stderr, "\nUser cancel, exiting...\n"); |
|
|
|
|
if (ppm_benchmark) { |
|
|
|
|
fprintf(stderr, "Samples per million lost (minimum): %i\n", (int)(1000000L * dropped_samples / total_samples)); |
|
|
|
|
#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 |
|
|
|
|
if (ppm_benchmark) { |
|
|
|
|
printf("Cumulative PPM error: %i\n", ppm_report()); |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
fprintf(stderr, "\nLibrary error %d, exiting...\n", r); |
|
|
|
|