From 50cfd95da14b37678326fdf17fe2ec18213bfb3c Mon Sep 17 00:00:00 2001 From: Helge Weissig <helgew@grajagan.org> Date: Mon, 19 Jan 2015 12:05:01 -0800 Subject: [PATCH] removed rtl-sdr files and modified CMake and autotools configurations --- .gitignore | 6 +- AUTHORS | 24 +- CMakeLists.txt | 75 +- Doxyfile.in | 4 +- Makefile.am | 8 +- cmake/Modules/FindLibRTLSDR.cmake | 28 + cmake/Modules/FindLibUSB.cmake | 28 - cmake/Modules/FindThreads.cmake | 246 --- configure.ac | 26 +- include/CMakeLists.txt | 4 +- include/Makefile.am | 6 +- include/reg_field.h | 60 - include/rtl-sdr.h | 366 ---- include/rtl-sdr_export.h | 47 - include/rtlsdr_i2c.h | 8 - include/tuner_e4k.h | 224 --- include/tuner_fc0012.h | 36 - include/tuner_fc0013.h | 37 - include/tuner_fc2580.h | 127 -- include/tuner_r820t.h | 196 -- librtlsdr.pc.in | 11 - rtl-sdr.rules | 101 - rtl433.pc.in | 9 + src/CMakeLists.txt | 122 +- src/Makefile.am | 45 +- src/librtlsdr.c | 1698 ---------------- src/rtl_adsb.c | 512 ----- src/rtl_eeprom.c | 423 ---- src/rtl_fm.c | 838 -------- src/rtl_sdr.c | 297 --- src/rtl_tcp.c | 604 ------ src/rtl_test.c | 379 ---- src/tuner_e4k.c | 978 --------- src/tuner_fc0012.c | 345 ---- src/tuner_fc0013.c | 500 ----- src/tuner_fc2580.c | 494 ----- src/tuner_r820t.c | 3050 ----------------------------- 37 files changed, 109 insertions(+), 11853 deletions(-) create mode 100644 cmake/Modules/FindLibRTLSDR.cmake delete mode 100644 cmake/Modules/FindLibUSB.cmake delete mode 100644 cmake/Modules/FindThreads.cmake delete mode 100644 include/reg_field.h delete mode 100644 include/rtl-sdr.h delete mode 100644 include/rtl-sdr_export.h delete mode 100644 include/rtlsdr_i2c.h delete mode 100644 include/tuner_e4k.h delete mode 100644 include/tuner_fc0012.h delete mode 100644 include/tuner_fc0013.h delete mode 100644 include/tuner_fc2580.h delete mode 100644 include/tuner_r820t.h delete mode 100644 librtlsdr.pc.in delete mode 100644 rtl-sdr.rules create mode 100644 rtl433.pc.in delete mode 100644 src/librtlsdr.c delete mode 100644 src/rtl_adsb.c delete mode 100644 src/rtl_eeprom.c delete mode 100644 src/rtl_fm.c delete mode 100644 src/rtl_sdr.c delete mode 100644 src/rtl_tcp.c delete mode 100644 src/rtl_test.c delete mode 100644 src/tuner_e4k.c delete mode 100644 src/tuner_fc0012.c delete mode 100644 src/tuner_fc0013.c delete mode 100644 src/tuner_fc2580.c delete mode 100644 src/tuner_r820t.c diff --git a/.gitignore b/.gitignore index 55821f1f..c95e2551 100644 --- a/.gitignore +++ b/.gitignore @@ -17,6 +17,7 @@ config.log config.status config.guess configure +compile depcomp missing ltmain.sh @@ -24,7 +25,7 @@ install-sh stamp-h1 libtool Doxyfile -build +.dirstamp .tarball-version .version @@ -37,9 +38,6 @@ src/rtl_sdr src/rtl_tcp CMakeCache.txt -*/CMakeFiles -CMakeFiles -*.cmake build/ .cproject diff --git a/AUTHORS b/AUTHORS index 36da22ff..8bb30cef 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,4 +1,20 @@ -Steve Markgraf <steve@steve-m.de> -Dimitri Stolnikov <horiz0n@gmx.net> -Hoernchen <la@tfc-server.de> -Kyle Keen <keenerd@gmail.com> +Benjamin Larsson <benjamin@southpole.se> +Sven Killig <sven@killig.de> +Benjamin Larsson <banan@ludd.ltu.se> +rct <rct+github@r-t.org> +johan <johan@E6410> +Thomas Kerpe <toke@toke.de> +Jens Jensen <zerog2k@yahoo.com> +Sven <sonic@sonic-VGN-Z41WD-B.(none)> +Martin Hauke <mardnh@gmx.de> +magellannh <pi@raspberrypi.(none)> +jules69350 <julien.sangouard@gmail.com> +arantius <arantius@gmail.com> +andreaaizza <andrea@andreaaizza.com> +Trueffelwurm <jens@trueffelwurm.de> +Tomasz Brzezina <tombrz@Bonawentura.brzezina.pl> +Paul F-Y <pbfy00@gmail.com> +CornĂ© van Strien <github@atilas.nl> +Baruch Even <baruch@ev-en.org> +Andrea <andrea@andreaaizza.com> +Helge Weissig <helgew@grajagan.org> diff --git a/CMakeLists.txt b/CMakeLists.txt index 61ceb084..a5542e10 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,4 @@ -# Copyright 2012 OSMOCOM Project -# -# This file is part of rtl-sdr -# -# GNU Radio is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3, or (at your option) -# any later version. -# -# GNU Radio is distributed in the hope that it will be useful, +# rtl_433 is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. @@ -22,7 +13,9 @@ # Project setup ######################################################################## cmake_minimum_required(VERSION 2.6) -project(rtlsdr C) +project(rtl433 C) +set (rtl433_VERSION_MAJOR 1) +set (rtl433_VERSION_MINOR 0) #select the release build type by default to get optimization flags if(NOT CMAKE_BUILD_TYPE) @@ -50,32 +43,16 @@ endif() # Find build dependencies ######################################################################## find_package(PkgConfig) -find_package(LibUSB) -set(THREADS_USE_PTHREADS_WIN32 true) -find_package(Threads) +find_package(LibRTLSDR) -if(NOT LIBUSB_FOUND) - message(FATAL_ERROR "LibUSB 1.0 required to compile rtl-sdr") -endif() -if(NOT THREADS_FOUND) - message(FATAL_ERROR "pthreads(-win32) required to compile rtl-sdr") -endif() ######################################################################## # Setup the include and linker paths ######################################################################## include_directories( ${CMAKE_SOURCE_DIR}/include - ${LIBUSB_INCLUDE_DIR} - ${THREADS_PTHREADS_INCLUDE_DIR} + ${LIBRTLSDR_INCLUDE_DIRS} ) -#link_directories( -# ... -#) - -# Set component parameters -#set(INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/include CACHE INTERNAL "" FORCE) - ######################################################################## # Create uninstall target ######################################################################## @@ -88,45 +65,20 @@ add_custom_target(uninstall ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake ) -######################################################################## -# Install udev rules -######################################################################## -option(INSTALL_UDEV_RULES "Install udev rules for RTL-SDR" OFF) -if (INSTALL_UDEV_RULES) - install ( - FILES rtl-sdr.rules - DESTINATION "/etc/udev/rules.d" - COMPONENT "udev" - ) -else (INSTALL_UDEV_RULES) - message (STATUS "Udev rules not being installed, install them with -DINSTALL_UDEV_RULES=ON") -endif (INSTALL_UDEV_RULES) - ######################################################################## # Add subdirectories ######################################################################## add_subdirectory(include) add_subdirectory(src) -######################################################################## -# Create Pkg Config File -######################################################################## -FOREACH(inc ${LIBUSB_INCLUDE_DIR}) - LIST(APPEND RTLSDR_PC_CFLAGS "-I${inc}") -ENDFOREACH(inc) - -FOREACH(lib ${LIBUSB_LIBRARY_DIRS}) - LIST(APPEND RTLSDR_PC_LIBS "-L${lib}") -ENDFOREACH(lib) - # use space-separation format for the pc file -STRING(REPLACE ";" " " RTLSDR_PC_CFLAGS "${RTLSDR_PC_CFLAGS}") -STRING(REPLACE ";" " " RTLSDR_PC_LIBS "${RTLSDR_PC_LIBS}") +STRING(REPLACE ";" " " RTL433_PC_CFLAGS "${RTL433_PC_CFLAGS}") +STRING(REPLACE ";" " " RTL433_PC_LIBS "${RTL433_PC_LIBS}") # unset these vars to avoid hard-coded paths to cross environment IF(CMAKE_CROSSCOMPILING) - UNSET(RTLSDR_PC_CFLAGS) - UNSET(RTLSDR_PC_LIBS) + UNSET(RTL433_PC_CFLAGS) + UNSET(RTL433_PC_LIBS) ENDIF(CMAKE_CROSSCOMPILING) set(prefix ${CMAKE_INSTALL_PREFIX}) @@ -134,12 +86,7 @@ set(exec_prefix \${prefix}) set(libdir \${exec_prefix}/lib) set(includedir \${prefix}/include) -CONFIGURE_FILE( - ${CMAKE_CURRENT_SOURCE_DIR}/librtlsdr.pc.in - ${CMAKE_CURRENT_BINARY_DIR}/librtlsdr.pc -@ONLY) - INSTALL( - FILES ${CMAKE_CURRENT_BINARY_DIR}/librtlsdr.pc + FILES DESTINATION lib/pkgconfig ) diff --git a/Doxyfile.in b/Doxyfile.in index 9278d4e1..e1b6d84e 100644 --- a/Doxyfile.in +++ b/Doxyfile.in @@ -25,7 +25,7 @@ DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. -PROJECT_NAME = librtlsdr +PROJECT_NAME = rtl433 # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or @@ -37,7 +37,7 @@ PROJECT_NUMBER = @VERSION@ # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. -PROJECT_BRIEF = "RTL-SDR library" +PROJECT_BRIEF = "RTL-433 utility" # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not diff --git a/Makefile.am b/Makefile.am index 2ffa5320..520d3f08 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,7 +5,7 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include SUBDIRS = include src pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = librtlsdr.pc +pkgconfig_DATA = rtl433.pc BUILT_SOURCES = $(top_srcdir)/.version $(top_srcdir)/.version: @@ -13,12 +13,6 @@ $(top_srcdir)/.version: dist-hook: echo $(VERSION) > $(distdir)/.tarball-version -install-udev-rules: - $(INSTALL_DATA) rtl-sdr.rules /etc/udev/rules.d - -uninstall-udev-rules: - rm -rf /etc/udev/rules.d/rtl-sdr.rules - EXTRA_DIST = git-version-gen if HAVE_DOXYGEN diff --git a/cmake/Modules/FindLibRTLSDR.cmake b/cmake/Modules/FindLibRTLSDR.cmake new file mode 100644 index 00000000..ea63daa3 --- /dev/null +++ b/cmake/Modules/FindLibRTLSDR.cmake @@ -0,0 +1,28 @@ +INCLUDE(FindPkgConfig) +if(NOT LIBRTLSDR_FOUND) + pkg_check_modules (LIBRTLSDR_PKG librtlsdr) + find_path(LIBRTLSDR_INCLUDE_DIRS NAMES rtl-sdr.h + PATHS + ${LIBRTLSDR_PKG_INCLUDE_DIRS} + /usr/include + /usr/local/include + ) + + find_library(LIBRTLSDR_LIBRARIES NAMES rtlsdr + PATHS + ${LIBRTLSDR_PKG_LIBRARY_DIRS} + /usr/lib + /usr/local/lib + ) + +if(LIBRTLSDR_INCLUDE_DIRS AND LIBRTLSDR_LIBRARIES) + set(LIBRTLSDR_FOUND TRUE CACHE INTERNAL "librtlsdr found") + message(STATUS "Found librtlsdr: ${LIBRTLSDR_INCLUDE_DIRS}, ${LIBRTLSDR_LIBRARIES}") +else(LIBRTLSDR_INCLUDE_DIRS AND LIBRTLSDR_LIBRARIES) + set(LIBRTLSDR_FOUND FALSE CACHE INTERNAL "librtlsdr found") + message(STATUS "librtlsdr not found.") +endif(LIBRTLSDR_INCLUDE_DIRS AND LIBRTLSDR_LIBRARIES) + +mark_as_advanced(LIBRTLSDR_LIBRARIES LIBRTLSDR_INCLUDE_DIRS) + +endif(NOT LIBRTLSDR_FOUND) diff --git a/cmake/Modules/FindLibUSB.cmake b/cmake/Modules/FindLibUSB.cmake deleted file mode 100644 index 97f3db67..00000000 --- a/cmake/Modules/FindLibUSB.cmake +++ /dev/null @@ -1,28 +0,0 @@ -if(NOT LIBUSB_FOUND) - pkg_check_modules (LIBUSB_PKG libusb-1.0) - find_path(LIBUSB_INCLUDE_DIR NAMES libusb.h - PATHS - ${LIBUSB_PKG_INCLUDE_DIRS} - /usr/include/libusb-1.0 - /usr/include - /usr/local/include - ) - - find_library(LIBUSB_LIBRARIES NAMES usb-1.0 - PATHS - ${LIBUSB_PKG_LIBRARY_DIRS} - /usr/lib - /usr/local/lib - ) - -if(LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES) - set(LIBUSB_FOUND TRUE CACHE INTERNAL "libusb-1.0 found") - message(STATUS "Found libusb-1.0: ${LIBUSB_INCLUDE_DIR}, ${LIBUSB_LIBRARIES}") -else(LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES) - set(LIBUSB_FOUND FALSE CACHE INTERNAL "libusb-1.0 found") - message(STATUS "libusb-1.0 not found.") -endif(LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES) - -mark_as_advanced(LIBUSB_INCLUDE_DIR LIBUSB_LIBRARIES) - -endif(NOT LIBUSB_FOUND) diff --git a/cmake/Modules/FindThreads.cmake b/cmake/Modules/FindThreads.cmake deleted file mode 100644 index 8028b158..00000000 --- a/cmake/Modules/FindThreads.cmake +++ /dev/null @@ -1,246 +0,0 @@ -# Updated FindThreads.cmake that supports pthread-win32 -# Downloaded from http://www.vtk.org/Bug/bug_view_advanced_page.php?bug_id=6399 - -# - This module determines the thread library of the system. -# -# The following variables are set -# CMAKE_THREAD_LIBS_INIT - the thread library -# CMAKE_USE_SPROC_INIT - are we using sproc? -# CMAKE_USE_WIN32_THREADS_INIT - using WIN32 threads? -# CMAKE_USE_PTHREADS_INIT - are we using pthreads -# CMAKE_HP_PTHREADS_INIT - are we using hp pthreads -# -# If use of pthreads-win32 is desired, the following variables -# can be set. -# -# THREADS_USE_PTHREADS_WIN32 - -# Setting this to true searches for the pthreads-win32 -# port (since CMake 2.8.0) -# -# THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME -# C = no exceptions (default) -# (NOTE: This is the default scheme on most POSIX thread -# implementations and what you should probably be using) -# CE = C++ Exception Handling -# SE = Structure Exception Handling (MSVC only) -# (NOTE: Changing this option from the default may affect -# the portability of your application. See pthreads-win32 -# documentation for more details.) -# -#====================================================== -# Example usage where threading library -# is provided by the system: -# -# find_package(Threads REQUIRED) -# add_executable(foo foo.cc) -# target_link_libraries(foo ${CMAKE_THREAD_LIBS_INIT}) -# -# Example usage if pthreads-win32 is desired on Windows -# or a system provided thread library: -# -# set(THREADS_USE_PTHREADS_WIN32 true) -# find_package(Threads REQUIRED) -# include_directories(${THREADS_PTHREADS_INCLUDE_DIR}) -# -# add_executable(foo foo.cc) -# target_link_libraries(foo ${CMAKE_THREAD_LIBS_INIT}) -# - -INCLUDE (CheckIncludeFiles) -INCLUDE (CheckLibraryExists) -SET(Threads_FOUND FALSE) - -IF(WIN32 AND NOT CYGWIN AND THREADS_USE_PTHREADS_WIN32) - SET(_Threads_ptwin32 true) -ENDIF() - -# Do we have sproc? -IF(CMAKE_SYSTEM MATCHES IRIX) - CHECK_INCLUDE_FILES("sys/types.h;sys/prctl.h" CMAKE_HAVE_SPROC_H) -ENDIF() - -IF(CMAKE_HAVE_SPROC_H) - # We have sproc - SET(CMAKE_USE_SPROC_INIT 1) - -ELSEIF(_Threads_ptwin32) - - IF(NOT DEFINED THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME) - # Assign the default scheme - SET(THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME "C") - ELSE() - # Validate the scheme specified by the user - IF(NOT THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "C" AND - NOT THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "CE" AND - NOT THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "SE") - MESSAGE(FATAL_ERROR "See documentation for FindPthreads.cmake, only C, CE, and SE modes are allowed") - ENDIF() - IF(NOT MSVC AND THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "SE") - MESSAGE(FATAL_ERROR "Structured Exception Handling is only allowed for MSVC") - ENDIF(NOT MSVC AND THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME STREQUAL "SE") - ENDIF() - - FIND_PATH(THREADS_PTHREADS_INCLUDE_DIR pthread.h) - - # Determine the library filename - IF(MSVC) - SET(_Threads_pthreads_libname - pthreadV${THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME}2) - ELSEIF(MINGW) - SET(_Threads_pthreads_libname - pthreadG${THREADS_PTHREADS_WIN32_EXCEPTION_SCHEME}2) - ELSE() - MESSAGE(FATAL_ERROR "This should never happen") - ENDIF() - - # Use the include path to help find the library if possible - SET(_Threads_lib_paths "") - IF(THREADS_PTHREADS_INCLUDE_DIR) - GET_FILENAME_COMPONENT(_Threads_root_dir - ${THREADS_PTHREADS_INCLUDE_DIR} PATH) - SET(_Threads_lib_paths ${_Threads_root_dir}/lib) - ENDIF() - FIND_LIBRARY(THREADS_PTHREADS_WIN32_LIBRARY - NAMES ${_Threads_pthreads_libname} - PATHS ${_Threads_lib_paths} - DOC "The Portable Threads Library for Win32" - NO_SYSTEM_PATH - ) - - IF(THREADS_PTHREADS_INCLUDE_DIR AND THREADS_PTHREADS_WIN32_LIBRARY) - MARK_AS_ADVANCED(THREADS_PTHREADS_INCLUDE_DIR) - SET(CMAKE_THREAD_LIBS_INIT ${THREADS_PTHREADS_WIN32_LIBRARY}) - SET(CMAKE_HAVE_THREADS_LIBRARY 1) - SET(Threads_FOUND TRUE) - ENDIF() - - MARK_AS_ADVANCED(THREADS_PTHREADS_WIN32_LIBRARY) - -ELSE() - # Do we have pthreads? - CHECK_INCLUDE_FILES("pthread.h" CMAKE_HAVE_PTHREAD_H) - IF(CMAKE_HAVE_PTHREAD_H) - - # - # We have pthread.h - # Let's check for the library now. - # - SET(CMAKE_HAVE_THREADS_LIBRARY) - IF(NOT THREADS_HAVE_PTHREAD_ARG) - - # Do we have -lpthreads - CHECK_LIBRARY_EXISTS(pthreads pthread_create "" CMAKE_HAVE_PTHREADS_CREATE) - IF(CMAKE_HAVE_PTHREADS_CREATE) - SET(CMAKE_THREAD_LIBS_INIT "-lpthreads") - SET(CMAKE_HAVE_THREADS_LIBRARY 1) - SET(Threads_FOUND TRUE) - ENDIF() - - # Ok, how about -lpthread - CHECK_LIBRARY_EXISTS(pthread pthread_create "" CMAKE_HAVE_PTHREAD_CREATE) - IF(CMAKE_HAVE_PTHREAD_CREATE) - SET(CMAKE_THREAD_LIBS_INIT "-lpthread") - SET(Threads_FOUND TRUE) - SET(CMAKE_HAVE_THREADS_LIBRARY 1) - ENDIF() - - IF(CMAKE_SYSTEM MATCHES "SunOS.*") - # On sun also check for -lthread - CHECK_LIBRARY_EXISTS(thread thr_create "" CMAKE_HAVE_THR_CREATE) - IF(CMAKE_HAVE_THR_CREATE) - SET(CMAKE_THREAD_LIBS_INIT "-lthread") - SET(CMAKE_HAVE_THREADS_LIBRARY 1) - SET(Threads_FOUND TRUE) - ENDIF() - ENDIF(CMAKE_SYSTEM MATCHES "SunOS.*") - - ENDIF(NOT THREADS_HAVE_PTHREAD_ARG) - - IF(NOT CMAKE_HAVE_THREADS_LIBRARY) - # If we did not found -lpthread, -lpthread, or -lthread, look for -pthread - IF("THREADS_HAVE_PTHREAD_ARG" MATCHES "^THREADS_HAVE_PTHREAD_ARG") - MESSAGE(STATUS "Check if compiler accepts -pthread") - TRY_RUN(THREADS_PTHREAD_ARG THREADS_HAVE_PTHREAD_ARG - ${CMAKE_BINARY_DIR} - ${CMAKE_ROOT}/Modules/CheckForPthreads.c - CMAKE_FLAGS -DLINK_LIBRARIES:STRING=-pthread - COMPILE_OUTPUT_VARIABLE OUTPUT) - - IF(THREADS_HAVE_PTHREAD_ARG) - IF(THREADS_PTHREAD_ARG MATCHES "^2$") - SET(Threads_FOUND TRUE) - MESSAGE(STATUS "Check if compiler accepts -pthread - yes") - ELSE() - MESSAGE(STATUS "Check if compiler accepts -pthread - no") - FILE(APPEND - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Determining if compiler accepts -pthread returned ${THREADS_PTHREAD_ARG} instead of 2. The compiler had the following output:\n${OUTPUT}\n\n") - ENDIF() - ELSE() - MESSAGE(STATUS "Check if compiler accepts -pthread - no") - FILE(APPEND - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log - "Determining if compiler accepts -pthread failed with the following output:\n${OUTPUT}\n\n") - ENDIF() - - ENDIF("THREADS_HAVE_PTHREAD_ARG" MATCHES "^THREADS_HAVE_PTHREAD_ARG") - - IF(THREADS_HAVE_PTHREAD_ARG) - SET(Threads_FOUND TRUE) - SET(CMAKE_THREAD_LIBS_INIT "-pthread") - ENDIF() - - ENDIF(NOT CMAKE_HAVE_THREADS_LIBRARY) - ENDIF(CMAKE_HAVE_PTHREAD_H) -ENDIF() - -IF(CMAKE_THREAD_LIBS_INIT) - SET(CMAKE_USE_PTHREADS_INIT 1) - SET(Threads_FOUND TRUE) -ENDIF() - -IF(CMAKE_SYSTEM MATCHES "Windows" - AND NOT THREADS_USE_PTHREADS_WIN32) - SET(CMAKE_USE_WIN32_THREADS_INIT 1) - SET(Threads_FOUND TRUE) -ENDIF() - -IF(CMAKE_USE_PTHREADS_INIT) - IF(CMAKE_SYSTEM MATCHES "HP-UX-*") - # Use libcma if it exists and can be used. It provides more - # symbols than the plain pthread library. CMA threads - # have actually been deprecated: - # http://docs.hp.com/en/B3920-90091/ch12s03.html#d0e11395 - # http://docs.hp.com/en/947/d8.html - # but we need to maintain compatibility here. - # The CMAKE_HP_PTHREADS setting actually indicates whether CMA threads - # are available. - CHECK_LIBRARY_EXISTS(cma pthread_attr_create "" CMAKE_HAVE_HP_CMA) - IF(CMAKE_HAVE_HP_CMA) - SET(CMAKE_THREAD_LIBS_INIT "-lcma") - SET(CMAKE_HP_PTHREADS_INIT 1) - SET(Threads_FOUND TRUE) - ENDIF(CMAKE_HAVE_HP_CMA) - SET(CMAKE_USE_PTHREADS_INIT 1) - ENDIF() - - IF(CMAKE_SYSTEM MATCHES "OSF1-V*") - SET(CMAKE_USE_PTHREADS_INIT 0) - SET(CMAKE_THREAD_LIBS_INIT ) - ENDIF() - - IF(CMAKE_SYSTEM MATCHES "CYGWIN_NT*") - SET(CMAKE_USE_PTHREADS_INIT 1) - SET(Threads_FOUND TRUE) - SET(CMAKE_THREAD_LIBS_INIT ) - SET(CMAKE_USE_WIN32_THREADS_INIT 0) - ENDIF() -ENDIF(CMAKE_USE_PTHREADS_INIT) - -INCLUDE(FindPackageHandleStandardArgs) -IF(_Threads_ptwin32) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(Threads DEFAULT_MSG - THREADS_PTHREADS_WIN32_LIBRARY THREADS_PTHREADS_INCLUDE_DIR) -ELSE() - FIND_PACKAGE_HANDLE_STANDARD_ARGS(Threads DEFAULT_MSG Threads_FOUND) -ENDIF() diff --git a/configure.ac b/configure.ac index a947e804..0d32080e 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,8 @@ -AC_INIT([librtlsdr], +AC_INIT([rtl433], m4_esyscmd([./git-version-gen .tarball-version]), - [osmocom-sdr@lists.osmocom.org]) + [rtl_433@googlegroups.com]) -AM_INIT_AUTOMAKE([dist-bzip2]) +AM_INIT_AUTOMAKE([dist-bzip2 subdir-objects]) dnl kernel style compile messages m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) @@ -14,9 +14,9 @@ AC_PROG_INSTALL LT_INIT AC_PROG_LIBTOOL -PKG_CHECK_MODULES(LIBUSB, libusb-1.0 >= 1.0) -LIBS="$LIBS $LIBUSB_LIBS" -CFLAGS="$CFLAGS $LIBUSB_CFLAGS" +PKG_CHECK_MODULES(LIBRTLSDR, librtlsdr) +LIBS="$LIBS $LIBRTLSDR_LIBS" +CFLAGS="$CFLAGS $LIBRTLSDR_CFLAGS" AC_PATH_PROG(DOXYGEN,doxygen,false) AM_CONDITIONAL(HAVE_DOXYGEN, test $DOXYGEN != false) @@ -26,24 +26,12 @@ AC_CONFIG_MACRO_DIR([m4]) dnl checks for header files AC_HEADER_STDC AC_CHECK_HEADERS(sys/types.h) -AC_CHECK_HEADERS(pthread.h,, [AC_MSG_ERROR([pthread.h required])]) # pc variables AC_SUBST(RTLSDR_PC_LIBS,["$LIBS"]) AC_SUBST(RTLSDR_PC_CFLAGS,["$CFLAGS"]) dnl checks for required libraries -dnl pthreads -AC_CHECK_LIB(pthread, pthread_create, [LIBS="$LIBS -lpthread"]) - -dnl libmath (for rtl_fm) -AC_CHECK_LIB(m, atan2, [LIBS="$LIBS -lm"]) - -dnl libmath (for rtl_adsb) -AC_CHECK_LIB(m, sqrt, [LIBS="$LIBS -lm"]) - -dnl librealtime (for rtl_test) -AC_CHECK_LIB(rt, clock_gettime, [LIBS="$LIBS -lrt"]) # The following test is taken from WebKit's webkit.m4 saved_CFLAGS="$CFLAGS" @@ -68,7 +56,7 @@ dnl Generate the output AM_CONFIG_HEADER(config.h) AC_OUTPUT( - librtlsdr.pc + rtl433.pc include/Makefile src/Makefile Makefile diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 507c0c7a..09d03586 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -21,7 +21,7 @@ # Install public header files ######################################################################## install(FILES - rtl-sdr.h - rtl-sdr_export.h + rtl_433.h + rtl_433_devices.h DESTINATION include ) diff --git a/include/Makefile.am b/include/Makefile.am index 1c45b89e..0205bd62 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -1,5 +1,3 @@ -rtlsdr_HEADERS = rtl-sdr.h rtl-sdr_export.h +rtl433_HEADERS = rtl_433.h rtl_433_devices.h -noinst_HEADERS = reg_field.h rtlsdr_i2c.h tuner_e4k.h tuner_fc0012.h tuner_fc0013.h tuner_fc2580.h tuner_r820t.h - -rtlsdrdir = $(includedir) +rtl433dir = $(includedir) diff --git a/include/reg_field.h b/include/reg_field.h deleted file mode 100644 index 18a69222..00000000 --- a/include/reg_field.h +++ /dev/null @@ -1,60 +0,0 @@ -#ifndef _REG_FIELD_H -#define _REG_FIELD_H - -#include <stdint.h> -#include <stdarg.h> - -enum cmd_op { - CMD_OP_GET = (1 << 0), - CMD_OP_SET = (1 << 1), - CMD_OP_EXEC = (1 << 2), -}; - -enum pstate { - ST_IN_CMD, - ST_IN_ARG, -}; - -struct strbuf { - uint8_t idx; - char buf[32]; -}; - -struct cmd_state { - struct strbuf cmd; - struct strbuf arg; - enum pstate state; - void (*out)(const char *format, va_list ap); -}; - -struct cmd { - const char *cmd; - uint32_t ops; - int (*cb)(struct cmd_state *cs, enum cmd_op op, const char *cmd, - int argc, char **argv); - const char *help; -}; - -/* structure describing a field in a register */ -struct reg_field { - uint8_t reg; - uint8_t shift; - uint8_t width; -}; - -struct reg_field_ops { - const struct reg_field *fields; - const char **field_names; - uint32_t num_fields; - void *data; - int (*write_cb)(void *data, uint32_t reg, uint32_t val); - uint32_t (*read_cb)(void *data, uint32_t reg); -}; - -uint32_t reg_field_read(struct reg_field_ops *ops, struct reg_field *field); -int reg_field_write(struct reg_field_ops *ops, struct reg_field *field, uint32_t val); -int reg_field_cmd(struct cmd_state *cs, enum cmd_op op, - const char *cmd, int argc, char **argv, - struct reg_field_ops *ops); - -#endif diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h deleted file mode 100644 index 75bfd3fd..00000000 --- a/include/rtl-sdr.h +++ /dev/null @@ -1,366 +0,0 @@ -/* - * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver - * Copyright (C) 2012 by Steve Markgraf <steve@steve-m.de> - * Copyright (C) 2012 by Dimitri Stolnikov <horiz0n@gmx.net> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef __RTL_SDR_H -#define __RTL_SDR_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include <stdint.h> -#include <rtl-sdr_export.h> - -typedef struct rtlsdr_dev rtlsdr_dev_t; - -RTLSDR_API uint32_t rtlsdr_get_device_count(void); - -RTLSDR_API const char* rtlsdr_get_device_name(uint32_t index); - -/*! - * Get USB device strings. - * - * NOTE: The string arguments must provide space for up to 256 bytes. - * - * \param index the device index - * \param manufact manufacturer name, may be NULL - * \param product product name, may be NULL - * \param serial serial number, may be NULL - * \return 0 on success - */ -RTLSDR_API int rtlsdr_get_device_usb_strings(uint32_t index, - char *manufact, - char *product, - char *serial); - -/*! - * Get device index by USB serial string descriptor. - * - * \param serial serial string of the device - * \return device index of first device where the name matched - * \return -1 if name is NULL - * \return -2 if no devices were found at all - * \return -3 if devices were found, but none with matching name - */ -RTLSDR_API int rtlsdr_get_index_by_serial(const char *serial); - -RTLSDR_API int rtlsdr_open(rtlsdr_dev_t **dev, uint32_t index); - -RTLSDR_API int rtlsdr_close(rtlsdr_dev_t *dev); - -/* configuration functions */ - -/*! - * Set crystal oscillator frequencies used for the RTL2832 and the tuner IC. - * - * Usually both ICs use the same clock. Changing the clock may make sense if - * you are applying an external clock to the tuner or to compensate the - * frequency (and samplerate) error caused by the original (cheap) crystal. - * - * NOTE: Call this function only if you fully understand the implications. - * - * \param dev the device handle given by rtlsdr_open() - * \param rtl_freq frequency value used to clock the RTL2832 in Hz - * \param tuner_freq frequency value used to clock the tuner IC in Hz - * \return 0 on success - */ -RTLSDR_API int rtlsdr_set_xtal_freq(rtlsdr_dev_t *dev, uint32_t rtl_freq, - uint32_t tuner_freq); - -/*! - * Get crystal oscillator frequencies used for the RTL2832 and the tuner IC. - * - * Usually both ICs use the same clock. - * - * \param dev the device handle given by rtlsdr_open() - * \param rtl_freq frequency value used to clock the RTL2832 in Hz - * \param tuner_freq frequency value used to clock the tuner IC in Hz - * \return 0 on success - */ -RTLSDR_API int rtlsdr_get_xtal_freq(rtlsdr_dev_t *dev, uint32_t *rtl_freq, - uint32_t *tuner_freq); - -/*! - * Get USB device strings. - * - * NOTE: The string arguments must provide space for up to 256 bytes. - * - * \param dev the device handle given by rtlsdr_open() - * \param manufact manufacturer name, may be NULL - * \param product product name, may be NULL - * \param serial serial number, may be NULL - * \return 0 on success - */ -RTLSDR_API int rtlsdr_get_usb_strings(rtlsdr_dev_t *dev, char *manufact, - char *product, char *serial); - -/*! - * Write the device EEPROM - * - * \param dev the device handle given by rtlsdr_open() - * \param data buffer of data to be written - * \param offset address where the data should be written - * \param len length of the data - * \return 0 on success - * \return -1 if device handle is invalid - * \return -2 if EEPROM size is exceeded - * \return -3 if no EEPROM was found - */ - -RTLSDR_API int rtlsdr_write_eeprom(rtlsdr_dev_t *dev, uint8_t *data, - uint8_t offset, uint16_t len); - -/*! - * Read the device EEPROM - * - * \param dev the device handle given by rtlsdr_open() - * \param data buffer where the data should be written - * \param offset address where the data should be read from - * \param len length of the data - * \return 0 on success - * \return -1 if device handle is invalid - * \return -2 if EEPROM size is exceeded - * \return -3 if no EEPROM was found - */ - -RTLSDR_API int rtlsdr_read_eeprom(rtlsdr_dev_t *dev, uint8_t *data, - uint8_t offset, uint16_t len); - -RTLSDR_API int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq); - -/*! - * Get actual frequency the device is tuned to. - * - * \param dev the device handle given by rtlsdr_open() - * \return 0 on error, frequency in Hz otherwise - */ -RTLSDR_API uint32_t rtlsdr_get_center_freq(rtlsdr_dev_t *dev); - -/*! - * Set the frequency correction value for the device. - * - * \param dev the device handle given by rtlsdr_open() - * \param ppm correction value in parts per million (ppm) - * \return 0 on success - */ -RTLSDR_API int rtlsdr_set_freq_correction(rtlsdr_dev_t *dev, int ppm); - -/*! - * Get actual frequency correction value of the device. - * - * \param dev the device handle given by rtlsdr_open() - * \return correction value in parts per million (ppm) - */ -RTLSDR_API int rtlsdr_get_freq_correction(rtlsdr_dev_t *dev); - -enum rtlsdr_tuner { - RTLSDR_TUNER_UNKNOWN = 0, - RTLSDR_TUNER_E4000, - RTLSDR_TUNER_FC0012, - RTLSDR_TUNER_FC0013, - RTLSDR_TUNER_FC2580, - RTLSDR_TUNER_R820T -}; - -/*! - * Get the tuner type. - * - * \param dev the device handle given by rtlsdr_open() - * \return RTLSDR_TUNER_UNKNOWN on error, tuner type otherwise - */ -RTLSDR_API enum rtlsdr_tuner rtlsdr_get_tuner_type(rtlsdr_dev_t *dev); - -/*! - * Get a list of gains supported by the tuner. - * - * NOTE: The gains argument must be preallocated by the caller. If NULL is - * being given instead, the number of available gain values will be returned. - * - * \param dev the device handle given by rtlsdr_open() - * \param gains array of gain values. In tenths of a dB, 115 means 11.5 dB. - * \return <= 0 on error, number of available (returned) gain values otherwise - */ -RTLSDR_API int rtlsdr_get_tuner_gains(rtlsdr_dev_t *dev, int *gains); - -/*! - * Set the gain for the device. - * Manual gain mode must be enabled for this to work. - * - * Valid gain values (in tenths of a dB) for the E4000 tuner: - * -10, 15, 40, 65, 90, 115, 140, 165, 190, - * 215, 240, 290, 340, 420, 430, 450, 470, 490 - * - * Valid gain values may be queried with \ref rtlsdr_get_tuner_gains function. - * - * \param dev the device handle given by rtlsdr_open() - * \param gain in tenths of a dB, 115 means 11.5 dB. - * \return 0 on success - */ -RTLSDR_API int rtlsdr_set_tuner_gain(rtlsdr_dev_t *dev, int gain); - -/*! - * Get actual gain the device is configured to. - * - * \param dev the device handle given by rtlsdr_open() - * \return 0 on error, gain in tenths of a dB, 115 means 11.5 dB. - */ -RTLSDR_API int rtlsdr_get_tuner_gain(rtlsdr_dev_t *dev); - -/*! - * Set the intermediate frequency gain for the device. - * - * \param dev the device handle given by rtlsdr_open() - * \param stage intermediate frequency gain stage number (1 to 6 for E4000) - * \param gain in tenths of a dB, -30 means -3.0 dB. - * \return 0 on success - */ -RTLSDR_API int rtlsdr_set_tuner_if_gain(rtlsdr_dev_t *dev, int stage, int gain); - -/*! - * Set the gain mode (automatic/manual) for the device. - * Manual gain mode must be enabled for the gain setter function to work. - * - * \param dev the device handle given by rtlsdr_open() - * \param manual gain mode, 1 means manual gain mode shall be enabled. - * \return 0 on success - */ -RTLSDR_API int rtlsdr_set_tuner_gain_mode(rtlsdr_dev_t *dev, int manual); - -/* this will select the baseband filters according to the requested sample rate */ -RTLSDR_API int rtlsdr_set_sample_rate(rtlsdr_dev_t *dev, uint32_t rate); - -/*! - * Get actual sample rate the device is configured to. - * - * \param dev the device handle given by rtlsdr_open() - * \return 0 on error, sample rate in Hz otherwise - */ -RTLSDR_API uint32_t rtlsdr_get_sample_rate(rtlsdr_dev_t *dev); - -/*! - * Enable test mode that returns an 8 bit counter instead of the samples. - * The counter is generated inside the RTL2832. - * - * \param dev the device handle given by rtlsdr_open() - * \param test mode, 1 means enabled, 0 disabled - * \return 0 on success - */ -RTLSDR_API int rtlsdr_set_testmode(rtlsdr_dev_t *dev, int on); - -/*! - * Enable or disable the internal digital AGC of the RTL2832. - * - * \param dev the device handle given by rtlsdr_open() - * \param digital AGC mode, 1 means enabled, 0 disabled - * \return 0 on success - */ -RTLSDR_API int rtlsdr_set_agc_mode(rtlsdr_dev_t *dev, int on); - -/*! - * Enable or disable the direct sampling mode. When enabled, the IF mode - * of the RTL2832 is activated, and rtlsdr_set_center_freq() will control - * the IF-frequency of the DDC, which can be used to tune from 0 to 28.8 MHz - * (xtal frequency of the RTL2832). - * - * \param dev the device handle given by rtlsdr_open() - * \param on 0 means disabled, 1 I-ADC input enabled, 2 Q-ADC input enabled - * \return 0 on success - */ -RTLSDR_API int rtlsdr_set_direct_sampling(rtlsdr_dev_t *dev, int on); - -/*! - * Get state of the direct sampling mode - * - * \param dev the device handle given by rtlsdr_open() - * \return -1 on error, 0 means disabled, 1 I-ADC input enabled - * 2 Q-ADC input enabled - */ -RTLSDR_API int rtlsdr_get_direct_sampling(rtlsdr_dev_t *dev); - -/*! - * Enable or disable offset tuning for zero-IF tuners, which allows to avoid - * problems caused by the DC offset of the ADCs and 1/f noise. - * - * \param dev the device handle given by rtlsdr_open() - * \param on 0 means disabled, 1 enabled - * \return 0 on success - */ -RTLSDR_API int rtlsdr_set_offset_tuning(rtlsdr_dev_t *dev, int on); - -/*! - * Get state of the offset tuning mode - * - * \param dev the device handle given by rtlsdr_open() - * \return -1 on error, 0 means disabled, 1 enabled - */ -RTLSDR_API int rtlsdr_get_offset_tuning(rtlsdr_dev_t *dev); - -/* streaming functions */ - -RTLSDR_API int rtlsdr_reset_buffer(rtlsdr_dev_t *dev); - -RTLSDR_API int rtlsdr_read_sync(rtlsdr_dev_t *dev, void *buf, int len, int *n_read); - -typedef void(*rtlsdr_read_async_cb_t)(unsigned char *buf, uint32_t len, void *ctx); - -/*! - * Read samples from the device asynchronously. This function will block until - * it is being canceled using rtlsdr_cancel_async() - * - * NOTE: This function is deprecated and is subject for removal. - * - * \param dev the device handle given by rtlsdr_open() - * \param cb callback function to return received samples - * \param ctx user specific context to pass via the callback function - * \return 0 on success - */ -RTLSDR_API int rtlsdr_wait_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx); - -/*! - * Read samples from the device asynchronously. This function will block until - * it is being canceled using rtlsdr_cancel_async() - * - * \param dev the device handle given by rtlsdr_open() - * \param cb callback function to return received samples - * \param ctx user specific context to pass via the callback function - * \param buf_num optional buffer count, buf_num * buf_len = overall buffer size - * set to 0 for default buffer count (32) - * \param buf_len optional buffer length, must be multiple of 512, - * set to 0 for default buffer length (16 * 32 * 512) - * \return 0 on success - */ -RTLSDR_API int rtlsdr_read_async(rtlsdr_dev_t *dev, - rtlsdr_read_async_cb_t cb, - void *ctx, - uint32_t buf_num, - uint32_t buf_len); - -/*! - * Cancel all pending asynchronous operations on the device. - * - * \param dev the device handle given by rtlsdr_open() - * \return 0 on success - */ -RTLSDR_API int rtlsdr_cancel_async(rtlsdr_dev_t *dev); - -#ifdef __cplusplus -} -#endif - -#endif /* __RTL_SDR_H */ diff --git a/include/rtl-sdr_export.h b/include/rtl-sdr_export.h deleted file mode 100644 index 69e178d1..00000000 --- a/include/rtl-sdr_export.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver - * Copyright (C) 2012 by Hoernchen <la@tfc-server.de> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#ifndef RTLSDR_EXPORT_H -#define RTLSDR_EXPORT_H - -#if defined __GNUC__ -# if __GNUC__ >= 4 -# define __SDR_EXPORT __attribute__((visibility("default"))) -# define __SDR_IMPORT __attribute__((visibility("default"))) -# else -# define __SDR_EXPORT -# define __SDR_IMPORT -# endif -#elif _MSC_VER -# define __SDR_EXPORT __declspec(dllexport) -# define __SDR_IMPORT __declspec(dllimport) -#else -# define __SDR_EXPORT -# define __SDR_IMPORT -#endif - -#ifndef rtlsdr_STATIC -# ifdef rtlsdr_EXPORTS -# define RTLSDR_API __SDR_EXPORT -# else -# define RTLSDR_API __SDR_IMPORT -# endif -#else -#define RTLSDR_API -#endif -#endif /* RTLSDR_EXPORT_H */ diff --git a/include/rtlsdr_i2c.h b/include/rtlsdr_i2c.h deleted file mode 100644 index 76766893..00000000 --- a/include/rtlsdr_i2c.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __I2C_H -#define __I2C_H - -uint32_t rtlsdr_get_tuner_clock(void *dev); -int rtlsdr_i2c_write_fn(void *dev, uint8_t addr, uint8_t *buf, int len); -int rtlsdr_i2c_read_fn(void *dev, uint8_t addr, uint8_t *buf, int len); - -#endif diff --git a/include/tuner_e4k.h b/include/tuner_e4k.h deleted file mode 100644 index 6db6b2ad..00000000 --- a/include/tuner_e4k.h +++ /dev/null @@ -1,224 +0,0 @@ -#ifndef _E4K_TUNER_H -#define _E4K_TUNER_H - -/* - * Elonics E4000 tuner driver - * - * (C) 2011-2012 by Harald Welte <laforge@gnumonks.org> - * (C) 2012 by Sylvain Munaut <tnt@246tNt.com> - * (C) 2012 by Hoernchen <la@tfc-server.de> - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#define E4K_I2C_ADDR 0xc8 -#define E4K_CHECK_ADDR 0x02 -#define E4K_CHECK_VAL 0x40 - -enum e4k_reg { - E4K_REG_MASTER1 = 0x00, - E4K_REG_MASTER2 = 0x01, - E4K_REG_MASTER3 = 0x02, - E4K_REG_MASTER4 = 0x03, - E4K_REG_MASTER5 = 0x04, - E4K_REG_CLK_INP = 0x05, - E4K_REG_REF_CLK = 0x06, - E4K_REG_SYNTH1 = 0x07, - E4K_REG_SYNTH2 = 0x08, - E4K_REG_SYNTH3 = 0x09, - E4K_REG_SYNTH4 = 0x0a, - E4K_REG_SYNTH5 = 0x0b, - E4K_REG_SYNTH6 = 0x0c, - E4K_REG_SYNTH7 = 0x0d, - E4K_REG_SYNTH8 = 0x0e, - E4K_REG_SYNTH9 = 0x0f, - E4K_REG_FILT1 = 0x10, - E4K_REG_FILT2 = 0x11, - E4K_REG_FILT3 = 0x12, - // gap - E4K_REG_GAIN1 = 0x14, - E4K_REG_GAIN2 = 0x15, - E4K_REG_GAIN3 = 0x16, - E4K_REG_GAIN4 = 0x17, - // gap - E4K_REG_AGC1 = 0x1a, - E4K_REG_AGC2 = 0x1b, - E4K_REG_AGC3 = 0x1c, - E4K_REG_AGC4 = 0x1d, - E4K_REG_AGC5 = 0x1e, - E4K_REG_AGC6 = 0x1f, - E4K_REG_AGC7 = 0x20, - E4K_REG_AGC8 = 0x21, - // gap - E4K_REG_AGC11 = 0x24, - E4K_REG_AGC12 = 0x25, - // gap - E4K_REG_DC1 = 0x29, - E4K_REG_DC2 = 0x2a, - E4K_REG_DC3 = 0x2b, - E4K_REG_DC4 = 0x2c, - E4K_REG_DC5 = 0x2d, - E4K_REG_DC6 = 0x2e, - E4K_REG_DC7 = 0x2f, - E4K_REG_DC8 = 0x30, - // gap - E4K_REG_QLUT0 = 0x50, - E4K_REG_QLUT1 = 0x51, - E4K_REG_QLUT2 = 0x52, - E4K_REG_QLUT3 = 0x53, - // gap - E4K_REG_ILUT0 = 0x60, - E4K_REG_ILUT1 = 0x61, - E4K_REG_ILUT2 = 0x62, - E4K_REG_ILUT3 = 0x63, - // gap - E4K_REG_DCTIME1 = 0x70, - E4K_REG_DCTIME2 = 0x71, - E4K_REG_DCTIME3 = 0x72, - E4K_REG_DCTIME4 = 0x73, - E4K_REG_PWM1 = 0x74, - E4K_REG_PWM2 = 0x75, - E4K_REG_PWM3 = 0x76, - E4K_REG_PWM4 = 0x77, - E4K_REG_BIAS = 0x78, - E4K_REG_CLKOUT_PWDN = 0x7a, - E4K_REG_CHFILT_CALIB = 0x7b, - E4K_REG_I2C_REG_ADDR = 0x7d, - // FIXME -}; - -#define E4K_MASTER1_RESET (1 << 0) -#define E4K_MASTER1_NORM_STBY (1 << 1) -#define E4K_MASTER1_POR_DET (1 << 2) - -#define E4K_SYNTH1_PLL_LOCK (1 << 0) -#define E4K_SYNTH1_BAND_SHIF 1 - -#define E4K_SYNTH7_3PHASE_EN (1 << 3) - -#define E4K_SYNTH8_VCOCAL_UPD (1 << 2) - -#define E4K_FILT3_DISABLE (1 << 5) - -#define E4K_AGC1_LIN_MODE (1 << 4) -#define E4K_AGC1_LNA_UPDATE (1 << 5) -#define E4K_AGC1_LNA_G_LOW (1 << 6) -#define E4K_AGC1_LNA_G_HIGH (1 << 7) - -#define E4K_AGC6_LNA_CAL_REQ (1 << 4) - -#define E4K_AGC7_MIX_GAIN_AUTO (1 << 0) -#define E4K_AGC7_GAIN_STEP_5dB (1 << 5) - -#define E4K_AGC8_SENS_LIN_AUTO (1 << 0) - -#define E4K_AGC11_LNA_GAIN_ENH (1 << 0) - -#define E4K_DC1_CAL_REQ (1 << 0) - -#define E4K_DC5_I_LUT_EN (1 << 0) -#define E4K_DC5_Q_LUT_EN (1 << 1) -#define E4K_DC5_RANGE_DET_EN (1 << 2) -#define E4K_DC5_RANGE_EN (1 << 3) -#define E4K_DC5_TIMEVAR_EN (1 << 4) - -#define E4K_CLKOUT_DISABLE 0x96 - -#define E4K_CHFCALIB_CMD (1 << 0) - -#define E4K_AGC1_MOD_MASK 0xF - -enum e4k_agc_mode { - E4K_AGC_MOD_SERIAL = 0x0, - E4K_AGC_MOD_IF_PWM_LNA_SERIAL = 0x1, - E4K_AGC_MOD_IF_PWM_LNA_AUTONL = 0x2, - E4K_AGC_MOD_IF_PWM_LNA_SUPERV = 0x3, - E4K_AGC_MOD_IF_SERIAL_LNA_PWM = 0x4, - E4K_AGC_MOD_IF_PWM_LNA_PWM = 0x5, - E4K_AGC_MOD_IF_DIG_LNA_SERIAL = 0x6, - E4K_AGC_MOD_IF_DIG_LNA_AUTON = 0x7, - E4K_AGC_MOD_IF_DIG_LNA_SUPERV = 0x8, - E4K_AGC_MOD_IF_SERIAL_LNA_AUTON = 0x9, - E4K_AGC_MOD_IF_SERIAL_LNA_SUPERV = 0xa, -}; - -enum e4k_band { - E4K_BAND_VHF2 = 0, - E4K_BAND_VHF3 = 1, - E4K_BAND_UHF = 2, - E4K_BAND_L = 3, -}; - -enum e4k_mixer_filter_bw { - E4K_F_MIX_BW_27M = 0, - E4K_F_MIX_BW_4M6 = 8, - E4K_F_MIX_BW_4M2 = 9, - E4K_F_MIX_BW_3M8 = 10, - E4K_F_MIX_BW_3M4 = 11, - E4K_F_MIX_BW_3M = 12, - E4K_F_MIX_BW_2M7 = 13, - E4K_F_MIX_BW_2M3 = 14, - E4K_F_MIX_BW_1M9 = 15, -}; - -enum e4k_if_filter { - E4K_IF_FILTER_MIX, - E4K_IF_FILTER_CHAN, - E4K_IF_FILTER_RC -}; -struct e4k_pll_params { - uint32_t fosc; - uint32_t intended_flo; - uint32_t flo; - uint16_t x; - uint8_t z; - uint8_t r; - uint8_t r_idx; - uint8_t threephase; -}; - -struct e4k_state { - void *i2c_dev; - uint8_t i2c_addr; - enum e4k_band band; - struct e4k_pll_params vco; - void *rtl_dev; -}; - -int e4k_init(struct e4k_state *e4k); -int e4k_if_gain_set(struct e4k_state *e4k, uint8_t stage, int8_t value); -int e4k_mixer_gain_set(struct e4k_state *e4k, int8_t value); -int e4k_commonmode_set(struct e4k_state *e4k, int8_t value); -int e4k_tune_freq(struct e4k_state *e4k, uint32_t freq); -int e4k_tune_params(struct e4k_state *e4k, struct e4k_pll_params *p); -uint32_t e4k_compute_pll_params(struct e4k_pll_params *oscp, uint32_t fosc, uint32_t intended_flo); -int e4k_if_filter_bw_get(struct e4k_state *e4k, enum e4k_if_filter filter); -int e4k_if_filter_bw_set(struct e4k_state *e4k, enum e4k_if_filter filter, - uint32_t bandwidth); -int e4k_if_filter_chan_enable(struct e4k_state *e4k, int on); -int e4k_rf_filter_set(struct e4k_state *e4k); - -int e4k_reg_write(struct e4k_state *e4k, uint8_t reg, uint8_t val); -uint8_t e4k_reg_read(struct e4k_state *e4k, uint8_t reg); - -int e4k_manual_dc_offset(struct e4k_state *e4k, int8_t iofs, int8_t irange, int8_t qofs, int8_t qrange); -int e4k_dc_offset_calibrate(struct e4k_state *e4k); -int e4k_dc_offset_gen_table(struct e4k_state *e4k); - -int e4k_set_lna_gain(struct e4k_state *e4k, int32_t gain); -int e4k_enable_manual_gain(struct e4k_state *e4k, uint8_t manual); -int e4k_set_enh_gain(struct e4k_state *e4k, int32_t gain); -#endif /* _E4K_TUNER_H */ diff --git a/include/tuner_fc0012.h b/include/tuner_fc0012.h deleted file mode 100644 index 9dd5356f..00000000 --- a/include/tuner_fc0012.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Fitipower FC0012 tuner driver - * - * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@gmx.net> - * - * modified for use in librtlsdr - * Copyright (C) 2012 Steve Markgraf <steve@steve-m.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef _FC0012_H_ -#define _FC0012_H_ - -#define FC0012_I2C_ADDR 0xc6 -#define FC0012_CHECK_ADDR 0x00 -#define FC0012_CHECK_VAL 0xa1 - -int fc0012_init(void *dev); -int fc0012_set_params(void *dev, uint32_t freq, uint32_t bandwidth); -int fc0012_set_gain(void *dev, int gain); - -#endif diff --git a/include/tuner_fc0013.h b/include/tuner_fc0013.h deleted file mode 100644 index 68a26eee..00000000 --- a/include/tuner_fc0013.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Fitipower FC0013 tuner driver - * - * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@gmx.net> - * - * modified for use in librtlsdr - * Copyright (C) 2012 Steve Markgraf <steve@steve-m.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#ifndef _FC0013_H_ -#define _FC0013_H_ - -#define FC0013_I2C_ADDR 0xc6 -#define FC0013_CHECK_ADDR 0x00 -#define FC0013_CHECK_VAL 0xa3 - -int fc0013_init(void *dev); -int fc0013_set_params(void *dev, uint32_t freq, uint32_t bandwidth); -int fc0013_set_gain_mode(void *dev, int manual); -int fc0013_set_lna_gain(void *dev, int gain); - -#endif diff --git a/include/tuner_fc2580.h b/include/tuner_fc2580.h deleted file mode 100644 index 9ebd935b..00000000 --- a/include/tuner_fc2580.h +++ /dev/null @@ -1,127 +0,0 @@ -#ifndef __TUNER_FC2580_H -#define __TUNER_FC2580_H - -#define BORDER_FREQ 2600000 //2.6GHz : The border frequency which determines whether Low VCO or High VCO is used -#define USE_EXT_CLK 0 //0 : Use internal XTAL Oscillator / 1 : Use External Clock input -#define OFS_RSSI 57 - -#define FC2580_I2C_ADDR 0xac -#define FC2580_CHECK_ADDR 0x01 -#define FC2580_CHECK_VAL 0x56 - -typedef enum { - FC2580_UHF_BAND, - FC2580_L_BAND, - FC2580_VHF_BAND, - FC2580_NO_BAND -} fc2580_band_type; - -typedef enum { - FC2580_FCI_FAIL, - FC2580_FCI_SUCCESS -} fc2580_fci_result_type; - -enum FUNCTION_STATUS -{ - FUNCTION_SUCCESS, - FUNCTION_ERROR, -}; - -extern void fc2580_wait_msec(void *pTuner, int a); - -fc2580_fci_result_type fc2580_i2c_write(void *pTuner, unsigned char reg, unsigned char val); -fc2580_fci_result_type fc2580_i2c_read(void *pTuner, unsigned char reg, unsigned char *read_data); - -/*============================================================================== - fc2580 initial setting - - This function is a generic function which gets called to initialize - - fc2580 in DVB-H mode or L-Band TDMB mode - - <input parameter> - - ifagc_mode - type : integer - 1 : Internal AGC - 2 : Voltage Control Mode - -==============================================================================*/ -fc2580_fci_result_type fc2580_set_init(void *pTuner, int ifagc_mode, unsigned int freq_xtal ); - -/*============================================================================== - fc2580 frequency setting - - This function is a generic function which gets called to change LO Frequency - - of fc2580 in DVB-H mode or L-Band TDMB mode - - <input parameter> - - f_lo - Value of target LO Frequency in 'kHz' unit - ex) 2.6GHz = 2600000 - -==============================================================================*/ -fc2580_fci_result_type fc2580_set_freq(void *pTuner, unsigned int f_lo, unsigned int freq_xtal ); - - -/*============================================================================== - fc2580 filter BW setting - - This function is a generic function which gets called to change Bandwidth - - frequency of fc2580's channel selection filter - - <input parameter> - - filter_bw - 1 : 1.53MHz(TDMB) - 6 : 6MHz - 7 : 7MHz - 8 : 7.8MHz - - -==============================================================================*/ -fc2580_fci_result_type fc2580_set_filter( void *pTuner, unsigned char filter_bw, unsigned int freq_xtal ); - -// The following context is FC2580 tuner API source code -// Definitions - -// AGC mode -enum FC2580_AGC_MODE -{ - FC2580_AGC_INTERNAL = 1, - FC2580_AGC_EXTERNAL = 2, -}; - - -// Bandwidth mode -enum FC2580_BANDWIDTH_MODE -{ - FC2580_BANDWIDTH_1530000HZ = 1, - FC2580_BANDWIDTH_6000000HZ = 6, - FC2580_BANDWIDTH_7000000HZ = 7, - FC2580_BANDWIDTH_8000000HZ = 8, -}; - -// Manipulaing functions -int -fc2580_Initialize( - void *pTuner - ); - -int -fc2580_SetRfFreqHz( - void *pTuner, - unsigned long RfFreqHz - ); - -// Extra manipulaing functions -int -fc2580_SetBandwidthMode( - void *pTuner, - int BandwidthMode - ); - -#endif diff --git a/include/tuner_r820t.h b/include/tuner_r820t.h deleted file mode 100644 index f9bd4cfd..00000000 --- a/include/tuner_r820t.h +++ /dev/null @@ -1,196 +0,0 @@ -#ifndef _R820T_TUNER_H -#define _R820T_TUNER_H - -#define R820T_I2C_ADDR 0x34 -#define R820T_CHECK_ADDR 0x00 -#define R820T_CHECK_VAL 0x69 - -#define R820T_IF_FREQ 3570000 - -//*************************************************************** -//* INCLUDES.H -//*************************************************************** -#define VERSION "R820T_v1.49_ASTRO" -#define VER_NUM 49 - -#define USE_16M_XTAL FALSE -#define R828_Xtal 28800 - -#define USE_DIPLEXER FALSE -#define TUNER_CLK_OUT TRUE - -#ifndef _UINT_X_ -#define _UINT_X_ 1 -typedef unsigned char UINT8; -typedef unsigned short UINT16; -typedef unsigned int UINT32; -#endif - -#define TRUE 1 -#define FALSE 0 - -#define FUNCTION_SUCCESS 0 -#define FUNCTION_ERROR -1 - -typedef enum _R828_ErrCode -{ - RT_Success, - RT_Fail -}R828_ErrCode; - -typedef enum _Rafael_Chip_Type //Don't modify chip list -{ - R828 = 0, - R828D, - R828S, - R820T, - R820C, - R620D, - R620S -}Rafael_Chip_Type; -//----------------------------------------------------------// -// R828 Parameter // -//----------------------------------------------------------// - -extern UINT8 R828_ADDRESS; - -#define DIP_FREQ 320000 -#define IMR_TRIAL 9 -#define VCO_pwr_ref 0x02 - -extern UINT32 R828_IF_khz; -extern UINT32 R828_CAL_LO_khz; -extern UINT8 R828_IMR_point_num; -extern UINT8 R828_IMR_done_flag; -extern UINT8 Rafael_Chip; - -typedef enum _R828_Standard_Type //Don't remove standand list!! -{ - NTSC_MN = 0, - PAL_I, - PAL_DK, - PAL_B_7M, //no use - PAL_BGH_8M, //for PAL B/G, PAL G/H - SECAM_L, - SECAM_L1_INV, //for SECAM L' - SECAM_L1, //no use - ATV_SIZE, - DVB_T_6M = ATV_SIZE, - DVB_T_7M, - DVB_T_7M_2, - DVB_T_8M, - DVB_T2_6M, - DVB_T2_7M, - DVB_T2_7M_2, - DVB_T2_8M, - DVB_T2_1_7M, - DVB_T2_10M, - DVB_C_8M, - DVB_C_6M, - ISDB_T, - DTMB, - R828_ATSC, - FM, - STD_SIZE -}R828_Standard_Type; - -extern UINT8 R828_Fil_Cal_flag[STD_SIZE]; - -typedef enum _R828_SetFreq_Type -{ - FAST_MODE = TRUE, - NORMAL_MODE = FALSE -}R828_SetFreq_Type; - -typedef enum _R828_LoopThrough_Type -{ - LOOP_THROUGH = TRUE, - SIGLE_IN = FALSE -}R828_LoopThrough_Type; - - -typedef enum _R828_InputMode_Type -{ - AIR_IN = 0, - CABLE_IN_1, - CABLE_IN_2 -}R828_InputMode_Type; - -typedef enum _R828_IfAgc_Type -{ - IF_AGC1 = 0, - IF_AGC2 -}R828_IfAgc_Type; - -typedef enum _R828_GPIO_Type -{ - HI_SIG = TRUE, - LO_SIG = FALSE -}R828_GPIO_Type; - -typedef struct _R828_Set_Info -{ - UINT32 RF_Hz; - UINT32 RF_KHz; - R828_Standard_Type R828_Standard; - R828_LoopThrough_Type RT_Input; - R828_InputMode_Type RT_InputMode; - R828_IfAgc_Type R828_IfAgc_Select; -}R828_Set_Info; - -typedef struct _R828_RF_Gain_Info -{ - UINT8 RF_gain1; - UINT8 RF_gain2; - UINT8 RF_gain_comb; -}R828_RF_Gain_Info; - -typedef enum _R828_RF_Gain_TYPE -{ - RF_AUTO = 0, - RF_MANUAL -}R828_RF_Gain_TYPE; - -typedef struct _R828_I2C_LEN_TYPE -{ - UINT8 RegAddr; - UINT8 Data[50]; - UINT8 Len; -}R828_I2C_LEN_TYPE; - -typedef struct _R828_I2C_TYPE -{ - UINT8 RegAddr; - UINT8 Data; -}R828_I2C_TYPE; -//----------------------------------------------------------// -// R828 Function // -//----------------------------------------------------------// -R828_ErrCode R828_Init(void *pTuner); -R828_ErrCode R828_Standby(void *pTuner, R828_LoopThrough_Type R828_LoopSwitch); -R828_ErrCode R828_GPIO(void *pTuner, R828_GPIO_Type R828_GPIO_Conrl); -R828_ErrCode R828_SetStandard(void *pTuner, R828_Standard_Type RT_Standard); -R828_ErrCode R828_SetFrequency(void *pTuner, R828_Set_Info R828_INFO, R828_SetFreq_Type R828_SetFreqMode); -R828_ErrCode R828_GetRfGain(void *pTuner, R828_RF_Gain_Info *pR828_rf_gain); -R828_ErrCode R828_SetRfGain(void *pTuner, int gain); -R828_ErrCode R828_RfGainMode(void *pTuner, int manual); - -int -r820t_SetRfFreqHz( - void *pTuner, - unsigned long RfFreqHz - ); - -int -r820t_SetStandardMode( - void *pTuner, - int StandardMode - ); - -int -r820t_SetStandby( - void *pTuner, - int LoopThroughType - ); - -#endif /* _R820T_TUNER_H */ diff --git a/librtlsdr.pc.in b/librtlsdr.pc.in deleted file mode 100644 index 5e55049a..00000000 --- a/librtlsdr.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@ - -Name: RTL-SDR Library -Description: C Utility Library -Version: @VERSION@ -Cflags: -I${includedir}/ @RTLSDR_PC_CFLAGS@ -Libs: -L${libdir} -lrtlsdr -lusb-1.0 -Libs.private: @RTLSDR_PC_LIBS@ diff --git a/rtl-sdr.rules b/rtl-sdr.rules deleted file mode 100644 index 1f68c45f..00000000 --- a/rtl-sdr.rules +++ /dev/null @@ -1,101 +0,0 @@ -# -# Copyright 2012 Osmocom rtl-sdr project -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. -# - -# original RTL2832U vid/pid (hama nano, for example) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2832", MODE:="0666" - -# ezcap EzTV668 (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2838", MODE:="0666" - -# Terratec Cinergy T Stick Black (rev 1) (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00a9", MODE:="0666" - -# Terratec NOXON rev 1 (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b3", MODE:="0666" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b4", MODE:="0666" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00b7", MODE:="0666" -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00c6", MODE:="0666" - -# Terratec Cinergy T Stick RC (Rev.3) (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00d3", MODE:="0666" - -# Terratec T Stick PLUS (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00d7", MODE:="0666" - -# Terratec NOXON rev 2 (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0ccd", ATTRS{idProduct}=="00e0", MODE:="0666" - -# PixelView PV-DT235U(RN) (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1554", ATTRS{idProduct}=="5020", MODE:="0666" - -# Compro Videomate U620F (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="185b", ATTRS{idProduct}=="0620", MODE:="0666" - -# Compro Videomate U650F (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="185b", ATTRS{idProduct}=="0650", MODE:="0666" - -# Compro Videomate U680F (E4000) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="185b", ATTRS{idProduct}=="0680", MODE:="0666" - -# Sweex DVB-T USB (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="a803", MODE:="0666" - -# GTek T803 (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="b803", MODE:="0666" - -# Lifeview LV5TDeluxe (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="c803", MODE:="0666" - -# MyGica TD312 (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="d286", MODE:="0666" - -# PROlectrix DV107669 (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1f4d", ATTRS{idProduct}=="d803", MODE:="0666" - -# Zaapa ZT-MINDVBZP (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d398", MODE:="0666" - -# Twintech UT-40 (FC0013) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d3a4", MODE:="0666" - -# Dexatek DK DVB-T Dongle (Logilink VG0002A) (FC2580) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1101", MODE:="0666" - -# Dexatek DK DVB-T Dongle (MSI DigiVox mini II V3.0) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1102", MODE:="0666" - -# Dexatek DK 5217 DVB-T Dongle (FC2580) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1103", MODE:="0666" - -# MSI DigiVox Micro HD (FC2580) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1d19", ATTRS{idProduct}=="1104", MODE:="0666" - -# Genius TVGo DVB-T03 USB dongle (Ver. B) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="0458", ATTRS{idProduct}=="707f", MODE:="0666" - -# GIGABYTE GT-U7300 (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d393", MODE:="0666" - -# DIKOM USB-DVBT HD -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d394", MODE:="0666" - -# Peak 102569AGPK (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d395", MODE:="0666" - -# SVEON STV20 DVB-T USB & FM (FC0012) -SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d39d", MODE:="0666" - diff --git a/rtl433.pc.in b/rtl433.pc.in new file mode 100644 index 00000000..ca9b850b --- /dev/null +++ b/rtl433.pc.in @@ -0,0 +1,9 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: RTL-433 Utility +Description: C Utility +Version: @VERSION@ +Cflags: -I${includedir}/ @RTL433_PC_CFLAGS@ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index db9f3080..c573583a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,13 +1,9 @@ -# Copyright 2012 OSMOCOM Project -# -# This file is part of rtl-sdr -# -# GNU Radio is free software; you can redistribute it and/or modify +# rtl_433 is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3, or (at your option) # any later version. # -# GNU Radio is distributed in the hope that it will be useful, +# rtl_433 is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. @@ -17,61 +13,9 @@ # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. -######################################################################## -# Setup library -######################################################################## -add_library(rtlsdr_shared SHARED - librtlsdr.c - tuner_e4k.c - tuner_fc0012.c - tuner_fc0013.c - tuner_fc2580.c - tuner_r820t.c -) - -target_link_libraries(rtlsdr_shared - ${LIBUSB_LIBRARIES} -) - -set_target_properties(rtlsdr_shared PROPERTIES DEFINE_SYMBOL "rtlsdr_EXPORTS") -set_target_properties(rtlsdr_shared PROPERTIES OUTPUT_NAME rtlsdr) -set_target_properties(rtlsdr_shared PROPERTIES SOVERSION 0 VERSION 0.0.0) - -add_library(rtlsdr_static STATIC - librtlsdr.c - tuner_e4k.c - tuner_fc0012.c - tuner_fc0013.c - tuner_fc2580.c - tuner_r820t.c -) - -if(WIN32) -add_library(libgetopt_static STATIC - getopt/getopt.c -) -endif() - -target_link_libraries(rtlsdr_static - ${LIBUSB_LIBRARIES} -) - -set_property(TARGET rtlsdr_static APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" ) - -if(NOT WIN32) -# Force same library filename for static and shared variants of the library -set_target_properties(rtlsdr_static PROPERTIES OUTPUT_NAME rtlsdr) -endif() - ######################################################################## # Build utility ######################################################################## -add_executable(rtl_sdr rtl_sdr.c) -add_executable(rtl_tcp rtl_tcp.c) -add_executable(rtl_test rtl_test.c) -add_executable(rtl_fm rtl_fm.c) -add_executable(rtl_eeprom rtl_eeprom.c) -add_executable(rtl_adsb rtl_adsb.c) add_executable(rtl_433 rtl_433.c devices/silvercrest.c @@ -87,69 +31,21 @@ add_executable(rtl_433 devices/intertechno.c devices/alecto.c devices/newkaku.c) + +target_link_libraries(rtl_433 + ${LIBRTLSDR_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} +) + -set(INSTALL_TARGETS rtlsdr_shared rtlsdr_static rtl_sdr rtl_tcp rtl_test rtl_fm rtl_eeprom rtl_adsb rtl_433) - -target_link_libraries(rtl_sdr rtlsdr_shared - ${LIBUSB_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} -) -target_link_libraries(rtl_tcp rtlsdr_shared - ${LIBUSB_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} -) -target_link_libraries(rtl_test rtlsdr_shared - ${LIBUSB_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} -) -target_link_libraries(rtl_fm rtlsdr_shared - ${LIBUSB_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} -) -target_link_libraries(rtl_433 rtlsdr_shared - ${LIBUSB_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} -) -target_link_libraries(rtl_eeprom rtlsdr_shared - ${LIBUSB_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} -) -target_link_libraries(rtl_adsb rtlsdr_shared - ${LIBUSB_LIBRARIES} - ${CMAKE_THREAD_LIBS_INIT} -) +set(INSTALL_TARGETS rtl_433) if(UNIX) -target_link_libraries(rtl_fm m) target_link_libraries(rtl_433 m) -target_link_libraries(rtl_adsb m) -if(APPLE) - target_link_libraries(rtl_test m) -else() - target_link_libraries(rtl_test m rt) -endif() endif() -if(WIN32) -target_link_libraries(rtl_sdr libgetopt_static) -target_link_libraries(rtl_tcp libgetopt_static) -target_link_libraries(rtl_test libgetopt_static) -target_link_libraries(rtl_fm libgetopt_static) -target_link_libraries(rtl_433 libgetopt_static) -target_link_libraries(rtl_eeprom libgetopt_static) -target_link_libraries(rtl_adsb libgetopt_static) -set_property(TARGET rtl_sdr APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" ) -set_property(TARGET rtl_tcp APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" ) -set_property(TARGET rtl_test APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" ) -set_property(TARGET rtl_fm APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" ) -set_property(TARGET rtl_433 APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" ) -set_property(TARGET rtl_eeprom APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" ) -set_property(TARGET rtl_adsb APPEND PROPERTY COMPILE_DEFINITIONS "rtlsdr_STATIC" ) -endif() ######################################################################## # Install built library files & utilities ######################################################################## install(TARGETS ${INSTALL_TARGETS} - LIBRARY DESTINATION lib${LIB_SUFFIX} # .so/.dylib file - ARCHIVE DESTINATION lib${LIB_SUFFIX} # .lib file RUNTIME DESTINATION bin # .dll file ) diff --git a/src/Makefile.am b/src/Makefile.am index be48fbd7..430d998a 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,34 +1,21 @@ -# This is _NOT_ the library release version, it's an API version. -# Please read Chapter 6 "Library interface versions" of the libtool documentation before making any modification -LIBVERSION=0:0:0 - INCLUDES = $(all_includes) -I$(top_srcdir)/include AM_CFLAGS = ${CFLAGS} -fPIC ${SYMBOL_VISIBILITY} -lib_LTLIBRARIES = librtlsdr.la +bin_PROGRAMS = rtl_433 -librtlsdr_la_SOURCES = librtlsdr.c tuner_e4k.c tuner_fc0012.c tuner_fc0013.c tuner_fc2580.c tuner_r820t.c -librtlsdr_la_LDFLAGS = -version-info $(LIBVERSION) +rtl_433_SOURCES = rtl_433.c \ + devices/acurite.c \ + devices/intertechno.c \ + devices/newkaku.c \ + devices/rubicson.c \ + devices/waveman.c \ + devices/alecto.c \ + devices/lacrosse.c \ + devices/oregon_scientific.c \ + devices/silvercrest.c \ + devices/elv.c \ + devices/mebus.c \ + devices/prologue.c \ + devices/steffen.c -bin_PROGRAMS = rtl_sdr rtl_tcp rtl_test rtl_fm rtl_eeprom rtl_adsb rtl_433 - -rtl_sdr_SOURCES = rtl_sdr.c -rtl_sdr_LDADD = librtlsdr.la - -rtl_tcp_SOURCES = rtl_tcp.c -rtl_tcp_LDADD = librtlsdr.la - -rtl_test_SOURCES = rtl_test.c -rtl_test_LDADD = librtlsdr.la $(LIBM) - -rtl_fm_SOURCES = rtl_fm.c -rtl_fm_LDADD = librtlsdr.la $(LIBM) - -rtl_eeprom_SOURCES = rtl_eeprom.c -rtl_eeprom_LDADD = librtlsdr.la $(LIBM) - -rtl_adsb_SOURCES = rtl_adsb.c -rtl_adsb_LDADD = librtlsdr.la $(LIBM) - -rtl_433_SOURCES = rtl_433.c -rtl_433_LDADD = librtlsdr.la $(LIBM) +rtl_433_LDADD = $(LIBRTLSDR) $(LIBM) diff --git a/src/librtlsdr.c b/src/librtlsdr.c deleted file mode 100644 index 7aaa9716..00000000 --- a/src/librtlsdr.c +++ /dev/null @@ -1,1698 +0,0 @@ -/* - * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver - * Copyright (C) 2012 by Steve Markgraf <steve@steve-m.de> - * Copyright (C) 2012 by Dimitri Stolnikov <horiz0n@gmx.net> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <errno.h> -#include <signal.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#ifndef _WIN32 -#include <unistd.h> -#define min(a, b) (((a) < (b)) ? (a) : (b)) -#endif - -#include <libusb.h> - -/* - * All libusb callback functions should be marked with the LIBUSB_CALL macro - * to ensure that they are compiled with the same calling convention as libusb. - * - * If the macro isn't available in older libusb versions, we simply define it. - */ -#ifndef LIBUSB_CALL -#define LIBUSB_CALL -#endif - -/* two raised to the power of n */ -#define TWO_POW(n) ((double)(1ULL<<(n))) - -#include "rtl-sdr.h" -#include "tuner_e4k.h" -#include "tuner_fc0012.h" -#include "tuner_fc0013.h" -#include "tuner_fc2580.h" -#include "tuner_r820t.h" - -typedef struct rtlsdr_tuner_iface { - /* tuner interface */ - int (*init)(void *); - int (*exit)(void *); - int (*set_freq)(void *, uint32_t freq /* Hz */); - int (*set_bw)(void *, int bw /* Hz */); - int (*set_gain)(void *, int gain /* tenth dB */); - int (*set_if_gain)(void *, int stage, int gain /* tenth dB */); - int (*set_gain_mode)(void *, int manual); -} rtlsdr_tuner_iface_t; - -enum rtlsdr_async_status { - RTLSDR_INACTIVE = 0, - RTLSDR_CANCELING, - RTLSDR_RUNNING -}; - -struct rtlsdr_dev { - libusb_context *ctx; - struct libusb_device_handle *devh; - uint32_t xfer_buf_num; - uint32_t xfer_buf_len; - struct libusb_transfer **xfer; - unsigned char **xfer_buf; - rtlsdr_read_async_cb_t cb; - void *cb_ctx; - enum rtlsdr_async_status async_status; - /* rtl demod context */ - uint32_t rate; /* Hz */ - uint32_t rtl_xtal; /* Hz */ - int direct_sampling; - /* tuner context */ - enum rtlsdr_tuner tuner_type; - rtlsdr_tuner_iface_t *tuner; - uint32_t tun_xtal; /* Hz */ - uint32_t freq; /* Hz */ - uint32_t offs_freq; /* Hz */ - int corr; /* ppm */ - int gain; /* tenth dB */ - struct e4k_state e4k_s; -}; - -void rtlsdr_set_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int val); - -/* generic tuner interface functions, shall be moved to the tuner implementations */ -int e4000_init(void *dev) { - rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; - devt->e4k_s.i2c_addr = E4K_I2C_ADDR; - rtlsdr_get_xtal_freq(devt, NULL, &devt->e4k_s.vco.fosc); - devt->e4k_s.rtl_dev = dev; - return e4k_init(&devt->e4k_s); -} -int e4000_exit(void *dev) { return 0; } -int e4000_set_freq(void *dev, uint32_t freq) { - rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; - return e4k_tune_freq(&devt->e4k_s, freq); -} - -int e4000_set_bw(void *dev, int bw) { - int r = 0; - rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; - - r |= e4k_if_filter_bw_set(&devt->e4k_s, E4K_IF_FILTER_MIX, bw); - r |= e4k_if_filter_bw_set(&devt->e4k_s, E4K_IF_FILTER_RC, bw); - r |= e4k_if_filter_bw_set(&devt->e4k_s, E4K_IF_FILTER_CHAN, bw); - - return r; -} - -int e4000_set_gain(void *dev, int gain) { - rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; - int mixgain = (gain > 340) ? 12 : 4; -#if 0 - int enhgain = (gain - 420); -#endif - if(e4k_set_lna_gain(&devt->e4k_s, min(300, gain - mixgain * 10)) == -EINVAL) - return -1; - if(e4k_mixer_gain_set(&devt->e4k_s, mixgain) == -EINVAL) - return -1; -#if 0 /* enhanced mixer gain seems to have no effect */ - if(enhgain >= 0) - if(e4k_set_enh_gain(&devt->e4k_s, enhgain) == -EINVAL) - return -1; -#endif - return 0; -} -int e4000_set_if_gain(void *dev, int stage, int gain) { - rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; - return e4k_if_gain_set(&devt->e4k_s, (uint8_t)stage, (int8_t)(gain / 10)); -} -int e4000_set_gain_mode(void *dev, int manual) { - rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; - return e4k_enable_manual_gain(&devt->e4k_s, manual); -} - -int _fc0012_init(void *dev) { return fc0012_init(dev); } -int fc0012_exit(void *dev) { return 0; } -int fc0012_set_freq(void *dev, uint32_t freq) { - /* select V-band/U-band filter */ - rtlsdr_set_gpio_bit(dev, 6, (freq > 300000000) ? 1 : 0); - return fc0012_set_params(dev, freq, 6000000); -} -int fc0012_set_bw(void *dev, int bw) { return 0; } -int _fc0012_set_gain(void *dev, int gain) { return fc0012_set_gain(dev, gain); } -int fc0012_set_gain_mode(void *dev, int manual) { return 0; } - -int _fc0013_init(void *dev) { return fc0013_init(dev); } -int fc0013_exit(void *dev) { return 0; } -int fc0013_set_freq(void *dev, uint32_t freq) { - return fc0013_set_params(dev, freq, 6000000); -} -int fc0013_set_bw(void *dev, int bw) { return 0; } -int _fc0013_set_gain(void *dev, int gain) { return fc0013_set_lna_gain(dev, gain); } - -int fc2580_init(void *dev) { return fc2580_Initialize(dev); } -int fc2580_exit(void *dev) { return 0; } -int _fc2580_set_freq(void *dev, uint32_t freq) { - return fc2580_SetRfFreqHz(dev, freq); -} -int fc2580_set_bw(void *dev, int bw) { return fc2580_SetBandwidthMode(dev, 1); } -int fc2580_set_gain(void *dev, int gain) { return 0; } -int fc2580_set_gain_mode(void *dev, int manual) { return 0; } - -int r820t_init(void *dev) { - int r = R828_Init(dev); - r820t_SetStandardMode(dev, DVB_T_6M); - return r; -} -int r820t_exit(void *dev) { return 0; } -int r820t_set_freq(void *dev, uint32_t freq) { return r820t_SetRfFreqHz(dev, freq); } -int r820t_set_bw(void *dev, int bw) { return 0; } -int r820t_set_gain(void *dev, int gain) { return R828_SetRfGain(dev, gain); } -int r820t_set_gain_mode(void *dev, int manual) { return R828_RfGainMode(dev, manual); } - -/* definition order must match enum rtlsdr_tuner */ -static rtlsdr_tuner_iface_t tuners[] = { - { - NULL, NULL, NULL, NULL, NULL, NULL, NULL /* dummy for unknown tuners */ - }, - { - e4000_init, e4000_exit, - e4000_set_freq, e4000_set_bw, e4000_set_gain, e4000_set_if_gain, - e4000_set_gain_mode - }, - { - _fc0012_init, fc0012_exit, - fc0012_set_freq, fc0012_set_bw, _fc0012_set_gain, NULL, - fc0012_set_gain_mode - }, - { - _fc0013_init, fc0013_exit, - fc0013_set_freq, fc0013_set_bw, _fc0013_set_gain, NULL, - fc0013_set_gain_mode - }, - { - fc2580_init, fc2580_exit, - _fc2580_set_freq, fc2580_set_bw, fc2580_set_gain, NULL, - fc2580_set_gain_mode - }, - { - r820t_init, r820t_exit, - r820t_set_freq, r820t_set_bw, r820t_set_gain, NULL, - r820t_set_gain_mode - }, -}; - -typedef struct rtlsdr_dongle { - uint16_t vid; - uint16_t pid; - const char *name; -} rtlsdr_dongle_t; - -/* - * Please add your device here and send a patch to osmocom-sdr@lists.osmocom.org - */ -static rtlsdr_dongle_t known_devices[] = { - { 0x0bda, 0x2832, "Generic RTL2832U (e.g. hama nano)" }, - { 0x0bda, 0x2838, "ezcap USB 2.0 DVB-T/DAB/FM dongle" }, - { 0x0ccd, 0x00a9, "Terratec Cinergy T Stick Black (rev 1)" }, - { 0x0ccd, 0x00b3, "Terratec NOXON DAB/DAB+ USB dongle (rev 1)" }, - { 0x0ccd, 0x00b4, "Terratec NOXON DAB/DAB+ USB dongle (rev 1)" }, - { 0x0ccd, 0x00b7, "Terratec NOXON DAB/DAB+ USB dongle (rev 1)" }, - { 0x0ccd, 0x00c6, "Terratec NOXON DAB/DAB+ USB dongle (rev 1)" }, - { 0x0ccd, 0x00d3, "Terratec Cinergy T Stick RC (Rev.3)" }, - { 0x0ccd, 0x00d7, "Terratec T Stick PLUS" }, - { 0x0ccd, 0x00e0, "Terratec NOXON DAB/DAB+ USB dongle (rev 2)" }, - { 0x1554, 0x5020, "PixelView PV-DT235U(RN)" }, - { 0x185b, 0x0620, "Compro Videomate U620F"}, - { 0x185b, 0x0650, "Compro Videomate U650F"}, - { 0x185b, 0x0680, "Compro Videomate U680F"}, - { 0x1f4d, 0xa803, "Sweex DVB-T USB" }, - { 0x1f4d, 0xb803, "GTek T803" }, - { 0x1f4d, 0xc803, "Lifeview LV5TDeluxe" }, - { 0x1f4d, 0xd286, "MyGica TD312" }, - { 0x1f4d, 0xd803, "PROlectrix DV107669" }, - { 0x1b80, 0xd398, "Zaapa ZT-MINDVBZP" }, - { 0x1b80, 0xd3a4, "Twintech UT-40" }, - { 0x1d19, 0x1101, "Dexatek DK DVB-T Dongle (Logilink VG0002A)" }, - { 0x1d19, 0x1102, "Dexatek DK DVB-T Dongle (MSI DigiVox mini II V3.0)" }, - { 0x1d19, 0x1103, "Dexatek Technology Ltd. DK 5217 DVB-T Dongle" }, - { 0x1d19, 0x1104, "MSI DigiVox Micro HD" }, - { 0x0458, 0x707f, "Genius TVGo DVB-T03 USB dongle (Ver. B)" }, - { 0x1b80, 0xd393, "GIGABYTE GT-U7300" }, - { 0x1b80, 0xd394, "DIKOM USB-DVBT HD" }, - { 0x1b80, 0xd395, "Peak 102569AGPK" }, - { 0x1b80, 0xd39d, "SVEON STV20 DVB-T USB & FM" }, -}; - -#define DEFAULT_BUF_NUMBER 32 -#define DEFAULT_BUF_LENGTH (16 * 32 * 512) - -#define DEF_RTL_XTAL_FREQ 28800000 -#define MIN_RTL_XTAL_FREQ (DEF_RTL_XTAL_FREQ - 1000) -#define MAX_RTL_XTAL_FREQ (DEF_RTL_XTAL_FREQ + 1000) - -#define MAX_SAMP_RATE 3200000 - -#define CTRL_IN (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN) -#define CTRL_OUT (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT) -#define CTRL_TIMEOUT 300 -#define BULK_TIMEOUT 0 - -#define EEPROM_ADDR 0xa0 - -enum usb_reg { - USB_SYSCTL = 0x2000, - USB_CTRL = 0x2010, - USB_STAT = 0x2014, - USB_EPA_CFG = 0x2144, - USB_EPA_CTL = 0x2148, - USB_EPA_MAXPKT = 0x2158, - USB_EPA_MAXPKT_2 = 0x215a, - USB_EPA_FIFO_CFG = 0x2160, -}; - -enum sys_reg { - DEMOD_CTL = 0x3000, - GPO = 0x3001, - GPI = 0x3002, - GPOE = 0x3003, - GPD = 0x3004, - SYSINTE = 0x3005, - SYSINTS = 0x3006, - GP_CFG0 = 0x3007, - GP_CFG1 = 0x3008, - SYSINTE_1 = 0x3009, - SYSINTS_1 = 0x300a, - DEMOD_CTL_1 = 0x300b, - IR_SUSPEND = 0x300c, -}; - -enum blocks { - DEMODB = 0, - USBB = 1, - SYSB = 2, - TUNB = 3, - ROMB = 4, - IRB = 5, - IICB = 6, -}; - -int rtlsdr_read_array(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_t *array, uint8_t len) -{ - int r; - uint16_t index = (block << 8); - - r = libusb_control_transfer(dev->devh, CTRL_IN, 0, addr, index, array, len, CTRL_TIMEOUT); -#if 0 - if (r < 0) - fprintf(stderr, "%s failed with %d\n", __FUNCTION__, r); -#endif - return r; -} - -int rtlsdr_write_array(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_t *array, uint8_t len) -{ - int r; - uint16_t index = (block << 8) | 0x10; - - r = libusb_control_transfer(dev->devh, CTRL_OUT, 0, addr, index, array, len, CTRL_TIMEOUT); -#if 0 - if (r < 0) - fprintf(stderr, "%s failed with %d\n", __FUNCTION__, r); -#endif - return r; -} - -int rtlsdr_i2c_write_reg(rtlsdr_dev_t *dev, uint8_t i2c_addr, uint8_t reg, uint8_t val) -{ - uint16_t addr = i2c_addr; - uint8_t data[2]; - - data[0] = reg; - data[1] = val; - return rtlsdr_write_array(dev, IICB, addr, (uint8_t *)&data, 2); -} - -uint8_t rtlsdr_i2c_read_reg(rtlsdr_dev_t *dev, uint8_t i2c_addr, uint8_t reg) -{ - uint16_t addr = i2c_addr; - uint8_t data = 0; - - rtlsdr_write_array(dev, IICB, addr, ®, 1); - rtlsdr_read_array(dev, IICB, addr, &data, 1); - - return data; -} - -/* TODO clean this up again */ -int e4k_reg_write(struct e4k_state *e4k, uint8_t reg, uint8_t val) -{ - return rtlsdr_i2c_write_reg((rtlsdr_dev_t*)e4k->rtl_dev, e4k->i2c_addr, reg, val);} - -uint8_t e4k_reg_read(struct e4k_state *e4k, uint8_t reg) -{ - return rtlsdr_i2c_read_reg((rtlsdr_dev_t*)e4k->rtl_dev, e4k->i2c_addr, reg); -} - -int rtlsdr_i2c_write(rtlsdr_dev_t *dev, uint8_t i2c_addr, uint8_t *buffer, int len) -{ - uint16_t addr = i2c_addr; - - if (!dev) - return -1; - - return rtlsdr_write_array(dev, IICB, addr, buffer, len); -} - -int rtlsdr_i2c_read(rtlsdr_dev_t *dev, uint8_t i2c_addr, uint8_t *buffer, int len) -{ - uint16_t addr = i2c_addr; - - if (!dev) - return -1; - - return rtlsdr_read_array(dev, IICB, addr, buffer, len); -} - -uint16_t rtlsdr_read_reg(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_t len) -{ - int r; - unsigned char data[2]; - uint16_t index = (block << 8); - uint16_t reg; - - r = libusb_control_transfer(dev->devh, CTRL_IN, 0, addr, index, data, len, CTRL_TIMEOUT); - - if (r < 0) - fprintf(stderr, "%s failed with %d\n", __FUNCTION__, r); - - reg = (data[1] << 8) | data[0]; - - return reg; -} - -int rtlsdr_write_reg(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint16_t val, uint8_t len) -{ - int r; - unsigned char data[2]; - - uint16_t index = (block << 8) | 0x10; - - if (len == 1) - data[0] = val & 0xff; - else - data[0] = val >> 8; - - data[1] = val & 0xff; - - r = libusb_control_transfer(dev->devh, CTRL_OUT, 0, addr, index, data, len, CTRL_TIMEOUT); - - if (r < 0) - fprintf(stderr, "%s failed with %d\n", __FUNCTION__, r); - - return r; -} - -uint16_t rtlsdr_demod_read_reg(rtlsdr_dev_t *dev, uint8_t page, uint16_t addr, uint8_t len) -{ - int r; - unsigned char data[2]; - - uint16_t index = page; - uint16_t reg; - addr = (addr << 8) | 0x20; - - r = libusb_control_transfer(dev->devh, CTRL_IN, 0, addr, index, data, len, CTRL_TIMEOUT); - - if (r < 0) - fprintf(stderr, "%s failed with %d\n", __FUNCTION__, r); - - reg = (data[1] << 8) | data[0]; - - return reg; -} - -int rtlsdr_demod_write_reg(rtlsdr_dev_t *dev, uint8_t page, uint16_t addr, uint16_t val, uint8_t len) -{ - int r; - unsigned char data[2]; - uint16_t index = 0x10 | page; - addr = (addr << 8) | 0x20; - - if (len == 1) - data[0] = val & 0xff; - else - data[0] = val >> 8; - - data[1] = val & 0xff; - - r = libusb_control_transfer(dev->devh, CTRL_OUT, 0, addr, index, data, len, CTRL_TIMEOUT); - - if (r < 0) - fprintf(stderr, "%s failed with %d\n", __FUNCTION__, r); - - rtlsdr_demod_read_reg(dev, 0x0a, 0x01, 1); - - return (r == len) ? 0 : -1; -} - -void rtlsdr_set_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int val) -{ - uint8_t r; - - gpio = 1 << gpio; - r = rtlsdr_read_reg(dev, SYSB, GPO, 1); - r = val ? (r | gpio) : (r & ~gpio); - rtlsdr_write_reg(dev, SYSB, GPO, r, 1); -} - -void rtlsdr_set_gpio_output(rtlsdr_dev_t *dev, uint8_t gpio) -{ - int r; - gpio = 1 << gpio; - - r = rtlsdr_read_reg(dev, SYSB, GPD, 1); - rtlsdr_write_reg(dev, SYSB, GPO, r & ~gpio, 1); - r = rtlsdr_read_reg(dev, SYSB, GPOE, 1); - rtlsdr_write_reg(dev, SYSB, GPOE, r | gpio, 1); -} - -void rtlsdr_set_i2c_repeater(rtlsdr_dev_t *dev, int on) -{ - rtlsdr_demod_write_reg(dev, 1, 0x01, on ? 0x18 : 0x10, 1); -} - -void rtlsdr_init_baseband(rtlsdr_dev_t *dev) -{ - unsigned int i; - - /* default FIR coefficients used for DAB/FM by the Windows driver, - * the DVB driver uses different ones */ - uint8_t fir_coeff[] = { - 0xca, 0xdc, 0xd7, 0xd8, 0xe0, 0xf2, 0x0e, 0x35, 0x06, 0x50, - 0x9c, 0x0d, 0x71, 0x11, 0x14, 0x71, 0x74, 0x19, 0x41, 0xa5, - }; - - /* initialize USB */ - rtlsdr_write_reg(dev, USBB, USB_SYSCTL, 0x09, 1); - rtlsdr_write_reg(dev, USBB, USB_EPA_MAXPKT, 0x0002, 2); - rtlsdr_write_reg(dev, USBB, USB_EPA_CTL, 0x1002, 2); - - /* poweron demod */ - rtlsdr_write_reg(dev, SYSB, DEMOD_CTL_1, 0x22, 1); - rtlsdr_write_reg(dev, SYSB, DEMOD_CTL, 0xe8, 1); - - /* reset demod (bit 3, soft_rst) */ - rtlsdr_demod_write_reg(dev, 1, 0x01, 0x14, 1); - rtlsdr_demod_write_reg(dev, 1, 0x01, 0x10, 1); - - /* disable spectrum inversion and adjacent channel rejection */ - rtlsdr_demod_write_reg(dev, 1, 0x15, 0x00, 1); - rtlsdr_demod_write_reg(dev, 1, 0x16, 0x0000, 2); - - /* clear both DDC shift and IF frequency registers */ - for (i = 0; i < 6; i++) - rtlsdr_demod_write_reg(dev, 1, 0x16 + i, 0x00, 1); - - /* set FIR coefficients */ - for (i = 0; i < sizeof (fir_coeff); i++) - rtlsdr_demod_write_reg(dev, 1, 0x1c + i, fir_coeff[i], 1); - - /* enable SDR mode, disable DAGC (bit 5) */ - rtlsdr_demod_write_reg(dev, 0, 0x19, 0x05, 1); - - /* init FSM state-holding register */ - rtlsdr_demod_write_reg(dev, 1, 0x93, 0xf0, 1); - rtlsdr_demod_write_reg(dev, 1, 0x94, 0x0f, 1); - - /* disable AGC (en_dagc, bit 0) (this seems to have no effect) */ - rtlsdr_demod_write_reg(dev, 1, 0x11, 0x00, 1); - - /* disable RF and IF AGC loop */ - rtlsdr_demod_write_reg(dev, 1, 0x04, 0x00, 1); - - /* disable PID filter (enable_PID = 0) */ - rtlsdr_demod_write_reg(dev, 0, 0x61, 0x60, 1); - - /* opt_adc_iq = 0, default ADC_I/ADC_Q datapath */ - rtlsdr_demod_write_reg(dev, 0, 0x06, 0x80, 1); - - /* Enable Zero-IF mode (en_bbin bit), DC cancellation (en_dc_est), - * IQ estimation/compensation (en_iq_comp, en_iq_est) */ - rtlsdr_demod_write_reg(dev, 1, 0xb1, 0x1b, 1); - - /* disable 4.096 MHz clock output on pin TP_CK0 */ - rtlsdr_demod_write_reg(dev, 0, 0x0d, 0x83, 1); -} - -int rtlsdr_deinit_baseband(rtlsdr_dev_t *dev) -{ - int r = 0; - - if (!dev) - return -1; - - if (dev->tuner && dev->tuner->exit) { - rtlsdr_set_i2c_repeater(dev, 1); - r = dev->tuner->exit(dev); /* deinitialize tuner */ - rtlsdr_set_i2c_repeater(dev, 0); - } - - /* poweroff demodulator and ADCs */ - rtlsdr_write_reg(dev, SYSB, DEMOD_CTL, 0x20, 1); - - return r; -} - -int rtlsdr_set_if_freq(rtlsdr_dev_t *dev, uint32_t freq) -{ - uint32_t rtl_xtal; - int32_t if_freq; - uint8_t tmp; - int r; - - if (!dev) - return -1; - - /* read corrected clock value */ - if (rtlsdr_get_xtal_freq(dev, &rtl_xtal, NULL)) - return -2; - - if_freq = ((freq * TWO_POW(22)) / rtl_xtal) * (-1); - - tmp = (if_freq >> 16) & 0x3f; - r = rtlsdr_demod_write_reg(dev, 1, 0x19, tmp, 1); - tmp = (if_freq >> 8) & 0xff; - r |= rtlsdr_demod_write_reg(dev, 1, 0x1a, tmp, 1); - tmp = if_freq & 0xff; - r |= rtlsdr_demod_write_reg(dev, 1, 0x1b, tmp, 1); - - return r; -} - -int rtlsdr_set_sample_freq_correction(rtlsdr_dev_t *dev, int ppm) -{ - int r = 0; - uint8_t tmp; - int16_t offs = ppm * (-1) * TWO_POW(24) / 1000000; - - tmp = offs & 0xff; - r |= rtlsdr_demod_write_reg(dev, 1, 0x3f, tmp, 1); - tmp = (offs >> 8) & 0x3f; - r |= rtlsdr_demod_write_reg(dev, 1, 0x3e, tmp, 1); - - return r; -} - -int rtlsdr_set_xtal_freq(rtlsdr_dev_t *dev, uint32_t rtl_freq, uint32_t tuner_freq) -{ - int r = 0; - - if (!dev) - return -1; - - if (rtl_freq > 0 && - (rtl_freq < MIN_RTL_XTAL_FREQ || rtl_freq > MAX_RTL_XTAL_FREQ)) - return -2; - - if (rtl_freq > 0 && dev->rtl_xtal != rtl_freq) { - dev->rtl_xtal = rtl_freq; - - /* update xtal-dependent settings */ - if (dev->rate) - r = rtlsdr_set_sample_rate(dev, dev->rate); - } - - if (dev->tun_xtal != tuner_freq) { - if (0 == tuner_freq) - dev->tun_xtal = dev->rtl_xtal; - else - dev->tun_xtal = tuner_freq; - - /* read corrected clock value into e4k structure */ - if (rtlsdr_get_xtal_freq(dev, NULL, &dev->e4k_s.vco.fosc)) - return -3; - - /* update xtal-dependent settings */ - if (dev->freq) - r = rtlsdr_set_center_freq(dev, dev->freq); - } - - return r; -} - -int rtlsdr_get_xtal_freq(rtlsdr_dev_t *dev, uint32_t *rtl_freq, uint32_t *tuner_freq) -{ - if (!dev) - return -1; - - #define APPLY_PPM_CORR(val,ppm) (((val) * (1.0 + (ppm) / 1e6))) - - if (rtl_freq) - *rtl_freq = (uint32_t) APPLY_PPM_CORR(dev->rtl_xtal, dev->corr); - - if (tuner_freq) - *tuner_freq = (uint32_t) APPLY_PPM_CORR(dev->tun_xtal, dev->corr); - - return 0; -} - -int rtlsdr_get_usb_strings(rtlsdr_dev_t *dev, char *manufact, char *product, - char *serial) -{ - struct libusb_device_descriptor dd; - libusb_device *device = NULL; - const int buf_max = 256; - int r = 0; - - if (!dev || !dev->devh) - return -1; - - device = libusb_get_device(dev->devh); - - r = libusb_get_device_descriptor(device, &dd); - if (r < 0) - return -1; - - if (manufact) { - memset(manufact, 0, buf_max); - libusb_get_string_descriptor_ascii(dev->devh, dd.iManufacturer, - (unsigned char *)manufact, - buf_max); - } - - if (product) { - memset(product, 0, buf_max); - libusb_get_string_descriptor_ascii(dev->devh, dd.iProduct, - (unsigned char *)product, - buf_max); - } - - if (serial) { - memset(serial, 0, buf_max); - libusb_get_string_descriptor_ascii(dev->devh, dd.iSerialNumber, - (unsigned char *)serial, - buf_max); - } - - return 0; -} - -int rtlsdr_write_eeprom(rtlsdr_dev_t *dev, uint8_t *data, uint8_t offset, uint16_t len) -{ - int r = 0; - int i; - uint8_t cmd[2]; - - if (!dev) - return -1; - - if ((len + offset) > 256) - return -2; - - for (i = 0; i < len; i++) { - cmd[0] = i + offset; - r = rtlsdr_write_array(dev, IICB, EEPROM_ADDR, cmd, 1); - r = rtlsdr_read_array(dev, IICB, EEPROM_ADDR, &cmd[1], 1); - - /* only write the byte if it differs */ - if (cmd[1] == data[i]) - continue; - - cmd[1] = data[i]; - r = rtlsdr_write_array(dev, IICB, EEPROM_ADDR, cmd, 2); - if (r != sizeof(cmd)) - return -3; - - /* for some EEPROMs (e.g. ATC 240LC02) we need a delay - * between write operations, otherwise they will fail */ -#ifdef _WIN32 - Sleep(5); -#else - usleep(5000); -#endif - } - - return 0; -} - -int rtlsdr_read_eeprom(rtlsdr_dev_t *dev, uint8_t *data, uint8_t offset, uint16_t len) -{ - int r = 0; - int i; - - if (!dev) - return -1; - - if ((len + offset) > 256) - return -2; - - r = rtlsdr_write_array(dev, IICB, EEPROM_ADDR, &offset, 1); - if (r < 0) - return -3; - - for (i = 0; i < len; i++) { - r = rtlsdr_read_array(dev, IICB, EEPROM_ADDR, data + i, 1); - - if (r < 0) - return -3; - } - - return r; -} - -int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq) -{ - int r = -1; - - if (!dev || !dev->tuner) - return -1; - - if (dev->direct_sampling) { - r = rtlsdr_set_if_freq(dev, freq); - } else if (dev->tuner && dev->tuner->set_freq) { - rtlsdr_set_i2c_repeater(dev, 1); - r = dev->tuner->set_freq(dev, freq - dev->offs_freq); - rtlsdr_set_i2c_repeater(dev, 0); - } - - if (!r) - dev->freq = freq; - else - dev->freq = 0; - - return r; -} - -uint32_t rtlsdr_get_center_freq(rtlsdr_dev_t *dev) -{ - if (!dev) - return 0; - - return dev->freq; -} - -int rtlsdr_set_freq_correction(rtlsdr_dev_t *dev, int ppm) -{ - int r = 0; - - if (!dev) - return -1; - - if (dev->corr == ppm) - return -2; - - dev->corr = ppm; - - r |= rtlsdr_set_sample_freq_correction(dev, ppm); - - /* read corrected clock value into e4k structure */ - if (rtlsdr_get_xtal_freq(dev, NULL, &dev->e4k_s.vco.fosc)) - return -3; - - if (dev->freq) /* retune to apply new correction value */ - r |= rtlsdr_set_center_freq(dev, dev->freq); - - return r; -} - -int rtlsdr_get_freq_correction(rtlsdr_dev_t *dev) -{ - if (!dev) - return 0; - - return dev->corr; -} - -enum rtlsdr_tuner rtlsdr_get_tuner_type(rtlsdr_dev_t *dev) -{ - if (!dev) - return RTLSDR_TUNER_UNKNOWN; - - return dev->tuner_type; -} - -int rtlsdr_get_tuner_gains(rtlsdr_dev_t *dev, int *gains) -{ - /* all gain values are expressed in tenths of a dB */ - const int e4k_gains[] = { -10, 15, 40, 65, 90, 115, 140, 165, 190, 215, - 240, 290, 340, 420 }; - const int fc0012_gains[] = { -99, -40, 71, 179, 192 }; - const int fc0013_gains[] = { -99, -73, -65, -63, -60, -58, -54, 58, 61, - 63, 65, 67, 68, 70, 71, 179, 181, 182, - 184, 186, 188, 191, 197 }; - const int fc2580_gains[] = { 0 /* no gain values */ }; - const int r820t_gains[] = { 0, 9, 14, 27, 37, 77, 87, 125, 144, 157, - 166, 197, 207, 229, 254, 280, 297, 328, - 338, 364, 372, 386, 402, 421, 434, 439, - 445, 480, 496 }; - const int unknown_gains[] = { 0 /* no gain values */ }; - - const int *ptr = NULL; - int len = 0; - - if (!dev) - return -1; - - switch (dev->tuner_type) { - case RTLSDR_TUNER_E4000: - ptr = e4k_gains; len = sizeof(e4k_gains); - break; - case RTLSDR_TUNER_FC0012: - ptr = fc0012_gains; len = sizeof(fc0012_gains); - break; - case RTLSDR_TUNER_FC0013: - ptr = fc0013_gains; len = sizeof(fc0013_gains); - break; - case RTLSDR_TUNER_FC2580: - ptr = fc2580_gains; len = sizeof(fc2580_gains); - break; - case RTLSDR_TUNER_R820T: - ptr = r820t_gains; len = sizeof(r820t_gains); - break; - default: - ptr = unknown_gains; len = sizeof(unknown_gains); - break; - } - - if (!gains) { /* no buffer provided, just return the count */ - return len / sizeof(int); - } else { - if (len) - memcpy(gains, ptr, len); - - return len / sizeof(int); - } -} - -int rtlsdr_set_tuner_gain(rtlsdr_dev_t *dev, int gain) -{ - int r = 0; - - if (!dev || !dev->tuner) - return -1; - - if (dev->tuner->set_gain) { - rtlsdr_set_i2c_repeater(dev, 1); - r = dev->tuner->set_gain((void *)dev, gain); - rtlsdr_set_i2c_repeater(dev, 0); - } - - if (!r) - dev->gain = gain; - else - dev->gain = 0; - - return r; -} - -int rtlsdr_get_tuner_gain(rtlsdr_dev_t *dev) -{ - if (!dev) - return 0; - - return dev->gain; -} - -int rtlsdr_set_tuner_if_gain(rtlsdr_dev_t *dev, int stage, int gain) -{ - int r = 0; - - if (!dev || !dev->tuner) - return -1; - - if (dev->tuner->set_if_gain) { - rtlsdr_set_i2c_repeater(dev, 1); - r = dev->tuner->set_if_gain(dev, stage, gain); - rtlsdr_set_i2c_repeater(dev, 0); - } - - return r; -} - -int rtlsdr_set_tuner_gain_mode(rtlsdr_dev_t *dev, int mode) -{ - int r = 0; - - if (!dev || !dev->tuner) - return -1; - - if (dev->tuner->set_gain_mode) { - rtlsdr_set_i2c_repeater(dev, 1); - r = dev->tuner->set_gain_mode((void *)dev, mode); - rtlsdr_set_i2c_repeater(dev, 0); - } - - return r; -} - -int rtlsdr_set_sample_rate(rtlsdr_dev_t *dev, uint32_t samp_rate) -{ - int r = 0; - uint16_t tmp; - uint32_t rsamp_ratio; - double real_rate; - - if (!dev) - return -1; - - /* check for the maximum rate the resampler supports */ - if (samp_rate > MAX_SAMP_RATE) - samp_rate = MAX_SAMP_RATE; - - rsamp_ratio = (dev->rtl_xtal * TWO_POW(22)) / samp_rate; - rsamp_ratio &= ~3; - - real_rate = (dev->rtl_xtal * TWO_POW(22)) / rsamp_ratio; - - if ( ((double)samp_rate) != real_rate ) - fprintf(stderr, "Exact sample rate is: %f Hz\n", real_rate); - - if (dev->tuner && dev->tuner->set_bw) { - rtlsdr_set_i2c_repeater(dev, 1); - dev->tuner->set_bw(dev, (int)real_rate); - rtlsdr_set_i2c_repeater(dev, 0); - } - - dev->rate = (uint32_t)real_rate; - - tmp = (rsamp_ratio >> 16); - r |= rtlsdr_demod_write_reg(dev, 1, 0x9f, tmp, 2); - tmp = rsamp_ratio & 0xffff; - r |= rtlsdr_demod_write_reg(dev, 1, 0xa1, tmp, 2); - - r |= rtlsdr_set_sample_freq_correction(dev, dev->corr); - - /* reset demod (bit 3, soft_rst) */ - r |= rtlsdr_demod_write_reg(dev, 1, 0x01, 0x14, 1); - r |= rtlsdr_demod_write_reg(dev, 1, 0x01, 0x10, 1); - - /* recalculate offset frequency if offset tuning is enabled */ - if (dev->offs_freq) - rtlsdr_set_offset_tuning(dev, 1); - - return r; -} - -uint32_t rtlsdr_get_sample_rate(rtlsdr_dev_t *dev) -{ - if (!dev) - return 0; - - return dev->rate; -} - -int rtlsdr_set_testmode(rtlsdr_dev_t *dev, int on) -{ - if (!dev) - return -1; - - return rtlsdr_demod_write_reg(dev, 0, 0x19, on ? 0x03 : 0x05, 1); -} - -int rtlsdr_set_agc_mode(rtlsdr_dev_t *dev, int on) -{ - if (!dev) - return -1; - - return rtlsdr_demod_write_reg(dev, 0, 0x19, on ? 0x25 : 0x05, 1); -} - -int rtlsdr_set_direct_sampling(rtlsdr_dev_t *dev, int on) -{ - int r = 0; - - if (!dev) - return -1; - - if (on) { - if (dev->tuner && dev->tuner->exit) { - rtlsdr_set_i2c_repeater(dev, 1); - r = dev->tuner->exit(dev); - rtlsdr_set_i2c_repeater(dev, 0); - } - - /* disable Zero-IF mode */ - r |= rtlsdr_demod_write_reg(dev, 1, 0xb1, 0x1a, 1); - - /* disable spectrum inversion */ - r |= rtlsdr_demod_write_reg(dev, 1, 0x15, 0x00, 1); - - /* only enable In-phase ADC input */ - r |= rtlsdr_demod_write_reg(dev, 0, 0x08, 0x4d, 1); - - /* swap I and Q ADC, this allows to select between two inputs */ - r |= rtlsdr_demod_write_reg(dev, 0, 0x06, (on > 1) ? 0x90 : 0x80, 1); - - fprintf(stderr, "Enabled direct sampling mode, input %i\n", on); - dev->direct_sampling = on; - } else { - if (dev->tuner && dev->tuner->init) { - rtlsdr_set_i2c_repeater(dev, 1); - r |= dev->tuner->init(dev); - rtlsdr_set_i2c_repeater(dev, 0); - } - - if (dev->tuner_type == RTLSDR_TUNER_R820T) { - r |= rtlsdr_set_if_freq(dev, R820T_IF_FREQ); - - /* enable spectrum inversion */ - r |= rtlsdr_demod_write_reg(dev, 1, 0x15, 0x01, 1); - } else { - r |= rtlsdr_set_if_freq(dev, 0); - - /* enable In-phase + Quadrature ADC input */ - r |= rtlsdr_demod_write_reg(dev, 0, 0x08, 0xcd, 1); - - /* Enable Zero-IF mode */ - r |= rtlsdr_demod_write_reg(dev, 1, 0xb1, 0x1b, 1); - } - - /* opt_adc_iq = 0, default ADC_I/ADC_Q datapath */ - r |= rtlsdr_demod_write_reg(dev, 0, 0x06, 0x80, 1); - - fprintf(stderr, "Disabled direct sampling mode\n"); - dev->direct_sampling = 0; - } - - r |= rtlsdr_set_center_freq(dev, dev->freq); - - return r; -} - -int rtlsdr_get_direct_sampling(rtlsdr_dev_t *dev) -{ - if (!dev) - return -1; - - return dev->direct_sampling; -} - -int rtlsdr_set_offset_tuning(rtlsdr_dev_t *dev, int on) -{ - int r = 0; - - if (!dev) - return -1; - - if (dev->tuner_type == RTLSDR_TUNER_R820T) - return -2; - - if (dev->direct_sampling) - return -3; - - /* based on keenerds 1/f noise measurements */ - dev->offs_freq = on ? ((dev->rate / 2) * 170 / 100) : 0; - r |= rtlsdr_set_if_freq(dev, dev->offs_freq); - - if (dev->tuner && dev->tuner->set_bw) { - rtlsdr_set_i2c_repeater(dev, 1); - dev->tuner->set_bw(dev, on ? (2 * dev->offs_freq) : dev->rate); - rtlsdr_set_i2c_repeater(dev, 0); - } - - if (dev->freq > dev->offs_freq) - r |= rtlsdr_set_center_freq(dev, dev->freq); - - return r; -} - -int rtlsdr_get_offset_tuning(rtlsdr_dev_t *dev) -{ - if (!dev) - return -1; - - return (dev->offs_freq) ? 1 : 0; -} - -static rtlsdr_dongle_t *find_known_device(uint16_t vid, uint16_t pid) -{ - unsigned int i; - rtlsdr_dongle_t *device = NULL; - - for (i = 0; i < sizeof(known_devices)/sizeof(rtlsdr_dongle_t); i++ ) { - if (known_devices[i].vid == vid && known_devices[i].pid == pid) { - device = &known_devices[i]; - break; - } - } - - return device; -} - -uint32_t rtlsdr_get_device_count(void) -{ - int i; - libusb_context *ctx; - libusb_device **list; - uint32_t device_count = 0; - struct libusb_device_descriptor dd; - ssize_t cnt; - - libusb_init(&ctx); - - cnt = libusb_get_device_list(ctx, &list); - - for (i = 0; i < cnt; i++) { - libusb_get_device_descriptor(list[i], &dd); - - if (find_known_device(dd.idVendor, dd.idProduct)) - device_count++; - } - - libusb_free_device_list(list, 1); - - libusb_exit(ctx); - - return device_count; -} - -const char *rtlsdr_get_device_name(uint32_t index) -{ - int i; - libusb_context *ctx; - libusb_device **list; - struct libusb_device_descriptor dd; - rtlsdr_dongle_t *device = NULL; - uint32_t device_count = 0; - ssize_t cnt; - - libusb_init(&ctx); - - cnt = libusb_get_device_list(ctx, &list); - - for (i = 0; i < cnt; i++) { - libusb_get_device_descriptor(list[i], &dd); - - device = find_known_device(dd.idVendor, dd.idProduct); - - if (device) { - device_count++; - - if (index == device_count - 1) - break; - } - } - - libusb_free_device_list(list, 1); - - libusb_exit(ctx); - - if (device) - return device->name; - else - return ""; -} - -int rtlsdr_get_device_usb_strings(uint32_t index, char *manufact, - char *product, char *serial) -{ - int r = -2; - int i; - libusb_context *ctx; - libusb_device **list; - struct libusb_device_descriptor dd; - rtlsdr_dongle_t *device = NULL; - rtlsdr_dev_t devt; - uint32_t device_count = 0; - ssize_t cnt; - - libusb_init(&ctx); - - cnt = libusb_get_device_list(ctx, &list); - - for (i = 0; i < cnt; i++) { - libusb_get_device_descriptor(list[i], &dd); - - device = find_known_device(dd.idVendor, dd.idProduct); - - if (device) { - device_count++; - - if (index == device_count - 1) { - r = libusb_open(list[i], &devt.devh); - if (!r) { - r = rtlsdr_get_usb_strings(&devt, - manufact, - product, - serial); - libusb_close(devt.devh); - } - break; - } - } - } - - libusb_free_device_list(list, 1); - - libusb_exit(ctx); - - return r; -} - -int rtlsdr_get_index_by_serial(const char *serial) -{ - int i, cnt, r; - char str[256]; - - if (!serial) - return -1; - - cnt = rtlsdr_get_device_count(); - - if (!cnt) - return -2; - - for (i = 0; i < cnt; i++) { - r = rtlsdr_get_device_usb_strings(i, NULL, NULL, str); - if (!r && !strcmp(serial, str)) - return i; - } - - return -3; -} - -int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index) -{ - 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_open(device, &dev->devh); - 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); - - libusb_detach_kernel_driver(dev->devh, 0); - - 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; - - /* perform a dummy write, if it fails, reset the device */ - if (rtlsdr_write_reg(dev, USBB, USB_SYSCTL, 0x09, 1) < 0) { - fprintf(stderr, "Resetting device...\n"); - libusb_reset_device(dev->devh); - } - - 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 rtlsdr_close(rtlsdr_dev_t *dev) -{ - if (!dev) - return -1; - - /* block until all async operations have been completed (if any) */ - while (RTLSDR_INACTIVE != dev->async_status) { -#ifdef _WIN32 - Sleep(1); -#else - usleep(1000); -#endif - } - - rtlsdr_deinit_baseband(dev); - - libusb_release_interface(dev->devh, 0); - libusb_close(dev->devh); - - libusb_exit(dev->ctx); - - free(dev); - - return 0; -} - -int rtlsdr_reset_buffer(rtlsdr_dev_t *dev) -{ - if (!dev) - return -1; - - rtlsdr_write_reg(dev, USBB, USB_EPA_CTL, 0x1002, 2); - rtlsdr_write_reg(dev, USBB, USB_EPA_CTL, 0x0000, 2); - - return 0; -} - -int rtlsdr_read_sync(rtlsdr_dev_t *dev, void *buf, int len, int *n_read) -{ - if (!dev) - return -1; - - return libusb_bulk_transfer(dev->devh, 0x81, buf, len, n_read, BULK_TIMEOUT); -} - -static void LIBUSB_CALL _libusb_callback(struct libusb_transfer *xfer) -{ - rtlsdr_dev_t *dev = (rtlsdr_dev_t *)xfer->user_data; - - if (LIBUSB_TRANSFER_COMPLETED == xfer->status) { - if (dev->cb) - dev->cb(xfer->buffer, xfer->actual_length, dev->cb_ctx); - - libusb_submit_transfer(xfer); /* resubmit transfer */ - } else if (LIBUSB_TRANSFER_CANCELLED == xfer->status) { - /* nothing to do */ - } else { - /*fprintf(stderr, "transfer status: %d\n", xfer->status);*/ - } -} - -int rtlsdr_wait_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx) -{ - return rtlsdr_read_async(dev, cb, ctx, 0, 0); -} - -static int _rtlsdr_alloc_async_buffers(rtlsdr_dev_t *dev) -{ - unsigned int i; - - if (!dev) - return -1; - - if (!dev->xfer) { - dev->xfer = malloc(dev->xfer_buf_num * - sizeof(struct libusb_transfer *)); - - for(i = 0; i < dev->xfer_buf_num; ++i) - dev->xfer[i] = libusb_alloc_transfer(0); - } - - if (!dev->xfer_buf) { - dev->xfer_buf = malloc(dev->xfer_buf_num * - sizeof(unsigned char *)); - - for(i = 0; i < dev->xfer_buf_num; ++i) - dev->xfer_buf[i] = malloc(dev->xfer_buf_len); - } - - return 0; -} - -static int _rtlsdr_free_async_buffers(rtlsdr_dev_t *dev) -{ - unsigned int i; - - if (!dev) - return -1; - - if (dev->xfer) { - for(i = 0; i < dev->xfer_buf_num; ++i) { - if (dev->xfer[i]) { - libusb_free_transfer(dev->xfer[i]); - } - } - - free(dev->xfer); - dev->xfer = NULL; - } - - if (dev->xfer_buf) { - for(i = 0; i < dev->xfer_buf_num; ++i) { - if (dev->xfer_buf[i]) - free(dev->xfer_buf[i]); - } - - free(dev->xfer_buf); - dev->xfer_buf = NULL; - } - - return 0; -} - -int rtlsdr_read_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx, - uint32_t buf_num, uint32_t buf_len) -{ - unsigned int i; - int r = 0; - struct timeval tv = { 1, 0 }; - enum rtlsdr_async_status next_status = RTLSDR_INACTIVE; - - if (!dev) - return -1; - - if (RTLSDR_INACTIVE != dev->async_status) - return -2; - - dev->async_status = RTLSDR_RUNNING; - - dev->cb = cb; - dev->cb_ctx = ctx; - - if (buf_num > 0) - dev->xfer_buf_num = buf_num; - else - dev->xfer_buf_num = DEFAULT_BUF_NUMBER; - - if (buf_len > 0 && buf_len % 512 == 0) /* len must be multiple of 512 */ - dev->xfer_buf_len = buf_len; - else - dev->xfer_buf_len = DEFAULT_BUF_LENGTH; - - _rtlsdr_alloc_async_buffers(dev); - - for(i = 0; i < dev->xfer_buf_num; ++i) { - libusb_fill_bulk_transfer(dev->xfer[i], - dev->devh, - 0x81, - dev->xfer_buf[i], - dev->xfer_buf_len, - _libusb_callback, - (void *)dev, - BULK_TIMEOUT); - - libusb_submit_transfer(dev->xfer[i]); - } - - while (RTLSDR_INACTIVE != dev->async_status) { - r = libusb_handle_events_timeout(dev->ctx, &tv); - if (r < 0) { - /*fprintf(stderr, "handle_events returned: %d\n", r);*/ - if (r == LIBUSB_ERROR_INTERRUPTED) /* stray signal */ - continue; - break; - } - - if (RTLSDR_CANCELING == dev->async_status) { - next_status = RTLSDR_INACTIVE; - - if (!dev->xfer) - break; - - for(i = 0; i < dev->xfer_buf_num; ++i) { - if (!dev->xfer[i]) - continue; - - if (LIBUSB_TRANSFER_CANCELLED != - dev->xfer[i]->status) { - libusb_cancel_transfer(dev->xfer[i]); - next_status = RTLSDR_CANCELING; - } - } - - if (RTLSDR_INACTIVE == next_status) - break; - } - } - - _rtlsdr_free_async_buffers(dev); - - dev->async_status = next_status; - - return r; -} - -int rtlsdr_cancel_async(rtlsdr_dev_t *dev) -{ - if (!dev) - return -1; - - /* if streaming, try to cancel gracefully */ - if (RTLSDR_RUNNING == dev->async_status) { - dev->async_status = RTLSDR_CANCELING; - return 0; - } - - /* if called while in pending state, change the state forcefully */ - if (RTLSDR_INACTIVE != dev->async_status) { - dev->async_status = RTLSDR_INACTIVE; - return 0; - } - - return -2; -} - -uint32_t rtlsdr_get_tuner_clock(void *dev) -{ - uint32_t tuner_freq; - - if (!dev) - return 0; - - /* read corrected clock value */ - if (rtlsdr_get_xtal_freq((rtlsdr_dev_t *)dev, NULL, &tuner_freq)) - return 0; - - return tuner_freq; -} - -int rtlsdr_i2c_write_fn(void *dev, uint8_t addr, uint8_t *buf, int len) -{ - if (dev) - return rtlsdr_i2c_write(((rtlsdr_dev_t *)dev), addr, buf, len); - - return -1; -} - -int rtlsdr_i2c_read_fn(void *dev, uint8_t addr, uint8_t *buf, int len) -{ - if (dev) - return rtlsdr_i2c_read(((rtlsdr_dev_t *)dev), addr, buf, len); - - return -1; -} diff --git a/src/rtl_adsb.c b/src/rtl_adsb.c deleted file mode 100644 index 2fb74188..00000000 --- a/src/rtl_adsb.c +++ /dev/null @@ -1,512 +0,0 @@ -/* - * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver - * Copyright (C) 2012 by Steve Markgraf <steve@steve-m.de> - * Copyright (C) 2012 by Hoernchen <la@tfc-server.de> - * Copyright (C) 2012 by Kyle Keen <keenerd@gmail.com> - * Copyright (C) 2012 by Youssef Touil <youssef@sdrsharp.com> - * Copyright (C) 2012 by Ian Gilmour <ian@sdrsharp.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - - -#include <errno.h> -#include <signal.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <math.h> - -#ifndef _WIN32 -#include <unistd.h> -#else -#include <Windows.h> -#include <fcntl.h> -#include <io.h> -#include "getopt/getopt.h" -#endif - -#include <semaphore.h> -#include <pthread.h> -#include <libusb.h> - -#include "rtl-sdr.h" - -#ifdef _WIN32 -#define sleep Sleep -#define round(x) (x > 0.0 ? floor(x + 0.5): ceil(x - 0.5)) -#endif - -#define ADSB_RATE 2000000 -#define ADSB_FREQ 1090000000 -#define DEFAULT_ASYNC_BUF_NUMBER 12 -#define DEFAULT_BUF_LENGTH (16 * 16384) -#define AUTO_GAIN -100 - -static pthread_t demod_thread; -static sem_t data_ready; -static volatile int do_exit = 0; -static rtlsdr_dev_t *dev = NULL; - -/* look up table, could be made smaller */ -uint8_t pyth[129][129]; - -/* todo, bundle these up in a struct */ -uint8_t *buffer; -int verbose_output = 0; -int short_output = 0; -double quality = 1.0; -int allowed_errors = 5; -FILE *file; -int adsb_frame[14]; -#define preamble_len 16 -#define long_frame 112 -#define short_frame 56 - -void usage(void) -{ - fprintf(stderr, - "rtl_adsb, a simple ADS-B decoder\n\n" - "Use:\trtl_adsb [-R] [-g gain] [-p ppm] [output file]\n" - "\t[-d device_index (default: 0)]\n" - "\t[-V verbove output (default: off)]\n" - "\t[-S show short frames (default: off)]\n" - "\t[-Q quality (0: no sanity checks, 0.5: half bit, 1: one bit (default), 2: two bits)]\n" - "\t[-e allowed_errors (default: 5)]\n" - "\t[-g tuner_gain (default: automatic)]\n" - "\t[-p ppm_error (default: 0)]\n" - "\tfilename (a '-' dumps samples to stdout)\n" - "\t (omitting the filename also uses stdout)\n\n" - "Streaming with netcat:\n" - "\trtl_adsb | netcat -lp 8080\n" - "\twhile true; do rtl_adsb | nc -lp 8080; done\n" - "Streaming with socat:\n" - "\trtl_adsb | socat -u - TCP4:sdrsharp.com:47806\n" - "\n"); - exit(1); -} - -#ifdef _WIN32 -BOOL WINAPI -sighandler(int signum) -{ - if (CTRL_C_EVENT == signum) { - fprintf(stderr, "Signal caught, exiting!\n"); - do_exit = 1; - rtlsdr_cancel_async(dev); - return TRUE; - } - return FALSE; -} -#else -static void sighandler(int signum) -{ - fprintf(stderr, "Signal caught, exiting!\n"); - do_exit = 1; - rtlsdr_cancel_async(dev); -} -#endif - -void display(int *frame, int len) -{ - int i, df; - if (!short_output && len <= short_frame) { - return;} - df = (frame[0] >> 3) & 0x1f; - if (quality == 0.0 && !(df==11 || df==17 || df==18 || df==19)) { - return;} - fprintf(file, "*"); - for (i=0; i<((len+7)/8); i++) { - fprintf(file, "%02x", frame[i]);} - fprintf(file, ";\r\n"); - if (!verbose_output) { - return;} - fprintf(file, "DF=%i CA=%i\n", df, frame[0] & 0x07); - fprintf(file, "ICAO Address=%06x\n", frame[1] << 16 | frame[2] << 8 | frame[3]); - if (len <= short_frame) { - return;} - fprintf(file, "PI=0x%06x\n", frame[11] << 16 | frame[12] << 8 | frame[13]); - fprintf(file, "Type Code=%i S.Type/Ant.=%x\n", (frame[4] >> 3) & 0x1f, frame[4] & 0x07); - fprintf(file, "--------------\n"); -} - -void pyth_precompute(void) -{ - int x, y; - double scale = 1.408 ; /* use the full 8 bits */ - for (x=0; x<129; x++) { - for (y=0; y<129; y++) { - pyth[x][y] = (uint8_t)round(scale * sqrt(x*x + y*y)); - }} -} - -inline uint8_t abs8(uint8_t x) -/* do not subtract 128 from the raw iq, this handles it */ -{ - if (x >= 128) { - return x - 128;} - return 128 - x; -} - -int magnitute(uint8_t *buf, int len) -/* takes i/q, changes buf in place, returns new len */ -{ - int i; - for (i=0; i<len; i+=2) { - buf[i/2] = pyth[abs8(buf[i])][abs8(buf[i+1])]; - } - return len/2; -} - -inline uint8_t single_manchester(uint8_t a, uint8_t b, uint8_t c, uint8_t d) -/* takes 4 consecutive real samples, return 0 or 1, 255 on error */ -{ - int bit, bit_p; - bit_p = a > b; - bit = c > d; - - if (quality == 0.0) { - return bit;} - - if (quality == 0.5) { - if ( bit && bit_p && b > c) { - return 255;} - if (!bit && !bit_p && b < c) { - return 255;} - return bit; - } - - if (quality == 1.0) { - if ( bit && bit_p && c > b) { - return 1;} - if ( bit && !bit_p && d < b) { - return 1;} - if (!bit && bit_p && d > b) { - return 0;} - if (!bit && !bit_p && c < b) { - return 0;} - return 255; - } - - if ( bit && bit_p && c > b && d < a) { - return 1;} - if ( bit && !bit_p && c > a && d < b) { - return 1;} - if (!bit && bit_p && c < a && d > b) { - return 0;} - if (!bit && !bit_p && c < b && d > a) { - return 0;} - return 255; -} - -inline uint8_t min8(uint8_t a, uint8_t b) -{ - return a<b ? a : b; -} - -inline uint8_t max8(uint8_t a, uint8_t b) -{ - return a>b ? a : b; -} - -inline int preamble(uint8_t *buf, int len, int i) -/* returns 0/1 for preamble at index i */ -{ - int i2; - uint8_t low = 0; - uint8_t high = 255; - for (i2=0; i2<preamble_len; i2++) { - switch (i2) { - case 0: - case 2: - case 7: - case 9: - //high = min8(high, buf[i+i2]); - high = buf[i+i2]; - break; - default: - //low = max8(low, buf[i+i2]); - low = buf[i+i2]; - break; - } - if (high <= low) { - return 0;} - } - return 1; -} - -void manchester(uint8_t *buf, int len) -/* overwrites magnitude buffer with valid bits (255 on errors) */ -{ - /* a and b hold old values to verify local manchester */ - uint8_t a=0, b=0; - uint8_t bit; - int i, i2, start, errors; - // todo, allow wrap across buffers - i = 0; - while (i < len) { - /* find preamble */ - for ( ; i < (len - preamble_len); i++) { - if (!preamble(buf, len, i)) { - continue;} - a = buf[i]; - b = buf[i+1]; - for (i2=0; i2<preamble_len; i2++) { - buf[i+i2] = 253;} - i += preamble_len; - break; - } - i2 = start = i; - errors = 0; - /* mark bits until encoding breaks */ - for ( ; i < len; i+=2, i2++) { - bit = single_manchester(a, b, buf[i], buf[i+1]); - a = buf[i]; - b = buf[i+1]; - if (bit == 255) { - errors += 1; - if (errors > allowed_errors) { - buf[i2] = 255; - break; - } else { - bit = a > b; - /* these don't have to match the bit */ - a = 0; - b = 255; - } - } - buf[i] = buf[i+1] = 254; /* to be overwritten */ - buf[i2] = bit; - } - } -} - -void messages(uint8_t *buf, int len) -{ - int i, i2, start, preamble_found; - int data_i, index, shift, frame_len; - // todo, allow wrap across buffers - for (i=0; i<len; i++) { - if (buf[i] > 1) { - continue;} - frame_len = long_frame; - data_i = 0; - for (index=0; index<14; index++) { - adsb_frame[index] = 0;} - for(; i<len && buf[i]<=1 && data_i<frame_len; i++, data_i++) { - if (buf[i]) { - index = data_i / 8; - shift = 7 - (data_i % 8); - adsb_frame[index] |= (uint8_t)(1<<shift); - } - if (data_i == 7) { - if (adsb_frame[0] == 0) { - break;} - if (adsb_frame[0] & 0x80) { - frame_len = long_frame;} - else { - frame_len = short_frame;} - } - } - if (data_i < (frame_len-1)) { - continue;} - display(adsb_frame, frame_len); - fflush(file); - } -} - -static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) -{ - int dr_val; - if (do_exit) { - return;} - memcpy(buffer, buf, len); - sem_getvalue(&data_ready, &dr_val); - if (dr_val <= 0) { - sem_post(&data_ready);} -} - -static void *demod_thread_fn(void *arg) -{ - int len; - while (!do_exit) { - sem_wait(&data_ready); - len = magnitute(buffer, DEFAULT_BUF_LENGTH); - manchester(buffer, len); - messages(buffer, len); - } - rtlsdr_cancel_async(dev); - return 0; -} - -int main(int argc, char **argv) -{ -#ifndef _WIN32 - struct sigaction sigact; -#endif - char *filename = NULL; - int n_read, r, opt; - int i, gain = AUTO_GAIN; /* tenths of a dB */ - uint32_t dev_index = 0; - int device_count; - int ppm_error = 0; - char vendor[256], product[256], serial[256]; - sem_init(&data_ready, 0, 0); - pyth_precompute(); - - while ((opt = getopt(argc, argv, "d:g:p:e:Q:VS")) != -1) - { - switch (opt) { - case 'd': - dev_index = atoi(optarg); - break; - case 'g': - gain = (int)(atof(optarg) * 10); - break; - case 'p': - ppm_error = atoi(optarg); - break; - case 'V': - verbose_output = 1; - break; - case 'S': - short_output = 1; - break; - case 'e': - allowed_errors = atoi(optarg); - break; - case 'Q': - quality = atof(optarg); - break; - default: - usage(); - return 0; - } - } - - if (argc <= optind) { - filename = "-"; - } else { - filename = argv[optind]; - } - - buffer = malloc(DEFAULT_BUF_LENGTH * 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)); - - 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 - - if (strcmp(filename, "-") == 0) { /* Write samples to stdout */ - file = stdout; - setvbuf(stdout, NULL, _IONBF, 0); -#ifdef _WIN32 - _setmode(_fileno(file), _O_BINARY); -#endif - } 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) { - r = rtlsdr_set_tuner_gain_mode(dev, 0); - } else { - r = rtlsdr_set_tuner_gain_mode(dev, 1); - r = rtlsdr_set_tuner_gain(dev, gain); - } - if (r != 0) { - fprintf(stderr, "WARNING: Failed to set tuner gain.\n"); - } else if (gain == AUTO_GAIN) { - fprintf(stderr, "Tuner gain set to automatic.\n"); - } else { - fprintf(stderr, "Tuner gain set to %0.2f dB.\n", gain/10.0); - } - - r = rtlsdr_set_freq_correction(dev, ppm_error); - r = rtlsdr_set_agc_mode(dev, 1); - - /* Set the tuner frequency */ - r = rtlsdr_set_center_freq(dev, ADSB_FREQ); - if (r < 0) { - fprintf(stderr, "WARNING: Failed to set center freq.\n");} - else { - fprintf(stderr, "Tuned to %u Hz.\n", ADSB_FREQ);} - - /* Set the sample rate */ - fprintf(stderr, "Sampling at %u Hz.\n", ADSB_RATE); - r = rtlsdr_set_sample_rate(dev, ADSB_RATE); - if (r < 0) { - fprintf(stderr, "WARNING: Failed to set sample rate.\n");} - - /* 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");} - - /* flush old junk */ - sleep(1); - rtlsdr_read_sync(dev, NULL, 4096, NULL); - - 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); - - if (file != stdout) { - fclose(file);} - - rtlsdr_close(dev); - free(buffer); - return r >= 0 ? r : -r; -} - diff --git a/src/rtl_eeprom.c b/src/rtl_eeprom.c deleted file mode 100644 index 35191dee..00000000 --- a/src/rtl_eeprom.c +++ /dev/null @@ -1,423 +0,0 @@ -/* - * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver - * rtl_eeprom, EEPROM modification tool - * Copyright (C) 2012 by Steve Markgraf <steve@steve-m.de> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <string.h> -#include <stdio.h> -#include <stdlib.h> - -#ifndef _WIN32 -#include <unistd.h> -#else -#include <Windows.h> -#include "getopt/getopt.h" -#endif - -#include "rtl-sdr.h" - -#define EEPROM_SIZE 256 -#define MAX_STR_SIZE 256 -#define STR_OFFSET 0x09 - -static rtlsdr_dev_t *dev = NULL; - -typedef struct rtlsdr_config { - uint16_t vendor_id; - uint16_t product_id; - char manufacturer[MAX_STR_SIZE]; - char product[MAX_STR_SIZE]; - char serial[MAX_STR_SIZE]; - int have_serial; - int enable_ir; - int remote_wakeup; -} rtlsdr_config_t; - -void dump_config(rtlsdr_config_t *conf) -{ - fprintf(stderr, "__________________________________________\n"); - fprintf(stderr, "Vendor ID:\t\t0x%04x\n", conf->vendor_id); - fprintf(stderr, "Product ID:\t\t0x%04x\n", conf->product_id); - fprintf(stderr, "Manufacturer:\t\t%s\n", conf->manufacturer); - fprintf(stderr, "Product:\t\t%s\n", conf->product); - fprintf(stderr, "Serial number:\t\t%s\n", conf->serial); - fprintf(stderr, "Serial number enabled:\t"); - fprintf(stderr, conf->have_serial ? "yes\n": "no\n"); - fprintf(stderr, "IR endpoint enabled:\t"); - fprintf(stderr, conf->enable_ir ? "yes\n": "no\n"); - fprintf(stderr, "Remote wakeup enabled:\t"); - fprintf(stderr, conf->remote_wakeup ? "yes\n": "no\n"); - fprintf(stderr, "__________________________________________\n"); -} - -void usage(void) -{ - fprintf(stderr, - "rtl_eeprom, an EEPROM programming tool for " - "RTL2832 based DVB-T receivers\n\n" - "Usage:\n" - "\t[-d device_index (default: 0)]\n" - "\t[-m <str> set manufacturer string]\n" - "\t[-p <str> set product string]\n" - "\t[-s <str> set serial number string]\n" - "\t[-i <0,1> disable/enable IR-endpoint]\n" - "\t[-g <conf> generate default config and write to device]\n" - "\t[ <conf> can be one of:]\n" - "\t[ realtek\t\tRealtek default (as without EEPROM)]\n" - "\t[ realtek_oem\t\tRealtek default OEM with EEPROM]\n" - "\t[ noxon\t\tTerratec NOXON DAB Stick]\n" - "\t[ terratec_black\tTerratec T Stick Black]\n" - "\t[ terratec_plus\tTerratec T Stick+ (DVB-T/DAB)]\n" - "\t[-w <filename> write dumped file to device]\n" - "\t[-r <filename> dump EEPROM to file]\n" - "\t[-h display this help text]\n" - "\nUse on your own risk, especially -w!\n"); - exit(1); -} - -int get_string_descriptor(int pos, uint8_t *data, char *str) -{ - int len, i, j = 0; - - len = data[pos]; - - if (data[pos + 1] != 0x03) - fprintf(stderr, "Error: invalid string descriptor!\n"); - - for (i = 2; i < len; i += 2) - str[j++] = data[pos + i]; - - str[j] = 0x00; - - return pos + i; -} - -int set_string_descriptor(int pos, uint8_t *data, char *str) -{ - int i = 0, j = 2; - - if (pos < 0) - return -1; - - data[pos + 1] = 0x03; - - while (str[i] != 0x00) { - if ((pos + j) >= 78) { - fprintf(stderr, "Error: string too long, truncated!\n"); - return -1; - } - data[pos + j++] = str[i++]; - data[pos + j++] = 0x00; - } - - data[pos] = j; - - return pos + j; -} - -int parse_eeprom_to_conf(rtlsdr_config_t *conf, uint8_t *dat) -{ - int pos; - - if ((dat[0] != 0x28) || (dat[1] != 0x32)) - fprintf(stderr, "Error: invalid RTL2832 EEPROM header!\n"); - - conf->vendor_id = dat[2] | (dat[3] << 8); - conf->product_id = dat[4] | (dat[5] << 8); - conf->have_serial = (dat[6] == 0xa5) ? 1 : 0; - conf->remote_wakeup = (dat[7] & 0x01) ? 1 : 0; - conf->enable_ir = (dat[7] & 0x02) ? 1 : 0; - - pos = get_string_descriptor(STR_OFFSET, dat, conf->manufacturer); - pos = get_string_descriptor(pos, dat, conf->product); - get_string_descriptor(pos, dat, conf->serial); - - return 0; -} - -int gen_eeprom_from_conf(rtlsdr_config_t *conf, uint8_t *dat) -{ - int pos; - - dat[0] = 0x28; - dat[1] = 0x32; - dat[2] = conf->vendor_id & 0xff; - dat[3] = (conf->vendor_id >> 8) & 0xff ; - dat[4] = conf->product_id & 0xff; - dat[5] = (conf->product_id >> 8) & 0xff; - dat[6] = conf->have_serial ? 0xa5 : 0x00; - dat[7] = 0x14; - dat[7] |= conf->remote_wakeup ? 0x01 : 0x00; - dat[7] |= conf->enable_ir ? 0x02 : 0x00; - dat[8] = 0x02; - - pos = set_string_descriptor(STR_OFFSET, dat, conf->manufacturer); - pos = set_string_descriptor(pos, dat, conf->product); - pos = set_string_descriptor(pos, dat, conf->serial); - - dat[78] = 0x00; /* length of IR config */ - - return pos; -} - -enum configs { - CONF_NONE = 0, - REALTEK, - REALTEK_EEPROM, - TERRATEC_NOXON, - TERRATEC_T_BLACK, - TERRATEC_T_PLUS, -}; - -void gen_default_conf(rtlsdr_config_t *conf, int config) -{ - switch (config) { - case REALTEK: - fprintf(stderr, "Realtek default (as without EEPROM)\n"); - conf->vendor_id = 0x0bda; - conf->product_id = 0x2832; - strcpy(conf->manufacturer, "Generic"); - strcpy(conf->product, "RTL2832U DVB-T"); - strcpy(conf->serial, "0"); - conf->have_serial = 1; - conf->enable_ir = 0; - conf->remote_wakeup = 1; - break; - case REALTEK_EEPROM: - fprintf(stderr, "Realtek default OEM with EEPROM\n"); - conf->vendor_id = 0x0bda; - conf->product_id = 0x2838; - strcpy(conf->manufacturer, "Realtek"); - strcpy(conf->product, "RTL2838UHIDIR"); - strcpy(conf->serial, "00000001"); - conf->have_serial = 1; - conf->enable_ir = 1; - conf->remote_wakeup = 0; - break; - case TERRATEC_NOXON: - fprintf(stderr, "Terratec NOXON DAB Stick\n"); - conf->vendor_id = 0x0ccd; - conf->product_id = 0x00b3; - strcpy(conf->manufacturer, "NOXON"); - strcpy(conf->product, "DAB Stick"); - strcpy(conf->serial, "0"); - conf->have_serial = 1; - conf->enable_ir = 0; - conf->remote_wakeup = 1; - break; - case TERRATEC_T_BLACK: - fprintf(stderr, "Terratec T Stick Black\n"); - conf->vendor_id = 0x0ccd; - conf->product_id = 0x00a9; - strcpy(conf->manufacturer, "Realtek"); - strcpy(conf->product, "RTL2838UHIDIR"); - strcpy(conf->serial, "00000001"); - conf->have_serial = 1; - conf->enable_ir = 1; - conf->remote_wakeup = 0; - break; - case TERRATEC_T_PLUS: - fprintf(stderr, "Terratec ran T Stick+\n"); - conf->vendor_id = 0x0ccd; - conf->product_id = 0x00d7; - strcpy(conf->manufacturer, "Realtek"); - strcpy(conf->product, "RTL2838UHIDIR"); - strcpy(conf->serial, "00000001"); - conf->have_serial = 1; - conf->enable_ir = 1; - conf->remote_wakeup = 0; - break; - default: - break; - }; -} - -int main(int argc, char **argv) -{ - int i, r, opt; - uint32_t dev_index = 0; - int device_count; - char *filename = NULL; - FILE *file = NULL; - char *manuf_str = NULL; - char *product_str = NULL; - char *serial_str = NULL; - uint8_t buf[EEPROM_SIZE]; - rtlsdr_config_t conf; - int flash_file = 0; - int default_config = 0; - int change = 0; - int ir_endpoint = 0; - char ch; - - while ((opt = getopt(argc, argv, "d:m:p:s:i:g:w:r:h?")) != -1) { - switch (opt) { - case 'd': - dev_index = atoi(optarg); - break; - case 'm': - manuf_str = optarg; - change = 1; - break; - case 'p': - product_str = optarg; - change = 1; - break; - case 's': - serial_str = optarg; - change = 1; - break; - case 'i': - ir_endpoint = (atoi(optarg) > 0) ? 1 : -1; - change = 1; - break; - case 'g': - if (!strcmp(optarg, "realtek")) - default_config = REALTEK; - else if (!strcmp(optarg, "realtek_oem")) - default_config = REALTEK_EEPROM; - else if (!strcmp(optarg, "noxon")) - default_config = TERRATEC_NOXON; - else if (!strcmp(optarg, "terratec_black")) - default_config = TERRATEC_T_BLACK; - else if (!strcmp(optarg, "terratec_plus")) - default_config = TERRATEC_T_PLUS; - - if (default_config != CONF_NONE) - change = 1; - break; - case 'w': - flash_file = 1; - change = 1; - case 'r': - filename = optarg; - break; - default: - usage(); - break; - } - } - - 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); - } - - fprintf(stderr, "\n"); - - r = rtlsdr_read_eeprom(dev, buf, 0, EEPROM_SIZE); - if (r < 0) { - if (r == -3) - fprintf(stderr, "No EEPROM has been found.\n"); - else - fprintf(stderr, "Failed to read EEPROM, err %i.\n", r); - goto exit; - } - - if (r < 0) - return -1; - - fprintf(stderr, "Current configuration:\n"); - parse_eeprom_to_conf(&conf, buf); - dump_config(&conf); - - if (filename) { - file = fopen(filename, flash_file ? "rb" : "wb"); - if (!file) { - fprintf(stderr, "Error opening file!\n"); - goto exit; - } - if (flash_file) { - if (fread(buf, 1, sizeof(buf), file) != sizeof(buf)) - fprintf(stderr, "Error reading file!\n"); - } else { - if (fwrite(buf, 1, sizeof(buf), file) != sizeof(buf)) - fprintf(stderr, "Short write, exiting!\n"); - else - fprintf(stderr, "\nDump to %s successful.\n", filename); - } - } - - if (manuf_str) - strncpy((char*)&conf.manufacturer, manuf_str, MAX_STR_SIZE); - - if (product_str) - strncpy((char*)&conf.product, product_str, MAX_STR_SIZE); - - if (serial_str) { - conf.have_serial = 1; - strncpy((char*)&conf.serial, serial_str, MAX_STR_SIZE); - } - - if (ir_endpoint != 0) - conf.enable_ir = (ir_endpoint > 0) ? 1 : 0; - - if (!change) - goto exit; - - fprintf(stderr, "\nNew configuration:\n"); - - if (default_config != CONF_NONE) - gen_default_conf(&conf, default_config); - - if (!flash_file) { - if (gen_eeprom_from_conf(&conf, buf) < 0) - goto exit; - } - - parse_eeprom_to_conf(&conf, buf); - dump_config(&conf); - - fprintf(stderr, "Write new configuration to device [y/n]? "); - - while ((ch = getchar())) { - if (ch != 'y') - goto exit; - else - break; - } - - r = rtlsdr_write_eeprom(dev, buf, 0, flash_file ? EEPROM_SIZE : 128); - if (r < 0) - fprintf(stderr, "Error while writing EEPROM: %i\n", r); - else - fprintf(stderr, "Configuration successfully written.\n"); - -exit: - if (file) - fclose(file); - - rtlsdr_close(dev); - - return r >= 0 ? r : -r; -} diff --git a/src/rtl_fm.c b/src/rtl_fm.c deleted file mode 100644 index 45f8e065..00000000 --- a/src/rtl_fm.c +++ /dev/null @@ -1,838 +0,0 @@ -/* - * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver - * Copyright (C) 2012 by Steve Markgraf <steve@steve-m.de> - * Copyright (C) 2012 by Hoernchen <la@tfc-server.de> - * Copyright (C) 2012 by Kyle Keen <keenerd@gmail.com> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - - -/* - * written because people could not do real time - * FM demod on Atom hardware with GNU radio - * based on rtl_sdr.c and rtl_tcp.c - * todo: realtime ARMv5 - * remove float math (disqualifies complex.h) - * in-place array operations - * sanity checks - * nicer FIR than square - * scale squelch to other input parameters - * test all the demodulations - * pad output on hop - * nearest gain approx - * frequency ranges could be stored better - */ - -#include <errno.h> -#include <signal.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <math.h> - -#ifndef _WIN32 -#include <unistd.h> -#else -#include <Windows.h> -#include <fcntl.h> -#include <io.h> -#include "getopt/getopt.h" -#define usleep(x) Sleep(x/1000) -#define round(x) (x > 0.0 ? floor(x + 0.5): ceil(x - 0.5)) -#endif - -#include <semaphore.h> -#include <pthread.h> -#include <libusb.h> - -#include "rtl-sdr.h" - -#define DEFAULT_SAMPLE_RATE 24000 -#define DEFAULT_ASYNC_BUF_NUMBER 32 -#define DEFAULT_BUF_LENGTH (1 * 16384) -#define MAXIMUM_OVERSAMPLE 16 -#define MAXIMUM_BUF_LENGTH (MAXIMUM_OVERSAMPLE * DEFAULT_BUF_LENGTH) -#define AUTO_GAIN -100 - -static pthread_t demod_thread; -static sem_t data_ready; -static int do_exit = 0; -static rtlsdr_dev_t *dev = NULL; -static int lcm_post[17] = {1,1,1,3,1,5,3,7,1,9,5,11,3,13,7,15,1}; - -struct fm_state -{ - int now_r; - int now_j; - int pre_r; - int pre_j; - int prev_index; - int downsample; /* min 1, max 256 */ - int post_downsample; - int output_scale; - int squelch_level; - int conseq_squelch; - int squelch_hits; - int terminate_on_squelch; - int exit_flag; - uint8_t buf[MAXIMUM_BUF_LENGTH]; - uint32_t buf_len; - int signal[MAXIMUM_BUF_LENGTH]; /* 16 bit signed i/q pairs */ - int16_t signal2[MAXIMUM_BUF_LENGTH]; /* signal has lowpass, signal2 has demod */ - int signal_len; - int signal2_len; - FILE *file; - int edge; - uint32_t freqs[1000]; - int freq_len; - int freq_now; - uint32_t sample_rate; - int output_rate; - int fir_enable; - int fir[256]; /* fir_len == downsample */ - int fir_sum; - int custom_atan; - int deemph; - int deemph_a; - int now_lpr; - int prev_lpr_index; - void (*mode_demod)(struct fm_state*); -}; - -void usage(void) -{ - fprintf(stderr, - "rtl_fm, a simple narrow band FM demodulator for RTL2832 based DVB-T receivers\n\n" - "Use:\trtl_fm -f freq [-options] [filename]\n" - "\t-f frequency_to_tune_to [Hz]\n" - "\t (use multiple -f for scanning, requires squelch)\n" - "\t (ranges supported, -f 118M:137M:25k)\n" - "\t[-s sample_rate (default: 24k)]\n" - "\t[-d device_index (default: 0)]\n" - "\t[-g tuner_gain (default: automatic)]\n" - "\t[-l squelch_level (default: 0/off)]\n" - "\t[-o oversampling (default: 1, 4 recommended)]\n" - "\t[-p ppm_error (default: 0)]\n" - "\t[-E sets lower edge tuning (default: center)]\n" - "\t[-N enables NBFM mode (default: on)]\n" - "\t[-W enables WBFM mode (default: off)]\n" - "\t (-N -s 170k -o 4 -A -r 32k -l 0 -D)\n" - "\tfilename (a '-' dumps samples to stdout)\n" - "\t (omitting the filename also uses stdout)\n\n" - "Experimental options:\n" - "\t[-r output_rate (default: same as -s)]\n" - "\t[-t squelch_delay (default: 20)]\n" - "\t (+values will mute/scan, -values will exit)\n" - "\t[-M enables AM mode (default: off)]\n" - "\t[-L enables LSB mode (default: off)]\n" - "\t[-U enables USB mode (default: off)]\n" - //"\t[-D enables DSB mode (default: off)]\n" - "\t[-R enables raw mode (default: off, 2x16 bit output)]\n" - "\t[-F enables high quality FIR (default: off/square)]\n" - "\t[-D enables de-emphasis (default: off)]\n" - "\t[-A enables high speed arctan (default: off)]\n\n" - "Produces signed 16 bit ints, use Sox or aplay to hear them.\n" - "\trtl_fm ... - | play -t raw -r 24k -e signed-integer -b 16 -c 1 -V1 -\n" - "\t | aplay -r 24k -f S16_LE -t raw -c 1\n" - "\t -s 22.5k - | multimon -t raw /dev/stdin\n\n"); - exit(1); -} - -#ifdef _WIN32 -BOOL WINAPI -sighandler(int signum) -{ - if (CTRL_C_EVENT == signum) { - fprintf(stderr, "Signal caught, exiting!\n"); - do_exit = 1; - rtlsdr_cancel_async(dev); - return TRUE; - } - return FALSE; -} -#else -static void sighandler(int signum) -{ - fprintf(stderr, "Signal caught, exiting!\n"); - do_exit = 1; - rtlsdr_cancel_async(dev); -} -#endif - -void rotate_90(unsigned char *buf, uint32_t len) -/* 90 rotation is 1+0j, 0+1j, -1+0j, 0-1j - or [0, 1, -3, 2, -4, -5, 7, -6] */ -{ - uint32_t i; - unsigned char tmp; - for (i=0; i<len; i+=8) { - /* uint8_t negation = 255 - x */ - tmp = 255 - buf[i+3]; - buf[i+3] = buf[i+2]; - buf[i+2] = tmp; - - buf[i+4] = 255 - buf[i+4]; - buf[i+5] = 255 - buf[i+5]; - - tmp = 255 - buf[i+6]; - buf[i+6] = buf[i+7]; - buf[i+7] = tmp; - } -} - -void low_pass(struct fm_state *fm, unsigned char *buf, uint32_t len) -/* simple square window FIR */ -{ - int i=0, i2=0; - while (i < (int)len) { - fm->now_r += ((int)buf[i] - 128); - fm->now_j += ((int)buf[i+1] - 128); - i += 2; - fm->prev_index++; - if (fm->prev_index < fm->downsample) { - continue; - } - fm->signal[i2] = fm->now_r * fm->output_scale; - fm->signal[i2+1] = fm->now_j * fm->output_scale; - fm->prev_index = 0; - fm->now_r = 0; - fm->now_j = 0; - i2 += 2; - } - fm->signal_len = i2; -} - -void build_fir(struct fm_state *fm) -/* for now, a simple triangle - * fancy FIRs are equally expensive, so use one */ -/* point = sum(sample[i] * fir[i] * fir_len / fir_sum) */ -{ - int i, len; - len = fm->downsample; - for(i = 0; i < (len/2); i++) { - fm->fir[i] = i; - } - for(i = len-1; i >= (len/2); i--) { - fm->fir[i] = len - i; - } - fm->fir_sum = 0; - for(i = 0; i < len; i++) { - fm->fir_sum += fm->fir[i]; - } -} - -void low_pass_fir(struct fm_state *fm, unsigned char *buf, uint32_t len) -/* perform an arbitrary FIR, doubles CPU use */ -// possibly bugged, or overflowing -{ - int i=0, i2=0, i3=0; - while (i < (int)len) { - i3 = fm->prev_index; - fm->now_r += ((int)buf[i] - 128) * fm->fir[i3] * fm->downsample / fm->fir_sum; - fm->now_j += ((int)buf[i+1] - 128) * fm->fir[i3] * fm->downsample / fm->fir_sum; - i += 2; - fm->prev_index++; - if (fm->prev_index < fm->downsample) { - continue; - } - fm->signal[i2] = fm->now_r * fm->output_scale; - fm->signal[i2+1] = fm->now_j * fm->output_scale; - fm->prev_index = 0; - fm->now_r = 0; - fm->now_j = 0; - i2 += 2; - } - fm->signal_len = i2; -} - -int low_pass_simple(int16_t *signal2, int len, int step) -// no wrap around, length must be multiple of step -{ - int i, i2, sum; - for(i=0; i < len; i+=step) { - sum = 0; - for(i2=0; i2<step; i2++) { - sum += (int)signal2[i + i2]; - } - //signal2[i/step] = (int16_t)(sum / step); - signal2[i/step] = (int16_t)(sum); - } - signal2[i/step + 1] = signal2[i/step]; - return len / step; -} - -void low_pass_real(struct fm_state *fm) -/* simple square window FIR */ -// add support for upsampling? -{ - int i=0, i2=0; - int fast = (int)fm->sample_rate / fm->post_downsample; - int slow = fm->output_rate; - while (i < fm->signal2_len) { - fm->now_lpr += fm->signal2[i]; - i++; - fm->prev_lpr_index += slow; - if (fm->prev_lpr_index < fast) { - continue; - } - fm->signal2[i2] = (int16_t)(fm->now_lpr / (fast/slow)); - fm->prev_lpr_index -= fast; - fm->now_lpr = 0; - i2 += 1; - } - fm->signal2_len = i2; -} - -/* define our own complex math ops - because ARMv5 has no hardware float */ - -void multiply(int ar, int aj, int br, int bj, int *cr, int *cj) -{ - *cr = ar*br - aj*bj; - *cj = aj*br + ar*bj; -} - -int polar_discriminant(int ar, int aj, int br, int bj) -{ - int cr, cj; - double angle; - multiply(ar, aj, br, -bj, &cr, &cj); - angle = atan2((double)cj, (double)cr); - return (int)(angle / 3.14159 * (1<<14)); -} - -int fast_atan2(int y, int x) -/* pre scaled for int16 */ -{ - int yabs, angle; - int pi4=(1<<12), pi34=3*(1<<12); // note pi = 1<<14 - if (x==0 && y==0) { - return 0; - } - yabs = y; - if (yabs < 0) { - yabs = -yabs; - } - if (x >= 0) { - angle = pi4 - pi4 * (x-yabs) / (x+yabs); - } else { - angle = pi34 - pi4 * (x+yabs) / (yabs-x); - } - if (y < 0) { - return -angle; - } - return angle; -} - -int polar_disc_fast(int ar, int aj, int br, int bj) -{ - int cr, cj; - multiply(ar, aj, br, -bj, &cr, &cj); - return fast_atan2(cj, cr); -} - -void fm_demod(struct fm_state *fm) -{ - int i, pcm; - pcm = polar_discriminant(fm->signal[0], fm->signal[1], - fm->pre_r, fm->pre_j); - fm->signal2[0] = (int16_t)pcm; - for (i = 2; i < (fm->signal_len); i += 2) { - if (fm->custom_atan) { - pcm = polar_disc_fast(fm->signal[i], fm->signal[i+1], - fm->signal[i-2], fm->signal[i-1]); - } else { - pcm = polar_discriminant(fm->signal[i], fm->signal[i+1], - fm->signal[i-2], fm->signal[i-1]); - } - fm->signal2[i/2] = (int16_t)pcm; - } - fm->pre_r = fm->signal[fm->signal_len - 2]; - fm->pre_j = fm->signal[fm->signal_len - 1]; - fm->signal2_len = fm->signal_len/2; -} - -void am_demod(struct fm_state *fm) -// todo, fix this extreme laziness -{ - int i, pcm; - for (i = 0; i < (fm->signal_len); i += 2) { - // hypot uses floats but won't overflow - //fm->signal2[i/2] = (int16_t)hypot(fm->signal[i], fm->signal[i+1]); - pcm = fm->signal[i] * fm->signal[i]; - pcm += fm->signal[i+1] * fm->signal[i+1]; - fm->signal2[i/2] = (int16_t)sqrt(pcm); // * fm->output_scale; - } - fm->signal2_len = fm->signal_len/2; - // lowpass? (3khz) highpass? (dc) -} - -void usb_demod(struct fm_state *fm) -{ - int i, pcm; - for (i = 0; i < (fm->signal_len); i += 2) { - pcm = fm->signal[i] + fm->signal[i+1]; - fm->signal2[i/2] = (int16_t)pcm; // * fm->output_scale; - } - fm->signal2_len = fm->signal_len/2; -} - -void lsb_demod(struct fm_state *fm) -{ - int i, pcm; - for (i = 0; i < (fm->signal_len); i += 2) { - pcm = fm->signal[i] - fm->signal[i+1]; - fm->signal2[i/2] = (int16_t)pcm; // * fm->output_scale; - } - fm->signal2_len = fm->signal_len/2; -} - -void raw_demod(struct fm_state *fm) -{ - /* hacky and pointless code */ - int i; - for (i = 0; i < (fm->signal_len); i++) { - fm->signal2[i] = (int16_t)fm->signal[i]; - } - fm->signal2_len = fm->signal_len; -} - -void deemph_filter(struct fm_state *fm) -{ - static int avg; // cheating... - int i, d; - // de-emph IIR - // avg = avg * (1 - alpha) + sample * alpha; - for (i = 0; i < fm->signal2_len; i++) { - d = fm->signal2[i] - avg; - if (d > 0) { - avg += (d + fm->deemph_a/2) / fm->deemph_a; - } else { - avg += (d - fm->deemph_a/2) / fm->deemph_a; - } - fm->signal2[i] = (int16_t)avg; - } -} - -int mad(int *samples, int len, int step) -/* mean average deviation */ -{ - int i=0, sum=0, ave=0; - if (len == 0) - {return 0;} - for (i=0; i<len; i+=step) { - sum += samples[i]; - } - ave = sum / (len * step); - sum = 0; - for (i=0; i<len; i+=step) { - sum += abs(samples[i] - ave); - } - return sum / (len / step); -} - -int post_squelch(struct fm_state *fm) -/* returns 1 for active signal, 0 for no signal */ -{ - int dev_r, dev_j, len, sq_l; - /* only for small samples, big samples need chunk processing */ - len = fm->signal_len; - sq_l = fm->squelch_level; - dev_r = mad(&(fm->signal[0]), len, 2); - dev_j = mad(&(fm->signal[1]), len, 2); - if ((dev_r > sq_l) || (dev_j > sq_l)) { - fm->squelch_hits = 0; - return 1; - } - fm->squelch_hits++; - return 0; -} - -static void optimal_settings(struct fm_state *fm, int freq, int hopping) -{ - int r, capture_freq, capture_rate; - fm->downsample = (1000000 / fm->sample_rate) + 1; - fm->freq_now = freq; - capture_rate = fm->downsample * fm->sample_rate; - capture_freq = fm->freqs[freq] + capture_rate/4; - capture_freq += fm->edge * fm->sample_rate / 2; - fm->output_scale = (1<<15) / (128 * fm->downsample); - if (fm->output_scale < 1) { - fm->output_scale = 1;} - fm->output_scale = 1; - /* Set the frequency */ - r = rtlsdr_set_center_freq(dev, (uint32_t)capture_freq); - if (hopping) { - return;} - fprintf(stderr, "Oversampling input by: %ix.\n", fm->downsample); - fprintf(stderr, "Oversampling output by: %ix.\n", fm->post_downsample); - fprintf(stderr, "Buffer size: %0.2fms\n", - 1000 * 0.5 * lcm_post[fm->post_downsample] * (float)DEFAULT_BUF_LENGTH / (float)capture_rate); - if (r < 0) { - fprintf(stderr, "WARNING: Failed to set center freq.\n");} - else { - fprintf(stderr, "Tuned to %u Hz.\n", capture_freq);} - - /* Set the sample rate */ - fprintf(stderr, "Sampling at %u Hz.\n", capture_rate); - if (fm->output_rate > 0) { - fprintf(stderr, "Output at %u Hz.\n", fm->output_rate); - } else { - fprintf(stderr, "Output at %u Hz.\n", fm->sample_rate/fm->post_downsample);} - r = rtlsdr_set_sample_rate(dev, (uint32_t)capture_rate); - if (r < 0) { - fprintf(stderr, "WARNING: Failed to set sample rate.\n");} - -} - -void full_demod(struct fm_state *fm) -{ - int i, sr, freq_next, hop = 0; - 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); - } - 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);} - /* 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, NULL, 4096, NULL); - } -} - -static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) -{ - struct fm_state *fm2 = ctx; - int dr_val; - if (do_exit) { - return;} - if (!ctx) { - return;} - memcpy(fm2->buf, buf, len); - fm2->buf_len = len; - /* single threaded uses 25% less CPU? */ - /* full_demod(fm2); */ - sem_getvalue(&data_ready, &dr_val); - if (dr_val <= 0) { - sem_post(&data_ready);} -} - -static void *demod_thread_fn(void *arg) -{ - struct fm_state *fm2 = arg; - while (!do_exit) { - sem_wait(&data_ready); - full_demod(fm2); - if (fm2->exit_flag) { - do_exit = 1; - rtlsdr_cancel_async(dev);} - } - return 0; -} - -double atofs(char* f) -/* standard suffixes */ -{ - char* chop; - double suff = 1.0; - chop = malloc((strlen(f)+1)*sizeof(char)); - strncpy(chop, f, strlen(f)-1); - switch (f[strlen(f)-1]) { - case 'G': - suff *= 1e3; - case 'M': - suff *= 1e3; - case 'k': - suff *= 1e3; - suff *= atof(chop);} - free(chop); - if (suff != 1.0) { - return suff;} - return atof(f); -} - -void frequency_range(struct fm_state *fm, char *arg) -{ - char *start, *stop, *step; - int i; - start = arg; - stop = strchr(start, ':') + 1; - stop[-1] = '\0'; - step = strchr(stop, ':') + 1; - step[-1] = '\0'; - for(i=(int)atofs(start); i<=(int)atofs(stop); i+=(int)atofs(step)) - { - fm->freqs[fm->freq_len] = (uint32_t)i; - fm->freq_len++; - } - stop[-1] = ':'; - step[-1] = ':'; -} - -int main(int argc, char **argv) -{ -#ifndef _WIN32 - struct sigaction sigact; -#endif - struct fm_state fm; - char *filename = NULL; - int n_read, r, opt, wb_mode = 0; - int i, gain = AUTO_GAIN; // tenths of a dB - uint8_t *buffer; - uint32_t dev_index = 0; - int device_count; - int ppm_error = 0; - char vendor[256], product[256], serial[256]; - fm.freqs[0] = 100000000; - fm.sample_rate = DEFAULT_SAMPLE_RATE; - fm.squelch_level = 0; - fm.conseq_squelch = 20; - fm.terminate_on_squelch = 0; - fm.freq_len = 0; - fm.edge = 0; - fm.fir_enable = 0; - fm.prev_index = 0; - fm.post_downsample = 1; // once this works, default = 4 - fm.custom_atan = 0; - fm.deemph = 0; - fm.output_rate = -1; // flag for disabled - fm.mode_demod = &fm_demod; - sem_init(&data_ready, 0, 0); - - while ((opt = getopt(argc, argv, "d:f:g:s:b:l:o:t:r:p:EFANWMULRD")) != -1) { - switch (opt) { - case 'd': - dev_index = atoi(optarg); - break; - case 'f': - if (strchr(optarg, ':')) - {frequency_range(&fm, optarg);} - else - { - fm.freqs[fm.freq_len] = (uint32_t)atofs(optarg); - fm.freq_len++; - } - break; - case 'g': - gain = (int)(atof(optarg) * 10); - break; - case 'l': - fm.squelch_level = (int)atof(optarg); - break; - case 's': - fm.sample_rate = (uint32_t)atofs(optarg); - break; - case 'r': - fm.output_rate = (int)atofs(optarg); - break; - case 'o': - fm.post_downsample = (int)atof(optarg); - if (fm.post_downsample < 1 || fm.post_downsample > MAXIMUM_OVERSAMPLE) { - fprintf(stderr, "Oversample must be between 1 and %i\n", MAXIMUM_OVERSAMPLE);} - break; - case 't': - fm.conseq_squelch = (int)atof(optarg); - if (fm.conseq_squelch < 0) { - fm.conseq_squelch = -fm.conseq_squelch; - fm.terminate_on_squelch = 1; - } - break; - case 'p': - ppm_error = atoi(optarg); - break; - case 'E': - fm.edge = 1; - break; - case 'F': - fm.fir_enable = 1; - break; - case 'A': - fm.custom_atan = 1; - break; - case 'D': - fm.deemph = 1; - break; - case 'N': - fm.mode_demod = &fm_demod; - break; - case 'W': - wb_mode = 1; - fm.mode_demod = &fm_demod; - fm.sample_rate = 170000; - fm.output_rate = 32000; - fm.custom_atan = 1; - fm.post_downsample = 4; - fm.deemph = 1; - fm.squelch_level = 0; - break; - case 'M': - fm.mode_demod = &am_demod; - break; - case 'U': - fm.mode_demod = &usb_demod; - break; - case 'L': - fm.mode_demod = &lsb_demod; - break; - case 'R': - fm.mode_demod = &raw_demod; - break; - default: - usage(); - break; - } - } - /* quadruple sample_rate to limit to Δθ to ±π/2 */ - fm.sample_rate *= fm.post_downsample; - - if (fm.freq_len > 1) { - fm.terminate_on_squelch = 0; - } - - if (argc <= optind) { - //usage(); - filename = "-"; - } else { - filename = argv[optind]; - } - - buffer = malloc(lcm_post[fm.post_downsample] * DEFAULT_BUF_LENGTH * 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)); - - 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 - - /* WBFM is special */ - if (wb_mode) { - fm.freqs[0] += 16000; - } - - if (fm.deemph) { - fm.deemph_a = (int)round(1.0/((1.0-exp(-1.0/(fm.output_rate * 75e-6))))); - } - - optimal_settings(&fm, 0, 0); - build_fir(&fm); - - /* Set the tuner gain */ - if (gain == AUTO_GAIN) { - r = rtlsdr_set_tuner_gain_mode(dev, 0); - } else { - r = rtlsdr_set_tuner_gain_mode(dev, 1); - r = rtlsdr_set_tuner_gain(dev, gain); - } - if (r != 0) { - fprintf(stderr, "WARNING: Failed to set tuner gain.\n"); - } else if (gain == AUTO_GAIN) { - fprintf(stderr, "Tuner gain set to automatic.\n"); - } else { - fprintf(stderr, "Tuner gain set to %0.2f dB.\n", gain/10.0); - } - r = rtlsdr_set_freq_correction(dev, ppm_error); - - if (strcmp(filename, "-") == 0) { /* Write samples to stdout */ - fm.file = stdout; -#ifdef _WIN32 - _setmode(_fileno(fm.file), _O_BINARY); -#endif - } else { - fm.file = fopen(filename, "wb"); - if (!fm.file) { - fprintf(stderr, "Failed to open %s\n", filename); - exit(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");} - - pthread_create(&demod_thread, NULL, demod_thread_fn, (void *)(&fm)); - rtlsdr_read_async(dev, rtlsdr_callback, (void *)(&fm), - DEFAULT_ASYNC_BUF_NUMBER, - lcm_post[fm.post_downsample] * 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); - - if (fm.file != stdout) { - fclose(fm.file);} - - rtlsdr_close(dev); - free (buffer); - return r >= 0 ? r : -r; -} diff --git a/src/rtl_sdr.c b/src/rtl_sdr.c deleted file mode 100644 index eeb6dba1..00000000 --- a/src/rtl_sdr.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver - * Copyright (C) 2012 by Steve Markgraf <steve@steve-m.de> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <errno.h> -#include <signal.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> - -#ifndef _WIN32 -#include <unistd.h> -#else -#include <Windows.h> -#include <io.h> -#include <fcntl.h> -#include "getopt/getopt.h" -#endif - -#include "rtl-sdr.h" - -#define DEFAULT_SAMPLE_RATE 2048000 -#define DEFAULT_ASYNC_BUF_NUMBER 32 -#define DEFAULT_BUF_LENGTH (16 * 16384) -#define MINIMAL_BUF_LENGTH 512 -#define MAXIMAL_BUF_LENGTH (256 * 16384) - -static int do_exit = 0; -static uint32_t bytes_to_read = 0; -static rtlsdr_dev_t *dev = NULL; - -void usage(void) -{ - fprintf(stderr, - "rtl_sdr, an I/Q recorder for RTL2832 based DVB-T receivers\n\n" - "Usage:\t -f frequency_to_tune_to [Hz]\n" - "\t[-s samplerate (default: 2048000 Hz)]\n" - "\t[-d device_index (default: 0)]\n" - "\t[-g gain (default: 0 for auto)]\n" - "\t[-b output_block_size (default: 16 * 16384)]\n" - "\t[-n number of samples to read (default: 0, infinite)]\n" - "\t[-S force sync output (default: async)]\n" - "\tfilename (a '-' dumps samples to stdout)\n\n"); - exit(1); -} - -#ifdef _WIN32 -BOOL WINAPI -sighandler(int signum) -{ - if (CTRL_C_EVENT == signum) { - fprintf(stderr, "Signal caught, exiting!\n"); - do_exit = 1; - rtlsdr_cancel_async(dev); - return TRUE; - } - return FALSE; -} -#else -static void sighandler(int signum) -{ - fprintf(stderr, "Signal caught, exiting!\n"); - do_exit = 1; - rtlsdr_cancel_async(dev); -} -#endif - -static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) -{ - if (ctx) { - if (do_exit) - return; - - if ((bytes_to_read > 0) && (bytes_to_read < len)) { - len = bytes_to_read; - do_exit = 1; - rtlsdr_cancel_async(dev); - } - - if (fwrite(buf, 1, len, (FILE*)ctx) != len) { - fprintf(stderr, "Short write, samples lost, exiting!\n"); - rtlsdr_cancel_async(dev); - } - - if (bytes_to_read > 0) - bytes_to_read -= len; - } -} - -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 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:f:g:s:b:n:S::")) != -1) { - switch (opt) { - case 'd': - dev_index = 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)); - - 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); -out: - return r >= 0 ? r : -r; -} diff --git a/src/rtl_tcp.c b/src/rtl_tcp.c deleted file mode 100644 index 13f20faf..00000000 --- a/src/rtl_tcp.c +++ /dev/null @@ -1,604 +0,0 @@ -/* - * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver - * Copyright (C) 2012 by Steve Markgraf <steve@steve-m.de> - * Copyright (C) 2012 by Hoernchen <la@tfc-server.de> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <errno.h> -#include <signal.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> - -#ifndef _WIN32 -#include <unistd.h> -#include <arpa/inet.h> -#include <sys/socket.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/time.h> -#include <netinet/in.h> -#include <fcntl.h> -#else -#include <WinSock2.h> -#include "getopt/getopt.h" -#endif - -#include <pthread.h> - -#include "rtl-sdr.h" - -#ifdef _WIN32 -#pragma comment(lib, "ws2_32.lib") - -typedef int socklen_t; - -#else -#define closesocket close -#define SOCKADDR struct sockaddr -#define SOCKET int -#define SOCKET_ERROR -1 -#endif - -static SOCKET s; - -static pthread_t tcp_worker_thread; -static pthread_t command_thread; -static pthread_cond_t exit_cond; -static pthread_mutex_t exit_cond_lock; -static volatile int dead[2] = {0, 0}; - -static pthread_mutex_t ll_mutex; -static pthread_cond_t cond; - -struct llist { - char *data; - size_t len; - struct llist *next; -}; - -typedef struct { /* structure size must be multiple of 2 bytes */ - char magic[4]; - uint32_t tuner_type; - uint32_t tuner_gain_count; -} dongle_info_t; - -static rtlsdr_dev_t *dev = NULL; - -int global_numq = 0; -static struct llist *ll_buffers = 0; - -static int do_exit = 0; - -void usage(void) -{ - printf("rtl_tcp, an I/Q spectrum server for RTL2832 based DVB-T receivers\n\n" - "Usage:\t[-a listen address]\n" - "\t[-p listen port (default: 1234)]\n" - "\t[-f frequency to tune to [Hz]]\n" - "\t[-g gain (default: 0 for auto)]\n" - "\t[-s samplerate in Hz (default: 2048000 Hz)]\n" - "\t[-b number of buffers (default: 32, set by library)]\n" - "\t[-d device index (default: 0)]\n"); - exit(1); -} - -#ifdef _WIN32 -int gettimeofday(struct timeval *tv, void* ignored) -{ - FILETIME ft; - unsigned __int64 tmp = 0; - if (NULL != tv) { - GetSystemTimeAsFileTime(&ft); - tmp |= ft.dwHighDateTime; - tmp <<= 32; - tmp |= ft.dwLowDateTime; - tmp /= 10; - tmp -= 11644473600000000Ui64; - tv->tv_sec = (long)(tmp / 1000000UL); - tv->tv_usec = (long)(tmp % 1000000UL); - } - return 0; -} - -BOOL WINAPI -sighandler(int signum) -{ - if (CTRL_C_EVENT == signum) { - fprintf(stderr, "Signal caught, exiting!\n"); - do_exit = 1; - rtlsdr_cancel_async(dev); - return TRUE; - } - return FALSE; -} -#else -static void sighandler(int signum) -{ - fprintf(stderr, "Signal caught, exiting!\n"); - if (!do_exit) { - rtlsdr_cancel_async(dev); - do_exit = 1; - } -} -#endif - -void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) -{ - if(!do_exit) { - struct llist *rpt = (struct llist*)malloc(sizeof(struct llist)); - rpt->data = (char*)malloc(len); - memcpy(rpt->data, buf, len); - rpt->len = len; - rpt->next = NULL; - - pthread_mutex_lock(&ll_mutex); - - if (ll_buffers == NULL) { - ll_buffers = rpt; - } else { - struct llist *cur = ll_buffers; - int num_queued = 0; - - while (cur->next != NULL) { - cur = cur->next; - num_queued++; - } - cur->next = rpt; - - if (num_queued > global_numq) - printf("ll+, now %d\n", num_queued); - else if (num_queued < global_numq) - printf("ll-, now %d\n", num_queued); - - global_numq = num_queued; - } - pthread_cond_signal(&cond); - pthread_mutex_unlock(&ll_mutex); - } -} - -static void *tcp_worker(void *arg) -{ - struct llist *curelem,*prev; - int bytesleft,bytessent, index; - struct timeval tv= {1,0}; - struct timespec ts; - struct timeval tp; - fd_set writefds; - int r = 0; - - while(1) { - if(do_exit) - pthread_exit(0); - - pthread_mutex_lock(&ll_mutex); - gettimeofday(&tp, NULL); - ts.tv_sec = tp.tv_sec+5; - ts.tv_nsec = tp.tv_usec * 1000; - r = pthread_cond_timedwait(&cond, &ll_mutex, &ts); - if(r == ETIMEDOUT) { - pthread_mutex_unlock(&ll_mutex); - printf("worker cond timeout\n"); - sighandler(0); - dead[0]=1; - pthread_exit(NULL); - } - - curelem = ll_buffers; - ll_buffers = 0; - pthread_mutex_unlock(&ll_mutex); - - while(curelem != 0) { - bytesleft = curelem->len; - index = 0; - bytessent = 0; - while(bytesleft > 0) { - FD_ZERO(&writefds); - FD_SET(s, &writefds); - tv.tv_sec = 1; - tv.tv_usec = 0; - r = select(s+1, NULL, &writefds, NULL, &tv); - if(r) { - bytessent = send(s, &curelem->data[index], bytesleft, 0); - if (bytessent == SOCKET_ERROR) { - perror("worker socket error"); - sighandler(0); - dead[0]=1; - pthread_exit(NULL); - } else if (do_exit) { - printf("do_exit\n"); - dead[0]=1; - pthread_exit(NULL); - } else { - bytesleft -= bytessent; - index += bytessent; - } - } else if(do_exit) { - printf("worker socket bye\n"); - sighandler(0); - dead[0]=1; - pthread_exit(NULL); - } - } - prev = curelem; - curelem = curelem->next; - free(prev->data); - free(prev); - } - } -} - -static int set_gain_by_index(rtlsdr_dev_t *_dev, unsigned int index) -{ - int res = 0; - int* gains; - int count = rtlsdr_get_tuner_gains(_dev, NULL); - - if (count > 0 && (unsigned int)count > index) { - gains = malloc(sizeof(int) * count); - count = rtlsdr_get_tuner_gains(_dev, gains); - - res = rtlsdr_set_tuner_gain(_dev, gains[index]); - - free(gains); - } - - return res; -} - -#ifdef _WIN32 -#define __attribute__(x) -#pragma pack(push, 1) -#endif -struct command{ - unsigned char cmd; - unsigned int param; -}__attribute__((packed)); -#ifdef _WIN32 -#pragma pack(pop) -#endif -static void *command_worker(void *arg) -{ - int left, received; - fd_set readfds; - struct command cmd={0, 0}; - struct timeval tv= {1, 0}; - int r = 0; - uint32_t tmp; - - while(1) { - left=sizeof(cmd); - while(left >0) { - FD_ZERO(&readfds); - FD_SET(s, &readfds); - tv.tv_sec = 1; - tv.tv_usec = 0; - r = select(s+1, &readfds, NULL, NULL, &tv); - if(r) { - received = recv(s, (char*)&cmd+(sizeof(cmd)-left), left, 0); - if(received == SOCKET_ERROR){ - perror("comm recv socket error"); - sighandler(0); - dead[1]=1; - pthread_exit(NULL); - } else if(do_exit){ - printf("do exit\n"); - dead[1]=1; - pthread_exit(NULL); - } else { - left -= received; - } - } else if(do_exit) { - printf("comm recv bye\n"); - sighandler(0); - dead[1] = 1; - pthread_exit(NULL); - } - } - switch(cmd.cmd) { - case 0x01: - printf("set freq %d\n", ntohl(cmd.param)); - rtlsdr_set_center_freq(dev,ntohl(cmd.param)); - break; - case 0x02: - printf("set sample rate %d\n", ntohl(cmd.param)); - rtlsdr_set_sample_rate(dev, ntohl(cmd.param)); - break; - case 0x03: - printf("set gain mode %d\n", ntohl(cmd.param)); - rtlsdr_set_tuner_gain_mode(dev, ntohl(cmd.param)); - break; - case 0x04: - printf("set gain %d\n", ntohl(cmd.param)); - rtlsdr_set_tuner_gain(dev, ntohl(cmd.param)); - break; - case 0x05: - printf("set freq correction %d\n", ntohl(cmd.param)); - rtlsdr_set_freq_correction(dev, ntohl(cmd.param)); - break; - case 0x06: - tmp = ntohl(cmd.param); - printf("set if stage %d, gain %d\n", tmp >> 16, tmp & 0xffff); - rtlsdr_set_tuner_if_gain(dev, tmp >> 16, tmp & 0xffff); - break; - case 0x07: - printf("set test mode %d\n", ntohl(cmd.param)); - rtlsdr_set_testmode(dev, ntohl(cmd.param)); - break; - case 0x08: - printf("set agc mode %d\n", ntohl(cmd.param)); - rtlsdr_set_agc_mode(dev, ntohl(cmd.param)); - break; - case 0x09: - printf("set direct sampling %d\n", ntohl(cmd.param)); - rtlsdr_set_direct_sampling(dev, ntohl(cmd.param)); - break; - case 0x0a: - printf("set offset tuning %d\n", ntohl(cmd.param)); - rtlsdr_set_offset_tuning(dev, ntohl(cmd.param)); - break; - case 0x0b: - printf("set rtl xtal %d\n", ntohl(cmd.param)); - rtlsdr_set_xtal_freq(dev, ntohl(cmd.param), 0); - break; - case 0x0c: - printf("set tuner xtal %d\n", ntohl(cmd.param)); - rtlsdr_set_xtal_freq(dev, 0, ntohl(cmd.param)); - break; - case 0x0d: - printf("set tuner gain by index %d\n", ntohl(cmd.param)); - set_gain_by_index(dev, ntohl(cmd.param)); - break; - default: - break; - } - cmd.cmd = 0xff; - } -} - -int main(int argc, char **argv) -{ - int r, opt, i; - char* addr = "127.0.0.1"; - int port = 1234; - uint32_t frequency = 100000000, samp_rate = 2048000; - struct sockaddr_in local, remote; - int device_count; - uint32_t dev_index = 0, buf_num = 0; - int gain = 0; - struct llist *curelem,*prev; - pthread_attr_t attr; - void *status; - struct timeval tv = {1,0}; - struct linger ling = {1,0}; - SOCKET listensocket; - socklen_t rlen; - fd_set readfds; - u_long blockmode = 1; - dongle_info_t dongle_info; -#ifdef _WIN32 - WSADATA wsd; - i = WSAStartup(MAKEWORD(2,2), &wsd); -#else - struct sigaction sigact, sigign; -#endif - - while ((opt = getopt(argc, argv, "a:p:f:g:s:b:d:")) != -1) { - switch (opt) { - case 'd': - dev_index = 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 'a': - addr = optarg; - break; - case 'p': - port = atoi(optarg); - break; - case 'b': - buf_num = atoi(optarg); - break; - default: - usage(); - break; - } - } - - if (argc < optind) - usage(); - - device_count = rtlsdr_get_device_count(); - if (!device_count) { - fprintf(stderr, "No supported devices found.\n"); - exit(1); - } - - printf("Found %d device(s).\n", device_count); - - rtlsdr_open(&dev, dev_index); - if (NULL == dev) { - fprintf(stderr, "Failed to open rtlsdr device #%d.\n", dev_index); - exit(1); - } - - printf("Using %s\n", rtlsdr_get_device_name(dev_index)); -#ifndef _WIN32 - sigact.sa_handler = sighandler; - sigemptyset(&sigact.sa_mask); - sigact.sa_flags = 0; - sigign.sa_handler = SIG_IGN; - sigaction(SIGINT, &sigact, NULL); - sigaction(SIGTERM, &sigact, NULL); - sigaction(SIGQUIT, &sigact, NULL); - sigaction(SIGPIPE, &sigign, 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 %i 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); - } - - /* 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"); - - pthread_mutex_init(&exit_cond_lock, NULL); - pthread_mutex_init(&ll_mutex, NULL); - pthread_mutex_init(&exit_cond_lock, NULL); - pthread_cond_init(&cond, NULL); - pthread_cond_init(&exit_cond, NULL); - - memset(&local,0,sizeof(local)); - local.sin_family = AF_INET; - local.sin_port = htons(port); - local.sin_addr.s_addr = inet_addr(addr); - - listensocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - r = 1; - setsockopt(listensocket, SOL_SOCKET, SO_REUSEADDR, (char *)&r, sizeof(int)); - setsockopt(listensocket, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)); - bind(listensocket,(struct sockaddr *)&local,sizeof(local)); - - #ifdef _WIN32 - ioctlsocket(listensocket, FIONBIO, &blockmode); - #else - r = fcntl(listensocket, F_GETFL, 0); - r = fcntl(listensocket, F_SETFL, r | O_NONBLOCK); - #endif - - while(1) { - printf("listening...\n"); - printf("Use the device argument 'rtl_tcp=%s:%d' in OsmoSDR " - "(gr-osmosdr) source\n" - "to receive samples in GRC and control " - "rtl_tcp parameters (frequency, gain, ...).\n", - addr, port); - listen(listensocket,1); - - while(1) { - FD_ZERO(&readfds); - FD_SET(listensocket, &readfds); - tv.tv_sec = 1; - tv.tv_usec = 0; - r = select(listensocket+1, &readfds, NULL, NULL, &tv); - if(do_exit) { - goto out; - } else if(r) { - rlen = sizeof(remote); - s = accept(listensocket,(struct sockaddr *)&remote, &rlen); - break; - } - } - - setsockopt(s, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)); - - printf("client accepted!\n"); - - memset(&dongle_info, 0, sizeof(dongle_info)); - memcpy(&dongle_info.magic, "RTL0", 4); - - r = rtlsdr_get_tuner_type(dev); - if (r >= 0) - dongle_info.tuner_type = htonl(r); - - r = rtlsdr_get_tuner_gains(dev, NULL); - if (r >= 0) - dongle_info.tuner_gain_count = htonl(r); - - r = send(s, (const char *)&dongle_info, sizeof(dongle_info), 0); - if (sizeof(dongle_info) != r) - printf("failed to send dongle information\n"); - - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - r = pthread_create(&tcp_worker_thread, &attr, tcp_worker, NULL); - r = pthread_create(&command_thread, &attr, command_worker, NULL); - pthread_attr_destroy(&attr); - - r = rtlsdr_read_async(dev, rtlsdr_callback, NULL, buf_num, 0); - - if(!dead[0]) - pthread_join(tcp_worker_thread, &status); - dead[0]=0; - - if(!dead[1]) - pthread_join(command_thread, &status); - dead[1]=0; - - closesocket(s); - - printf("all threads dead..\n"); - curelem = ll_buffers; - ll_buffers = 0; - - while(curelem != 0) { - prev = curelem; - curelem = curelem->next; - free(prev->data); - free(prev); - } - - do_exit = 0; - global_numq = 0; - } - -out: - rtlsdr_close(dev); - closesocket(listensocket); - closesocket(s); - #ifdef _WIN32 - WSACleanup(); - #endif - printf("bye!\n"); - return r >= 0 ? r : -r; -} diff --git a/src/rtl_test.c b/src/rtl_test.c deleted file mode 100644 index fa546286..00000000 --- a/src/rtl_test.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver - * Copyright (C) 2012 by Steve Markgraf <steve@steve-m.de> - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <errno.h> -#include <signal.h> -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <math.h> - -#ifdef __APPLE__ -#include <sys/time.h> -#else -#include <time.h> -#endif - -#ifndef _WIN32 -#include <unistd.h> -#else -#include <Windows.h> -#include "getopt/getopt.h" -#endif - -#include "rtl-sdr.h" - -#define DEFAULT_SAMPLE_RATE 2048000 -#define DEFAULT_ASYNC_BUF_NUMBER 32 -#define DEFAULT_BUF_LENGTH (16 * 16384) -#define MINIMAL_BUF_LENGTH 512 -#define MAXIMAL_BUF_LENGTH (256 * 16384) - -#define MHZ(x) ((x)*1000*1000) - -#define PPM_DURATION 10 - -static int do_exit = 0; -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) -{ - fprintf(stderr, - "rtl_test, a benchmark tool for RTL2832 based DVB-T receivers\n\n" - "Usage:\n" - "\t[-s samplerate (default: 2048000 Hz)]\n" - "\t[-d device_index (default: 0)]\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[-S force sync output (default: async)]\n"); - exit(1); -} - -#ifdef _WIN32 -BOOL WINAPI -sighandler(int signum) -{ - if (CTRL_C_EVENT == signum) { - fprintf(stderr, "Signal caught, exiting!\n"); - do_exit = 1; - rtlsdr_cancel_async(dev); - return TRUE; - } - return FALSE; -} -#else -static void sighandler(int signum) -{ - fprintf(stderr, "Signal caught, exiting!\n"); - do_exit = 1; - rtlsdr_cancel_async(dev); -} -#endif - -uint8_t bcnt, uninit = 1; - -static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) -{ - uint32_t i, lost = 0; - int64_t ns; - - 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]); - bcnt = buf[i]; - } - - bcnt++; - } - - if (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) -{ - uint32_t freq, gap_start = 0, gap_end = 0; - uint32_t range_start = 0, range_end = 0; - - fprintf(stderr, "Benchmarking E4000 PLL...\n"); - - /* find tuner range start */ - for (freq = MHZ(70); freq > MHZ(1); freq -= MHZ(1)) { - if (rtlsdr_set_center_freq(dev, freq) < 0) { - range_start = freq; - break; - } - } - - /* find tuner range end */ - for (freq = MHZ(2000); freq < MHZ(2300UL); freq += MHZ(1)) { - if (rtlsdr_set_center_freq(dev, freq) < 0) { - range_end = freq; - break; - } - } - - /* find start of L-band gap */ - for (freq = MHZ(1000); freq < MHZ(1300); freq += MHZ(1)) { - if (rtlsdr_set_center_freq(dev, freq) < 0) { - gap_start = freq; - break; - } - } - - /* find end of L-band gap */ - for (freq = MHZ(1300); freq > MHZ(1000); freq -= MHZ(1)) { - if (rtlsdr_set_center_freq(dev, freq) < 0) { - gap_end = freq; - break; - } - } - - fprintf(stderr, "E4K range: %i to %i MHz\n", - range_start/MHZ(1) + 1, range_end/MHZ(1) - 1); - - fprintf(stderr, "E4K L-band gap: %i to %i MHz\n", - gap_start/MHZ(1), gap_end/MHZ(1)); -} - -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 (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; -} diff --git a/src/tuner_e4k.c b/src/tuner_e4k.c deleted file mode 100644 index 0232f88e..00000000 --- a/src/tuner_e4k.c +++ /dev/null @@ -1,978 +0,0 @@ -/* - * Elonics E4000 tuner driver - * - * (C) 2011-2012 by Harald Welte <laforge@gnumonks.org> - * (C) 2012 by Sylvain Munaut <tnt@246tNt.com> - * (C) 2012 by Hoernchen <la@tfc-server.de> - * - * All Rights Reserved - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <limits.h> -#include <stdint.h> -#include <errno.h> -#include <string.h> -#include <stdio.h> - -#include <reg_field.h> -#include <tuner_e4k.h> - -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) - -/* If this is defined, the limits are somewhat relaxed compared to what the - * vendor claims is possible */ -#define OUT_OF_SPEC - -#define MHZ(x) ((x)*1000*1000) -#define KHZ(x) ((x)*1000) - -uint32_t unsigned_delta(uint32_t a, uint32_t b) -{ - if (a > b) - return a - b; - else - return b - a; -} - -/* look-up table bit-width -> mask */ -static const uint8_t width2mask[] = { - 0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff -}; - -/*********************************************************************** - * Register Access */ - -#if 0 -/*! \brief Write a register of the tuner chip - * \param[in] e4k reference to the tuner - * \param[in] reg number of the register - * \param[in] val value to be written - * \returns 0 on success, negative in case of error - */ -int e4k_reg_write(struct e4k_state *e4k, uint8_t reg, uint8_t val) -{ - /* FIXME */ - return 0; -} - -/*! \brief Read a register of the tuner chip - * \param[in] e4k reference to the tuner - * \param[in] reg number of the register - * \returns positive 8bit register contents on success, negative in case of error - */ -int e4k_reg_read(struct e4k_state *e4k, uint8_t reg) -{ - /* FIXME */ - return 0; -} -#endif - -/*! \brief Set or clear some (masked) bits inside a register - * \param[in] e4k reference to the tuner - * \param[in] reg number of the register - * \param[in] mask bit-mask of the value - * \param[in] val data value to be written to register - * \returns 0 on success, negative in case of error - */ -static int e4k_reg_set_mask(struct e4k_state *e4k, uint8_t reg, - uint8_t mask, uint8_t val) -{ - uint8_t tmp = e4k_reg_read(e4k, reg); - - if ((tmp & mask) == val) - return 0; - - return e4k_reg_write(e4k, reg, (tmp & ~mask) | (val & mask)); -} - -/*! \brief Write a given field inside a register - * \param[in] e4k reference to the tuner - * \param[in] field structure describing the field - * \param[in] val value to be written - * \returns 0 on success, negative in case of error - */ -static int e4k_field_write(struct e4k_state *e4k, const struct reg_field *field, uint8_t val) -{ - int rc; - uint8_t mask; - - rc = e4k_reg_read(e4k, field->reg); - if (rc < 0) - return rc; - - mask = width2mask[field->width] << field->shift; - - return e4k_reg_set_mask(e4k, field->reg, mask, val << field->shift); -} - -/*! \brief Read a given field inside a register - * \param[in] e4k reference to the tuner - * \param[in] field structure describing the field - * \returns positive value of the field, negative in case of error - */ -static int e4k_field_read(struct e4k_state *e4k, const struct reg_field *field) -{ - int rc; - - rc = e4k_reg_read(e4k, field->reg); - if (rc < 0) - return rc; - - rc = (rc >> field->shift) & width2mask[field->width]; - - return rc; -} - -/*********************************************************************** - * Filter Control */ - -static const uint32_t rf_filt_center_uhf[] = { - MHZ(360), MHZ(380), MHZ(405), MHZ(425), - MHZ(450), MHZ(475), MHZ(505), MHZ(540), - MHZ(575), MHZ(615), MHZ(670), MHZ(720), - MHZ(760), MHZ(840), MHZ(890), MHZ(970) -}; - -static const uint32_t rf_filt_center_l[] = { - MHZ(1300), MHZ(1320), MHZ(1360), MHZ(1410), - MHZ(1445), MHZ(1460), MHZ(1490), MHZ(1530), - MHZ(1560), MHZ(1590), MHZ(1640), MHZ(1660), - MHZ(1680), MHZ(1700), MHZ(1720), MHZ(1750) -}; - -static int closest_arr_idx(const uint32_t *arr, unsigned int arr_size, uint32_t freq) -{ - unsigned int i, bi = 0; - uint32_t best_delta = 0xffffffff; - - /* iterate over the array containing a list of the center - * frequencies, selecting the closest one */ - for (i = 0; i < arr_size; i++) { - uint32_t delta = unsigned_delta(freq, arr[i]); - if (delta < best_delta) { - best_delta = delta; - bi = i; - } - } - - return bi; -} - -/* return 4-bit index as to which RF filter to select */ -static int choose_rf_filter(enum e4k_band band, uint32_t freq) -{ - int rc; - - switch (band) { - case E4K_BAND_VHF2: - case E4K_BAND_VHF3: - rc = 0; - break; - case E4K_BAND_UHF: - rc = closest_arr_idx(rf_filt_center_uhf, - ARRAY_SIZE(rf_filt_center_uhf), - freq); - break; - case E4K_BAND_L: - rc = closest_arr_idx(rf_filt_center_l, - ARRAY_SIZE(rf_filt_center_l), - freq); - break; - default: - rc = -EINVAL; - break; - } - - return rc; -} - -/* \brief Automatically select apropriate RF filter based on e4k state */ -int e4k_rf_filter_set(struct e4k_state *e4k) -{ - int rc; - - rc = choose_rf_filter(e4k->band, e4k->vco.flo); - if (rc < 0) - return rc; - - return e4k_reg_set_mask(e4k, E4K_REG_FILT1, 0xF, rc); -} - -/* Mixer Filter */ -static const uint32_t mix_filter_bw[] = { - KHZ(27000), KHZ(27000), KHZ(27000), KHZ(27000), - KHZ(27000), KHZ(27000), KHZ(27000), KHZ(27000), - KHZ(4600), KHZ(4200), KHZ(3800), KHZ(3400), - KHZ(3300), KHZ(2700), KHZ(2300), KHZ(1900) -}; - -/* IF RC Filter */ -static const uint32_t ifrc_filter_bw[] = { - KHZ(21400), KHZ(21000), KHZ(17600), KHZ(14700), - KHZ(12400), KHZ(10600), KHZ(9000), KHZ(7700), - KHZ(6400), KHZ(5300), KHZ(4400), KHZ(3400), - KHZ(2600), KHZ(1800), KHZ(1200), KHZ(1000) -}; - -/* IF Channel Filter */ -static const uint32_t ifch_filter_bw[] = { - KHZ(5500), KHZ(5300), KHZ(5000), KHZ(4800), - KHZ(4600), KHZ(4400), KHZ(4300), KHZ(4100), - KHZ(3900), KHZ(3800), KHZ(3700), KHZ(3600), - KHZ(3400), KHZ(3300), KHZ(3200), KHZ(3100), - KHZ(3000), KHZ(2950), KHZ(2900), KHZ(2800), - KHZ(2750), KHZ(2700), KHZ(2600), KHZ(2550), - KHZ(2500), KHZ(2450), KHZ(2400), KHZ(2300), - KHZ(2280), KHZ(2240), KHZ(2200), KHZ(2150) -}; - -static const uint32_t *if_filter_bw[] = { - mix_filter_bw, - ifch_filter_bw, - ifrc_filter_bw, -}; - -static const uint32_t if_filter_bw_len[] = { - ARRAY_SIZE(mix_filter_bw), - ARRAY_SIZE(ifch_filter_bw), - ARRAY_SIZE(ifrc_filter_bw), -}; - -static const struct reg_field if_filter_fields[] = { - { - E4K_REG_FILT2, 4, 4, - }, - { - E4K_REG_FILT3, 0, 5, - }, - { - E4K_REG_FILT2, 0, 4, - } -}; - -static int find_if_bw(enum e4k_if_filter filter, uint32_t bw) -{ - if (filter >= ARRAY_SIZE(if_filter_bw)) - return -EINVAL; - - return closest_arr_idx(if_filter_bw[filter], - if_filter_bw_len[filter], bw); -} - -/*! \brief Set the filter band-width of any of the IF filters - * \param[in] e4k reference to the tuner chip - * \param[in] filter filter to be configured - * \param[in] bandwidth bandwidth to be configured - * \returns positive actual filter band-width, negative in case of error - */ -int e4k_if_filter_bw_set(struct e4k_state *e4k, enum e4k_if_filter filter, - uint32_t bandwidth) -{ - int bw_idx; - const struct reg_field *field; - - if (filter >= ARRAY_SIZE(if_filter_bw)) - return -EINVAL; - - bw_idx = find_if_bw(filter, bandwidth); - - field = &if_filter_fields[filter]; - - return e4k_field_write(e4k, field, bw_idx); -} - -/*! \brief Enables / Disables the channel filter - * \param[in] e4k reference to the tuner chip - * \param[in] on 1=filter enabled, 0=filter disabled - * \returns 0 success, negative errors - */ -int e4k_if_filter_chan_enable(struct e4k_state *e4k, int on) -{ - return e4k_reg_set_mask(e4k, E4K_REG_FILT3, E4K_FILT3_DISABLE, - on ? 0 : E4K_FILT3_DISABLE); -} - -int e4k_if_filter_bw_get(struct e4k_state *e4k, enum e4k_if_filter filter) -{ - const uint32_t *arr; - int rc; - const struct reg_field *field; - - if (filter >= ARRAY_SIZE(if_filter_bw)) - return -EINVAL; - - field = &if_filter_fields[filter]; - - rc = e4k_field_read(e4k, field); - if (rc < 0) - return rc; - - arr = if_filter_bw[filter]; - - return arr[rc]; -} - - -/*********************************************************************** - * Frequency Control */ - -#define E4K_FVCO_MIN_KHZ 2600000 /* 2.6 GHz */ -#define E4K_FVCO_MAX_KHZ 3900000 /* 3.9 GHz */ -#define E4K_PLL_Y 65536 - -#ifdef OUT_OF_SPEC -#define E4K_FLO_MIN_MHZ 50 -#define E4K_FLO_MAX_MHZ 2200UL -#else -#define E4K_FLO_MIN_MHZ 64 -#define E4K_FLO_MAX_MHZ 1700 -#endif - -struct pll_settings { - uint32_t freq; - uint8_t reg_synth7; - uint8_t mult; -}; - -static const struct pll_settings pll_vars[] = { - {KHZ(72400), (1 << 3) | 7, 48}, - {KHZ(81200), (1 << 3) | 6, 40}, - {KHZ(108300), (1 << 3) | 5, 32}, - {KHZ(162500), (1 << 3) | 4, 24}, - {KHZ(216600), (1 << 3) | 3, 16}, - {KHZ(325000), (1 << 3) | 2, 12}, - {KHZ(350000), (1 << 3) | 1, 8}, - {KHZ(432000), (0 << 3) | 3, 8}, - {KHZ(667000), (0 << 3) | 2, 6}, - {KHZ(1200000), (0 << 3) | 1, 4} -}; - -static int is_fvco_valid(uint32_t fvco_z) -{ - /* check if the resulting fosc is valid */ - if (fvco_z/1000 < E4K_FVCO_MIN_KHZ || - fvco_z/1000 > E4K_FVCO_MAX_KHZ) { - fprintf(stderr, "[E4K] Fvco %u invalid\n", fvco_z); - return 0; - } - - return 1; -} - -static int is_fosc_valid(uint32_t fosc) -{ - if (fosc < MHZ(16) || fosc > MHZ(30)) { - fprintf(stderr, "[E4K] Fosc %u invalid\n", fosc); - return 0; - } - - return 1; -} - -static int is_z_valid(uint32_t z) -{ - if (z > 255) { - fprintf(stderr, "[E4K] Z %u invalid\n", z); - return 0; - } - - return 1; -} - -/*! \brief Determine if 3-phase mixing shall be used or not */ -static int use_3ph_mixing(uint32_t flo) -{ - /* this is a magic number somewhre between VHF and UHF */ - if (flo < MHZ(350)) - return 1; - - return 0; -} - -/* \brief compute Fvco based on Fosc, Z and X - * \returns positive value (Fvco in Hz), 0 in case of error */ -static uint64_t compute_fvco(uint32_t f_osc, uint8_t z, uint16_t x) -{ - uint64_t fvco_z, fvco_x, fvco; - - /* We use the following transformation in order to - * handle the fractional part with integer arithmetic: - * Fvco = Fosc * (Z + X/Y) <=> Fvco = Fosc * Z + (Fosc * X)/Y - * This avoids X/Y = 0. However, then we would overflow a 32bit - * integer, as we cannot hold e.g. 26 MHz * 65536 either. - */ - fvco_z = (uint64_t)f_osc * z; - -#if 0 - if (!is_fvco_valid(fvco_z)) - return 0; -#endif - - fvco_x = ((uint64_t)f_osc * x) / E4K_PLL_Y; - - fvco = fvco_z + fvco_x; - - return fvco; -} - -static uint32_t compute_flo(uint32_t f_osc, uint8_t z, uint16_t x, uint8_t r) -{ - uint64_t fvco = compute_fvco(f_osc, z, x); - if (fvco == 0) - return -EINVAL; - - return fvco / r; -} - -static int e4k_band_set(struct e4k_state *e4k, enum e4k_band band) -{ - int rc; - - switch (band) { - case E4K_BAND_VHF2: - case E4K_BAND_VHF3: - case E4K_BAND_UHF: - e4k_reg_write(e4k, E4K_REG_BIAS, 3); - break; - case E4K_BAND_L: - e4k_reg_write(e4k, E4K_REG_BIAS, 0); - break; - } - - /* workaround: if we don't reset this register before writing to it, - * we get a gap between 325-350 MHz */ - rc = e4k_reg_set_mask(e4k, E4K_REG_SYNTH1, 0x06, 0); - rc = e4k_reg_set_mask(e4k, E4K_REG_SYNTH1, 0x06, band << 1); - if (rc >= 0) - e4k->band = band; - - return rc; -} - -/*! \brief Compute PLL parameters for givent target frequency - * \param[out] oscp Oscillator parameters, if computation successful - * \param[in] fosc Clock input frequency applied to the chip (Hz) - * \param[in] intended_flo target tuning frequency (Hz) - * \returns actual PLL frequency, as close as possible to intended_flo, - * 0 in case of error - */ -uint32_t e4k_compute_pll_params(struct e4k_pll_params *oscp, uint32_t fosc, uint32_t intended_flo) -{ - uint32_t i; - uint8_t r = 2; - uint64_t intended_fvco, remainder; - uint64_t z = 0; - uint32_t x; - int flo; - int three_phase_mixing = 0; - oscp->r_idx = 0; - - if (!is_fosc_valid(fosc)) - return 0; - - for(i = 0; i < ARRAY_SIZE(pll_vars); ++i) { - if(intended_flo < pll_vars[i].freq) { - three_phase_mixing = (pll_vars[i].reg_synth7 & 0x08) ? 1 : 0; - oscp->r_idx = pll_vars[i].reg_synth7; - r = pll_vars[i].mult; - break; - } - } - - //fprintf(stderr, "[E4K] Fint=%u, R=%u\n", intended_flo, r); - - /* flo(max) = 1700MHz, R(max) = 48, we need 64bit! */ - intended_fvco = (uint64_t)intended_flo * r; - - /* compute integral component of multiplier */ - z = intended_fvco / fosc; - - /* compute fractional part. this will not overflow, - * as fosc(max) = 30MHz and z(max) = 255 */ - remainder = intended_fvco - (fosc * z); - /* remainder(max) = 30MHz, E4K_PLL_Y = 65536 -> 64bit! */ - x = (remainder * E4K_PLL_Y) / fosc; - /* x(max) as result of this computation is 65536 */ - - flo = compute_flo(fosc, z, x, r); - - oscp->fosc = fosc; - oscp->flo = flo; - oscp->intended_flo = intended_flo; - oscp->r = r; -// oscp->r_idx = pll_vars[i].reg_synth7 & 0x0; - oscp->threephase = three_phase_mixing; - oscp->x = x; - oscp->z = z; - - return flo; -} - -int e4k_tune_params(struct e4k_state *e4k, struct e4k_pll_params *p) -{ - uint8_t val; - - /* program R + 3phase/2phase */ - e4k_reg_write(e4k, E4K_REG_SYNTH7, p->r_idx); - /* program Z */ - e4k_reg_write(e4k, E4K_REG_SYNTH3, p->z); - /* program X */ - e4k_reg_write(e4k, E4K_REG_SYNTH4, p->x & 0xff); - e4k_reg_write(e4k, E4K_REG_SYNTH5, p->x >> 8); - - /* we're in auto calibration mode, so there's no need to trigger it */ - - memcpy(&e4k->vco, p, sizeof(e4k->vco)); - - /* set the band */ - if (e4k->vco.flo < MHZ(140)) - e4k_band_set(e4k, E4K_BAND_VHF2); - else if (e4k->vco.flo < MHZ(350)) - e4k_band_set(e4k, E4K_BAND_VHF3); - else if (e4k->vco.flo < MHZ(1135)) - e4k_band_set(e4k, E4K_BAND_UHF); - else - e4k_band_set(e4k, E4K_BAND_L); - - /* select and set proper RF filter */ - e4k_rf_filter_set(e4k); - - return e4k->vco.flo; -} - -/*! \brief High-level tuning API, just specify frquency - * - * This function will compute matching PLL parameters, program them into the - * hardware and set the band as well as RF filter. - * - * \param[in] e4k reference to tuner - * \param[in] freq frequency in Hz - * \returns actual tuned frequency, negative in case of error - */ -int e4k_tune_freq(struct e4k_state *e4k, uint32_t freq) -{ - uint32_t rc; - struct e4k_pll_params p; - - /* determine PLL parameters */ - rc = e4k_compute_pll_params(&p, e4k->vco.fosc, freq); - if (!rc) - return -EINVAL; - - /* actually tune to those parameters */ - rc = e4k_tune_params(e4k, &p); - - /* check PLL lock */ - rc = e4k_reg_read(e4k, E4K_REG_SYNTH1); - if (!(rc & 0x01)) { - fprintf(stderr, "[E4K] PLL not locked for %u Hz!\n", freq); - return -1; - } - - return 0; -} - -/*********************************************************************** - * Gain Control */ - -static const int8_t if_stage1_gain[] = { - -3, 6 -}; - -static const int8_t if_stage23_gain[] = { - 0, 3, 6, 9 -}; - -static const int8_t if_stage4_gain[] = { - 0, 1, 2, 2 -}; - -static const int8_t if_stage56_gain[] = { - 3, 6, 9, 12, 15, 15, 15, 15 -}; - -static const int8_t *if_stage_gain[] = { - 0, - if_stage1_gain, - if_stage23_gain, - if_stage23_gain, - if_stage4_gain, - if_stage56_gain, - if_stage56_gain -}; - -static const uint8_t if_stage_gain_len[] = { - 0, - ARRAY_SIZE(if_stage1_gain), - ARRAY_SIZE(if_stage23_gain), - ARRAY_SIZE(if_stage23_gain), - ARRAY_SIZE(if_stage4_gain), - ARRAY_SIZE(if_stage56_gain), - ARRAY_SIZE(if_stage56_gain) -}; - -static const struct reg_field if_stage_gain_regs[] = { - { 0, 0, 0 }, - { E4K_REG_GAIN3, 0, 1 }, - { E4K_REG_GAIN3, 1, 2 }, - { E4K_REG_GAIN3, 3, 2 }, - { E4K_REG_GAIN3, 5, 2 }, - { E4K_REG_GAIN4, 0, 3 }, - { E4K_REG_GAIN4, 3, 3 } -}; - -static const int32_t lnagain[] = { - -50, 0, - -25, 1, - 0, 4, - 25, 5, - 50, 6, - 75, 7, - 100, 8, - 125, 9, - 150, 10, - 175, 11, - 200, 12, - 250, 13, - 300, 14, -}; - -static const int32_t enhgain[] = { - 10, 30, 50, 70 -}; - -int e4k_set_lna_gain(struct e4k_state *e4k, int32_t gain) -{ - uint32_t i; - for(i = 0; i < ARRAY_SIZE(lnagain)/2; ++i) { - if(lnagain[i*2] == gain) { - e4k_reg_set_mask(e4k, E4K_REG_GAIN1, 0xf, lnagain[i*2+1]); - return gain; - } - } - return -EINVAL; -} - -int e4k_set_enh_gain(struct e4k_state *e4k, int32_t gain) -{ - uint32_t i; - for(i = 0; i < ARRAY_SIZE(enhgain); ++i) { - if(enhgain[i] == gain) { - e4k_reg_set_mask(e4k, E4K_REG_AGC11, 0x7, E4K_AGC11_LNA_GAIN_ENH | (i << 1)); - return gain; - } - } - e4k_reg_set_mask(e4k, E4K_REG_AGC11, 0x7, 0); - - /* special case: 0 = off*/ - if(0 == gain) - return 0; - else - return -EINVAL; -} - -int e4k_enable_manual_gain(struct e4k_state *e4k, uint8_t manual) -{ - if (manual) { - /* Set LNA mode to manual */ - e4k_reg_set_mask(e4k, E4K_REG_AGC1, E4K_AGC1_MOD_MASK, E4K_AGC_MOD_SERIAL); - - /* Set Mixer Gain Control to manual */ - e4k_reg_set_mask(e4k, E4K_REG_AGC7, E4K_AGC7_MIX_GAIN_AUTO, 0); - } else { - /* Set LNA mode to auto */ - e4k_reg_set_mask(e4k, E4K_REG_AGC1, E4K_AGC1_MOD_MASK, E4K_AGC_MOD_IF_SERIAL_LNA_AUTON); - /* Set Mixer Gain Control to auto */ - e4k_reg_set_mask(e4k, E4K_REG_AGC7, E4K_AGC7_MIX_GAIN_AUTO, 1); - - e4k_reg_set_mask(e4k, E4K_REG_AGC11, 0x7, 0); - } - - return 0; -} - -static int find_stage_gain(uint8_t stage, int8_t val) -{ - const int8_t *arr; - int i; - - if (stage >= ARRAY_SIZE(if_stage_gain)) - return -EINVAL; - - arr = if_stage_gain[stage]; - - for (i = 0; i < if_stage_gain_len[stage]; i++) { - if (arr[i] == val) - return i; - } - return -EINVAL; -} - -/*! \brief Set the gain of one of the IF gain stages - * \param [e4k] handle to the tuner chip - * \param [stage] number of the stage (1..6) - * \param [value] gain value in dB - * \returns 0 on success, negative in case of error - */ -int e4k_if_gain_set(struct e4k_state *e4k, uint8_t stage, int8_t value) -{ - int rc; - uint8_t mask; - const struct reg_field *field; - - rc = find_stage_gain(stage, value); - if (rc < 0) - return rc; - - /* compute the bit-mask for the given gain field */ - field = &if_stage_gain_regs[stage]; - mask = width2mask[field->width] << field->shift; - - return e4k_reg_set_mask(e4k, field->reg, mask, rc << field->shift); -} - -int e4k_mixer_gain_set(struct e4k_state *e4k, int8_t value) -{ - uint8_t bit; - - switch (value) { - case 4: - bit = 0; - break; - case 12: - bit = 1; - break; - default: - return -EINVAL; - } - - return e4k_reg_set_mask(e4k, E4K_REG_GAIN2, 1, bit); -} - -int e4k_commonmode_set(struct e4k_state *e4k, int8_t value) -{ - if(value < 0) - return -EINVAL; - else if(value > 7) - return -EINVAL; - - return e4k_reg_set_mask(e4k, E4K_REG_DC7, 7, value); -} - -/*********************************************************************** - * DC Offset */ - -int e4k_manual_dc_offset(struct e4k_state *e4k, int8_t iofs, int8_t irange, int8_t qofs, int8_t qrange) -{ - int res; - - if((iofs < 0x00) || (iofs > 0x3f)) - return -EINVAL; - if((irange < 0x00) || (irange > 0x03)) - return -EINVAL; - if((qofs < 0x00) || (qofs > 0x3f)) - return -EINVAL; - if((qrange < 0x00) || (qrange > 0x03)) - return -EINVAL; - - res = e4k_reg_set_mask(e4k, E4K_REG_DC2, 0x3f, iofs); - if(res < 0) - return res; - - res = e4k_reg_set_mask(e4k, E4K_REG_DC3, 0x3f, qofs); - if(res < 0) - return res; - - res = e4k_reg_set_mask(e4k, E4K_REG_DC4, 0x33, (qrange << 4) | irange); - return res; -} - -/*! \brief Perform a DC offset calibration right now - * \param [e4k] handle to the tuner chip - */ -int e4k_dc_offset_calibrate(struct e4k_state *e4k) -{ - /* make sure the DC range detector is enabled */ - e4k_reg_set_mask(e4k, E4K_REG_DC5, E4K_DC5_RANGE_DET_EN, E4K_DC5_RANGE_DET_EN); - - return e4k_reg_write(e4k, E4K_REG_DC1, 0x01); -} - - -static const int8_t if_gains_max[] = { - 0, 6, 9, 9, 2, 15, 15 -}; - -struct gain_comb { - int8_t mixer_gain; - int8_t if1_gain; - uint8_t reg; -}; - -static const struct gain_comb dc_gain_comb[] = { - { 4, -3, 0x50 }, - { 4, 6, 0x51 }, - { 12, -3, 0x52 }, - { 12, 6, 0x53 }, -}; - -#define TO_LUT(offset, range) (offset | (range << 6)) - -int e4k_dc_offset_gen_table(struct e4k_state *e4k) -{ - uint32_t i; - - /* FIXME: read ont current gain values and write them back - * before returning to the caller */ - - /* disable auto mixer gain */ - e4k_reg_set_mask(e4k, E4K_REG_AGC7, E4K_AGC7_MIX_GAIN_AUTO, 0); - - /* set LNA/IF gain to full manual */ - e4k_reg_set_mask(e4k, E4K_REG_AGC1, E4K_AGC1_MOD_MASK, - E4K_AGC_MOD_SERIAL); - - /* set all 'other' gains to maximum */ - for (i = 2; i <= 6; i++) - e4k_if_gain_set(e4k, i, if_gains_max[i]); - - /* iterate over all mixer + if_stage_1 gain combinations */ - for (i = 0; i < ARRAY_SIZE(dc_gain_comb); i++) { - uint8_t offs_i, offs_q, range, range_i, range_q; - - /* set the combination of mixer / if1 gain */ - e4k_mixer_gain_set(e4k, dc_gain_comb[i].mixer_gain); - e4k_if_gain_set(e4k, 1, dc_gain_comb[i].if1_gain); - - /* perform actual calibration */ - e4k_dc_offset_calibrate(e4k); - - /* extract I/Q offset and range values */ - offs_i = e4k_reg_read(e4k, E4K_REG_DC2) & 0x3f; - offs_q = e4k_reg_read(e4k, E4K_REG_DC3) & 0x3f; - range = e4k_reg_read(e4k, E4K_REG_DC4); - range_i = range & 0x3; - range_q = (range >> 4) & 0x3; - - fprintf(stderr, "[E4K] Table %u I=%u/%u, Q=%u/%u\n", - i, range_i, offs_i, range_q, offs_q); - - /* write into the table */ - e4k_reg_write(e4k, dc_gain_comb[i].reg, - TO_LUT(offs_q, range_q)); - e4k_reg_write(e4k, dc_gain_comb[i].reg + 0x10, - TO_LUT(offs_i, range_i)); - } - - return 0; -} - -/*********************************************************************** - * Initialization */ - -static int magic_init(struct e4k_state *e4k) -{ - e4k_reg_write(e4k, 0x7e, 0x01); - e4k_reg_write(e4k, 0x7f, 0xfe); - e4k_reg_write(e4k, 0x82, 0x00); - e4k_reg_write(e4k, 0x86, 0x50); /* polarity A */ - e4k_reg_write(e4k, 0x87, 0x20); - e4k_reg_write(e4k, 0x88, 0x01); - e4k_reg_write(e4k, 0x9f, 0x7f); - e4k_reg_write(e4k, 0xa0, 0x07); - - return 0; -} - -/*! \brief Initialize the E4K tuner - */ -int e4k_init(struct e4k_state *e4k) -{ - /* make a dummy i2c read or write command, will not be ACKed! */ - e4k_reg_read(e4k, 0); - - /* Make sure we reset everything and clear POR indicator */ - e4k_reg_write(e4k, E4K_REG_MASTER1, - E4K_MASTER1_RESET | - E4K_MASTER1_NORM_STBY | - E4K_MASTER1_POR_DET - ); - - /* Configure clock input */ - e4k_reg_write(e4k, E4K_REG_CLK_INP, 0x00); - - /* Disable clock output */ - e4k_reg_write(e4k, E4K_REG_REF_CLK, 0x00); - e4k_reg_write(e4k, E4K_REG_CLKOUT_PWDN, 0x96); - - /* Write some magic values into registers */ - magic_init(e4k); -#if 0 - /* Set common mode voltage a bit higher for more margin 850 mv */ - e4k_commonmode_set(e4k, 4); - - /* Initialize DC offset lookup tables */ - e4k_dc_offset_gen_table(e4k); - - /* Enable time variant DC correction */ - e4k_reg_write(e4k, E4K_REG_DCTIME1, 0x01); - e4k_reg_write(e4k, E4K_REG_DCTIME2, 0x01); -#endif - - /* Set LNA mode to manual */ - e4k_reg_write(e4k, E4K_REG_AGC4, 0x10); /* High threshold */ - e4k_reg_write(e4k, E4K_REG_AGC5, 0x04); /* Low threshold */ - e4k_reg_write(e4k, E4K_REG_AGC6, 0x1a); /* LNA calib + loop rate */ - - e4k_reg_set_mask(e4k, E4K_REG_AGC1, E4K_AGC1_MOD_MASK, - E4K_AGC_MOD_SERIAL); - - /* Set Mixer Gain Control to manual */ - e4k_reg_set_mask(e4k, E4K_REG_AGC7, E4K_AGC7_MIX_GAIN_AUTO, 0); - -#if 0 - /* Enable LNA Gain enhancement */ - e4k_reg_set_mask(e4k, E4K_REG_AGC11, 0x7, - E4K_AGC11_LNA_GAIN_ENH | (2 << 1)); - - /* Enable automatic IF gain mode switching */ - e4k_reg_set_mask(e4k, E4K_REG_AGC8, 0x1, E4K_AGC8_SENS_LIN_AUTO); -#endif - - /* Use auto-gain as default */ - e4k_enable_manual_gain(e4k, 0); - - /* Select moderate gain levels */ - e4k_if_gain_set(e4k, 1, 6); - e4k_if_gain_set(e4k, 2, 0); - e4k_if_gain_set(e4k, 3, 0); - e4k_if_gain_set(e4k, 4, 0); - e4k_if_gain_set(e4k, 5, 9); - e4k_if_gain_set(e4k, 6, 9); - - /* Set the most narrow filter we can possibly use */ - e4k_if_filter_bw_set(e4k, E4K_IF_FILTER_MIX, KHZ(1900)); - e4k_if_filter_bw_set(e4k, E4K_IF_FILTER_RC, KHZ(1000)); - e4k_if_filter_bw_set(e4k, E4K_IF_FILTER_CHAN, KHZ(2150)); - e4k_if_filter_chan_enable(e4k, 1); - - /* Disable time variant DC correction and LUT */ - e4k_reg_set_mask(e4k, E4K_REG_DC5, 0x03, 0); - e4k_reg_set_mask(e4k, E4K_REG_DCTIME1, 0x03, 0); - e4k_reg_set_mask(e4k, E4K_REG_DCTIME2, 0x03, 0); - - return 0; -} diff --git a/src/tuner_fc0012.c b/src/tuner_fc0012.c deleted file mode 100644 index 768cf1c4..00000000 --- a/src/tuner_fc0012.c +++ /dev/null @@ -1,345 +0,0 @@ -/* - * Fitipower FC0012 tuner driver - * - * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@gmx.net> - * - * modified for use in librtlsdr - * Copyright (C) 2012 Steve Markgraf <steve@steve-m.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <stdint.h> -#include <stdio.h> - -#include "rtlsdr_i2c.h" -#include "tuner_fc0012.h" - -static int fc0012_writereg(void *dev, uint8_t reg, uint8_t val) -{ - uint8_t data[2]; - data[0] = reg; - data[1] = val; - - if (rtlsdr_i2c_write_fn(dev, FC0012_I2C_ADDR, data, 2) < 0) - return -1; - - return 0; -} - -static int fc0012_readreg(void *dev, uint8_t reg, uint8_t *val) -{ - uint8_t data = reg; - - if (rtlsdr_i2c_write_fn(dev, FC0012_I2C_ADDR, &data, 1) < 0) - return -1; - - if (rtlsdr_i2c_read_fn(dev, FC0012_I2C_ADDR, &data, 1) < 0) - return -1; - - *val = data; - - return 0; -} - -/* Incomplete list of register settings: - * - * Name Reg Bits Desc - * CHIP_ID 0x00 0-7 Chip ID (constant 0xA1) - * RF_A 0x01 0-3 Number of count-to-9 cycles in RF - * divider (suggested: 2..9) - * RF_M 0x02 0-7 Total number of cycles (to-8 and to-9) - * in RF divider - * RF_K_HIGH 0x03 0-6 Bits 8..14 of fractional divider - * RF_K_LOW 0x04 0-7 Bits 0..7 of fractional RF divider - * RF_OUTDIV_A 0x05 3-7 Power of two required? - * LNA_POWER_DOWN 0x06 0 Set to 1 to switch off low noise amp - * RF_OUTDIV_B 0x06 1 Set to select 3 instead of 2 for the - * RF output divider - * VCO_SPEED 0x06 3 Select tuning range of VCO: - * 0 = Low range, (ca. 1.1 - 1.5GHz) - * 1 = High range (ca. 1.4 - 1.8GHz) - * BANDWIDTH 0x06 6-7 Set bandwidth. 6MHz = 0x80, 7MHz=0x40 - * 8MHz=0x00 - * XTAL_SPEED 0x07 5 Set to 1 for 28.8MHz Crystal input - * or 0 for 36MHz - * <agc params> 0x08 0-7 - * EN_CAL_RSSI 0x09 4 Enable calibrate RSSI - * (Receive Signal Strength Indicator) - * LNA_FORCE 0x0d 0 - * AGC_FORCE 0x0d ? - * LNA_GAIN 0x13 3-4 Low noise amp gain - * LNA_COMPS 0x15 3 ? - * VCO_CALIB 0x0e 7 Set high then low to calibrate VCO - * (fast lock?) - * VCO_VOLTAGE 0x0e 0-6 Read Control voltage of VCO - * (big value -> low freq) - */ - -int fc0012_init(void *dev) -{ - int ret = 0; - unsigned int i; - uint8_t reg[] = { - 0x00, /* dummy reg. 0 */ - 0x05, /* reg. 0x01 */ - 0x10, /* reg. 0x02 */ - 0x00, /* reg. 0x03 */ - 0x00, /* reg. 0x04 */ - 0x0f, /* reg. 0x05: may also be 0x0a */ - 0x00, /* reg. 0x06: divider 2, VCO slow */ - 0x00, /* reg. 0x07: may also be 0x0f */ - 0xff, /* reg. 0x08: AGC Clock divide by 256, AGC gain 1/256, - Loop Bw 1/8 */ - 0x6e, /* reg. 0x09: Disable LoopThrough, Enable LoopThrough: 0x6f */ - 0xb8, /* reg. 0x0a: Disable LO Test Buffer */ - 0x82, /* reg. 0x0b: Output Clock is same as clock frequency, - may also be 0x83 */ - 0xfc, /* reg. 0x0c: depending on AGC Up-Down mode, may need 0xf8 */ - 0x02, /* reg. 0x0d: AGC Not Forcing & LNA Forcing, 0x02 for DVB-T */ - 0x00, /* reg. 0x0e */ - 0x00, /* reg. 0x0f */ - 0x00, /* reg. 0x10: may also be 0x0d */ - 0x00, /* reg. 0x11 */ - 0x1f, /* reg. 0x12: Set to maximum gain */ - 0x08, /* reg. 0x13: Set to Middle Gain: 0x08, - Low Gain: 0x00, High Gain: 0x10, enable IX2: 0x80 */ - 0x00, /* reg. 0x14 */ - 0x04, /* reg. 0x15: Enable LNA COMPS */ - }; - -#if 0 - switch (rtlsdr_get_tuner_clock(dev)) { - case FC_XTAL_27_MHZ: - case FC_XTAL_28_8_MHZ: - reg[0x07] |= 0x20; - break; - case FC_XTAL_36_MHZ: - default: - break; - } -#endif - reg[0x07] |= 0x20; - -// if (priv->dual_master) - reg[0x0c] |= 0x02; - - for (i = 1; i < sizeof(reg); i++) { - ret = fc0012_writereg(dev, i, reg[i]); - if (ret) - break; - } - - return ret; -} - -int fc0012_set_params(void *dev, uint32_t freq, uint32_t bandwidth) -{ - int i, ret = 0; - uint8_t reg[7], am, pm, multi, tmp; - uint64_t f_vco; - uint32_t xtal_freq_div_2; - uint16_t xin, xdiv; - int vco_select = 0; - - xtal_freq_div_2 = rtlsdr_get_tuner_clock(dev) / 2; - - /* select frequency divider and the frequency of VCO */ - if (freq < 37084000) { /* freq * 96 < 3560000000 */ - multi = 96; - reg[5] = 0x82; - reg[6] = 0x00; - } else if (freq < 55625000) { /* freq * 64 < 3560000000 */ - multi = 64; - reg[5] = 0x82; - reg[6] = 0x02; - } else if (freq < 74167000) { /* freq * 48 < 3560000000 */ - multi = 48; - reg[5] = 0x42; - reg[6] = 0x00; - } else if (freq < 111250000) { /* freq * 32 < 3560000000 */ - multi = 32; - reg[5] = 0x42; - reg[6] = 0x02; - } else if (freq < 148334000) { /* freq * 24 < 3560000000 */ - multi = 24; - reg[5] = 0x22; - reg[6] = 0x00; - } else if (freq < 222500000) { /* freq * 16 < 3560000000 */ - multi = 16; - reg[5] = 0x22; - reg[6] = 0x02; - } else if (freq < 296667000) { /* freq * 12 < 3560000000 */ - multi = 12; - reg[5] = 0x12; - reg[6] = 0x00; - } else if (freq < 445000000) { /* freq * 8 < 3560000000 */ - multi = 8; - reg[5] = 0x12; - reg[6] = 0x02; - } else if (freq < 593334000) { /* freq * 6 < 3560000000 */ - multi = 6; - reg[5] = 0x0a; - reg[6] = 0x00; - } else { - multi = 4; - reg[5] = 0x0a; - reg[6] = 0x02; - } - - f_vco = freq * multi; - - if (f_vco >= 3060000000U) { - reg[6] |= 0x08; - vco_select = 1; - } - - /* From divided value (XDIV) determined the FA and FP value */ - xdiv = (uint16_t)(f_vco / xtal_freq_div_2); - if ((f_vco - xdiv * xtal_freq_div_2) >= (xtal_freq_div_2 / 2)) - xdiv++; - - pm = (uint8_t)(xdiv / 8); - am = (uint8_t)(xdiv - (8 * pm)); - - if (am < 2) { - am += 8; - pm--; - } - - if (pm > 31) { - reg[1] = am + (8 * (pm - 31)); - reg[2] = 31; - } else { - reg[1] = am; - reg[2] = pm; - } - - if ((reg[1] > 15) || (reg[2] < 0x0b)) { - fprintf(stderr, "[FC0012] no valid PLL combination " - "found for %u Hz!\n", freq); - return -1; - } - - /* fix clock out */ - reg[6] |= 0x20; - - /* From VCO frequency determines the XIN ( fractional part of Delta - Sigma PLL) and divided value (XDIV) */ - xin = (uint16_t)((f_vco - (f_vco / xtal_freq_div_2) * xtal_freq_div_2) / 1000); - xin = (xin << 15) / (xtal_freq_div_2 / 1000); - if (xin >= 16384) - xin += 32768; - - reg[3] = xin >> 8; /* xin with 9 bit resolution */ - reg[4] = xin & 0xff; - - reg[6] &= 0x3f; /* bits 6 and 7 describe the bandwidth */ - switch (bandwidth) { - case 6000000: - reg[6] |= 0x80; - break; - case 7000000: - reg[6] |= 0x40; - break; - case 8000000: - default: - break; - } - - /* modified for Realtek demod */ - reg[5] |= 0x07; - - for (i = 1; i <= 6; i++) { - ret = fc0012_writereg(dev, i, reg[i]); - if (ret) - goto exit; - } - - /* VCO Calibration */ - ret = fc0012_writereg(dev, 0x0e, 0x80); - if (!ret) - ret = fc0012_writereg(dev, 0x0e, 0x00); - - /* VCO Re-Calibration if needed */ - if (!ret) - ret = fc0012_writereg(dev, 0x0e, 0x00); - - if (!ret) { -// msleep(10); - ret = fc0012_readreg(dev, 0x0e, &tmp); - } - if (ret) - goto exit; - - /* vco selection */ - tmp &= 0x3f; - - if (vco_select) { - if (tmp > 0x3c) { - reg[6] &= ~0x08; - ret = fc0012_writereg(dev, 0x06, reg[6]); - if (!ret) - ret = fc0012_writereg(dev, 0x0e, 0x80); - if (!ret) - ret = fc0012_writereg(dev, 0x0e, 0x00); - } - } else { - if (tmp < 0x02) { - reg[6] |= 0x08; - ret = fc0012_writereg(dev, 0x06, reg[6]); - if (!ret) - ret = fc0012_writereg(dev, 0x0e, 0x80); - if (!ret) - ret = fc0012_writereg(dev, 0x0e, 0x00); - } - } - -exit: - return ret; -} - -int fc0012_set_gain(void *dev, int gain) -{ - int ret; - uint8_t tmp = 0; - - ret = fc0012_readreg(dev, 0x13, &tmp); - - /* mask bits off */ - tmp &= 0xe0; - - switch (gain) { - case -99: /* -9.9 dB */ - tmp |= 0x02; - break; - case -40: /* -4 dB */ - break; - case 71: - tmp |= 0x08; /* 7.1 dB */ - break; - case 179: - tmp |= 0x17; /* 17.9 dB */ - break; - case 192: - default: - tmp |= 0x10; /* 19.2 dB */ - break; - } - - ret = fc0012_writereg(dev, 0x13, tmp); - - return ret; -} diff --git a/src/tuner_fc0013.c b/src/tuner_fc0013.c deleted file mode 100644 index 78b696ee..00000000 --- a/src/tuner_fc0013.c +++ /dev/null @@ -1,500 +0,0 @@ -/* - * Fitipower FC0013 tuner driver - * - * Copyright (C) 2012 Hans-Frieder Vogt <hfvogt@gmx.net> - * partially based on driver code from Fitipower - * Copyright (C) 2010 Fitipower Integrated Technology Inc - * - * modified for use in librtlsdr - * Copyright (C) 2012 Steve Markgraf <steve@steve-m.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include <stdint.h> -#include <stdio.h> - -#include "rtlsdr_i2c.h" -#include "tuner_fc0013.h" - -static int fc0013_writereg(void *dev, uint8_t reg, uint8_t val) -{ - uint8_t data[2]; - data[0] = reg; - data[1] = val; - - if (rtlsdr_i2c_write_fn(dev, FC0013_I2C_ADDR, data, 2) < 0) - return -1; - - return 0; -} - -static int fc0013_readreg(void *dev, uint8_t reg, uint8_t *val) -{ - uint8_t data = reg; - - if (rtlsdr_i2c_write_fn(dev, FC0013_I2C_ADDR, &data, 1) < 0) - return -1; - - if (rtlsdr_i2c_read_fn(dev, FC0013_I2C_ADDR, &data, 1) < 0) - return -1; - - *val = data; - - return 0; -} - -int fc0013_init(void *dev) -{ - int ret = 0; - unsigned int i; - uint8_t reg[] = { - 0x00, /* reg. 0x00: dummy */ - 0x09, /* reg. 0x01 */ - 0x16, /* reg. 0x02 */ - 0x00, /* reg. 0x03 */ - 0x00, /* reg. 0x04 */ - 0x17, /* reg. 0x05 */ - 0x02, /* reg. 0x06: LPF bandwidth */ - 0x0a, /* reg. 0x07: CHECK */ - 0xff, /* reg. 0x08: AGC Clock divide by 256, AGC gain 1/256, - Loop Bw 1/8 */ - 0x6e, /* reg. 0x09: Disable LoopThrough, Enable LoopThrough: 0x6f */ - 0xb8, /* reg. 0x0a: Disable LO Test Buffer */ - 0x82, /* reg. 0x0b: CHECK */ - 0xfc, /* reg. 0x0c: depending on AGC Up-Down mode, may need 0xf8 */ - 0x01, /* reg. 0x0d: AGC Not Forcing & LNA Forcing, may need 0x02 */ - 0x00, /* reg. 0x0e */ - 0x00, /* reg. 0x0f */ - 0x00, /* reg. 0x10 */ - 0x00, /* reg. 0x11 */ - 0x00, /* reg. 0x12 */ - 0x00, /* reg. 0x13 */ - 0x50, /* reg. 0x14: DVB-t High Gain, UHF. - Middle Gain: 0x48, Low Gain: 0x40 */ - 0x01, /* reg. 0x15 */ - }; -#if 0 - switch (rtlsdr_get_tuner_clock(dev)) { - case FC_XTAL_27_MHZ: - case FC_XTAL_28_8_MHZ: - reg[0x07] |= 0x20; - break; - case FC_XTAL_36_MHZ: - default: - break; - } -#endif - reg[0x07] |= 0x20; - -// if (dev->dual_master) - reg[0x0c] |= 0x02; - - for (i = 1; i < sizeof(reg); i++) { - ret = fc0013_writereg(dev, i, reg[i]); - if (ret < 0) - break; - } - - return ret; -} - -int fc0013_rc_cal_add(void *dev, int rc_val) -{ - int ret; - uint8_t rc_cal; - int val; - - /* push rc_cal value, get rc_cal value */ - ret = fc0013_writereg(dev, 0x10, 0x00); - if (ret) - goto error_out; - - /* get rc_cal value */ - ret = fc0013_readreg(dev, 0x10, &rc_cal); - if (ret) - goto error_out; - - rc_cal &= 0x0f; - - val = (int)rc_cal + rc_val; - - /* forcing rc_cal */ - ret = fc0013_writereg(dev, 0x0d, 0x11); - if (ret) - goto error_out; - - /* modify rc_cal value */ - if (val > 15) - ret = fc0013_writereg(dev, 0x10, 0x0f); - else if (val < 0) - ret = fc0013_writereg(dev, 0x10, 0x00); - else - ret = fc0013_writereg(dev, 0x10, (uint8_t)val); - -error_out: - return ret; -} - -int fc0013_rc_cal_reset(void *dev) -{ - int ret; - - ret = fc0013_writereg(dev, 0x0d, 0x01); - if (!ret) - ret = fc0013_writereg(dev, 0x10, 0x00); - - return ret; -} - -static int fc0013_set_vhf_track(void *dev, uint32_t freq) -{ - int ret; - uint8_t tmp; - - ret = fc0013_readreg(dev, 0x1d, &tmp); - if (ret) - goto error_out; - tmp &= 0xe3; - if (freq <= 177500000) { /* VHF Track: 7 */ - ret = fc0013_writereg(dev, 0x1d, tmp | 0x1c); - } else if (freq <= 184500000) { /* VHF Track: 6 */ - ret = fc0013_writereg(dev, 0x1d, tmp | 0x18); - } else if (freq <= 191500000) { /* VHF Track: 5 */ - ret = fc0013_writereg(dev, 0x1d, tmp | 0x14); - } else if (freq <= 198500000) { /* VHF Track: 4 */ - ret = fc0013_writereg(dev, 0x1d, tmp | 0x10); - } else if (freq <= 205500000) { /* VHF Track: 3 */ - ret = fc0013_writereg(dev, 0x1d, tmp | 0x0c); - } else if (freq <= 219500000) { /* VHF Track: 2 */ - ret = fc0013_writereg(dev, 0x1d, tmp | 0x08); - } else if (freq < 300000000) { /* VHF Track: 1 */ - ret = fc0013_writereg(dev, 0x1d, tmp | 0x04); - } else { /* UHF and GPS */ - ret = fc0013_writereg(dev, 0x1d, tmp | 0x1c); - } - -error_out: - return ret; -} - -int fc0013_set_params(void *dev, uint32_t freq, uint32_t bandwidth) -{ - int i, ret = 0; - uint8_t reg[7], am, pm, multi, tmp; - uint64_t f_vco; - uint32_t xtal_freq_div_2; - uint16_t xin, xdiv; - int vco_select = 0; - - xtal_freq_div_2 = rtlsdr_get_tuner_clock(dev) / 2; - - /* set VHF track */ - ret = fc0013_set_vhf_track(dev, freq); - if (ret) - goto exit; - - if (freq < 300000000) { - /* enable VHF filter */ - ret = fc0013_readreg(dev, 0x07, &tmp); - if (ret) - goto exit; - ret = fc0013_writereg(dev, 0x07, tmp | 0x10); - if (ret) - goto exit; - - /* disable UHF & disable GPS */ - ret = fc0013_readreg(dev, 0x14, &tmp); - if (ret) - goto exit; - ret = fc0013_writereg(dev, 0x14, tmp & 0x1f); - if (ret) - goto exit; - } else if (freq <= 862000000) { - /* disable VHF filter */ - ret = fc0013_readreg(dev, 0x07, &tmp); - if (ret) - goto exit; - ret = fc0013_writereg(dev, 0x07, tmp & 0xef); - if (ret) - goto exit; - - /* enable UHF & disable GPS */ - ret = fc0013_readreg(dev, 0x14, &tmp); - if (ret) - goto exit; - ret = fc0013_writereg(dev, 0x14, (tmp & 0x1f) | 0x40); - if (ret) - goto exit; - } else { - /* disable VHF filter */ - ret = fc0013_readreg(dev, 0x07, &tmp); - if (ret) - goto exit; - ret = fc0013_writereg(dev, 0x07, tmp & 0xef); - if (ret) - goto exit; - - /* disable UHF & enable GPS */ - ret = fc0013_readreg(dev, 0x14, &tmp); - if (ret) - goto exit; - ret = fc0013_writereg(dev, 0x14, (tmp & 0x1f) | 0x20); - if (ret) - goto exit; - } - - /* select frequency divider and the frequency of VCO */ - if (freq < 37084000) { /* freq * 96 < 3560000000 */ - multi = 96; - reg[5] = 0x82; - reg[6] = 0x00; - } else if (freq < 55625000) { /* freq * 64 < 3560000000 */ - multi = 64; - reg[5] = 0x02; - reg[6] = 0x02; - } else if (freq < 74167000) { /* freq * 48 < 3560000000 */ - multi = 48; - reg[5] = 0x42; - reg[6] = 0x00; - } else if (freq < 111250000) { /* freq * 32 < 3560000000 */ - multi = 32; - reg[5] = 0x82; - reg[6] = 0x02; - } else if (freq < 148334000) { /* freq * 24 < 3560000000 */ - multi = 24; - reg[5] = 0x22; - reg[6] = 0x00; - } else if (freq < 222500000) { /* freq * 16 < 3560000000 */ - multi = 16; - reg[5] = 0x42; - reg[6] = 0x02; - } else if (freq < 296667000) { /* freq * 12 < 3560000000 */ - multi = 12; - reg[5] = 0x12; - reg[6] = 0x00; - } else if (freq < 445000000) { /* freq * 8 < 3560000000 */ - multi = 8; - reg[5] = 0x22; - reg[6] = 0x02; - } else if (freq < 593334000) { /* freq * 6 < 3560000000 */ - multi = 6; - reg[5] = 0x0a; - reg[6] = 0x00; - } else if (freq < 950000000) { /* freq * 4 < 3800000000 */ - multi = 4; - reg[5] = 0x12; - reg[6] = 0x02; - } else { - multi = 2; - reg[5] = 0x0a; - reg[6] = 0x02; - } - - f_vco = freq * multi; - - if (f_vco >= 3060000000U) { - reg[6] |= 0x08; - vco_select = 1; - } - - /* From divided value (XDIV) determined the FA and FP value */ - xdiv = (uint16_t)(f_vco / xtal_freq_div_2); - if ((f_vco - xdiv * xtal_freq_div_2) >= (xtal_freq_div_2 / 2)) - xdiv++; - - pm = (uint8_t)(xdiv / 8); - am = (uint8_t)(xdiv - (8 * pm)); - - if (am < 2) { - am += 8; - pm--; - } - - if (pm > 31) { - reg[1] = am + (8 * (pm - 31)); - reg[2] = 31; - } else { - reg[1] = am; - reg[2] = pm; - } - - if ((reg[1] > 15) || (reg[2] < 0x0b)) { - fprintf(stderr, "[FC0013] no valid PLL combination " - "found for %u Hz!\n", freq); - return -1; - } - - /* fix clock out */ - reg[6] |= 0x20; - - /* From VCO frequency determines the XIN ( fractional part of Delta - Sigma PLL) and divided value (XDIV) */ - xin = (uint16_t)((f_vco - (f_vco / xtal_freq_div_2) * xtal_freq_div_2) / 1000); - xin = (xin << 15) / (xtal_freq_div_2 / 1000); - if (xin >= 16384) - xin += 32768; - - reg[3] = xin >> 8; - reg[4] = xin & 0xff; - - reg[6] &= 0x3f; /* bits 6 and 7 describe the bandwidth */ - switch (bandwidth) { - case 6000000: - reg[6] |= 0x80; - break; - case 7000000: - reg[6] |= 0x40; - break; - case 8000000: - default: - break; - } - - /* modified for Realtek demod */ - reg[5] |= 0x07; - - for (i = 1; i <= 6; i++) { - ret = fc0013_writereg(dev, i, reg[i]); - if (ret) - goto exit; - } - - ret = fc0013_readreg(dev, 0x11, &tmp); - if (ret) - goto exit; - if (multi == 64) - ret = fc0013_writereg(dev, 0x11, tmp | 0x04); - else - ret = fc0013_writereg(dev, 0x11, tmp & 0xfb); - if (ret) - goto exit; - - /* VCO Calibration */ - ret = fc0013_writereg(dev, 0x0e, 0x80); - if (!ret) - ret = fc0013_writereg(dev, 0x0e, 0x00); - - /* VCO Re-Calibration if needed */ - if (!ret) - ret = fc0013_writereg(dev, 0x0e, 0x00); - - if (!ret) { -// msleep(10); - ret = fc0013_readreg(dev, 0x0e, &tmp); - } - if (ret) - goto exit; - - /* vco selection */ - tmp &= 0x3f; - - if (vco_select) { - if (tmp > 0x3c) { - reg[6] &= ~0x08; - ret = fc0013_writereg(dev, 0x06, reg[6]); - if (!ret) - ret = fc0013_writereg(dev, 0x0e, 0x80); - if (!ret) - ret = fc0013_writereg(dev, 0x0e, 0x00); - } - } else { - if (tmp < 0x02) { - reg[6] |= 0x08; - ret = fc0013_writereg(dev, 0x06, reg[6]); - if (!ret) - ret = fc0013_writereg(dev, 0x0e, 0x80); - if (!ret) - ret = fc0013_writereg(dev, 0x0e, 0x00); - } - } - -exit: - return ret; -} - -int fc0013_set_gain_mode(void *dev, int manual) -{ - int ret = 0; - uint8_t tmp = 0; - - ret |= fc0013_readreg(dev, 0x0d, &tmp); - - if (manual) - tmp |= (1 << 3); - else - tmp &= ~(1 << 3); - - ret |= fc0013_writereg(dev, 0x0d, tmp); - - /* set a fixed IF-gain for now */ - ret |= fc0013_writereg(dev, 0x13, 0x0a); - - return ret; -} - -int fc0013_lna_gains[] ={ - -99, 0x02, - -73, 0x03, - -65, 0x05, - -63, 0x04, - -63, 0x00, - -60, 0x07, - -58, 0x01, - -54, 0x06, - 58, 0x0f, - 61, 0x0e, - 63, 0x0d, - 65, 0x0c, - 67, 0x0b, - 68, 0x0a, - 70, 0x09, - 71, 0x08, - 179, 0x17, - 181, 0x16, - 182, 0x15, - 184, 0x14, - 186, 0x13, - 188, 0x12, - 191, 0x11, - 197, 0x10 -}; - -#define GAIN_CNT (sizeof(fc0013_lna_gains) / sizeof(int) / 2) - -int fc0013_set_lna_gain(void *dev, int gain) -{ - int ret = 0; - unsigned int i; - uint8_t tmp = 0; - - ret |= fc0013_readreg(dev, 0x14, &tmp); - - /* mask bits off */ - tmp &= 0xe0; - - for (i = 0; i < GAIN_CNT; i++) { - if ((fc0013_lna_gains[i*2] >= gain) || (i+1 == GAIN_CNT)) { - tmp |= fc0013_lna_gains[i*2 + 1]; - break; - } - } - - /* set gain */ - ret |= fc0013_writereg(dev, 0x14, tmp); - - return ret; -} diff --git a/src/tuner_fc2580.c b/src/tuner_fc2580.c deleted file mode 100644 index d2eeba56..00000000 --- a/src/tuner_fc2580.c +++ /dev/null @@ -1,494 +0,0 @@ -/* - * FCI FC2580 tuner driver, taken from the kernel driver that can be found - * on http://linux.terratec.de/tv_en.html - * - * This driver is a mess, and should be cleaned up/rewritten. - * - */ - -#include <stdint.h> - -#include "rtlsdr_i2c.h" -#include "tuner_fc2580.h" - -/* 16.384 MHz (at least on the Logilink VG0002A) */ -#define CRYSTAL_FREQ 16384000 - -/* glue functions to rtl-sdr code */ - -fc2580_fci_result_type fc2580_i2c_write(void *pTuner, unsigned char reg, unsigned char val) -{ - uint8_t data[2]; - - data[0] = reg; - data[1] = val; - - if (rtlsdr_i2c_write_fn(pTuner, FC2580_I2C_ADDR, data, 2) < 0) - return FC2580_FCI_FAIL; - - return FC2580_FCI_SUCCESS; -} - -fc2580_fci_result_type fc2580_i2c_read(void *pTuner, unsigned char reg, unsigned char *read_data) -{ - uint8_t data = reg; - - if (rtlsdr_i2c_write_fn(pTuner, FC2580_I2C_ADDR, &data, 1) < 0) - return FC2580_FCI_FAIL; - - if (rtlsdr_i2c_read_fn(pTuner, FC2580_I2C_ADDR, &data, 1) < 0) - return FC2580_FCI_FAIL; - - *read_data = data; - - return FC2580_FCI_SUCCESS; -} - -int -fc2580_Initialize( - void *pTuner - ) -{ - int AgcMode; - unsigned int CrystalFreqKhz; - - //TODO set AGC mode - AgcMode = FC2580_AGC_EXTERNAL; - - // Initialize tuner with AGC mode. - // Note: CrystalFreqKhz = round(CrystalFreqHz / 1000) - CrystalFreqKhz = (unsigned int)((CRYSTAL_FREQ + 500) / 1000); - - if(fc2580_set_init(pTuner, AgcMode, CrystalFreqKhz) != FC2580_FCI_SUCCESS) - goto error_status_initialize_tuner; - - - return FUNCTION_SUCCESS; - - -error_status_initialize_tuner: - return FUNCTION_ERROR; -} - -int -fc2580_SetRfFreqHz( - void *pTuner, - unsigned long RfFreqHz - ) -{ - unsigned int RfFreqKhz; - unsigned int CrystalFreqKhz; - - // Set tuner RF frequency in KHz. - // Note: RfFreqKhz = round(RfFreqHz / 1000) - // CrystalFreqKhz = round(CrystalFreqHz / 1000) - RfFreqKhz = (unsigned int)((RfFreqHz + 500) / 1000); - CrystalFreqKhz = (unsigned int)((CRYSTAL_FREQ + 500) / 1000); - - if(fc2580_set_freq(pTuner, RfFreqKhz, CrystalFreqKhz) != FC2580_FCI_SUCCESS) - goto error_status_set_tuner_rf_frequency; - - return FUNCTION_SUCCESS; - -error_status_set_tuner_rf_frequency: - return FUNCTION_ERROR; -} - -/** - -@brief Set FC2580 tuner bandwidth mode. - -*/ -int -fc2580_SetBandwidthMode( - void *pTuner, - int BandwidthMode - ) -{ - unsigned int CrystalFreqKhz; - - // Set tuner bandwidth mode. - // Note: CrystalFreqKhz = round(CrystalFreqHz / 1000) - CrystalFreqKhz = (unsigned int)((CRYSTAL_FREQ + 500) / 1000); - - if(fc2580_set_filter(pTuner, (unsigned char)BandwidthMode, CrystalFreqKhz) != FC2580_FCI_SUCCESS) - goto error_status_set_tuner_bandwidth_mode; - - return FUNCTION_SUCCESS; - - -error_status_set_tuner_bandwidth_mode: - return FUNCTION_ERROR; -} - -void fc2580_wait_msec(void *pTuner, int a) -{ - /* USB latency is enough for now ;) */ -// usleep(a * 1000); - return; -} - -/*============================================================================== - fc2580 initial setting - - This function is a generic function which gets called to initialize - - fc2580 in DVB-H mode or L-Band TDMB mode - - <input parameter> - - ifagc_mode - type : integer - 1 : Internal AGC - 2 : Voltage Control Mode - -==============================================================================*/ -fc2580_fci_result_type fc2580_set_init( void *pTuner, int ifagc_mode, unsigned int freq_xtal ) -{ - fc2580_fci_result_type result = FC2580_FCI_SUCCESS; - - result &= fc2580_i2c_write(pTuner, 0x00, 0x00); /*** Confidential ***/ - result &= fc2580_i2c_write(pTuner, 0x12, 0x86); - result &= fc2580_i2c_write(pTuner, 0x14, 0x5C); - result &= fc2580_i2c_write(pTuner, 0x16, 0x3C); - result &= fc2580_i2c_write(pTuner, 0x1F, 0xD2); - result &= fc2580_i2c_write(pTuner, 0x09, 0xD7); - result &= fc2580_i2c_write(pTuner, 0x0B, 0xD5); - result &= fc2580_i2c_write(pTuner, 0x0C, 0x32); - result &= fc2580_i2c_write(pTuner, 0x0E, 0x43); - result &= fc2580_i2c_write(pTuner, 0x21, 0x0A); - result &= fc2580_i2c_write(pTuner, 0x22, 0x82); - if( ifagc_mode == 1 ) - { - result &= fc2580_i2c_write(pTuner, 0x45, 0x10); //internal AGC - result &= fc2580_i2c_write(pTuner, 0x4C, 0x00); //HOLD_AGC polarity - } - else if( ifagc_mode == 2 ) - { - result &= fc2580_i2c_write(pTuner, 0x45, 0x20); //Voltage Control Mode - result &= fc2580_i2c_write(pTuner, 0x4C, 0x02); //HOLD_AGC polarity - } - result &= fc2580_i2c_write(pTuner, 0x3F, 0x88); - result &= fc2580_i2c_write(pTuner, 0x02, 0x0E); - result &= fc2580_i2c_write(pTuner, 0x58, 0x14); - result &= fc2580_set_filter(pTuner, 8, freq_xtal); //BW = 7.8MHz - - return result; -} - - -/*============================================================================== - fc2580 frequency setting - - This function is a generic function which gets called to change LO Frequency - - of fc2580 in DVB-H mode or L-Band TDMB mode - - <input parameter> - freq_xtal: kHz - - f_lo - Value of target LO Frequency in 'kHz' unit - ex) 2.6GHz = 2600000 - -==============================================================================*/ -fc2580_fci_result_type fc2580_set_freq( void *pTuner, unsigned int f_lo, unsigned int freq_xtal ) -{ - unsigned int f_diff, f_diff_shifted, n_val, k_val; - unsigned int f_vco, r_val, f_comp; - unsigned char pre_shift_bits = 4;// number of preshift to prevent overflow in shifting f_diff to f_diff_shifted - unsigned char data_0x18; - unsigned char data_0x02 = (USE_EXT_CLK<<5)|0x0E; - - fc2580_band_type band = ( f_lo > 1000000 )? FC2580_L_BAND : ( f_lo > 400000 )? FC2580_UHF_BAND : FC2580_VHF_BAND; - - fc2580_fci_result_type result = FC2580_FCI_SUCCESS; - - f_vco = ( band == FC2580_UHF_BAND )? f_lo * 4 : (( band == FC2580_L_BAND )? f_lo * 2 : f_lo * 12); - r_val = ( f_vco >= 2*76*freq_xtal )? 1 : ( f_vco >= 76*freq_xtal )? 2 : 4; - f_comp = freq_xtal/r_val; - n_val = ( f_vco / 2 ) / f_comp; - - f_diff = f_vco - 2* f_comp * n_val; - f_diff_shifted = f_diff << ( 20 - pre_shift_bits ); - k_val = f_diff_shifted / ( ( 2* f_comp ) >> pre_shift_bits ); - - if( f_diff_shifted - k_val * ( ( 2* f_comp ) >> pre_shift_bits ) >= ( f_comp >> pre_shift_bits ) ) - k_val = k_val + 1; - - if( f_vco >= BORDER_FREQ ) //Select VCO Band - data_0x02 = data_0x02 | 0x08; //0x02[3] = 1; - else - data_0x02 = data_0x02 & 0xF7; //0x02[3] = 0; - -// if( band != curr_band ) { - switch(band) - { - case FC2580_UHF_BAND: - data_0x02 = (data_0x02 & 0x3F); - - result &= fc2580_i2c_write(pTuner, 0x25, 0xF0); - result &= fc2580_i2c_write(pTuner, 0x27, 0x77); - result &= fc2580_i2c_write(pTuner, 0x28, 0x53); - result &= fc2580_i2c_write(pTuner, 0x29, 0x60); - result &= fc2580_i2c_write(pTuner, 0x30, 0x09); - result &= fc2580_i2c_write(pTuner, 0x50, 0x8C); - result &= fc2580_i2c_write(pTuner, 0x53, 0x50); - - if( f_lo < 538000 ) - result &= fc2580_i2c_write(pTuner, 0x5F, 0x13); - else - result &= fc2580_i2c_write(pTuner, 0x5F, 0x15); - - if( f_lo < 538000 ) - { - result &= fc2580_i2c_write(pTuner, 0x61, 0x07); - result &= fc2580_i2c_write(pTuner, 0x62, 0x06); - result &= fc2580_i2c_write(pTuner, 0x67, 0x06); - result &= fc2580_i2c_write(pTuner, 0x68, 0x08); - result &= fc2580_i2c_write(pTuner, 0x69, 0x10); - result &= fc2580_i2c_write(pTuner, 0x6A, 0x12); - } - else if( f_lo < 794000 ) - { - result &= fc2580_i2c_write(pTuner, 0x61, 0x03); - result &= fc2580_i2c_write(pTuner, 0x62, 0x03); - result &= fc2580_i2c_write(pTuner, 0x67, 0x03); //ACI improve - result &= fc2580_i2c_write(pTuner, 0x68, 0x05); //ACI improve - result &= fc2580_i2c_write(pTuner, 0x69, 0x0C); - result &= fc2580_i2c_write(pTuner, 0x6A, 0x0E); - } - else - { - result &= fc2580_i2c_write(pTuner, 0x61, 0x07); - result &= fc2580_i2c_write(pTuner, 0x62, 0x06); - result &= fc2580_i2c_write(pTuner, 0x67, 0x07); - result &= fc2580_i2c_write(pTuner, 0x68, 0x09); - result &= fc2580_i2c_write(pTuner, 0x69, 0x10); - result &= fc2580_i2c_write(pTuner, 0x6A, 0x12); - } - - result &= fc2580_i2c_write(pTuner, 0x63, 0x15); - - result &= fc2580_i2c_write(pTuner, 0x6B, 0x0B); - result &= fc2580_i2c_write(pTuner, 0x6C, 0x0C); - result &= fc2580_i2c_write(pTuner, 0x6D, 0x78); - result &= fc2580_i2c_write(pTuner, 0x6E, 0x32); - result &= fc2580_i2c_write(pTuner, 0x6F, 0x14); - result &= fc2580_set_filter(pTuner, 8, freq_xtal); //BW = 7.8MHz - break; - case FC2580_VHF_BAND: - data_0x02 = (data_0x02 & 0x3F) | 0x80; - result &= fc2580_i2c_write(pTuner, 0x27, 0x77); - result &= fc2580_i2c_write(pTuner, 0x28, 0x33); - result &= fc2580_i2c_write(pTuner, 0x29, 0x40); - result &= fc2580_i2c_write(pTuner, 0x30, 0x09); - result &= fc2580_i2c_write(pTuner, 0x50, 0x8C); - result &= fc2580_i2c_write(pTuner, 0x53, 0x50); - result &= fc2580_i2c_write(pTuner, 0x5F, 0x0F); - result &= fc2580_i2c_write(pTuner, 0x61, 0x07); - result &= fc2580_i2c_write(pTuner, 0x62, 0x00); - result &= fc2580_i2c_write(pTuner, 0x63, 0x15); - result &= fc2580_i2c_write(pTuner, 0x67, 0x03); - result &= fc2580_i2c_write(pTuner, 0x68, 0x05); - result &= fc2580_i2c_write(pTuner, 0x69, 0x10); - result &= fc2580_i2c_write(pTuner, 0x6A, 0x12); - result &= fc2580_i2c_write(pTuner, 0x6B, 0x08); - result &= fc2580_i2c_write(pTuner, 0x6C, 0x0A); - result &= fc2580_i2c_write(pTuner, 0x6D, 0x78); - result &= fc2580_i2c_write(pTuner, 0x6E, 0x32); - result &= fc2580_i2c_write(pTuner, 0x6F, 0x54); - result &= fc2580_set_filter(pTuner, 7, freq_xtal); //BW = 6.8MHz - break; - case FC2580_L_BAND: - data_0x02 = (data_0x02 & 0x3F) | 0x40; - result &= fc2580_i2c_write(pTuner, 0x2B, 0x70); - result &= fc2580_i2c_write(pTuner, 0x2C, 0x37); - result &= fc2580_i2c_write(pTuner, 0x2D, 0xE7); - result &= fc2580_i2c_write(pTuner, 0x30, 0x09); - result &= fc2580_i2c_write(pTuner, 0x44, 0x20); - result &= fc2580_i2c_write(pTuner, 0x50, 0x8C); - result &= fc2580_i2c_write(pTuner, 0x53, 0x50); - result &= fc2580_i2c_write(pTuner, 0x5F, 0x0F); - result &= fc2580_i2c_write(pTuner, 0x61, 0x0F); - result &= fc2580_i2c_write(pTuner, 0x62, 0x00); - result &= fc2580_i2c_write(pTuner, 0x63, 0x13); - result &= fc2580_i2c_write(pTuner, 0x67, 0x00); - result &= fc2580_i2c_write(pTuner, 0x68, 0x02); - result &= fc2580_i2c_write(pTuner, 0x69, 0x0C); - result &= fc2580_i2c_write(pTuner, 0x6A, 0x0E); - result &= fc2580_i2c_write(pTuner, 0x6B, 0x08); - result &= fc2580_i2c_write(pTuner, 0x6C, 0x0A); - result &= fc2580_i2c_write(pTuner, 0x6D, 0xA0); - result &= fc2580_i2c_write(pTuner, 0x6E, 0x50); - result &= fc2580_i2c_write(pTuner, 0x6F, 0x14); - result &= fc2580_set_filter(pTuner, 1, freq_xtal); //BW = 1.53MHz - break; - default: - break; - } -// curr_band = band; -// } - - //A command about AGC clock's pre-divide ratio - if( freq_xtal >= 28000 ) - result &= fc2580_i2c_write(pTuner, 0x4B, 0x22 ); - - //Commands about VCO Band and PLL setting. - result &= fc2580_i2c_write(pTuner, 0x02, data_0x02); - data_0x18 = ( ( r_val == 1 )? 0x00 : ( ( r_val == 2 )? 0x10 : 0x20 ) ) + (unsigned char)(k_val >> 16); - result &= fc2580_i2c_write(pTuner, 0x18, data_0x18); //Load 'R' value and high part of 'K' values - result &= fc2580_i2c_write(pTuner, 0x1A, (unsigned char)( k_val >> 8 ) ); //Load middle part of 'K' value - result &= fc2580_i2c_write(pTuner, 0x1B, (unsigned char)( k_val ) ); //Load lower part of 'K' value - result &= fc2580_i2c_write(pTuner, 0x1C, (unsigned char)( n_val ) ); //Load 'N' value - - //A command about UHF LNA Load Cap - if( band == FC2580_UHF_BAND ) - result &= fc2580_i2c_write(pTuner, 0x2D, ( f_lo <= (unsigned int)794000 )? 0x9F : 0x8F ); //LNA_OUT_CAP - - - return result; -} - - -/*============================================================================== - fc2580 filter BW setting - - This function is a generic function which gets called to change Bandwidth - - frequency of fc2580's channel selection filter - - <input parameter> - freq_xtal: kHz - - filter_bw - 1 : 1.53MHz(TDMB) - 6 : 6MHz (Bandwidth 6MHz) - 7 : 6.8MHz (Bandwidth 7MHz) - 8 : 7.8MHz (Bandwidth 8MHz) - - -==============================================================================*/ -fc2580_fci_result_type fc2580_set_filter( void *pTuner, unsigned char filter_bw, unsigned int freq_xtal ) -{ - unsigned char cal_mon = 0, i; - fc2580_fci_result_type result = FC2580_FCI_SUCCESS; - - if(filter_bw == 1) - { - result &= fc2580_i2c_write(pTuner, 0x36, 0x1C); - result &= fc2580_i2c_write(pTuner, 0x37, (unsigned char)(4151*freq_xtal/1000000) ); - result &= fc2580_i2c_write(pTuner, 0x39, 0x00); - result &= fc2580_i2c_write(pTuner, 0x2E, 0x09); - } - if(filter_bw == 6) - { - result &= fc2580_i2c_write(pTuner, 0x36, 0x18); - result &= fc2580_i2c_write(pTuner, 0x37, (unsigned char)(4400*freq_xtal/1000000) ); - result &= fc2580_i2c_write(pTuner, 0x39, 0x00); - result &= fc2580_i2c_write(pTuner, 0x2E, 0x09); - } - else if(filter_bw == 7) - { - result &= fc2580_i2c_write(pTuner, 0x36, 0x18); - result &= fc2580_i2c_write(pTuner, 0x37, (unsigned char)(3910*freq_xtal/1000000) ); - result &= fc2580_i2c_write(pTuner, 0x39, 0x80); - result &= fc2580_i2c_write(pTuner, 0x2E, 0x09); - } - else if(filter_bw == 8) - { - result &= fc2580_i2c_write(pTuner, 0x36, 0x18); - result &= fc2580_i2c_write(pTuner, 0x37, (unsigned char)(3300*freq_xtal/1000000) ); - result &= fc2580_i2c_write(pTuner, 0x39, 0x80); - result &= fc2580_i2c_write(pTuner, 0x2E, 0x09); - } - - - for(i=0; i<5; i++) - { - fc2580_wait_msec(pTuner, 5);//wait 5ms - result &= fc2580_i2c_read(pTuner, 0x2F, &cal_mon); - if( (cal_mon & 0xC0) != 0xC0) - { - result &= fc2580_i2c_write(pTuner, 0x2E, 0x01); - result &= fc2580_i2c_write(pTuner, 0x2E, 0x09); - } - else - break; - } - - result &= fc2580_i2c_write(pTuner, 0x2E, 0x01); - - return result; -} - -/*============================================================================== - fc2580 RSSI function - - This function is a generic function which returns fc2580's - - current RSSI value. - - <input parameter> - none - - <return value> - int - rssi : estimated input power. - -==============================================================================*/ -//int fc2580_get_rssi(void) { -// -// unsigned char s_lna, s_rfvga, s_cfs, s_ifvga; -// int ofs_lna, ofs_rfvga, ofs_csf, ofs_ifvga, rssi; -// -// fc2580_i2c_read(0x71, &s_lna ); -// fc2580_i2c_read(0x72, &s_rfvga ); -// fc2580_i2c_read(0x73, &s_cfs ); -// fc2580_i2c_read(0x74, &s_ifvga ); -// -// -// ofs_lna = -// (curr_band==FC2580_UHF_BAND)? -// (s_lna==0)? 0 : -// (s_lna==1)? -6 : -// (s_lna==2)? -17 : -// (s_lna==3)? -22 : -30 : -// (curr_band==FC2580_VHF_BAND)? -// (s_lna==0)? 0 : -// (s_lna==1)? -6 : -// (s_lna==2)? -19 : -// (s_lna==3)? -24 : -32 : -// (curr_band==FC2580_L_BAND)? -// (s_lna==0)? 0 : -// (s_lna==1)? -6 : -// (s_lna==2)? -11 : -// (s_lna==3)? -16 : -34 : -// 0;//FC2580_NO_BAND -// ofs_rfvga = -s_rfvga+((s_rfvga>=11)? 1 : 0) + ((s_rfvga>=18)? 1 : 0); -// ofs_csf = -6*s_cfs; -// ofs_ifvga = s_ifvga/4; -// -// return rssi = ofs_lna+ofs_rfvga+ofs_csf+ofs_ifvga+OFS_RSSI; -// -//} - -/*============================================================================== - fc2580 Xtal frequency Setting - - This function is a generic function which sets - - the frequency of xtal. - - <input parameter> - - frequency - frequency value of internal(external) Xtal(clock) in kHz unit. - -==============================================================================*/ -//void fc2580_set_freq_xtal(unsigned int frequency) { -// -// freq_xtal = frequency; -// -//} - diff --git a/src/tuner_r820t.c b/src/tuner_r820t.c deleted file mode 100644 index fd3188d4..00000000 --- a/src/tuner_r820t.c +++ /dev/null @@ -1,3050 +0,0 @@ -/* - * R820T tuner driver, taken from Realteks RTL2832U Linux Kernel Driver - * - * This driver is a mess, and should be cleaned up/rewritten. - * - */ - -#include <stdint.h> -#include <stdio.h> - -#include "rtlsdr_i2c.h" -#include "tuner_r820t.h" - -int r820t_SetRfFreqHz(void *pTuner, unsigned long RfFreqHz) -{ - R828_Set_Info R828Info; - -// if(pExtra->IsStandardModeSet==NO) -// goto error_status_set_tuner_rf_frequency; - -// R828Info.R828_Standard = (R828_Standard_Type)pExtra->StandardMode; - R828Info.R828_Standard = (R828_Standard_Type)DVB_T_6M; - R828Info.RF_Hz = (UINT32)(RfFreqHz); - R828Info.RF_KHz = (UINT32)(RfFreqHz/1000); - - if(R828_SetFrequency(pTuner, R828Info, NORMAL_MODE) != RT_Success) - return FUNCTION_ERROR; - - return FUNCTION_SUCCESS; -} - -int r820t_SetStandardMode(void *pTuner, int StandardMode) -{ - if(R828_SetStandard(pTuner, (R828_Standard_Type)StandardMode) != RT_Success) - return FUNCTION_ERROR; - - return FUNCTION_SUCCESS; -} - -int r820t_SetStandby(void *pTuner, int LoopThroughType) -{ - - if(R828_Standby(pTuner, (R828_LoopThrough_Type)LoopThroughType) != RT_Success) - return FUNCTION_ERROR; - - return FUNCTION_SUCCESS; -} - -// The following context is implemented for R820T source code. - -/* just reverses the bits of a byte */ -int -r820t_Convert(int InvertNum) -{ - int ReturnNum; - int AddNum; - int BitNum; - int CountNum; - - ReturnNum = 0; - AddNum = 0x80; - BitNum = 0x01; - - for(CountNum = 0;CountNum < 8;CountNum ++) - { - if(BitNum & InvertNum) - ReturnNum += AddNum; - - AddNum /= 2; - BitNum *= 2; - } - - return ReturnNum; -} - -R828_ErrCode -I2C_Write_Len(void *pTuner, R828_I2C_LEN_TYPE *I2C_Info) -{ - unsigned char DeviceAddr; - - unsigned int i, j; - - unsigned char RegStartAddr; - unsigned char *pWritingBytes; - unsigned long ByteNum; - - unsigned char WritingBuffer[128]; - unsigned long WritingByteNum, WritingByteNumMax, WritingByteNumRem; - unsigned char RegWritingAddr; - - // Get regiser start address, writing bytes, and byte number. - RegStartAddr = I2C_Info->RegAddr; - pWritingBytes = I2C_Info->Data; - ByteNum = (unsigned long)I2C_Info->Len; - - // Calculate maximum writing byte number. -// WritingByteNumMax = pBaseInterface->I2cWritingByteNumMax - LEN_1_BYTE; - WritingByteNumMax = 2 - 1; //9 orig - - // Set tuner register bytes with writing bytes. - // Note: Set tuner register bytes considering maximum writing byte number. - for(i = 0; i < ByteNum; i += WritingByteNumMax) - { - // Set register writing address. - RegWritingAddr = RegStartAddr + i; - - // Calculate remainder writing byte number. - WritingByteNumRem = ByteNum - i; - - // Determine writing byte number. - WritingByteNum = (WritingByteNumRem > WritingByteNumMax) ? WritingByteNumMax : WritingByteNumRem; - - // Set writing buffer. - // Note: The I2C format of tuner register byte setting is as follows: - // start_bit + (DeviceAddr | writing_bit) + RegWritingAddr + writing_bytes (WritingByteNum bytes) + - // stop_bit - WritingBuffer[0] = RegWritingAddr; - - for(j = 0; j < WritingByteNum; j++) - WritingBuffer[j+1] = pWritingBytes[i + j]; - - // Set tuner register bytes with writing buffer. -// if(pI2cBridge->ForwardI2cWritingCmd(pI2cBridge, DeviceAddr, WritingBuffer, WritingByteNum + LEN_1_BYTE) != -// FUNCTION_SUCCESS) -// goto error_status_set_tuner_registers; - - if (rtlsdr_i2c_write_fn(pTuner, R820T_I2C_ADDR, WritingBuffer, WritingByteNum + 1) < 0) - return RT_Fail; - } - - return RT_Success; -} - -R828_ErrCode -I2C_Read_Len(void *pTuner, R828_I2C_LEN_TYPE *I2C_Info) -{ - uint8_t DeviceAddr; - - unsigned int i; - - uint8_t RegStartAddr; - uint8_t ReadingBytes[128]; - unsigned long ByteNum; - - // Get regiser start address, writing bytes, and byte number. - RegStartAddr = 0x00; - ByteNum = (unsigned long)I2C_Info->Len; - - // Set tuner register reading address. - // Note: The I2C format of tuner register reading address setting is as follows: - // start_bit + (DeviceAddr | writing_bit) + RegReadingAddr + stop_bit -// if(pI2cBridge->ForwardI2cWritingCmd(pI2cBridge, DeviceAddr, &RegStartAddr, LEN_1_BYTE) != FUNCTION_SUCCESS) -// goto error_status_set_tuner_register_reading_address; - - if (rtlsdr_i2c_write_fn(pTuner, R820T_I2C_ADDR, &RegStartAddr, 1) < 0) - return RT_Fail; - - // Get tuner register bytes. - // Note: The I2C format of tuner register byte getting is as follows: - // start_bit + (DeviceAddr | reading_bit) + reading_bytes (ReadingByteNum bytes) + stop_bit -// if(pI2cBridge->ForwardI2cReadingCmd(pI2cBridge, DeviceAddr, ReadingBytes, ByteNum) != FUNCTION_SUCCESS) -// goto error_status_get_tuner_registers; - - if (rtlsdr_i2c_read_fn(pTuner, R820T_I2C_ADDR, ReadingBytes, ByteNum) < 0) - return RT_Fail; - - for(i = 0; i<ByteNum; i++) - { - I2C_Info->Data[i] = (UINT8)r820t_Convert(ReadingBytes[i]); - } - - - return RT_Success; - - -error_status_get_tuner_registers: -error_status_set_tuner_register_reading_address: - - return RT_Fail; -} - -R828_ErrCode -I2C_Write(void *pTuner, R828_I2C_TYPE *I2C_Info) -{ - uint8_t WritingBuffer[2]; - - // Set writing bytes. - // Note: The I2C format of tuner register byte setting is as follows: - // start_bit + (DeviceAddr | writing_bit) + addr + data + stop_bit - WritingBuffer[0] = I2C_Info->RegAddr; - WritingBuffer[1] = I2C_Info->Data; - - // Set tuner register bytes with writing buffer. -// if(pI2cBridge->ForwardI2cWritingCmd(pI2cBridge, DeviceAddr, WritingBuffer, LEN_2_BYTE) != FUNCTION_SUCCESS) -// goto error_status_set_tuner_registers; - -// printf("called %s: %02x -> %02x\n", __FUNCTION__, WritingBuffer[0], WritingBuffer[1]); - - if (rtlsdr_i2c_write_fn(pTuner, R820T_I2C_ADDR, WritingBuffer, 2) < 0) - return RT_Fail; - - return RT_Success; -} - -void -R828_Delay_MS( - void *pTuner, - unsigned long WaitTimeMs - ) -{ - /* simply don't wait for now */ - return; -} - -//----------------------------------------------------- -// -// Filename: R820T.c -// -// This file is R820T tuner driver -// Copyright 2011 by Rafaelmicro., Inc. -// -//----------------------------------------------------- - - -//#include "stdafx.h" -//#include "R828.h" -//#include "..\I2C_Sys.h" - - -#if(TUNER_CLK_OUT==TRUE) //enable tuner clk output for share Xtal application -UINT8 R828_iniArry[27] = {0x83, 0x32, 0x75, 0xC0, 0x40, 0xD6, 0x6C, 0xF5, 0x63, - /* 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D */ - - 0x75, 0x68, 0x6C, 0x83, 0x80, 0x00, 0x0F, 0x00, 0xC0,//xtal_check - /* 0x0E 0x0F 0x10 0x11 0x12 0x13 0x14 0x15 0x16 */ - - 0x30, 0x48, 0xCC, 0x60, 0x00, 0x54, 0xAE, 0x4A, 0xC0}; - /* 0x17 0x18 0x19 0x1A 0x1B 0x1C 0x1D 0x1E 0x1F */ -#else -UINT8 R828_iniArry[27] = {0x83, 0x32, 0x75, 0xC0, 0x40, 0xD6, 0x6C, 0xF5, 0x63, - /* 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D */ - - 0x75, 0x78, 0x6C, 0x83, 0x80, 0x00, 0x0F, 0x00, 0xC0,//xtal_check - /* 0x0E 0x0F 0x10 0x11 0x12 0x13 0x14 0x15 0x16 */ - - 0x30, 0x48, 0xCC, 0x60, 0x00, 0x54, 0xAE, 0x4A, 0xC0}; - /* 0x17 0x18 0x19 0x1A 0x1B 0x1C 0x1D 0x1E 0x1F */ -#endif - -UINT8 R828_ADDRESS=0x34; -UINT8 Rafael_Chip = R820T; -//----------------------------------------------------------// -// Internal Structs // -//----------------------------------------------------------// -typedef struct _R828_SectType -{ - UINT8 Phase_Y; - UINT8 Gain_X; - UINT16 Value; -}R828_SectType; - -typedef enum _BW_Type -{ - BW_6M = 0, - BW_7M, - BW_8M, - BW_1_7M, - BW_10M, - BW_200K -}BW_Type; - -typedef struct _Sys_Info_Type -{ - UINT16 IF_KHz; - BW_Type BW; - UINT32 FILT_CAL_LO; - UINT8 FILT_GAIN; - UINT8 IMG_R; - UINT8 FILT_Q; - UINT8 HP_COR; - UINT8 EXT_ENABLE; - UINT8 LOOP_THROUGH; - UINT8 LT_ATT; - UINT8 FLT_EXT_WIDEST; - UINT8 POLYFIL_CUR; -}Sys_Info_Type; - -typedef struct _Freq_Info_Type -{ - UINT8 OPEN_D; - UINT8 RF_MUX_PLOY; - UINT8 TF_C; - UINT8 XTAL_CAP20P; - UINT8 XTAL_CAP10P; - UINT8 XTAL_CAP0P; - UINT8 IMR_MEM; -}Freq_Info_Type; - -typedef struct _SysFreq_Info_Type -{ - UINT8 LNA_TOP; - UINT8 LNA_VTH_L; - UINT8 MIXER_TOP; - UINT8 MIXER_VTH_L; - UINT8 AIR_CABLE1_IN; - UINT8 CABLE2_IN; - UINT8 PRE_DECT; - UINT8 LNA_DISCHARGE; - UINT8 CP_CUR; - UINT8 DIV_BUF_CUR; - UINT8 FILTER_CUR; -}SysFreq_Info_Type; - -//----------------------------------------------------------// -// Internal Parameters // -//----------------------------------------------------------// -enum XTAL_CAP_VALUE -{ - XTAL_LOW_CAP_30P = 0, - XTAL_LOW_CAP_20P, - XTAL_LOW_CAP_10P, - XTAL_LOW_CAP_0P, - XTAL_HIGH_CAP_0P -}; -UINT8 R828_Arry[27]; -R828_SectType IMR_Data[5] = { - {0, 0, 0}, - {0, 0, 0}, - {0, 0, 0}, - {0, 0, 0}, - {0, 0, 0} - };//Please keep this array data for standby mode. -R828_I2C_TYPE R828_I2C; -R828_I2C_LEN_TYPE R828_I2C_Len; - -UINT32 R828_IF_khz; -UINT32 R828_CAL_LO_khz; -UINT8 R828_IMR_point_num; -UINT8 R828_IMR_done_flag = FALSE; -UINT8 R828_Fil_Cal_flag[STD_SIZE]; -static UINT8 R828_Fil_Cal_code[STD_SIZE]; - -static UINT8 Xtal_cap_sel = XTAL_LOW_CAP_0P; -static UINT8 Xtal_cap_sel_tmp = XTAL_LOW_CAP_0P; -//----------------------------------------------------------// -// Internal static struct // -//----------------------------------------------------------// -static SysFreq_Info_Type SysFreq_Info1; -static Sys_Info_Type Sys_Info1; -//static Freq_Info_Type R828_Freq_Info; -static Freq_Info_Type Freq_Info1; -//----------------------------------------------------------// -// Internal Functions // -//----------------------------------------------------------// -R828_ErrCode R828_Xtal_Check(void *pTuner); -R828_ErrCode R828_InitReg(void *pTuner); -R828_ErrCode R828_IMR_Prepare(void *pTuner); -R828_ErrCode R828_IMR(void *pTuner, UINT8 IMR_MEM, int IM_Flag); -R828_ErrCode R828_PLL(void *pTuner, UINT32 LO_Freq, R828_Standard_Type R828_Standard); -R828_ErrCode R828_MUX(void *pTuner, UINT32 RF_KHz); -R828_ErrCode R828_IQ(void *pTuner, R828_SectType* IQ_Pont); -R828_ErrCode R828_IQ_Tree(void *pTuner, UINT8 FixPot, UINT8 FlucPot, UINT8 PotReg, R828_SectType* CompareTree); -R828_ErrCode R828_CompreCor(R828_SectType* CorArry); -R828_ErrCode R828_CompreStep(void *pTuner, R828_SectType* StepArry, UINT8 Pace); -R828_ErrCode R828_Muti_Read(void *pTuner, UINT8 IMR_Reg, UINT16* IMR_Result_Data); -R828_ErrCode R828_Section(void *pTuner, R828_SectType* SectionArry); -R828_ErrCode R828_F_IMR(void *pTuner, R828_SectType* IQ_Pont); -R828_ErrCode R828_IMR_Cross(void *pTuner, R828_SectType* IQ_Pont, UINT8* X_Direct); - -Sys_Info_Type R828_Sys_Sel(R828_Standard_Type R828_Standard); -Freq_Info_Type R828_Freq_Sel(UINT32 RF_freq); -SysFreq_Info_Type R828_SysFreq_Sel(R828_Standard_Type R828_Standard,UINT32 RF_freq); - -R828_ErrCode R828_Filt_Cal(void *pTuner, UINT32 Cal_Freq,BW_Type R828_BW); -//R828_ErrCode R828_SetFrequency(void *pTuner, R828_Set_Info R828_INFO, R828_SetFreq_Type R828_SetFreqMode); - -Sys_Info_Type R828_Sys_Sel(R828_Standard_Type R828_Standard) -{ - Sys_Info_Type R828_Sys_Info; - - switch (R828_Standard) - { - - case DVB_T_6M: - case DVB_T2_6M: - R828_Sys_Info.IF_KHz=3570; - R828_Sys_Info.BW=BW_6M; - R828_Sys_Info.FILT_CAL_LO=56000; //52000->56000 - R828_Sys_Info.FILT_GAIN=0x10; //+3dB, 6MHz on - R828_Sys_Info.IMG_R=0x00; //image negative - R828_Sys_Info.FILT_Q=0x10; //R10[4]:low Q(1'b1) - R828_Sys_Info.HP_COR=0x6B; // 1.7M disable, +2cap, 1.0MHz - R828_Sys_Info.EXT_ENABLE=0x60; //R30[6]=1 ext enable; R30[5]:1 ext at LNA max-1 - R828_Sys_Info.LOOP_THROUGH=0x00; //R5[7], LT ON - R828_Sys_Info.LT_ATT=0x00; //R31[7], LT ATT enable - R828_Sys_Info.FLT_EXT_WIDEST=0x00;//R15[7]: FLT_EXT_WIDE OFF - R828_Sys_Info.POLYFIL_CUR=0x60; //R25[6:5]:Min - break; - - case DVB_T_7M: - case DVB_T2_7M: - R828_Sys_Info.IF_KHz=4070; - R828_Sys_Info.BW=BW_7M; - R828_Sys_Info.FILT_CAL_LO=60000; - R828_Sys_Info.FILT_GAIN=0x10; //+3dB, 6MHz on - R828_Sys_Info.IMG_R=0x00; //image negative - R828_Sys_Info.FILT_Q=0x10; //R10[4]:low Q(1'b1) - R828_Sys_Info.HP_COR=0x2B; // 1.7M disable, +1cap, 1.0MHz - R828_Sys_Info.EXT_ENABLE=0x60; //R30[6]=1 ext enable; R30[5]:1 ext at LNA max-1 - R828_Sys_Info.LOOP_THROUGH=0x00; //R5[7], LT ON - R828_Sys_Info.LT_ATT=0x00; //R31[7], LT ATT enable - R828_Sys_Info.FLT_EXT_WIDEST=0x00;//R15[7]: FLT_EXT_WIDE OFF - R828_Sys_Info.POLYFIL_CUR=0x60; //R25[6:5]:Min - break; - - case DVB_T_7M_2: - case DVB_T2_7M_2: - R828_Sys_Info.IF_KHz=4570; - R828_Sys_Info.BW=BW_7M; - R828_Sys_Info.FILT_CAL_LO=63000; - R828_Sys_Info.FILT_GAIN=0x10; //+3dB, 6MHz on - R828_Sys_Info.IMG_R=0x00; //image negative - R828_Sys_Info.FILT_Q=0x10; //R10[4]:low Q(1'b1) - R828_Sys_Info.HP_COR=0x2A; // 1.7M disable, +1cap, 1.25MHz - R828_Sys_Info.EXT_ENABLE=0x60; //R30[6]=1 ext enable; R30[5]:1 ext at LNA max-1 - R828_Sys_Info.LOOP_THROUGH=0x00; //R5[7], LT ON - R828_Sys_Info.LT_ATT=0x00; //R31[7], LT ATT enable - R828_Sys_Info.FLT_EXT_WIDEST=0x00;//R15[7]: FLT_EXT_WIDE OFF - R828_Sys_Info.POLYFIL_CUR=0x60; //R25[6:5]:Min - break; - - case DVB_T_8M: - case DVB_T2_8M: - R828_Sys_Info.IF_KHz=4570; - R828_Sys_Info.BW=BW_8M; - R828_Sys_Info.FILT_CAL_LO=68500; - R828_Sys_Info.FILT_GAIN=0x10; //+3dB, 6MHz on - R828_Sys_Info.IMG_R=0x00; //image negative - R828_Sys_Info.FILT_Q=0x10; //R10[4]:low Q(1'b1) - R828_Sys_Info.HP_COR=0x0B; // 1.7M disable, +0cap, 1.0MHz - R828_Sys_Info.EXT_ENABLE=0x60; //R30[6]=1 ext enable; R30[5]:1 ext at LNA max-1 - R828_Sys_Info.LOOP_THROUGH=0x00; //R5[7], LT ON - R828_Sys_Info.LT_ATT=0x00; //R31[7], LT ATT enable - R828_Sys_Info.FLT_EXT_WIDEST=0x00;//R15[7]: FLT_EXT_WIDE OFF - R828_Sys_Info.POLYFIL_CUR=0x60; //R25[6:5]:Min - break; - - case ISDB_T: - R828_Sys_Info.IF_KHz=4063; - R828_Sys_Info.BW=BW_6M; - R828_Sys_Info.FILT_CAL_LO=59000; - R828_Sys_Info.FILT_GAIN=0x10; //+3dB, 6MHz on - R828_Sys_Info.IMG_R=0x00; //image negative - R828_Sys_Info.FILT_Q=0x10; //R10[4]:low Q(1'b1) - R828_Sys_Info.HP_COR=0x6A; // 1.7M disable, +2cap, 1.25MHz - R828_Sys_Info.EXT_ENABLE=0x40; //R30[6], ext enable; R30[5]:0 ext at LNA max - R828_Sys_Info.LOOP_THROUGH=0x00; //R5[7], LT ON - R828_Sys_Info.LT_ATT=0x00; //R31[7], LT ATT enable - R828_Sys_Info.FLT_EXT_WIDEST=0x00;//R15[7]: FLT_EXT_WIDE OFF - R828_Sys_Info.POLYFIL_CUR=0x60; //R25[6:5]:Min - break; - - default: //DVB_T_8M - R828_Sys_Info.IF_KHz=4570; - R828_Sys_Info.BW=BW_8M; - R828_Sys_Info.FILT_CAL_LO=68500; - R828_Sys_Info.FILT_GAIN=0x10; //+3dB, 6MHz on - R828_Sys_Info.IMG_R=0x00; //image negative - R828_Sys_Info.FILT_Q=0x10; //R10[4]:low Q(1'b1) - R828_Sys_Info.HP_COR=0x0D; // 1.7M disable, +0cap, 0.7MHz - R828_Sys_Info.EXT_ENABLE=0x60; //R30[6]=1 ext enable; R30[5]:1 ext at LNA max-1 - R828_Sys_Info.LOOP_THROUGH=0x00; //R5[7], LT ON - R828_Sys_Info.LT_ATT=0x00; //R31[7], LT ATT enable - R828_Sys_Info.FLT_EXT_WIDEST=0x00;//R15[7]: FLT_EXT_WIDE OFF - R828_Sys_Info.POLYFIL_CUR=0x60; //R25[6:5]:Min - break; - - } - - return R828_Sys_Info; -} - -Freq_Info_Type R828_Freq_Sel(UINT32 LO_freq) -{ - Freq_Info_Type R828_Freq_Info; - - if(LO_freq<50000) - { - R828_Freq_Info.OPEN_D=0x08; // low - R828_Freq_Info.RF_MUX_PLOY = 0x02; //R26[7:6]=0 (LPF) R26[1:0]=2 (low) - R828_Freq_Info.TF_C=0xDF; //R27[7:0] band2,band0 - R828_Freq_Info.XTAL_CAP20P=0x02; //R16[1:0] 20pF (10) - R828_Freq_Info.XTAL_CAP10P=0x01; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 0; - } - - else if(LO_freq>=50000 && LO_freq<55000) - { - R828_Freq_Info.OPEN_D=0x08; // low - R828_Freq_Info.RF_MUX_PLOY = 0x02; //R26[7:6]=0 (LPF) R26[1:0]=2 (low) - R828_Freq_Info.TF_C=0xBE; //R27[7:0] band4,band1 - R828_Freq_Info.XTAL_CAP20P=0x02; //R16[1:0] 20pF (10) - R828_Freq_Info.XTAL_CAP10P=0x01; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 0; - } - else if( LO_freq>=55000 && LO_freq<60000) - { - R828_Freq_Info.OPEN_D=0x08; // low - R828_Freq_Info.RF_MUX_PLOY = 0x02; //R26[7:6]=0 (LPF) R26[1:0]=2 (low) - R828_Freq_Info.TF_C=0x8B; //R27[7:0] band7,band4 - R828_Freq_Info.XTAL_CAP20P=0x02; //R16[1:0] 20pF (10) - R828_Freq_Info.XTAL_CAP10P=0x01; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 0; - } - else if( LO_freq>=60000 && LO_freq<65000) - { - R828_Freq_Info.OPEN_D=0x08; // low - R828_Freq_Info.RF_MUX_PLOY = 0x02; //R26[7:6]=0 (LPF) R26[1:0]=2 (low) - R828_Freq_Info.TF_C=0x7B; //R27[7:0] band8,band4 - R828_Freq_Info.XTAL_CAP20P=0x02; //R16[1:0] 20pF (10) - R828_Freq_Info.XTAL_CAP10P=0x01; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 0; - } - else if( LO_freq>=65000 && LO_freq<70000) - { - R828_Freq_Info.OPEN_D=0x08; // low - R828_Freq_Info.RF_MUX_PLOY = 0x02; //R26[7:6]=0 (LPF) R26[1:0]=2 (low) - R828_Freq_Info.TF_C=0x69; //R27[7:0] band9,band6 - R828_Freq_Info.XTAL_CAP20P=0x02; //R16[1:0] 20pF (10) - R828_Freq_Info.XTAL_CAP10P=0x01; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 0; - } - else if( LO_freq>=70000 && LO_freq<75000) - { - R828_Freq_Info.OPEN_D=0x08; // low - R828_Freq_Info.RF_MUX_PLOY = 0x02; //R26[7:6]=0 (LPF) R26[1:0]=2 (low) - R828_Freq_Info.TF_C=0x58; //R27[7:0] band10,band7 - R828_Freq_Info.XTAL_CAP20P=0x02; //R16[1:0] 20pF (10) - R828_Freq_Info.XTAL_CAP10P=0x01; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 0; - } - else if( LO_freq>=75000 && LO_freq<80000) - { - R828_Freq_Info.OPEN_D=0x00; // high - R828_Freq_Info.RF_MUX_PLOY = 0x02; //R26[7:6]=0 (LPF) R26[1:0]=2 (low) - R828_Freq_Info.TF_C=0x44; //R27[7:0] band11,band11 - R828_Freq_Info.XTAL_CAP20P=0x02; //R16[1:0] 20pF (10) - R828_Freq_Info.XTAL_CAP10P=0x01; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 0; - } - else if( LO_freq>=80000 && LO_freq<90000) - { - R828_Freq_Info.OPEN_D=0x00; // high - R828_Freq_Info.RF_MUX_PLOY = 0x02; //R26[7:6]=0 (LPF) R26[1:0]=2 (low) - R828_Freq_Info.TF_C=0x44; //R27[7:0] band11,band11 - R828_Freq_Info.XTAL_CAP20P=0x02; //R16[1:0] 20pF (10) - R828_Freq_Info.XTAL_CAP10P=0x01; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 0; - } - else if( LO_freq>=90000 && LO_freq<100000) - { - R828_Freq_Info.OPEN_D=0x00; // high - R828_Freq_Info.RF_MUX_PLOY = 0x02; //R26[7:6]=0 (LPF) R26[1:0]=2 (low) - R828_Freq_Info.TF_C=0x34; //R27[7:0] band12,band11 - R828_Freq_Info.XTAL_CAP20P=0x01; //R16[1:0] 10pF (01) - R828_Freq_Info.XTAL_CAP10P=0x01; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 0; - } - else if( LO_freq>=100000 && LO_freq<110000) - { - R828_Freq_Info.OPEN_D=0x00; // high - R828_Freq_Info.RF_MUX_PLOY = 0x02; //R26[7:6]=0 (LPF) R26[1:0]=2 (low) - R828_Freq_Info.TF_C=0x34; //R27[7:0] band12,band11 - R828_Freq_Info.XTAL_CAP20P=0x01; //R16[1:0] 10pF (01) - R828_Freq_Info.XTAL_CAP10P=0x01; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 0; - } - else if( LO_freq>=110000 && LO_freq<120000) - { - R828_Freq_Info.OPEN_D=0x00; // high - R828_Freq_Info.RF_MUX_PLOY = 0x02; //R26[7:6]=0 (LPF) R26[1:0]=2 (low) - R828_Freq_Info.TF_C=0x24; //R27[7:0] band13,band11 - R828_Freq_Info.XTAL_CAP20P=0x01; //R16[1:0] 10pF (01) - R828_Freq_Info.XTAL_CAP10P=0x01; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 1; - } - else if( LO_freq>=120000 && LO_freq<140000) - { - R828_Freq_Info.OPEN_D=0x00; // high - R828_Freq_Info.RF_MUX_PLOY = 0x02; //R26[7:6]=0 (LPF) R26[1:0]=2 (low) - R828_Freq_Info.TF_C=0x24; //R27[7:0] band13,band11 - R828_Freq_Info.XTAL_CAP20P=0x01; //R16[1:0] 10pF (01) - R828_Freq_Info.XTAL_CAP10P=0x01; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 1; - } - else if( LO_freq>=140000 && LO_freq<180000) - { - R828_Freq_Info.OPEN_D=0x00; // high - R828_Freq_Info.RF_MUX_PLOY = 0x02; //R26[7:6]=0 (LPF) R26[1:0]=2 (low) - R828_Freq_Info.TF_C=0x14; //R27[7:0] band14,band11 - R828_Freq_Info.XTAL_CAP20P=0x01; //R16[1:0] 10pF (01) - R828_Freq_Info.XTAL_CAP10P=0x01; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 1; - } - else if( LO_freq>=180000 && LO_freq<220000) - { - R828_Freq_Info.OPEN_D=0x00; // high - R828_Freq_Info.RF_MUX_PLOY = 0x02; //R26[7:6]=0 (LPF) R26[1:0]=2 (low) - R828_Freq_Info.TF_C=0x13; //R27[7:0] band14,band12 - R828_Freq_Info.XTAL_CAP20P=0x00; //R16[1:0] 0pF (00) - R828_Freq_Info.XTAL_CAP10P=0x00; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 1; - } - else if( LO_freq>=220000 && LO_freq<250000) - { - R828_Freq_Info.OPEN_D=0x00; // high - R828_Freq_Info.RF_MUX_PLOY = 0x02; //R26[7:6]=0 (LPF) R26[1:0]=2 (low) - R828_Freq_Info.TF_C=0x13; //R27[7:0] band14,band12 - R828_Freq_Info.XTAL_CAP20P=0x00; //R16[1:0] 0pF (00) - R828_Freq_Info.XTAL_CAP10P=0x00; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 2; - } - else if( LO_freq>=250000 && LO_freq<280000) - { - R828_Freq_Info.OPEN_D=0x00; // high - R828_Freq_Info.RF_MUX_PLOY = 0x02; //R26[7:6]=0 (LPF) R26[1:0]=2 (low) - R828_Freq_Info.TF_C=0x11; //R27[7:0] highest,highest - R828_Freq_Info.XTAL_CAP20P=0x00; //R16[1:0] 0pF (00) - R828_Freq_Info.XTAL_CAP10P=0x00; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 2; - } - else if( LO_freq>=280000 && LO_freq<310000) - { - R828_Freq_Info.OPEN_D=0x00; // high - R828_Freq_Info.RF_MUX_PLOY = 0x02; //R26[7:6]=0 (LPF) R26[1:0]=2 (low) - R828_Freq_Info.TF_C=0x00; //R27[7:0] highest,highest - R828_Freq_Info.XTAL_CAP20P=0x00; //R16[1:0] 0pF (00) - R828_Freq_Info.XTAL_CAP10P=0x00; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 2; - } - else if( LO_freq>=310000 && LO_freq<450000) - { - R828_Freq_Info.OPEN_D=0x00; // high - R828_Freq_Info.RF_MUX_PLOY = 0x41; //R26[7:6]=1 (bypass) R26[1:0]=1 (middle) - R828_Freq_Info.TF_C=0x00; //R27[7:0] highest,highest - R828_Freq_Info.XTAL_CAP20P=0x00; //R16[1:0] 0pF (00) - R828_Freq_Info.XTAL_CAP10P=0x00; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 2; - } - else if( LO_freq>=450000 && LO_freq<588000) - { - R828_Freq_Info.OPEN_D=0x00; // high - R828_Freq_Info.RF_MUX_PLOY = 0x41; //R26[7:6]=1 (bypass) R26[1:0]=1 (middle) - R828_Freq_Info.TF_C=0x00; //R27[7:0] highest,highest - R828_Freq_Info.XTAL_CAP20P=0x00; //R16[1:0] 0pF (00) - R828_Freq_Info.XTAL_CAP10P=0x00; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 3; - } - else if( LO_freq>=588000 && LO_freq<650000) - { - R828_Freq_Info.OPEN_D=0x00; // high - R828_Freq_Info.RF_MUX_PLOY = 0x40; //R26[7:6]=1 (bypass) R26[1:0]=0 (highest) - R828_Freq_Info.TF_C=0x00; //R27[7:0] highest,highest - R828_Freq_Info.XTAL_CAP20P=0x00; //R16[1:0] 0pF (00) - R828_Freq_Info.XTAL_CAP10P=0x00; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 3; - } - else - { - R828_Freq_Info.OPEN_D=0x00; // high - R828_Freq_Info.RF_MUX_PLOY = 0x40; //R26[7:6]=1 (bypass) R26[1:0]=0 (highest) - R828_Freq_Info.TF_C=0x00; //R27[7:0] highest,highest - R828_Freq_Info.XTAL_CAP20P=0x00; //R16[1:0] 0pF (00) - R828_Freq_Info.XTAL_CAP10P=0x00; - R828_Freq_Info.XTAL_CAP0P=0x00; - R828_Freq_Info.IMR_MEM = 4; - } - - return R828_Freq_Info; -} - -SysFreq_Info_Type R828_SysFreq_Sel(R828_Standard_Type R828_Standard,UINT32 RF_freq) -{ - SysFreq_Info_Type R828_SysFreq_Info; - - switch(R828_Standard) - { - - case DVB_T_6M: - case DVB_T_7M: - case DVB_T_7M_2: - case DVB_T_8M: - if( (RF_freq==506000) || (RF_freq==666000) || (RF_freq==818000) ) - { - R828_SysFreq_Info.MIXER_TOP=0x14; // MIXER TOP:14 , TOP-1, low-discharge - R828_SysFreq_Info.LNA_TOP=0xE5; // Detect BW 3, LNA TOP:4, PreDet Top:2 - R828_SysFreq_Info.CP_CUR=0x28; //101, 0.2 - R828_SysFreq_Info.DIV_BUF_CUR=0x20; // 10, 200u - } - else - { - R828_SysFreq_Info.MIXER_TOP=0x24; // MIXER TOP:13 , TOP-1, low-discharge - R828_SysFreq_Info.LNA_TOP=0xE5; // Detect BW 3, LNA TOP:4, PreDet Top:2 - R828_SysFreq_Info.CP_CUR=0x38; // 111, auto - R828_SysFreq_Info.DIV_BUF_CUR=0x30; // 11, 150u - } - R828_SysFreq_Info.LNA_VTH_L=0x53; // LNA VTH 0.84 , VTL 0.64 - R828_SysFreq_Info.MIXER_VTH_L=0x75; // MIXER VTH 1.04, VTL 0.84 - R828_SysFreq_Info.AIR_CABLE1_IN=0x00; - R828_SysFreq_Info.CABLE2_IN=0x00; - R828_SysFreq_Info.PRE_DECT=0x40; - R828_SysFreq_Info.LNA_DISCHARGE=14; - R828_SysFreq_Info.FILTER_CUR=0x40; // 10, low - break; - - - case DVB_T2_6M: - case DVB_T2_7M: - case DVB_T2_7M_2: - case DVB_T2_8M: - R828_SysFreq_Info.MIXER_TOP=0x24; // MIXER TOP:13 , TOP-1, low-discharge - R828_SysFreq_Info.LNA_TOP=0xE5; // Detect BW 3, LNA TOP:4, PreDet Top:2 - R828_SysFreq_Info.LNA_VTH_L=0x53; // LNA VTH 0.84 , VTL 0.64 - R828_SysFreq_Info.MIXER_VTH_L=0x75; // MIXER VTH 1.04, VTL 0.84 - R828_SysFreq_Info.AIR_CABLE1_IN=0x00; - R828_SysFreq_Info.CABLE2_IN=0x00; - R828_SysFreq_Info.PRE_DECT=0x40; - R828_SysFreq_Info.LNA_DISCHARGE=14; - R828_SysFreq_Info.CP_CUR=0x38; // 111, auto - R828_SysFreq_Info.DIV_BUF_CUR=0x30; // 11, 150u - R828_SysFreq_Info.FILTER_CUR=0x40; // 10, low - break; - - case ISDB_T: - R828_SysFreq_Info.MIXER_TOP=0x24; // MIXER TOP:13 , TOP-1, low-discharge - R828_SysFreq_Info.LNA_TOP=0xE5; // Detect BW 3, LNA TOP:4, PreDet Top:2 - R828_SysFreq_Info.LNA_VTH_L=0x75; // LNA VTH 1.04 , VTL 0.84 - R828_SysFreq_Info.MIXER_VTH_L=0x75; // MIXER VTH 1.04, VTL 0.84 - R828_SysFreq_Info.AIR_CABLE1_IN=0x00; - R828_SysFreq_Info.CABLE2_IN=0x00; - R828_SysFreq_Info.PRE_DECT=0x40; - R828_SysFreq_Info.LNA_DISCHARGE=14; - R828_SysFreq_Info.CP_CUR=0x38; // 111, auto - R828_SysFreq_Info.DIV_BUF_CUR=0x30; // 11, 150u - R828_SysFreq_Info.FILTER_CUR=0x40; // 10, low - break; - - default: //DVB-T 8M - R828_SysFreq_Info.MIXER_TOP=0x24; // MIXER TOP:13 , TOP-1, low-discharge - R828_SysFreq_Info.LNA_TOP=0xE5; // Detect BW 3, LNA TOP:4, PreDet Top:2 - R828_SysFreq_Info.LNA_VTH_L=0x53; // LNA VTH 0.84 , VTL 0.64 - R828_SysFreq_Info.MIXER_VTH_L=0x75; // MIXER VTH 1.04, VTL 0.84 - R828_SysFreq_Info.AIR_CABLE1_IN=0x00; - R828_SysFreq_Info.CABLE2_IN=0x00; - R828_SysFreq_Info.PRE_DECT=0x40; - R828_SysFreq_Info.LNA_DISCHARGE=14; - R828_SysFreq_Info.CP_CUR=0x38; // 111, auto - R828_SysFreq_Info.DIV_BUF_CUR=0x30; // 11, 150u - R828_SysFreq_Info.FILTER_CUR=0x40; // 10, low - break; - - } //end switch - -//DTV use Diplexer -#if(USE_DIPLEXER==TRUE) -if ((Rafael_Chip==R820C) || (Rafael_Chip==R820T) || (Rafael_Chip==R828S)) -{ - // Air-in (>=DIP_FREQ) & cable-1(<DIP_FREQ) - if(RF_freq >= DIP_FREQ) - { - R828_SysFreq_Info.AIR_CABLE1_IN = 0x00; //air in, cable-1 off - R828_SysFreq_Info.CABLE2_IN = 0x00; //cable-2 off - } - else - { - R828_SysFreq_Info.AIR_CABLE1_IN = 0x60; //cable-1 in, air off - R828_SysFreq_Info.CABLE2_IN = 0x00; //cable-2 off - } -} -#endif - return R828_SysFreq_Info; - - } - -R828_ErrCode R828_Xtal_Check(void *pTuner) -{ - UINT8 ArrayNum; - - ArrayNum = 27; - for(ArrayNum=0;ArrayNum<27;ArrayNum++) - { - R828_Arry[ArrayNum] = R828_iniArry[ArrayNum]; - } - - //cap 30pF & Drive Low - R828_I2C.RegAddr = 0x10; - R828_Arry[11] = (R828_Arry[11] & 0xF4) | 0x0B ; - R828_I2C.Data = R828_Arry[11]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //set pll autotune = 128kHz - R828_I2C.RegAddr = 0x1A; - R828_Arry[21] = R828_Arry[21] & 0xF3; - R828_I2C.Data = R828_Arry[21]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //set manual initial reg = 111111; - R828_I2C.RegAddr = 0x13; - R828_Arry[14] = (R828_Arry[14] & 0x80) | 0x7F; - R828_I2C.Data = R828_Arry[14]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //set auto - R828_I2C.RegAddr = 0x13; - R828_Arry[14] = (R828_Arry[14] & 0xBF); - R828_I2C.Data = R828_Arry[14]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_Delay_MS(pTuner, 5); - - R828_I2C_Len.RegAddr = 0x00; - R828_I2C_Len.Len = 3; - if(I2C_Read_Len(pTuner, &R828_I2C_Len) != RT_Success) - return RT_Fail; - - // if 30pF unlock, set to cap 20pF -#if (USE_16M_XTAL==TRUE) - //VCO=2360MHz for 16M Xtal. VCO band 26 - if(((R828_I2C_Len.Data[2] & 0x40) == 0x00) || ((R828_I2C_Len.Data[2] & 0x3F) > 29) || ((R828_I2C_Len.Data[2] & 0x3F) < 23)) -#else - if(((R828_I2C_Len.Data[2] & 0x40) == 0x00) || ((R828_I2C_Len.Data[2] & 0x3F) == 0x3F)) -#endif - { - //cap 20pF - R828_I2C.RegAddr = 0x10; - R828_Arry[11] = (R828_Arry[11] & 0xFC) | 0x02; - R828_I2C.Data = R828_Arry[11]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_Delay_MS(pTuner, 5); - - R828_I2C_Len.RegAddr = 0x00; - R828_I2C_Len.Len = 3; - if(I2C_Read_Len(pTuner, &R828_I2C_Len) != RT_Success) - return RT_Fail; - - // if 20pF unlock, set to cap 10pF -#if (USE_16M_XTAL==TRUE) - if(((R828_I2C_Len.Data[2] & 0x40) == 0x00) || ((R828_I2C_Len.Data[2] & 0x3F) > 29) || ((R828_I2C_Len.Data[2] & 0x3F) < 23)) -#else - if(((R828_I2C_Len.Data[2] & 0x40) == 0x00) || ((R828_I2C_Len.Data[2] & 0x3F) == 0x3F)) -#endif - { - //cap 10pF - R828_I2C.RegAddr = 0x10; - R828_Arry[11] = (R828_Arry[11] & 0xFC) | 0x01; - R828_I2C.Data = R828_Arry[11]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_Delay_MS(pTuner, 5); - - R828_I2C_Len.RegAddr = 0x00; - R828_I2C_Len.Len = 3; - if(I2C_Read_Len(pTuner, &R828_I2C_Len) != RT_Success) - return RT_Fail; - - // if 10pF unlock, set to cap 0pF -#if (USE_16M_XTAL==TRUE) - if(((R828_I2C_Len.Data[2] & 0x40) == 0x00) || ((R828_I2C_Len.Data[2] & 0x3F) > 29) || ((R828_I2C_Len.Data[2] & 0x3F) < 23)) -#else - if(((R828_I2C_Len.Data[2] & 0x40) == 0x00) || ((R828_I2C_Len.Data[2] & 0x3F) == 0x3F)) -#endif - { - //cap 0pF - R828_I2C.RegAddr = 0x10; - R828_Arry[11] = (R828_Arry[11] & 0xFC) | 0x00; - R828_I2C.Data = R828_Arry[11]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_Delay_MS(pTuner, 5); - - R828_I2C_Len.RegAddr = 0x00; - R828_I2C_Len.Len = 3; - if(I2C_Read_Len(pTuner, &R828_I2C_Len) != RT_Success) - return RT_Fail; - - // if unlock, set to high drive -#if (USE_16M_XTAL==TRUE) - if(((R828_I2C_Len.Data[2] & 0x40) == 0x00) || ((R828_I2C_Len.Data[2] & 0x3F) > 29) || ((R828_I2C_Len.Data[2] & 0x3F) < 23)) -#else - if(((R828_I2C_Len.Data[2] & 0x40) == 0x00) || ((R828_I2C_Len.Data[2] & 0x3F) == 0x3F)) -#endif - { - //X'tal drive high - R828_I2C.RegAddr = 0x10; - R828_Arry[11] = (R828_Arry[11] & 0xF7) ; - R828_I2C.Data = R828_Arry[11]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //R828_Delay_MS(15); - R828_Delay_MS(pTuner, 20); - - R828_I2C_Len.RegAddr = 0x00; - R828_I2C_Len.Len = 3; - if(I2C_Read_Len(pTuner, &R828_I2C_Len) != RT_Success) - return RT_Fail; - -#if (USE_16M_XTAL==TRUE) - if(((R828_I2C_Len.Data[2] & 0x40) == 0x00) || ((R828_I2C_Len.Data[2] & 0x3F) > 29) || ((R828_I2C_Len.Data[2] & 0x3F) < 23)) -#else - if(((R828_I2C_Len.Data[2] & 0x40) == 0x00) || ((R828_I2C_Len.Data[2] & 0x3F) == 0x3F)) -#endif - { - return RT_Fail; - } - else //0p+high drive lock - { - Xtal_cap_sel_tmp = XTAL_HIGH_CAP_0P; - } - } - else //0p lock - { - Xtal_cap_sel_tmp = XTAL_LOW_CAP_0P; - } - } - else //10p lock - { - Xtal_cap_sel_tmp = XTAL_LOW_CAP_10P; - } - } - else //20p lock - { - Xtal_cap_sel_tmp = XTAL_LOW_CAP_20P; - } - } - else // 30p lock - { - Xtal_cap_sel_tmp = XTAL_LOW_CAP_30P; - } - - return RT_Success; -} -R828_ErrCode R828_Init(void *pTuner) -{ -// R820T_EXTRA_MODULE *pExtra; - UINT8 i; - - // Get tuner extra module. -// pExtra = &(pTuner->Extra.R820t); - - //write initial reg - //if(R828_InitReg(pTuner) != RT_Success) - // return RT_Fail; - - if(R828_IMR_done_flag==FALSE) - { - - //write initial reg -// if(R828_InitReg(pTuner) != RT_Success) -// return RT_Fail; - - //Do Xtal check - if((Rafael_Chip==R820T) || (Rafael_Chip==R828S) || (Rafael_Chip==R820C)) - { - Xtal_cap_sel = XTAL_HIGH_CAP_0P; - } - else - { - if(R828_Xtal_Check(pTuner) != RT_Success) //1st - return RT_Fail; - - Xtal_cap_sel = Xtal_cap_sel_tmp; - - if(R828_Xtal_Check(pTuner) != RT_Success) //2nd - return RT_Fail; - - if(Xtal_cap_sel_tmp > Xtal_cap_sel) - { - Xtal_cap_sel = Xtal_cap_sel_tmp; - } - - if(R828_Xtal_Check(pTuner) != RT_Success) //3rd - return RT_Fail; - - if(Xtal_cap_sel_tmp > Xtal_cap_sel) - { - Xtal_cap_sel = Xtal_cap_sel_tmp; - } - - } - - //reset filter cal. - for (i=0; i<STD_SIZE; i++) - { - R828_Fil_Cal_flag[i] = FALSE; - R828_Fil_Cal_code[i] = 0; - } - -#if 0 - //start imr cal. - if(R828_InitReg(pTuner) != RT_Success) //write initial reg before doing cal - return RT_Fail; - - if(R828_IMR_Prepare(pTuner) != RT_Success) - return RT_Fail; - - if(R828_IMR(pTuner, 3, TRUE) != RT_Success) //Full K node 3 - return RT_Fail; - - if(R828_IMR(pTuner, 1, FALSE) != RT_Success) - return RT_Fail; - - if(R828_IMR(pTuner, 0, FALSE) != RT_Success) - return RT_Fail; - - if(R828_IMR(pTuner, 2, FALSE) != RT_Success) - return RT_Fail; - - if(R828_IMR(pTuner, 4, FALSE) != RT_Success) - return RT_Fail; - - R828_IMR_done_flag = TRUE; -#endif - } - - //write initial reg - if(R828_InitReg(pTuner) != RT_Success) - return RT_Fail; - - return RT_Success; -} - - - -R828_ErrCode R828_InitReg(void *pTuner) -{ - UINT8 InitArryCount; - UINT8 InitArryNum; - - InitArryCount = 0; - InitArryNum = 27; - - //UINT32 LO_KHz = 0; - - //Write Full Table - R828_I2C_Len.RegAddr = 0x05; - R828_I2C_Len.Len = InitArryNum; - for(InitArryCount = 0;InitArryCount < InitArryNum;InitArryCount ++) - { - R828_I2C_Len.Data[InitArryCount] = R828_iniArry[InitArryCount]; - } - if(I2C_Write_Len(pTuner, &R828_I2C_Len) != RT_Success) - return RT_Fail; - - return RT_Success; -} - - -R828_ErrCode R828_IMR_Prepare(void *pTuner) - -{ - UINT8 ArrayNum; - - ArrayNum=27; - - for(ArrayNum=0;ArrayNum<27;ArrayNum++) - { - R828_Arry[ArrayNum] = R828_iniArry[ArrayNum]; - } - //IMR Preparation - //lna off (air-in off) - R828_I2C.RegAddr = 0x05; - R828_Arry[0] = R828_Arry[0] | 0x20; - R828_I2C.Data = R828_Arry[0]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - //mixer gain mode = manual - R828_I2C.RegAddr = 0x07; - R828_Arry[2] = (R828_Arry[2] & 0xEF); - R828_I2C.Data = R828_Arry[2]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - //filter corner = lowest - R828_I2C.RegAddr = 0x0A; - R828_Arry[5] = R828_Arry[5] | 0x0F; - R828_I2C.Data = R828_Arry[5]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - //filter bw=+2cap, hp=5M - R828_I2C.RegAddr = 0x0B; - R828_Arry[6] = (R828_Arry[6] & 0x90) | 0x60; - R828_I2C.Data = R828_Arry[6]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - //adc=on, vga code mode, gain = 26.5dB - R828_I2C.RegAddr = 0x0C; - R828_Arry[7] = (R828_Arry[7] & 0x60) | 0x0B; - R828_I2C.Data = R828_Arry[7]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - //ring clk = on - R828_I2C.RegAddr = 0x0F; - R828_Arry[10] &= 0xF7; - R828_I2C.Data = R828_Arry[10]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - //ring power = on - R828_I2C.RegAddr = 0x18; - R828_Arry[19] = R828_Arry[19] | 0x10; - R828_I2C.Data = R828_Arry[19]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - //from ring = ring pll in - R828_I2C.RegAddr = 0x1C; - R828_Arry[23] = R828_Arry[23] | 0x02; - R828_I2C.Data = R828_Arry[23]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - //sw_pdect = det3 - R828_I2C.RegAddr = 0x1E; - R828_Arry[25] = R828_Arry[25] | 0x80; - R828_I2C.Data = R828_Arry[25]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - // Set filt_3dB - R828_Arry[1] = R828_Arry[1] | 0x20; - R828_I2C.RegAddr = 0x06; - R828_I2C.Data = R828_Arry[1]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - return RT_Success; -} - -R828_ErrCode R828_IMR(void *pTuner, UINT8 IMR_MEM, int IM_Flag) -{ - - UINT32 RingVCO; - UINT32 RingFreq; - UINT32 RingRef; - UINT8 n_ring; - UINT8 n; - - R828_SectType IMR_POINT; - - - RingVCO = 0; - RingFreq = 0; - RingRef = 0; - n_ring = 0; - - if (R828_Xtal>24000) - RingRef = R828_Xtal /2; - else - RingRef = R828_Xtal; - - for(n=0;n<16;n++) - { - if((16+n)* 8 * RingRef >= 3100000) - { - n_ring=n; - break; - } - - if(n==15) //n_ring not found - { - //return RT_Fail; - n_ring=n; - } - - } - - R828_Arry[19] &= 0xF0; //set ring[3:0] - R828_Arry[19] |= n_ring; - RingVCO = (16+n_ring)* 8 * RingRef; - R828_Arry[19]&=0xDF; //clear ring_se23 - R828_Arry[20]&=0xFC; //clear ring_seldiv - R828_Arry[26]&=0xFC; //clear ring_att - - switch(IMR_MEM) - { - case 0: - RingFreq = RingVCO/48; - R828_Arry[19]|=0x20; // ring_se23 = 1 - R828_Arry[20]|=0x03; // ring_seldiv = 3 - R828_Arry[26]|=0x02; // ring_att 10 - break; - case 1: - RingFreq = RingVCO/16; - R828_Arry[19]|=0x00; // ring_se23 = 0 - R828_Arry[20]|=0x02; // ring_seldiv = 2 - R828_Arry[26]|=0x00; // pw_ring 00 - break; - case 2: - RingFreq = RingVCO/8; - R828_Arry[19]|=0x00; // ring_se23 = 0 - R828_Arry[20]|=0x01; // ring_seldiv = 1 - R828_Arry[26]|=0x03; // pw_ring 11 - break; - case 3: - RingFreq = RingVCO/6; - R828_Arry[19]|=0x20; // ring_se23 = 1 - R828_Arry[20]|=0x00; // ring_seldiv = 0 - R828_Arry[26]|=0x03; // pw_ring 11 - break; - case 4: - RingFreq = RingVCO/4; - R828_Arry[19]|=0x00; // ring_se23 = 0 - R828_Arry[20]|=0x00; // ring_seldiv = 0 - R828_Arry[26]|=0x01; // pw_ring 01 - break; - default: - RingFreq = RingVCO/4; - R828_Arry[19]|=0x00; // ring_se23 = 0 - R828_Arry[20]|=0x00; // ring_seldiv = 0 - R828_Arry[26]|=0x01; // pw_ring 01 - break; - } - - - //write pw_ring,n_ring,ringdiv2 to I2C - - //------------n_ring,ring_se23----------// - R828_I2C.RegAddr = 0x18; - R828_I2C.Data = R828_Arry[19]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - //------------ring_sediv----------------// - R828_I2C.RegAddr = 0x19; - R828_I2C.Data = R828_Arry[20]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - //------------pw_ring-------------------// - R828_I2C.RegAddr = 0x1f; - R828_I2C.Data = R828_Arry[26]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //Must do before PLL() - if(R828_MUX(pTuner, RingFreq - 5300) != RT_Success) //MUX input freq ~ RF_in Freq - return RT_Fail; - - if(R828_PLL(pTuner, (RingFreq - 5300) * 1000, STD_SIZE) != RT_Success) //set pll freq = ring freq - 6M - return RT_Fail; - - if(IM_Flag == TRUE) - { - if(R828_IQ(pTuner, &IMR_POINT) != RT_Success) - return RT_Fail; - } - else - { - IMR_POINT.Gain_X = IMR_Data[3].Gain_X; - IMR_POINT.Phase_Y = IMR_Data[3].Phase_Y; - IMR_POINT.Value = IMR_Data[3].Value; - if(R828_F_IMR(pTuner, &IMR_POINT) != RT_Success) - return RT_Fail; - } - - //Save IMR Value - switch(IMR_MEM) - { - case 0: - IMR_Data[0].Gain_X = IMR_POINT.Gain_X; - IMR_Data[0].Phase_Y = IMR_POINT.Phase_Y; - IMR_Data[0].Value = IMR_POINT.Value; - break; - case 1: - IMR_Data[1].Gain_X = IMR_POINT.Gain_X; - IMR_Data[1].Phase_Y = IMR_POINT.Phase_Y; - IMR_Data[1].Value = IMR_POINT.Value; - break; - case 2: - IMR_Data[2].Gain_X = IMR_POINT.Gain_X; - IMR_Data[2].Phase_Y = IMR_POINT.Phase_Y; - IMR_Data[2].Value = IMR_POINT.Value; - break; - case 3: - IMR_Data[3].Gain_X = IMR_POINT.Gain_X; - IMR_Data[3].Phase_Y = IMR_POINT.Phase_Y; - IMR_Data[3].Value = IMR_POINT.Value; - break; - case 4: - IMR_Data[4].Gain_X = IMR_POINT.Gain_X; - IMR_Data[4].Phase_Y = IMR_POINT.Phase_Y; - IMR_Data[4].Value = IMR_POINT.Value; - break; - default: - IMR_Data[4].Gain_X = IMR_POINT.Gain_X; - IMR_Data[4].Phase_Y = IMR_POINT.Phase_Y; - IMR_Data[4].Value = IMR_POINT.Value; - break; - } - return RT_Success; -} - -R828_ErrCode R828_PLL(void *pTuner, UINT32 LO_Freq, R828_Standard_Type R828_Standard) -{ - -// R820T_EXTRA_MODULE *pExtra; - - UINT8 MixDiv; - UINT8 DivBuf; - UINT8 Ni; - UINT8 Si; - UINT8 DivNum; - UINT8 Nint; - UINT32 VCO_Min_kHz; - UINT32 VCO_Max_kHz; - uint64_t VCO_Freq; - UINT32 PLL_Ref; //Max 24000 (kHz) - UINT32 VCO_Fra; //VCO contribution by SDM (kHz) - UINT16 Nsdm; - UINT16 SDM; - UINT16 SDM16to9; - UINT16 SDM8to1; - //UINT8 Judge = 0; - UINT8 VCO_fine_tune; - - MixDiv = 2; - DivBuf = 0; - Ni = 0; - Si = 0; - DivNum = 0; - Nint = 0; - VCO_Min_kHz = 1770000; - VCO_Max_kHz = VCO_Min_kHz*2; - VCO_Freq = 0; - PLL_Ref = 0; //Max 24000 (kHz) - VCO_Fra = 0; //VCO contribution by SDM (kHz) - Nsdm = 2; - SDM = 0; - SDM16to9 = 0; - SDM8to1 = 0; - //UINT8 Judge = 0; - VCO_fine_tune = 0; - -#if 0 - if ((Rafael_Chip==R620D) || (Rafael_Chip==R828D) || (Rafael_Chip==R828)) //X'tal can't not exceed 20MHz for ATV - { - if(R828_Standard <= SECAM_L1) //ref set refdiv2, reffreq = Xtal/2 on ATV application - { - R828_Arry[11] |= 0x10; //b4=1 - PLL_Ref = R828_Xtal /2; - } - else //DTV, FilCal, IMR - { - R828_Arry[11] &= 0xEF; - PLL_Ref = R828_Xtal; - } - } - else - { - if(R828_Xtal > 24000) - { - R828_Arry[11] |= 0x10; //b4=1 - PLL_Ref = R828_Xtal /2; - } - else - { - R828_Arry[11] &= 0xEF; - PLL_Ref = R828_Xtal; - } - } -#endif - //FIXME hack - R828_Arry[11] &= 0xEF; - PLL_Ref = rtlsdr_get_tuner_clock(pTuner); - - R828_I2C.RegAddr = 0x10; - R828_I2C.Data = R828_Arry[11]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //set pll autotune = 128kHz - R828_I2C.RegAddr = 0x1A; - R828_Arry[21] = R828_Arry[21] & 0xF3; - R828_I2C.Data = R828_Arry[21]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //Set VCO current = 100 - R828_I2C.RegAddr = 0x12; - R828_Arry[13] = (R828_Arry[13] & 0x1F) | 0x80; - R828_I2C.Data = R828_Arry[13]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //Divider - while(MixDiv <= 64) - { - if((((LO_Freq/1000) * MixDiv) >= VCO_Min_kHz) && (((LO_Freq/1000) * MixDiv) < VCO_Max_kHz)) - { - DivBuf = MixDiv; - while(DivBuf > 2) - { - DivBuf = DivBuf >> 1; - DivNum ++; - } - break; - } - MixDiv = MixDiv << 1; - } - - R828_I2C_Len.RegAddr = 0x00; - R828_I2C_Len.Len = 5; - if(I2C_Read_Len(pTuner, &R828_I2C_Len) != RT_Success) - return RT_Fail; - - VCO_fine_tune = (R828_I2C_Len.Data[4] & 0x30)>>4; - - if(VCO_fine_tune > VCO_pwr_ref) - DivNum = DivNum - 1; - else if(VCO_fine_tune < VCO_pwr_ref) - DivNum = DivNum + 1; - - R828_I2C.RegAddr = 0x10; - R828_Arry[11] &= 0x1F; - R828_Arry[11] |= (DivNum << 5); - R828_I2C.Data = R828_Arry[11]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - VCO_Freq = (uint64_t)(LO_Freq * (uint64_t)MixDiv); - Nint = (UINT8) (VCO_Freq / 2 / PLL_Ref); - VCO_Fra = (UINT16) ((VCO_Freq - 2 * PLL_Ref * Nint) / 1000); - - //FIXME hack - PLL_Ref /= 1000; - -// printf("VCO_Freq = %lu, Nint= %u, VCO_Fra= %lu, LO_Freq= %u, MixDiv= %u\n", VCO_Freq, Nint, VCO_Fra, LO_Freq, MixDiv); - - //boundary spur prevention - if (VCO_Fra < PLL_Ref/64) //2*PLL_Ref/128 - VCO_Fra = 0; - else if (VCO_Fra > PLL_Ref*127/64) //2*PLL_Ref*127/128 - { - VCO_Fra = 0; - Nint ++; - } - else if((VCO_Fra > PLL_Ref*127/128) && (VCO_Fra < PLL_Ref)) //> 2*PLL_Ref*127/256, < 2*PLL_Ref*128/256 - VCO_Fra = PLL_Ref*127/128; // VCO_Fra = 2*PLL_Ref*127/256 - else if((VCO_Fra > PLL_Ref) && (VCO_Fra < PLL_Ref*129/128)) //> 2*PLL_Ref*128/256, < 2*PLL_Ref*129/256 - VCO_Fra = PLL_Ref*129/128; // VCO_Fra = 2*PLL_Ref*129/256 - else - VCO_Fra = VCO_Fra; - - if (Nint > 63) { - fprintf(stderr, "[R820T] No valid PLL values for %u Hz!\n", LO_Freq); - return RT_Fail; - } - - //N & S - Ni = (Nint - 13) / 4; - Si = Nint - 4 *Ni - 13; - R828_I2C.RegAddr = 0x14; - R828_Arry[15] = 0x00; - R828_Arry[15] |= (Ni + (Si << 6)); - R828_I2C.Data = R828_Arry[15]; - - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //pw_sdm - R828_I2C.RegAddr = 0x12; - R828_Arry[13] &= 0xF7; - if(VCO_Fra == 0) - R828_Arry[13] |= 0x08; - R828_I2C.Data = R828_Arry[13]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //SDM calculator - while(VCO_Fra > 1) - { - if (VCO_Fra > (2*PLL_Ref / Nsdm)) - { - SDM = SDM + 32768 / (Nsdm/2); - VCO_Fra = VCO_Fra - 2*PLL_Ref / Nsdm; - if (Nsdm >= 0x8000) - break; - } - Nsdm = Nsdm << 1; - } - - SDM16to9 = SDM >> 8; - SDM8to1 = SDM - (SDM16to9 << 8); - - R828_I2C.RegAddr = 0x16; - R828_Arry[17] = (UINT8) SDM16to9; - R828_I2C.Data = R828_Arry[17]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - R828_I2C.RegAddr = 0x15; - R828_Arry[16] = (UINT8) SDM8to1; - R828_I2C.Data = R828_Arry[16]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - -// R828_Delay_MS(10); - - if ((Rafael_Chip==R620D) || (Rafael_Chip==R828D) || (Rafael_Chip==R828)) - { - if(R828_Standard <= SECAM_L1) - R828_Delay_MS(pTuner, 20); - else - R828_Delay_MS(pTuner, 10); - } - else - { - R828_Delay_MS(pTuner, 10); - } - - //check PLL lock status - R828_I2C_Len.RegAddr = 0x00; - R828_I2C_Len.Len = 3; - if(I2C_Read_Len(pTuner, &R828_I2C_Len) != RT_Success) - return RT_Fail; - - if( (R828_I2C_Len.Data[2] & 0x40) == 0x00 ) - { - fprintf(stderr, "[R820T] PLL not locked for %u Hz!\n", LO_Freq); - R828_I2C.RegAddr = 0x12; - R828_Arry[13] = (R828_Arry[13] & 0x1F) | 0x60; //increase VCO current - R828_I2C.Data = R828_Arry[13]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - return RT_Fail; - } - - //set pll autotune = 8kHz - R828_I2C.RegAddr = 0x1A; - R828_Arry[21] = R828_Arry[21] | 0x08; - R828_I2C.Data = R828_Arry[21]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - return RT_Success; -} - -R828_ErrCode R828_MUX(void *pTuner, UINT32 RF_KHz) -{ - UINT8 RT_Reg08; - UINT8 RT_Reg09; - - RT_Reg08 = 0; - RT_Reg09 = 0; - - //Freq_Info_Type Freq_Info1; - Freq_Info1 = R828_Freq_Sel(RF_KHz); - - // Open Drain - R828_I2C.RegAddr = 0x17; - R828_Arry[18] = (R828_Arry[18] & 0xF7) | Freq_Info1.OPEN_D; - R828_I2C.Data = R828_Arry[18]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - // RF_MUX,Polymux - R828_I2C.RegAddr = 0x1A; - R828_Arry[21] = (R828_Arry[21] & 0x3C) | Freq_Info1.RF_MUX_PLOY; - R828_I2C.Data = R828_Arry[21]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - // TF BAND - R828_I2C.RegAddr = 0x1B; - R828_Arry[22] &= 0x00; - R828_Arry[22] |= Freq_Info1.TF_C; - R828_I2C.Data = R828_Arry[22]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - // XTAL CAP & Drive - R828_I2C.RegAddr = 0x10; - R828_Arry[11] &= 0xF4; - switch(Xtal_cap_sel) - { - case XTAL_LOW_CAP_30P: - case XTAL_LOW_CAP_20P: - R828_Arry[11] = R828_Arry[11] | Freq_Info1.XTAL_CAP20P | 0x08; - break; - - case XTAL_LOW_CAP_10P: - R828_Arry[11] = R828_Arry[11] | Freq_Info1.XTAL_CAP10P | 0x08; - break; - - case XTAL_LOW_CAP_0P: - R828_Arry[11] = R828_Arry[11] | Freq_Info1.XTAL_CAP0P | 0x08; - break; - - case XTAL_HIGH_CAP_0P: - R828_Arry[11] = R828_Arry[11] | Freq_Info1.XTAL_CAP0P | 0x00; - break; - - default: - R828_Arry[11] = R828_Arry[11] | Freq_Info1.XTAL_CAP0P | 0x08; - break; - } - R828_I2C.Data = R828_Arry[11]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //Set_IMR - if(R828_IMR_done_flag == TRUE) - { - RT_Reg08 = IMR_Data[Freq_Info1.IMR_MEM].Gain_X & 0x3F; - RT_Reg09 = IMR_Data[Freq_Info1.IMR_MEM].Phase_Y & 0x3F; - } - else - { - RT_Reg08 = 0; - RT_Reg09 = 0; - } - - R828_I2C.RegAddr = 0x08; - R828_Arry[3] = R828_iniArry[3] & 0xC0; - R828_Arry[3] = R828_Arry[3] | RT_Reg08; - R828_I2C.Data = R828_Arry[3]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_I2C.RegAddr = 0x09; - R828_Arry[4] = R828_iniArry[4] & 0xC0; - R828_Arry[4] = R828_Arry[4] | RT_Reg09; - R828_I2C.Data =R828_Arry[4] ; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - return RT_Success; -} - -R828_ErrCode R828_IQ(void *pTuner, R828_SectType* IQ_Pont) -{ - R828_SectType Compare_IQ[3]; -// R828_SectType CompareTemp; -// UINT8 IQ_Count = 0; - UINT8 VGA_Count; - UINT16 VGA_Read; - UINT8 X_Direction; // 1:X, 0:Y - - VGA_Count = 0; - VGA_Read = 0; - - // increase VGA power to let image significant - for(VGA_Count = 12;VGA_Count < 16;VGA_Count ++) - { - R828_I2C.RegAddr = 0x0C; - R828_I2C.Data = (R828_Arry[7] & 0xF0) + VGA_Count; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_Delay_MS(pTuner, 10); // - - if(R828_Muti_Read(pTuner, 0x01, &VGA_Read) != RT_Success) - return RT_Fail; - - if(VGA_Read > 40*4) - break; - } - - //initial 0x08, 0x09 - //Compare_IQ[0].Gain_X = 0x40; //should be 0xC0 in R828, Jason - //Compare_IQ[0].Phase_Y = 0x40; //should be 0x40 in R828 - Compare_IQ[0].Gain_X = R828_iniArry[3] & 0xC0; // Jason modified, clear b[5], b[4:0] - Compare_IQ[0].Phase_Y = R828_iniArry[4] & 0xC0; // - - //while(IQ_Count < 3) - //{ - // Determine X or Y - if(R828_IMR_Cross(pTuner, &Compare_IQ[0], &X_Direction) != RT_Success) - return RT_Fail; - - //if(X_Direction==1) - //{ - // if(R828_IQ_Tree(Compare_IQ[0].Phase_Y, Compare_IQ[0].Gain_X, 0x09, &Compare_IQ[0]) != RT_Success) //X - // return RT_Fail; - //} - //else - //{ - // if(R828_IQ_Tree(Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, 0x08, &Compare_IQ[0]) != RT_Success) //Y - // return RT_Fail; - //} - - /* - //--- X direction ---// - //X: 3 points - if(R828_IQ_Tree(Compare_IQ[0].Phase_Y, Compare_IQ[0].Gain_X, 0x09, &Compare_IQ[0]) != RT_Success) // - return RT_Fail; - - //compare and find min of 3 points. determine I/Q direction - if(R828_CompreCor(&Compare_IQ[0]) != RT_Success) - return RT_Fail; - - //increase step to find min value of this direction - if(R828_CompreStep(&Compare_IQ[0], 0x08) != RT_Success) - return RT_Fail; - */ - - if(X_Direction==1) - { - //compare and find min of 3 points. determine I/Q direction - if(R828_CompreCor(&Compare_IQ[0]) != RT_Success) - return RT_Fail; - - //increase step to find min value of this direction - if(R828_CompreStep(pTuner, &Compare_IQ[0], 0x08) != RT_Success) //X - return RT_Fail; - } - else - { - //compare and find min of 3 points. determine I/Q direction - if(R828_CompreCor(&Compare_IQ[0]) != RT_Success) - return RT_Fail; - - //increase step to find min value of this direction - if(R828_CompreStep(pTuner, &Compare_IQ[0], 0x09) != RT_Success) //Y - return RT_Fail; - } - /* - //--- Y direction ---// - //Y: 3 points - if(R828_IQ_Tree(Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, 0x08, &Compare_IQ[0]) != RT_Success) // - return RT_Fail; - - //compare and find min of 3 points. determine I/Q direction - if(R828_CompreCor(&Compare_IQ[0]) != RT_Success) - return RT_Fail; - - //increase step to find min value of this direction - if(R828_CompreStep(&Compare_IQ[0], 0x09) != RT_Success) - return RT_Fail; - */ - - //Another direction - if(X_Direction==1) - { - if(R828_IQ_Tree(pTuner, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, 0x08, &Compare_IQ[0]) != RT_Success) //Y - return RT_Fail; - - //compare and find min of 3 points. determine I/Q direction - if(R828_CompreCor(&Compare_IQ[0]) != RT_Success) - return RT_Fail; - - //increase step to find min value of this direction - if(R828_CompreStep(pTuner, &Compare_IQ[0], 0x09) != RT_Success) //Y - return RT_Fail; - } - else - { - if(R828_IQ_Tree(pTuner, Compare_IQ[0].Phase_Y, Compare_IQ[0].Gain_X, 0x09, &Compare_IQ[0]) != RT_Success) //X - return RT_Fail; - - //compare and find min of 3 points. determine I/Q direction - if(R828_CompreCor(&Compare_IQ[0]) != RT_Success) - return RT_Fail; - - //increase step to find min value of this direction - if(R828_CompreStep(pTuner, &Compare_IQ[0], 0x08) != RT_Success) //X - return RT_Fail; - } - //CompareTemp = Compare_IQ[0]; - - //--- Check 3 points again---// - if(X_Direction==1) - { - if(R828_IQ_Tree(pTuner, Compare_IQ[0].Phase_Y, Compare_IQ[0].Gain_X, 0x09, &Compare_IQ[0]) != RT_Success) //X - return RT_Fail; - } - else - { - if(R828_IQ_Tree(pTuner, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, 0x08, &Compare_IQ[0]) != RT_Success) //Y - return RT_Fail; - } - - //if(R828_IQ_Tree(Compare_IQ[0].Phase_Y, Compare_IQ[0].Gain_X, 0x09, &Compare_IQ[0]) != RT_Success) // - // return RT_Fail; - - if(R828_CompreCor(&Compare_IQ[0]) != RT_Success) - return RT_Fail; - - //if((CompareTemp.Gain_X == Compare_IQ[0].Gain_X) && (CompareTemp.Phase_Y == Compare_IQ[0].Phase_Y))//Ben Check - // break; - - //IQ_Count ++; - //} - //if(IQ_Count == 3) - // return RT_Fail; - - //Section-4 Check - /* - CompareTemp = Compare_IQ[0]; - for(IQ_Count = 0;IQ_Count < 5;IQ_Count ++) - { - if(R828_Section(&Compare_IQ[0]) != RT_Success) - return RT_Fail; - - if((CompareTemp.Gain_X == Compare_IQ[0].Gain_X) && (CompareTemp.Phase_Y == Compare_IQ[0].Phase_Y)) - break; - } - */ - - //Section-9 check - //if(R828_F_IMR(&Compare_IQ[0]) != RT_Success) - if(R828_Section(pTuner, &Compare_IQ[0]) != RT_Success) - return RT_Fail; - - *IQ_Pont = Compare_IQ[0]; - - //reset gain/phase control setting - R828_I2C.RegAddr = 0x08; - R828_I2C.Data = R828_iniArry[3] & 0xC0; //Jason - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_I2C.RegAddr = 0x09; - R828_I2C.Data = R828_iniArry[4] & 0xC0; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - return RT_Success; -} - -//-------------------------------------------------------------------------------------------- -// Purpose: record IMC results by input gain/phase location -// then adjust gain or phase positive 1 step and negtive 1 step, both record results -// input: FixPot: phase or gain -// FlucPot phase or gain -// PotReg: 0x08 or 0x09 -// CompareTree: 3 IMR trace and results -// output: TREU or FALSE -//-------------------------------------------------------------------------------------------- -R828_ErrCode R828_IQ_Tree(void *pTuner, UINT8 FixPot, UINT8 FlucPot, UINT8 PotReg, R828_SectType* CompareTree) -{ - UINT8 TreeCount; - UINT8 TreeTimes; - UINT8 TempPot; - UINT8 PntReg; - - TreeCount = 0; - TreeTimes = 3; - TempPot = 0; - PntReg = 0; - - if(PotReg == 0x08) - PntReg = 0x09; //phase control - else - PntReg = 0x08; //gain control - - for(TreeCount = 0;TreeCount < TreeTimes;TreeCount ++) - { - R828_I2C.RegAddr = PotReg; - R828_I2C.Data = FixPot; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_I2C.RegAddr = PntReg; - R828_I2C.Data = FlucPot; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - if(R828_Muti_Read(pTuner, 0x01, &CompareTree[TreeCount].Value) != RT_Success) - return RT_Fail; - - if(PotReg == 0x08) - { - CompareTree[TreeCount].Gain_X = FixPot; - CompareTree[TreeCount].Phase_Y = FlucPot; - } - else - { - CompareTree[TreeCount].Phase_Y = FixPot; - CompareTree[TreeCount].Gain_X = FlucPot; - } - - if(TreeCount == 0) //try right-side point - FlucPot ++; - else if(TreeCount == 1) //try left-side point - { - if((FlucPot & 0x1F) < 0x02) //if absolute location is 1, change I/Q direction - { - TempPot = 2 - (FlucPot & 0x1F); - if(FlucPot & 0x20) //b[5]:I/Q selection. 0:Q-path, 1:I-path - { - FlucPot &= 0xC0; - FlucPot |= TempPot; - } - else - { - FlucPot |= (0x20 | TempPot); - } - } - else - FlucPot -= 2; - } - } - - return RT_Success; -} - -//-----------------------------------------------------------------------------------/ -// Purpose: compare IMC result aray [0][1][2], find min value and store to CorArry[0] -// input: CorArry: three IMR data array -// output: TRUE or FALSE -//-----------------------------------------------------------------------------------/ -R828_ErrCode R828_CompreCor(R828_SectType* CorArry) -{ - UINT8 CompCount; - R828_SectType CorTemp; - - CompCount = 0; - - for(CompCount = 3;CompCount > 0;CompCount --) - { - if(CorArry[0].Value > CorArry[CompCount - 1].Value) //compare IMC result [0][1][2], find min value - { - CorTemp = CorArry[0]; - CorArry[0] = CorArry[CompCount - 1]; - CorArry[CompCount - 1] = CorTemp; - } - } - - return RT_Success; -} - -//-------------------------------------------------------------------------------------// -// Purpose: if (Gain<9 or Phase<9), Gain+1 or Phase+1 and compare with min value -// new < min => update to min and continue -// new > min => Exit -// input: StepArry: three IMR data array -// Pace: gain or phase register -// output: TRUE or FALSE -//-------------------------------------------------------------------------------------// -R828_ErrCode R828_CompreStep(void *pTuner, R828_SectType* StepArry, UINT8 Pace) -{ - //UINT8 StepCount = 0; - R828_SectType StepTemp; - - //min value already saved in StepArry[0] - StepTemp.Phase_Y = StepArry[0].Phase_Y; - StepTemp.Gain_X = StepArry[0].Gain_X; - - while(((StepTemp.Gain_X & 0x1F) < IMR_TRIAL) && ((StepTemp.Phase_Y & 0x1F) < IMR_TRIAL)) //5->10 - { - if(Pace == 0x08) - StepTemp.Gain_X ++; - else - StepTemp.Phase_Y ++; - - R828_I2C.RegAddr = 0x08; - R828_I2C.Data = StepTemp.Gain_X ; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_I2C.RegAddr = 0x09; - R828_I2C.Data = StepTemp.Phase_Y; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - if(R828_Muti_Read(pTuner, 0x01, &StepTemp.Value) != RT_Success) - return RT_Fail; - - if(StepTemp.Value <= StepArry[0].Value) - { - StepArry[0].Gain_X = StepTemp.Gain_X; - StepArry[0].Phase_Y = StepTemp.Phase_Y; - StepArry[0].Value = StepTemp.Value; - } - else - { - break; - } - - } //end of while() - - return RT_Success; -} - -//-----------------------------------------------------------------------------------/ -// Purpose: read multiple IMC results for stability -// input: IMR_Reg: IMC result address -// IMR_Result_Data: result -// output: TRUE or FALSE -//-----------------------------------------------------------------------------------/ -R828_ErrCode R828_Muti_Read(void *pTuner, UINT8 IMR_Reg, UINT16* IMR_Result_Data) //jason modified -{ - UINT8 ReadCount; - UINT16 ReadAmount; - UINT8 ReadMax; - UINT8 ReadMin; - UINT8 ReadData; - - ReadCount = 0; - ReadAmount = 0; - ReadMax = 0; - ReadMin = 255; - ReadData = 0; - - R828_Delay_MS(pTuner, 5); - - for(ReadCount = 0;ReadCount < 6;ReadCount ++) - { - R828_I2C_Len.RegAddr = 0x00; - R828_I2C_Len.Len = IMR_Reg + 1; //IMR_Reg = 0x01 - if(I2C_Read_Len(pTuner, &R828_I2C_Len) != RT_Success) - return RT_Fail; - - ReadData = R828_I2C_Len.Data[1]; - - ReadAmount = ReadAmount + (UINT16)ReadData; - - if(ReadData < ReadMin) - ReadMin = ReadData; - - if(ReadData > ReadMax) - ReadMax = ReadData; - } - *IMR_Result_Data = ReadAmount - (UINT16)ReadMax - (UINT16)ReadMin; - - return RT_Success; -} - -R828_ErrCode R828_Section(void *pTuner, R828_SectType* IQ_Pont) -{ - R828_SectType Compare_IQ[3]; - R828_SectType Compare_Bet[3]; - - //Try X-1 column and save min result to Compare_Bet[0] - if((IQ_Pont->Gain_X & 0x1F) == 0x00) - { - /* - if((IQ_Pont->Gain_X & 0xE0) == 0x40) //bug => only compare b[5], - Compare_IQ[0].Gain_X = 0x61; // Gain=1, I-path //Jason - else - Compare_IQ[0].Gain_X = 0x41; // Gain=1, Q-path - */ - Compare_IQ[0].Gain_X = ((IQ_Pont->Gain_X) & 0xDF) + 1; //Q-path, Gain=1 - } - else - Compare_IQ[0].Gain_X = IQ_Pont->Gain_X - 1; //left point - Compare_IQ[0].Phase_Y = IQ_Pont->Phase_Y; - - if(R828_IQ_Tree(pTuner, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, 0x08, &Compare_IQ[0]) != RT_Success) // y-direction - return RT_Fail; - - if(R828_CompreCor(&Compare_IQ[0]) != RT_Success) - return RT_Fail; - - Compare_Bet[0].Gain_X = Compare_IQ[0].Gain_X; - Compare_Bet[0].Phase_Y = Compare_IQ[0].Phase_Y; - Compare_Bet[0].Value = Compare_IQ[0].Value; - - //Try X column and save min result to Compare_Bet[1] - Compare_IQ[0].Gain_X = IQ_Pont->Gain_X; - Compare_IQ[0].Phase_Y = IQ_Pont->Phase_Y; - - if(R828_IQ_Tree(pTuner, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, 0x08, &Compare_IQ[0]) != RT_Success) - return RT_Fail; - - if(R828_CompreCor(&Compare_IQ[0]) != RT_Success) - return RT_Fail; - - Compare_Bet[1].Gain_X = Compare_IQ[0].Gain_X; - Compare_Bet[1].Phase_Y = Compare_IQ[0].Phase_Y; - Compare_Bet[1].Value = Compare_IQ[0].Value; - - //Try X+1 column and save min result to Compare_Bet[2] - if((IQ_Pont->Gain_X & 0x1F) == 0x00) - Compare_IQ[0].Gain_X = ((IQ_Pont->Gain_X) | 0x20) + 1; //I-path, Gain=1 - else - Compare_IQ[0].Gain_X = IQ_Pont->Gain_X + 1; - Compare_IQ[0].Phase_Y = IQ_Pont->Phase_Y; - - if(R828_IQ_Tree(pTuner, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, 0x08, &Compare_IQ[0]) != RT_Success) - return RT_Fail; - - if(R828_CompreCor(&Compare_IQ[0]) != RT_Success) - return RT_Fail; - - Compare_Bet[2].Gain_X = Compare_IQ[0].Gain_X; - Compare_Bet[2].Phase_Y = Compare_IQ[0].Phase_Y; - Compare_Bet[2].Value = Compare_IQ[0].Value; - - if(R828_CompreCor(&Compare_Bet[0]) != RT_Success) - return RT_Fail; - - *IQ_Pont = Compare_Bet[0]; - - return RT_Success; -} - -R828_ErrCode R828_IMR_Cross(void *pTuner, R828_SectType* IQ_Pont, UINT8* X_Direct) -{ - - R828_SectType Compare_Cross[5]; //(0,0)(0,Q-1)(0,I-1)(Q-1,0)(I-1,0) - R828_SectType Compare_Temp; - UINT8 CrossCount; - UINT8 Reg08; - UINT8 Reg09; - - CrossCount = 0; - Reg08 = R828_iniArry[3] & 0xC0; - Reg09 = R828_iniArry[4] & 0xC0; - - //memset(&Compare_Temp,0, sizeof(R828_SectType)); - Compare_Temp.Gain_X = 0; - Compare_Temp.Phase_Y = 0; - Compare_Temp.Value = 0; - - Compare_Temp.Value = 255; - - for(CrossCount=0; CrossCount<5; CrossCount++) - { - - if(CrossCount==0) - { - Compare_Cross[CrossCount].Gain_X = Reg08; - Compare_Cross[CrossCount].Phase_Y = Reg09; - } - else if(CrossCount==1) - { - Compare_Cross[CrossCount].Gain_X = Reg08; //0 - Compare_Cross[CrossCount].Phase_Y = Reg09 + 1; //Q-1 - } - else if(CrossCount==2) - { - Compare_Cross[CrossCount].Gain_X = Reg08; //0 - Compare_Cross[CrossCount].Phase_Y = (Reg09 | 0x20) + 1; //I-1 - } - else if(CrossCount==3) - { - Compare_Cross[CrossCount].Gain_X = Reg08 + 1; //Q-1 - Compare_Cross[CrossCount].Phase_Y = Reg09; - } - else - { - Compare_Cross[CrossCount].Gain_X = (Reg08 | 0x20) + 1; //I-1 - Compare_Cross[CrossCount].Phase_Y = Reg09; - } - - R828_I2C.RegAddr = 0x08; - R828_I2C.Data = Compare_Cross[CrossCount].Gain_X; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_I2C.RegAddr = 0x09; - R828_I2C.Data = Compare_Cross[CrossCount].Phase_Y; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - if(R828_Muti_Read(pTuner, 0x01, &Compare_Cross[CrossCount].Value) != RT_Success) - return RT_Fail; - - if( Compare_Cross[CrossCount].Value < Compare_Temp.Value) - { - Compare_Temp.Value = Compare_Cross[CrossCount].Value; - Compare_Temp.Gain_X = Compare_Cross[CrossCount].Gain_X; - Compare_Temp.Phase_Y = Compare_Cross[CrossCount].Phase_Y; - } - } //end for loop - - - if((Compare_Temp.Phase_Y & 0x1F)==1) //y-direction - { - *X_Direct = (UINT8) 0; - IQ_Pont[0].Gain_X = Compare_Cross[0].Gain_X; - IQ_Pont[0].Phase_Y = Compare_Cross[0].Phase_Y; - IQ_Pont[0].Value = Compare_Cross[0].Value; - - IQ_Pont[1].Gain_X = Compare_Cross[1].Gain_X; - IQ_Pont[1].Phase_Y = Compare_Cross[1].Phase_Y; - IQ_Pont[1].Value = Compare_Cross[1].Value; - - IQ_Pont[2].Gain_X = Compare_Cross[2].Gain_X; - IQ_Pont[2].Phase_Y = Compare_Cross[2].Phase_Y; - IQ_Pont[2].Value = Compare_Cross[2].Value; - } - else //(0,0) or x-direction - { - *X_Direct = (UINT8) 1; - IQ_Pont[0].Gain_X = Compare_Cross[0].Gain_X; - IQ_Pont[0].Phase_Y = Compare_Cross[0].Phase_Y; - IQ_Pont[0].Value = Compare_Cross[0].Value; - - IQ_Pont[1].Gain_X = Compare_Cross[3].Gain_X; - IQ_Pont[1].Phase_Y = Compare_Cross[3].Phase_Y; - IQ_Pont[1].Value = Compare_Cross[3].Value; - - IQ_Pont[2].Gain_X = Compare_Cross[4].Gain_X; - IQ_Pont[2].Phase_Y = Compare_Cross[4].Phase_Y; - IQ_Pont[2].Value = Compare_Cross[4].Value; - } - return RT_Success; -} - -//----------------------------------------------------------------------------------------// -// purpose: search surrounding points from previous point -// try (x-1), (x), (x+1) columns, and find min IMR result point -// input: IQ_Pont: previous point data(IMR Gain, Phase, ADC Result, RefRreq) -// will be updated to final best point -// output: TRUE or FALSE -//----------------------------------------------------------------------------------------// -R828_ErrCode R828_F_IMR(void *pTuner, R828_SectType* IQ_Pont) -{ - R828_SectType Compare_IQ[3]; - R828_SectType Compare_Bet[3]; - UINT8 VGA_Count; - UINT16 VGA_Read; - - VGA_Count = 0; - VGA_Read = 0; - - //VGA - for(VGA_Count = 12;VGA_Count < 16;VGA_Count ++) - { - R828_I2C.RegAddr = 0x0C; - R828_I2C.Data = (R828_Arry[7] & 0xF0) + VGA_Count; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_Delay_MS(pTuner, 10); - - if(R828_Muti_Read(pTuner, 0x01, &VGA_Read) != RT_Success) - return RT_Fail; - - if(VGA_Read > 40*4) - break; - } - - //Try X-1 column and save min result to Compare_Bet[0] - if((IQ_Pont->Gain_X & 0x1F) == 0x00) - { - Compare_IQ[0].Gain_X = ((IQ_Pont->Gain_X) & 0xDF) + 1; //Q-path, Gain=1 - } - else - Compare_IQ[0].Gain_X = IQ_Pont->Gain_X - 1; //left point - Compare_IQ[0].Phase_Y = IQ_Pont->Phase_Y; - - if(R828_IQ_Tree(pTuner, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, 0x08, &Compare_IQ[0]) != RT_Success) // y-direction - return RT_Fail; - - if(R828_CompreCor(&Compare_IQ[0]) != RT_Success) - return RT_Fail; - - Compare_Bet[0].Gain_X = Compare_IQ[0].Gain_X; - Compare_Bet[0].Phase_Y = Compare_IQ[0].Phase_Y; - Compare_Bet[0].Value = Compare_IQ[0].Value; - - //Try X column and save min result to Compare_Bet[1] - Compare_IQ[0].Gain_X = IQ_Pont->Gain_X; - Compare_IQ[0].Phase_Y = IQ_Pont->Phase_Y; - - if(R828_IQ_Tree(pTuner, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, 0x08, &Compare_IQ[0]) != RT_Success) - return RT_Fail; - - if(R828_CompreCor(&Compare_IQ[0]) != RT_Success) - return RT_Fail; - - Compare_Bet[1].Gain_X = Compare_IQ[0].Gain_X; - Compare_Bet[1].Phase_Y = Compare_IQ[0].Phase_Y; - Compare_Bet[1].Value = Compare_IQ[0].Value; - - //Try X+1 column and save min result to Compare_Bet[2] - if((IQ_Pont->Gain_X & 0x1F) == 0x00) - Compare_IQ[0].Gain_X = ((IQ_Pont->Gain_X) | 0x20) + 1; //I-path, Gain=1 - else - Compare_IQ[0].Gain_X = IQ_Pont->Gain_X + 1; - Compare_IQ[0].Phase_Y = IQ_Pont->Phase_Y; - - if(R828_IQ_Tree(pTuner, Compare_IQ[0].Gain_X, Compare_IQ[0].Phase_Y, 0x08, &Compare_IQ[0]) != RT_Success) - return RT_Fail; - - if(R828_CompreCor(&Compare_IQ[0]) != RT_Success) - return RT_Fail; - - Compare_Bet[2].Gain_X = Compare_IQ[0].Gain_X; - Compare_Bet[2].Phase_Y = Compare_IQ[0].Phase_Y; - Compare_Bet[2].Value = Compare_IQ[0].Value; - - if(R828_CompreCor(&Compare_Bet[0]) != RT_Success) - return RT_Fail; - - *IQ_Pont = Compare_Bet[0]; - - return RT_Success; -} - -R828_ErrCode R828_GPIO(void *pTuner, R828_GPIO_Type R828_GPIO_Conrl) -{ - if(R828_GPIO_Conrl == HI_SIG) - R828_Arry[10] |= 0x01; - else - R828_Arry[10] &= 0xFE; - - R828_I2C.RegAddr = 0x0F; - R828_I2C.Data = R828_Arry[10]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - return RT_Success; -} - -R828_ErrCode R828_SetStandard(void *pTuner, R828_Standard_Type RT_Standard) -{ - - // Used Normal Arry to Modify - UINT8 ArrayNum; - - ArrayNum = 27; - for(ArrayNum=0;ArrayNum<27;ArrayNum++) - { - R828_Arry[ArrayNum] = R828_iniArry[ArrayNum]; - } - - - // Record Init Flag & Xtal_check Result - if(R828_IMR_done_flag == TRUE) - R828_Arry[7] = (R828_Arry[7] & 0xF0) | 0x01 | (Xtal_cap_sel<<1); - else - R828_Arry[7] = (R828_Arry[7] & 0xF0) | 0x00; - - R828_I2C.RegAddr = 0x0C; - R828_I2C.Data = R828_Arry[7]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - // Record version - R828_I2C.RegAddr = 0x13; - R828_Arry[14] = (R828_Arry[14] & 0xC0) | VER_NUM; - R828_I2C.Data = R828_Arry[14]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - - //for LT Gain test - if(RT_Standard > SECAM_L1) - { - R828_I2C.RegAddr = 0x1D; //[5:3] LNA TOP - R828_I2C.Data = (R828_Arry[24] & 0xC7) | 0x00; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //R828_Delay_MS(1); - } - - // Look Up System Dependent Table - Sys_Info1 = R828_Sys_Sel(RT_Standard); - R828_IF_khz = Sys_Info1.IF_KHz; - R828_CAL_LO_khz = Sys_Info1.FILT_CAL_LO; - - // Filter Calibration - if(R828_Fil_Cal_flag[RT_Standard] == FALSE) - { - // do filter calibration - if(R828_Filt_Cal(pTuner, Sys_Info1.FILT_CAL_LO,Sys_Info1.BW) != RT_Success) - return RT_Fail; - - - // read and set filter code - R828_I2C_Len.RegAddr = 0x00; - R828_I2C_Len.Len = 5; - if(I2C_Read_Len(pTuner, &R828_I2C_Len) != RT_Success) - return RT_Fail; - - R828_Fil_Cal_code[RT_Standard] = R828_I2C_Len.Data[4] & 0x0F; - - //Filter Cali. Protection - if(R828_Fil_Cal_code[RT_Standard]==0 || R828_Fil_Cal_code[RT_Standard]==15) - { - if(R828_Filt_Cal(pTuner, Sys_Info1.FILT_CAL_LO,Sys_Info1.BW) != RT_Success) - return RT_Fail; - - R828_I2C_Len.RegAddr = 0x00; - R828_I2C_Len.Len = 5; - if(I2C_Read_Len(pTuner, &R828_I2C_Len) != RT_Success) - return RT_Fail; - - R828_Fil_Cal_code[RT_Standard] = R828_I2C_Len.Data[4] & 0x0F; - - if(R828_Fil_Cal_code[RT_Standard]==15) //narrowest - R828_Fil_Cal_code[RT_Standard] = 0; - - } - R828_Fil_Cal_flag[RT_Standard] = TRUE; - } - - // Set Filter Q - R828_Arry[5] = (R828_Arry[5] & 0xE0) | Sys_Info1.FILT_Q | R828_Fil_Cal_code[RT_Standard]; - R828_I2C.RegAddr = 0x0A; - R828_I2C.Data = R828_Arry[5]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - // Set BW, Filter_gain, & HP corner - R828_Arry[6]= (R828_Arry[6] & 0x10) | Sys_Info1.HP_COR; - R828_I2C.RegAddr = 0x0B; - R828_I2C.Data = R828_Arry[6]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - // Set Img_R - R828_Arry[2] = (R828_Arry[2] & 0x7F) | Sys_Info1.IMG_R; - R828_I2C.RegAddr = 0x07; - R828_I2C.Data = R828_Arry[2]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - - // Set filt_3dB, V6MHz - R828_Arry[1] = (R828_Arry[1] & 0xCF) | Sys_Info1.FILT_GAIN; - R828_I2C.RegAddr = 0x06; - R828_I2C.Data = R828_Arry[1]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //channel filter extension - R828_Arry[25] = (R828_Arry[25] & 0x9F) | Sys_Info1.EXT_ENABLE; - R828_I2C.RegAddr = 0x1E; - R828_I2C.Data = R828_Arry[25]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - - //Loop through - R828_Arry[0] = (R828_Arry[0] & 0x7F) | Sys_Info1.LOOP_THROUGH; - R828_I2C.RegAddr = 0x05; - R828_I2C.Data = R828_Arry[0]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //Loop through attenuation - R828_Arry[26] = (R828_Arry[26] & 0x7F) | Sys_Info1.LT_ATT; - R828_I2C.RegAddr = 0x1F; - R828_I2C.Data = R828_Arry[26]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //filter extention widest - R828_Arry[10] = (R828_Arry[10] & 0x7F) | Sys_Info1.FLT_EXT_WIDEST; - R828_I2C.RegAddr = 0x0F; - R828_I2C.Data = R828_Arry[10]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //RF poly filter current - R828_Arry[20] = (R828_Arry[20] & 0x9F) | Sys_Info1.POLYFIL_CUR; - R828_I2C.RegAddr = 0x19; - R828_I2C.Data = R828_Arry[20]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - return RT_Success; -} - -R828_ErrCode R828_Filt_Cal(void *pTuner, UINT32 Cal_Freq,BW_Type R828_BW) -{ - //set in Sys_sel() - /* - if(R828_BW == BW_8M) - { - //set filt_cap = no cap - R828_I2C.RegAddr = 0x0B; //reg11 - R828_Arry[6] &= 0x9F; //filt_cap = no cap - R828_I2C.Data = R828_Arry[6]; - } - else if(R828_BW == BW_7M) - { - //set filt_cap = +1 cap - R828_I2C.RegAddr = 0x0B; //reg11 - R828_Arry[6] &= 0x9F; //filt_cap = no cap - R828_Arry[6] |= 0x20; //filt_cap = +1 cap - R828_I2C.Data = R828_Arry[6]; - } - else if(R828_BW == BW_6M) - { - //set filt_cap = +2 cap - R828_I2C.RegAddr = 0x0B; //reg11 - R828_Arry[6] &= 0x9F; //filt_cap = no cap - R828_Arry[6] |= 0x60; //filt_cap = +2 cap - R828_I2C.Data = R828_Arry[6]; - } - - - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; -*/ - - // Set filt_cap - R828_I2C.RegAddr = 0x0B; - R828_Arry[6]= (R828_Arry[6] & 0x9F) | (Sys_Info1.HP_COR & 0x60); - R828_I2C.Data = R828_Arry[6]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - - //set cali clk =on - R828_I2C.RegAddr = 0x0F; //reg15 - R828_Arry[10] |= 0x04; //calibration clk=on - R828_I2C.Data = R828_Arry[10]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //X'tal cap 0pF for PLL - R828_I2C.RegAddr = 0x10; - R828_Arry[11] = (R828_Arry[11] & 0xFC) | 0x00; - R828_I2C.Data = R828_Arry[11]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //Set PLL Freq = Filter Cali Freq - if(R828_PLL(pTuner, Cal_Freq * 1000, STD_SIZE) != RT_Success) - return RT_Fail; - - //Start Trigger - R828_I2C.RegAddr = 0x0B; //reg11 - R828_Arry[6] |= 0x10; //vstart=1 - R828_I2C.Data = R828_Arry[6]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //delay 0.5ms - R828_Delay_MS(pTuner, 1); - - //Stop Trigger - R828_I2C.RegAddr = 0x0B; - R828_Arry[6] &= 0xEF; //vstart=0 - R828_I2C.Data = R828_Arry[6]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - - //set cali clk =off - R828_I2C.RegAddr = 0x0F; //reg15 - R828_Arry[10] &= 0xFB; //calibration clk=off - R828_I2C.Data = R828_Arry[10]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - return RT_Success; - -} - -R828_ErrCode R828_SetFrequency(void *pTuner, R828_Set_Info R828_INFO, R828_SetFreq_Type R828_SetFreqMode) -{ - UINT32 LO_Hz; - -#if 0 - // Check Input Frequency Range - if((R828_INFO.RF_KHz<40000) || (R828_INFO.RF_KHz>900000)) - { - return RT_Fail; - } -#endif - - if(R828_INFO.R828_Standard==SECAM_L1) - LO_Hz = R828_INFO.RF_Hz - (Sys_Info1.IF_KHz * 1000); - else - LO_Hz = R828_INFO.RF_Hz + (Sys_Info1.IF_KHz * 1000); - - //Set MUX dependent var. Must do before PLL( ) - if(R828_MUX(pTuner, LO_Hz/1000) != RT_Success) - return RT_Fail; - - //Set PLL - if(R828_PLL(pTuner, LO_Hz, R828_INFO.R828_Standard) != RT_Success) - return RT_Fail; - - R828_IMR_point_num = Freq_Info1.IMR_MEM; - - - //Set TOP,VTH,VTL - SysFreq_Info1 = R828_SysFreq_Sel(R828_INFO.R828_Standard, R828_INFO.RF_KHz); - - - // write DectBW, pre_dect_TOP - R828_Arry[24] = (R828_Arry[24] & 0x38) | (SysFreq_Info1.LNA_TOP & 0xC7); - R828_I2C.RegAddr = 0x1D; - R828_I2C.Data = R828_Arry[24]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - // write MIXER TOP, TOP+-1 - R828_Arry[23] = (R828_Arry[23] & 0x07) | (SysFreq_Info1.MIXER_TOP & 0xF8); - R828_I2C.RegAddr = 0x1C; - R828_I2C.Data = R828_Arry[23]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - - // write LNA VTHL - R828_Arry[8] = (R828_Arry[8] & 0x00) | SysFreq_Info1.LNA_VTH_L; - R828_I2C.RegAddr = 0x0D; - R828_I2C.Data = R828_Arry[8]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - // write MIXER VTHL - R828_Arry[9] = (R828_Arry[9] & 0x00) | SysFreq_Info1.MIXER_VTH_L; - R828_I2C.RegAddr = 0x0E; - R828_I2C.Data = R828_Arry[9]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - // Cable-1/Air in - R828_I2C.RegAddr = 0x05; - R828_Arry[0] &= 0x9F; - R828_Arry[0] |= SysFreq_Info1.AIR_CABLE1_IN; - R828_I2C.Data = R828_Arry[0]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - // Cable-2 in - R828_I2C.RegAddr = 0x06; - R828_Arry[1] &= 0xF7; - R828_Arry[1] |= SysFreq_Info1.CABLE2_IN; - R828_I2C.Data = R828_Arry[1]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //CP current - R828_I2C.RegAddr = 0x11; - R828_Arry[12] &= 0xC7; - R828_Arry[12] |= SysFreq_Info1.CP_CUR; - R828_I2C.Data = R828_Arry[12]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //div buffer current - R828_I2C.RegAddr = 0x17; - R828_Arry[18] &= 0xCF; - R828_Arry[18] |= SysFreq_Info1.DIV_BUF_CUR; - R828_I2C.Data = R828_Arry[18]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - // Set channel filter current - R828_I2C.RegAddr = 0x0A; - R828_Arry[5] = (R828_Arry[5] & 0x9F) | SysFreq_Info1.FILTER_CUR; - R828_I2C.Data = R828_Arry[5]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //Air-In only for Astrometa - R828_Arry[0] = (R828_Arry[0] & 0x9F) | 0x00; - R828_Arry[1] = (R828_Arry[1] & 0xF7) | 0x00; - - R828_I2C.RegAddr = 0x05; - R828_I2C.Data = R828_Arry[0]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_I2C.RegAddr = 0x06; - R828_I2C.Data = R828_Arry[1]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //Set LNA - if(R828_INFO.R828_Standard > SECAM_L1) - { - - if(R828_SetFreqMode==FAST_MODE) //FAST mode - { - //R828_Arry[24] = (R828_Arry[24] & 0xC7) | 0x20; //LNA TOP:4 - R828_Arry[24] = (R828_Arry[24] & 0xC7) | 0x00; //LNA TOP:lowest - R828_I2C.RegAddr = 0x1D; - R828_I2C.Data = R828_Arry[24]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_Arry[23] = (R828_Arry[23] & 0xFB); // 0: normal mode - R828_I2C.RegAddr = 0x1C; - R828_I2C.Data = R828_Arry[23]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_Arry[1] = (R828_Arry[1] & 0xBF); //0: PRE_DECT off - R828_I2C.RegAddr = 0x06; - R828_I2C.Data = R828_Arry[1]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //agc clk 250hz - R828_Arry[21] = (R828_Arry[21] & 0xCF) | 0x30; - R828_I2C.RegAddr = 0x1A; - R828_I2C.Data = R828_Arry[21]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - } - else //NORMAL mode - { - - R828_Arry[24] = (R828_Arry[24] & 0xC7) | 0x00; //LNA TOP:lowest - R828_I2C.RegAddr = 0x1D; - R828_I2C.Data = R828_Arry[24]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_Arry[23] = (R828_Arry[23] & 0xFB); // 0: normal mode - R828_I2C.RegAddr = 0x1C; - R828_I2C.Data = R828_Arry[23]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_Arry[1] = (R828_Arry[1] & 0xBF); //0: PRE_DECT off - R828_I2C.RegAddr = 0x06; - R828_I2C.Data = R828_Arry[1]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //agc clk 250hz - R828_Arry[21] = (R828_Arry[21] & 0xCF) | 0x30; //250hz - R828_I2C.RegAddr = 0x1A; - R828_I2C.Data = R828_Arry[21]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_Delay_MS(pTuner, 250); - - // PRE_DECT on - /* - R828_Arry[1] = (R828_Arry[1] & 0xBF) | SysFreq_Info1.PRE_DECT; - R828_I2C.RegAddr = 0x06; - R828_I2C.Data = R828_Arry[1]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - */ - // write LNA TOP = 3 - //R828_Arry[24] = (R828_Arry[24] & 0xC7) | (SysFreq_Info1.LNA_TOP & 0x38); - R828_Arry[24] = (R828_Arry[24] & 0xC7) | 0x18; //TOP=3 - R828_I2C.RegAddr = 0x1D; - R828_I2C.Data = R828_Arry[24]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - // write discharge mode - R828_Arry[23] = (R828_Arry[23] & 0xFB) | (SysFreq_Info1.MIXER_TOP & 0x04); - R828_I2C.RegAddr = 0x1C; - R828_I2C.Data = R828_Arry[23]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - // LNA discharge current - R828_Arry[25] = (R828_Arry[25] & 0xE0) | SysFreq_Info1.LNA_DISCHARGE; - R828_I2C.RegAddr = 0x1E; - R828_I2C.Data = R828_Arry[25]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //agc clk 60hz - R828_Arry[21] = (R828_Arry[21] & 0xCF) | 0x20; - R828_I2C.RegAddr = 0x1A; - R828_I2C.Data = R828_Arry[21]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - } - } - else - { - if(R828_SetFreqMode==NORMAL_MODE || R828_SetFreqMode==FAST_MODE) - { - /* - // PRE_DECT on - R828_Arry[1] = (R828_Arry[1] & 0xBF) | SysFreq_Info1.PRE_DECT; - R828_I2C.RegAddr = 0x06; - R828_I2C.Data = R828_Arry[1]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - */ - // PRE_DECT off - R828_Arry[1] = (R828_Arry[1] & 0xBF); //0: PRE_DECT off - R828_I2C.RegAddr = 0x06; - R828_I2C.Data = R828_Arry[1]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - // write LNA TOP - R828_Arry[24] = (R828_Arry[24] & 0xC7) | (SysFreq_Info1.LNA_TOP & 0x38); - R828_I2C.RegAddr = 0x1D; - R828_I2C.Data = R828_Arry[24]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - // write discharge mode - R828_Arry[23] = (R828_Arry[23] & 0xFB) | (SysFreq_Info1.MIXER_TOP & 0x04); - R828_I2C.RegAddr = 0x1C; - R828_I2C.Data = R828_Arry[23]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - // LNA discharge current - R828_Arry[25] = (R828_Arry[25] & 0xE0) | SysFreq_Info1.LNA_DISCHARGE; - R828_I2C.RegAddr = 0x1E; - R828_I2C.Data = R828_Arry[25]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - // agc clk 1Khz, external det1 cap 1u - R828_Arry[21] = (R828_Arry[21] & 0xCF) | 0x00; - R828_I2C.RegAddr = 0x1A; - R828_I2C.Data = R828_Arry[21]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_Arry[11] = (R828_Arry[11] & 0xFB) | 0x00; - R828_I2C.RegAddr = 0x10; - R828_I2C.Data = R828_Arry[11]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - } - } - - return RT_Success; - -} - -R828_ErrCode R828_Standby(void *pTuner, R828_LoopThrough_Type R828_LoopSwitch) -{ - if(R828_LoopSwitch == LOOP_THROUGH) - { - R828_I2C.RegAddr = 0x06; - R828_I2C.Data = 0xB1; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - R828_I2C.RegAddr = 0x05; - R828_I2C.Data = 0x03; - - - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - } - else - { - R828_I2C.RegAddr = 0x05; - R828_I2C.Data = 0xA3; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_I2C.RegAddr = 0x06; - R828_I2C.Data = 0xB1; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - } - - R828_I2C.RegAddr = 0x07; - R828_I2C.Data = 0x3A; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_I2C.RegAddr = 0x08; - R828_I2C.Data = 0x40; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_I2C.RegAddr = 0x09; - R828_I2C.Data = 0xC0; //polyfilter off - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_I2C.RegAddr = 0x0A; - R828_I2C.Data = 0x36; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_I2C.RegAddr = 0x0C; - R828_I2C.Data = 0x35; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_I2C.RegAddr = 0x0F; - R828_I2C.Data = 0x78; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_I2C.RegAddr = 0x11; - R828_I2C.Data = 0x03; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_I2C.RegAddr = 0x17; - R828_I2C.Data = 0xF4; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_I2C.RegAddr = 0x19; - R828_I2C.Data = 0x0C; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - - return RT_Success; -} - -R828_ErrCode R828_GetRfGain(void *pTuner, R828_RF_Gain_Info *pR828_rf_gain) -{ - - R828_I2C_Len.RegAddr = 0x00; - R828_I2C_Len.Len = 4; - if(I2C_Read_Len(pTuner, &R828_I2C_Len) != RT_Success) - return RT_Fail; - - pR828_rf_gain->RF_gain1 = (R828_I2C_Len.Data[3] & 0x0F); - pR828_rf_gain->RF_gain2 = ((R828_I2C_Len.Data[3] & 0xF0) >> 4); - pR828_rf_gain->RF_gain_comb = pR828_rf_gain->RF_gain1*2 + pR828_rf_gain->RF_gain2; - - return RT_Success; -} - - -/* measured with a Racal 6103E GSM test set at 928 MHz with -60 dBm - * input power, for raw results see: - * http://steve-m.de/projects/rtl-sdr/gain_measurement/r820t/ - */ - -#define VGA_BASE_GAIN -47 -static const int r820t_vga_gain_steps[] = { - 0, 26, 26, 30, 42, 35, 24, 13, 14, 32, 36, 34, 35, 37, 35, 36 -}; - -static const int r820t_lna_gain_steps[] = { - 0, 9, 13, 40, 38, 13, 31, 22, 26, 31, 26, 14, 19, 5, 35, 13 -}; - -static const int r820t_mixer_gain_steps[] = { - 0, 5, 10, 10, 19, 9, 10, 25, 17, 10, 8, 16, 13, 6, 3, -8 -}; - -R828_ErrCode R828_SetRfGain(void *pTuner, int gain) -{ - int i, total_gain = 0; - uint8_t mix_index = 0, lna_index = 0; - - for (i = 0; i < 15; i++) { - if (total_gain >= gain) - break; - - total_gain += r820t_lna_gain_steps[++lna_index]; - - if (total_gain >= gain) - break; - - total_gain += r820t_mixer_gain_steps[++mix_index]; - } - - /* set LNA gain */ - R828_I2C.RegAddr = 0x05; - R828_Arry[0] = (R828_Arry[0] & 0xF0) | lna_index; - R828_I2C.Data = R828_Arry[0]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - /* set Mixer gain */ - R828_I2C.RegAddr = 0x07; - R828_Arry[2] = (R828_Arry[2] & 0xF0) | mix_index; - R828_I2C.Data = R828_Arry[2]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - return RT_Success; -} - -R828_ErrCode R828_RfGainMode(void *pTuner, int manual) -{ - UINT8 MixerGain; - UINT8 LnaGain; - - MixerGain = 0; - LnaGain = 0; - - if (manual) { - //LNA auto off - R828_I2C.RegAddr = 0x05; - R828_Arry[0] = R828_Arry[0] | 0x10; - R828_I2C.Data = R828_Arry[0]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //Mixer auto off - R828_I2C.RegAddr = 0x07; - R828_Arry[2] = R828_Arry[2] & 0xEF; - R828_I2C.Data = R828_Arry[2]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - R828_I2C_Len.RegAddr = 0x00; - R828_I2C_Len.Len = 4; - if(I2C_Read_Len(pTuner, &R828_I2C_Len) != RT_Success) - return RT_Fail; - - /* set fixed VGA gain for now (16.3 dB) */ - R828_I2C.RegAddr = 0x0C; - R828_Arry[7] = (R828_Arry[7] & 0x60) | 0x08; - R828_I2C.Data = R828_Arry[7]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - - } else { - //LNA - R828_I2C.RegAddr = 0x05; - R828_Arry[0] = R828_Arry[0] & 0xEF; - R828_I2C.Data = R828_Arry[0]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - //Mixer - R828_I2C.RegAddr = 0x07; - R828_Arry[2] = R828_Arry[2] | 0x10; - R828_I2C.Data = R828_Arry[2]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - - /* set fixed VGA gain for now (26.5 dB) */ - R828_I2C.RegAddr = 0x0C; - R828_Arry[7] = (R828_Arry[7] & 0x60) | 0x0B; - R828_I2C.Data = R828_Arry[7]; - if(I2C_Write(pTuner, &R828_I2C) != RT_Success) - return RT_Fail; - } - - return RT_Success; -}