rtl_test: add ppm measurement

Use with caution, the result highly depends on the
accuracy of the clocksource your machine uses.
On some machines it may be quite accurate, on
others completely off.

Signed-off-by: Steve Markgraf <steve@steve-m.de>
master
Kyle Keen 12 years ago committed by Steve Markgraf
parent ed449bc04d
commit 995a195f4d
  1. 3
      configure.ac
  2. 5
      src/CMakeLists.txt
  3. 2
      src/Makefile.am
  4. 92
      src/rtl_test.c

@ -39,6 +39,9 @@ AC_CHECK_LIB(pthread, pthread_create, [LIBS="$LIBS -lpthread"])
dnl libmath (for rtl_fm) dnl libmath (for rtl_fm)
AC_CHECK_LIB(m, atan2, [LIBS="$LIBS -lm"]) AC_CHECK_LIB(m, atan2, [LIBS="$LIBS -lm"])
dnl librealtime (for rtl_test)
AC_CHECK_LIB(rt, clock_gettime, [LIBS="$LIBS"])
# The following test is taken from WebKit's webkit.m4 # The following test is taken from WebKit's webkit.m4
saved_CFLAGS="$CFLAGS" saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -fvisibility=hidden " CFLAGS="$CFLAGS -fvisibility=hidden "

@ -94,6 +94,11 @@ target_link_libraries(rtl_fm rtlsdr_shared
${CMAKE_THREAD_LIBS_INIT} ${CMAKE_THREAD_LIBS_INIT}
m m
) )
if(APPLE)
target_link_libraries(rtl_test m)
else()
target_link_libraries(rtl_test m rt)
endif()
endif() endif()
if(WIN32) if(WIN32)

@ -19,7 +19,7 @@ rtl_tcp_SOURCES = rtl_tcp.c
rtl_tcp_LDADD = librtlsdr.la rtl_tcp_LDADD = librtlsdr.la
rtl_test_SOURCES = rtl_test.c rtl_test_SOURCES = rtl_test.c
rtl_test_LDADD = librtlsdr.la rtl_test_LDADD = librtlsdr.la $(LIBM)
rtl_fm_SOURCES = rtl_fm.c rtl_fm_SOURCES = rtl_fm.c
rtl_fm_LDADD = librtlsdr.la $(LIBM) rtl_fm_LDADD = librtlsdr.la $(LIBM)

@ -21,6 +21,13 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <math.h>
#ifdef __APPLE__
#include <sys/time.h>
#else
#include <time.h>
#endif
#ifndef _WIN32 #ifndef _WIN32
#include <unistd.h> #include <unistd.h>
@ -39,9 +46,25 @@
#define MHZ(x) ((x)*1000*1000) #define MHZ(x) ((x)*1000*1000)
#define PPM_DURATION 10
static int do_exit = 0; static int do_exit = 0;
static rtlsdr_dev_t *dev = NULL; static rtlsdr_dev_t *dev = NULL;
static int ppm_benchmark = 0;
static int64_t ppm_count = 0L;
static int64_t ppm_total = 0L;
#ifndef _WIN32
static struct timespec ppm_start;
static struct timespec ppm_recent;
static struct timespec ppm_now;
#endif
#ifdef __APPLE__
static struct timeval tv;
#endif
void usage(void) void usage(void)
{ {
fprintf(stderr, fprintf(stderr,
@ -50,6 +73,9 @@ void usage(void)
"\t[-s samplerate (default: 2048000 Hz)]\n" "\t[-s samplerate (default: 2048000 Hz)]\n"
"\t[-d device_index (default: 0)]\n" "\t[-d device_index (default: 0)]\n"
"\t[-t enable Elonics E4000 tuner benchmark]\n" "\t[-t enable Elonics E4000 tuner benchmark]\n"
#ifndef _WIN32
"\t[-p enable PPM error measurement]\n"
#endif
"\t[-b output_block_size (default: 16 * 16384)]\n" "\t[-b output_block_size (default: 16 * 16384)]\n"
"\t[-S force sync output (default: async)]\n"); "\t[-S force sync output (default: async)]\n");
exit(1); exit(1);
@ -81,6 +107,8 @@ uint8_t bcnt, uninit = 1;
static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx)
{ {
uint32_t i, lost = 0; uint32_t i, lost = 0;
int64_t ns;
double perf_sec;
if (uninit) { if (uninit) {
bcnt = buf[0]; bcnt = buf[0];
@ -98,6 +126,35 @@ static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx)
if (lost) if (lost)
printf("lost at least %d bytes\n", lost); printf("lost at least %d bytes\n", lost);
if (!ppm_benchmark) {
return;
}
ppm_count += (int64_t)len;
#ifndef _WIN32
#ifndef __APPLE__
clock_gettime(CLOCK_REALTIME, &ppm_now);
#else
gettimeofday(&tv, NULL);
ppm_now.tv_sec = tv.tv_sec;
ppm_now.tv_nsec = tv.tv_usec*1000;
#endif
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",
(int)((1000000000L * ppm_count / 2L) / ns));
#ifndef __APPLE__
clock_gettime(CLOCK_REALTIME, &ppm_recent);
#else
gettimeofday(&tv, NULL);
ppm_recent.tv_sec = tv.tv_sec;
ppm_recent.tv_nsec = tv.tv_usec*1000;
#endif
ppm_total += ppm_count / 2L;
ppm_count = 0L;
}
#endif
} }
void e4k_benchmark(void) void e4k_benchmark(void)
@ -162,8 +219,11 @@ int main(int argc, char **argv)
int device_count; int device_count;
int count; int count;
int gains[100]; int gains[100];
int real_rate;
int64_t ns;
double perf_sec;
while ((opt = getopt(argc, argv, "d:s:b:tS::")) != -1) { while ((opt = getopt(argc, argv, "d:s:b:tpS::")) != -1) {
switch (opt) { switch (opt) {
case 'd': case 'd':
dev_index = atoi(optarg); dev_index = atoi(optarg);
@ -177,6 +237,9 @@ int main(int argc, char **argv)
case 't': case 't':
tuner_benchmark = 1; tuner_benchmark = 1;
break; break;
case 'p':
ppm_benchmark = PPM_DURATION;
break;
case 'S': case 'S':
sync_mode = 1; sync_mode = 1;
break; break;
@ -260,6 +323,21 @@ int main(int argc, char **argv)
if (r < 0) if (r < 0)
fprintf(stderr, "WARNING: Failed to reset buffers.\n"); 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 (sync_mode) { if (sync_mode) {
fprintf(stderr, "Reading samples in sync mode...\n"); fprintf(stderr, "Reading samples in sync mode...\n");
while (!do_exit) { while (!do_exit) {
@ -280,8 +358,18 @@ int main(int argc, char **argv)
DEFAULT_ASYNC_BUF_NUMBER, out_block_size); DEFAULT_ASYNC_BUF_NUMBER, out_block_size);
} }
if (do_exit) if (do_exit) {
fprintf(stderr, "\nUser cancel, exiting...\n"); 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 else
fprintf(stderr, "\nLibrary error %d, exiting...\n", r); fprintf(stderr, "\nLibrary error %d, exiting...\n", r);

Loading…
Cancel
Save