diff --git a/CMakeLists.txt b/CMakeLists.txt index 123f7a50..01d812b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,6 +3,9 @@ project(SDDC VERSION 1.0.1) include(CTest) +include(./cmake/CheckGit.cmake) +CheckGitSetup() + message(STATUS "CMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}") ### build options @@ -62,10 +65,10 @@ if (MSVC) else() if (USE_DEBUG_ASAN) - set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address") - set(CMAKE_CXX_FLAGS "-O0 -std=c++17 -Wall -Werror") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -fsanitize=address") + set(CMAKE_CXX_FLAGS "-O0 -g -std=c++17 -Wall -Werror") else() - set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -Wall -Werror") + set(CMAKE_CXX_FLAGS "-O3 -g -std=c++17 -Wall -Werror") endif(USE_DEBUG_ASAN) #add_compile_options(-Wall -Wextra -pedantic) include(FindPkgConfig) diff --git a/Core/CMakeLists.txt b/Core/CMakeLists.txt index b482862e..73052dca 100644 --- a/Core/CMakeLists.txt +++ b/Core/CMakeLists.txt @@ -1,5 +1,3 @@ -cmake_minimum_required(VERSION 3.13) - if (MSVC) file(GLOB ARCH_SRC "arch/win32/*.cpp" "arch/win32/CyAPI/*.cpp") else() diff --git a/Core/FX3Class.h b/Core/FX3Class.h index 071d95d7..8282e659 100644 --- a/Core/FX3Class.h +++ b/Core/FX3Class.h @@ -20,7 +20,7 @@ class fx3class { public: virtual ~fx3class(void) {} - virtual bool Open(const uint8_t* fw_data, uint32_t fw_size) = 0; + virtual bool Open(int index, const uint8_t* fw_data, uint32_t fw_size) = 0; virtual bool Control(FX3Command command, uint8_t data = 0) = 0; virtual bool Control(FX3Command command, uint32_t data) = 0; virtual bool Control(FX3Command command, uint64_t data) = 0; diff --git a/Core/arch/linux/FX3handler.cpp b/Core/arch/linux/FX3handler.cpp index f9e5dfcd..1b851266 100644 --- a/Core/arch/linux/FX3handler.cpp +++ b/Core/arch/linux/FX3handler.cpp @@ -3,8 +3,12 @@ #include "FX3handler.h" #include "usb_device.h" +struct usb_device_info *devlist; +int devlist_n; + fx3class* CreateUsbHandler() { + devlist_n = usb_device_get_device_list(&devlist); return new fx3handler(); } @@ -16,9 +20,9 @@ fx3handler::~fx3handler() { } -bool fx3handler::Open(const uint8_t* fw_data, uint32_t fw_size) +bool fx3handler::Open(int index, const uint8_t* fw_data, uint32_t fw_size) { - dev = usb_device_open(0, (const char*)fw_data, fw_size); + dev = usb_device_open(index, (const char*)fw_data, fw_size); return dev != nullptr; } @@ -96,5 +100,10 @@ bool fx3handler::ReadDebugTrace(uint8_t* pdata, uint8_t len) bool fx3handler::Enumerate(unsigned char &idx, char *lbuf, const uint8_t* fw_data, uint32_t fw_size) { - return true; // TBD + if (idx > devlist_n - 1) + return false; + + sprintf(lbuf, "%s sn:%s", devlist[idx].product, devlist[idx].serial_number); + + return true; } diff --git a/Core/arch/linux/FX3handler.h b/Core/arch/linux/FX3handler.h index 67c8ea05..89be15df 100644 --- a/Core/arch/linux/FX3handler.h +++ b/Core/arch/linux/FX3handler.h @@ -17,7 +17,7 @@ class fx3handler : public fx3class public: fx3handler(); virtual ~fx3handler(void); - bool Open(const uint8_t* fw_data, uint32_t fw_size) override; + bool Open(int index, const uint8_t* fw_data, uint32_t fw_size) override; bool Control(FX3Command command, uint8_t data) override; bool Control(FX3Command command, uint32_t data) override; bool Control(FX3Command command, uint64_t data) override; diff --git a/Core/arch/win32/FX3handler.cpp b/Core/arch/win32/FX3handler.cpp index a148c2bd..2a43f4ca 100644 --- a/Core/arch/win32/FX3handler.cpp +++ b/Core/arch/win32/FX3handler.cpp @@ -78,13 +78,13 @@ bool fx3handler::Enumerate(unsigned char& idx, char* lbuf, const uint8_t* fw_dat strcat(lbuf, "sn:"); strcat(lbuf, wchar2char((wchar_t*)fx3dev->SerialNumber)); fx3dev->Close(); - devidx = idx; // -> devidx return true; } -bool fx3handler::Open(const uint8_t* fw_data, uint32_t fw_size) { +bool fx3handler::Open(int index, const uint8_t* fw_data, uint32_t fw_size) { bool r = false; + devidx = index; if (!GetFx3DeviceStreamer()) { DbgPrintf("Failed to open device\n"); return r; diff --git a/Core/arch/win32/FX3handler.h b/Core/arch/win32/FX3handler.h index 67f109ca..6fa9649e 100644 --- a/Core/arch/win32/FX3handler.h +++ b/Core/arch/win32/FX3handler.h @@ -34,7 +34,7 @@ class fx3handler : public fx3class fx3handler(); virtual ~fx3handler(void); - bool Open(const uint8_t* fw_data, uint32_t fw_size); + bool Open(int idx, const uint8_t* fw_data, uint32_t fw_size); bool IsOn() { return Fx3IsOn; } bool Control(FX3Command command, uint8_t data); bool Control(FX3Command command, uint32_t data = 0); diff --git a/ExtIO_sddc/CMakeLists.txt b/ExtIO_sddc/CMakeLists.txt index b240322d..86c565ca 100644 --- a/ExtIO_sddc/CMakeLists.txt +++ b/ExtIO_sddc/CMakeLists.txt @@ -8,11 +8,11 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG") add_library(ExtIO_SDDC SHARED ${SRC}) -target_include_directories(ExtIO_SDDC PUBLIC "${LIBFFTW_INCLUDE_DIR}") -target_link_directories(ExtIO_SDDC PUBLIC "${LIBFFTW_LIBRARY_DIRS}") +target_include_directories(ExtIO_SDDC PUBLIC ${LIBFFTW_INCLUDE_DIR}) +target_link_directories(ExtIO_SDDC PUBLIC ${LIBFFTW_LIBRARY_DIRS}) target_link_libraries(ExtIO_SDDC PUBLIC ${LIBFFTW_LIBRARIES}) - +target_link_libraries(ExtIO_SDDC PRIVATE git_version) target_link_libraries(ExtIO_SDDC PRIVATE SDDC_CORE) target_link_libraries(ExtIO_SDDC PUBLIC Setupapi.lib) set_target_properties(ExtIO_SDDC PROPERTIES PREFIX "") diff --git a/ExtIO_sddc/ExtIO_sddc.cpp b/ExtIO_sddc/ExtIO_sddc.cpp index 82649c98..0c301347 100644 --- a/ExtIO_sddc/ExtIO_sddc.cpp +++ b/ExtIO_sddc/ExtIO_sddc.cpp @@ -16,6 +16,8 @@ #include "PScope_uti.h" #include "r2iq.h" +#include "git_version.h" + #define snprintf _snprintf #define DEFAULT_TUNE_FREQ 999000.0 /* Turin MW broadcast ! */ @@ -235,10 +237,8 @@ bool __declspec(dllexport) __stdcall InitHW(char *name, char *model, int& type) selected = DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_SELECTDEVICE), NULL, DlgSelectDevice, (LPARAM) &devicelist); } DbgPrintf("selected %d \n",selected); - idx = selected; - Fx3->Enumerate(idx, devicelist.dev[idx], res_data, res_size); - gbInitHW = Fx3->Open(res_data, res_size) && + gbInitHW = Fx3->Open(selected, res_data, res_size) && RadioHandler.Init(Fx3, Callback); // Check if it there hardware #ifdef _DEBUG @@ -358,7 +358,7 @@ int EXTIO_API StartHWdbl(double LOfreq) uint8_t hb, lb; hb = fw >> 8; lb = (uint8_t) fw; - sprintf(ebuffer, "%s v%s | FX3 v%d.%02d | %s ",SWNAME, SWVERSION ,hb,lb, RadioHandler.getName() ); + sprintf(ebuffer, "%s v%s (%s) | %s ", SWNAME, SWVERSION, kGitHash, RadioHandler.getName()); SetWindowText(h_dialog, ebuffer); EXTIO_STATUS_CHANGE(pfnCallback, extHw_RUNNING); } diff --git a/cmake/CheckGit.cmake b/cmake/CheckGit.cmake new file mode 100644 index 00000000..d1f85eca --- /dev/null +++ b/cmake/CheckGit.cmake @@ -0,0 +1,81 @@ +set(CURRENT_LIST_DIR ${CMAKE_CURRENT_LIST_DIR}) +if (NOT DEFINED pre_configure_dir) + set(pre_configure_dir ${CMAKE_CURRENT_LIST_DIR}) +endif () + +if (NOT DEFINED post_configure_dir) + set(post_configure_dir ${CMAKE_BINARY_DIR}/generated) +endif () + +set(pre_configure_file ${pre_configure_dir}/git_version.cpp.in) +set(post_configure_file ${post_configure_dir}/git_version.cpp) + +function(CheckGitWrite git_hash) + file(WRITE ${CMAKE_BINARY_DIR}/git-state.txt ${git_hash}) +endfunction() + +function(CheckGitRead git_hash) + if (EXISTS ${CMAKE_BINARY_DIR}/git-state.txt) + file(STRINGS ${CMAKE_BINARY_DIR}/git-state.txt CONTENT) + LIST(GET CONTENT 0 var) + + set(${git_hash} ${var} PARENT_SCOPE) + endif () +endfunction() + +function(CheckGitVersion) + # Get the latest abbreviated commit hash of the working branch + execute_process( + COMMAND git log -1 --format=%h + WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + OUTPUT_VARIABLE GIT_HASH + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + CheckGitRead(GIT_HASH_CACHE) + if (NOT EXISTS ${post_configure_dir}) + file(MAKE_DIRECTORY ${post_configure_dir}) + endif () + + if (NOT EXISTS ${post_configure_dir}/git_version.h) + file(COPY ${pre_configure_dir}/git_version.h DESTINATION ${post_configure_dir}) + endif() + + if (NOT DEFINED GIT_HASH_CACHE) + set(GIT_HASH_CACHE "INVALID") + endif () + + # Only update the git_version.cpp if the hash has changed. This will + # prevent us from rebuilding the project more than we need to. + if (NOT ${GIT_HASH} STREQUAL ${GIT_HASH_CACHE} OR NOT EXISTS ${post_configure_file}) + # Set che GIT_HASH_CACHE variable the next build won't have + # to regenerate the source file. + CheckGitWrite(${GIT_HASH}) + + configure_file(${pre_configure_file} ${post_configure_file} @ONLY) + endif () + +endfunction() + +function(CheckGitSetup) + + add_custom_target(AlwaysCheckGit COMMAND ${CMAKE_COMMAND} + -DRUN_CHECK_GIT_VERSION=1 + -Dpre_configure_dir=${pre_configure_dir} + -Dpost_configure_file=${post_configure_dir} + -DGIT_HASH_CACHE=${GIT_HASH_CACHE} + -P ${CURRENT_LIST_DIR}/CheckGit.cmake + BYPRODUCTS ${post_configure_file} + ) + + add_library(git_version ${CMAKE_BINARY_DIR}/generated/git_version.cpp) + target_include_directories(git_version PUBLIC ${CMAKE_BINARY_DIR}/generated) + add_dependencies(git_version AlwaysCheckGit) + + CheckGitVersion() +endfunction() + +# This is used to run this function from an external cmake process. +if (RUN_CHECK_GIT_VERSION) + CheckGitVersion() +endif () diff --git a/cmake/FileEmbed.cmake b/cmake/FileEmbed.cmake new file mode 100644 index 00000000..2396f070 --- /dev/null +++ b/cmake/FileEmbed.cmake @@ -0,0 +1,89 @@ +function(FileEmbedSetup) + + if (NOT EXISTS ${CMAKE_BINARY_DIR}/file_embed) + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}file_embed) + endif () + + if (NOT EXISTS ${CMAKE_BINARY_DIR}/file_embed/file_embed_empty.c) + file(WRITE ${CMAKE_BINARY_DIR}/file_embed/file_embed_empty.c "") + endif () + + add_library(file_embed ${CMAKE_BINARY_DIR}/file_embed/file_embed_empty.c) + target_include_directories(file_embed PUBLIC ${CMAKE_BINARY_DIR}/file_embed) + +endfunction() + +function(FileEmbedAdd file) + FileEmbedGenerate(${file} var) + target_sources(file_embed PUBLIC ${var}) + + add_custom_command( + OUTPUT ${var} + COMMAND ${CMAKE_COMMAND} + -DRUN_FILE_EMBED_GENERATE=1 + -DFILE_EMBED_GENERATE_PATH=${file} + -P ${CMAKE_SOURCE_DIR}/cmake/FileEmbed.cmake + MAIN_DEPENDENCY ${file} + ) +endfunction() + +function(FileEmbedGenerate file generated_c) + + get_filename_component(base_filename ${file} NAME) + set(output_filename "${base_filename}.c") + string(MAKE_C_IDENTIFIER ${base_filename} c_name) + file(READ ${file} content HEX) + message(${content}) + + # Separate into individual bytes. + string(REGEX MATCHALL "([A-Fa-f0-9][A-Fa-f0-9])" SEPARATED_HEX ${content}) + + set(output_c "") + + set(counter 0) + foreach (hex IN LISTS SEPARATED_HEX) + string(APPEND output_c "0x${hex},") + MATH(EXPR counter "${counter}+1") + if (counter GREATER 16) + string(APPEND output_c "\n ") + set(counter 0) + endif () + endforeach () + + set(output_c " +#include \"${c_name}.h\" +uint8_t ${c_name}_data[] = { + ${output_c} +}\; +unsigned ${c_name}_size = sizeof(${c_name}_data)\; +") + + set(output_h " +#ifndef ${c_name}_H +#define ${c_name}_H +#include \"stdint.h\" +extern uint8_t ${c_name}_data[]\; +extern unsigned ${c_name}_size\; +#endif // ${c_name}_H + ") + + + if (NOT EXISTS ${CMAKE_BINARY_DIR}/file_embed) + file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}file_embed) + endif () + + + file(WRITE ${CMAKE_BINARY_DIR}/file_embed/${c_name}.c + ${output_c}) + + file(WRITE ${CMAKE_BINARY_DIR}/file_embed/${c_name}.h + ${output_h}) + + set(${generated_c} ${CMAKE_BINARY_DIR}/file_embed/${c_name}.c PARENT_SCOPE) + +endfunction() + +if (RUN_FILE_EMBED_GENERATE) + FileEmbedGenerate(${FILE_EMBED_GENERATE_PATH} var) +endif () + diff --git a/cmake/git_version.cpp.in b/cmake/git_version.cpp.in new file mode 100644 index 00000000..cee21e70 --- /dev/null +++ b/cmake/git_version.cpp.in @@ -0,0 +1,2 @@ +#include "git_version.h" +const char *kGitHash = "@GIT_HASH@"; diff --git a/cmake/git_version.h b/cmake/git_version.h new file mode 100644 index 00000000..04e8efa4 --- /dev/null +++ b/cmake/git_version.h @@ -0,0 +1,7 @@ +#ifndef GIT_VERSION_H +#define GIT_VERSION_H + +extern const char *kGitHash; + +#endif // GIT_VERSION_H + diff --git a/libsddc/CMakeLists.txt b/libsddc/CMakeLists.txt index 452f90e5..7faa6954 100644 --- a/libsddc/CMakeLists.txt +++ b/libsddc/CMakeLists.txt @@ -4,6 +4,12 @@ if (MSVC) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) endif (MSVC) + +include(../cmake/FileEmbed.cmake) + +FileEmbedSetup() +FileEmbedAdd(${CMAKE_SOURCE_DIR}/SDDC_FX3.img) + include_directories("." "../Core") add_library(sddc SHARED @@ -13,14 +19,15 @@ add_library(sddc SHARED if (MSVC) target_link_libraries(sddc PUBLIC Setupapi.lib) else() - target_include_directories(sddc PUBLIC "${LIBUSB_INCLUDE_DIR}") - target_link_directories(sddc PUBLIC "${LIBUSB_LIBRARY_DIRS}") + target_include_directories(sddc PUBLIC ${LIBUSB_INCLUDE_DIR}) + target_link_directories(sddc PUBLIC ${LIBUSB_LIBRARY_DIRS}) target_link_libraries(sddc PUBLIC ${LIBUSB_LIBRARIES}) endif (MSVC) -target_include_directories(sddc PUBLIC "${LIBFFTW_INCLUDE_DIR}") -target_link_directories(sddc PUBLIC "${LIBFFTW_LIBRARY_DIRS}") +target_include_directories(sddc PUBLIC ${LIBFFTW_INCLUDE_DIR}) +target_link_directories(sddc PUBLIC ${LIBFFTW_LIBRARY_DIRS}) target_link_libraries(sddc PUBLIC ${LIBFFTW_LIBRARIES}) +target_link_libraries(sddc PUBLIC file_embed) target_link_libraries(sddc PRIVATE SDDC_CORE) set_target_properties(sddc PROPERTIES VERSION ${PROJECT_VERSION}) diff --git a/libsddc/libsddc.cpp b/libsddc/libsddc.cpp index 2509f4ab..c2b6ffb7 100644 --- a/libsddc/libsddc.cpp +++ b/libsddc/libsddc.cpp @@ -2,6 +2,15 @@ #include "config.h" #include "r2iq.h" #include "RadioHandler.h" +#include "string.h" + +#include +#include + +extern "C" +{ + #include "SDDC_FX3_img.h" +} struct sddc { @@ -9,16 +18,26 @@ struct sddc RadioHandlerClass* handler; uint8_t led; int samplerateidx; - double freq; + uint64_t freq; + + std::vector frame_buffers; + size_t frame_size; sddc_read_async_cb_t callback; void *callback_context; }; sddc_t *current_running; +fx3class *Fx3 = NULL; +std::vector devices; +// Callback of data +// Fill the ring buffer static void Callback(void* context, const float* data, uint32_t len) { + struct sddc *sddc = (struct sddc *)context; + + sddc->callback(len, data, sddc->callback_context); } class rawdata : public r2iqControlClass { @@ -37,64 +56,109 @@ class rawdata : public r2iqControlClass { int idx; }; +static void probe_devices() +{ + if (Fx3) + return; + + if (Fx3 == NULL) + { + Fx3 = CreateUsbHandler(); + } + + unsigned char idx = 0; + char devicename[1024]; + while (Fx3->Enumerate(idx, devicename, SDDC_FX3_img_data, SDDC_FX3_img_size) && (idx < MAXNDEV)) + { + // https://en.wikipedia.org/wiki/West_Bridge + int retry = 2; + while ((strncmp("WestBridge", devicename,sizeof("WestBridge")) != 0) && retry-- > 0) + Fx3->Enumerate(idx, devicename, SDDC_FX3_img_data, SDDC_FX3_img_size); // if it enumerates as BootLoader retry + devices.push_back(devicename); + idx++; + } + +} + int sddc_get_device_count() { - return 1; + probe_devices(); + + return devices.size(); } int sddc_get_device_info(struct sddc_device_info **sddc_device_infos) { - auto ret = new sddc_device_info(); - const char *todo = "TODO"; - ret->manufacturer = todo; - ret->product = todo; - ret->serial_number = todo; + int count = 0; + *sddc_device_infos = new sddc_device_info[devices.size()]; + probe_devices(); + + for(auto &s : devices) + { + auto ret = &(*sddc_device_infos)[count]; + ret->manufacturer = "SDDC"; + + char *product = new char[256]; + auto len = strchr(s.c_str(), ' ') - s.c_str(); + strncpy(product, s.c_str(), len); + product[len] = '\0'; + ret->product = product; + + char *serial = new char[256]; + strcpy(serial, strstr(s.c_str(), "sn:") + 3); + ret->serial_number = serial; - *sddc_device_infos = ret; + count++; + } - return 1; + return sddc_get_device_count(); } int sddc_free_device_info(struct sddc_device_info *sddc_device_infos) { - delete sddc_device_infos; + for (int i = 0; i < sddc_get_device_count(); i++) + { + delete[] sddc_device_infos[i].product; + delete[] sddc_device_infos[i].serial_number; + } + + delete[] sddc_device_infos; return 0; } -sddc_t *sddc_open(int index, const char* imagefile) +sddc_t *sddc_open(int index) { auto ret_val = new sddc_t(); + probe_devices(); - fx3class *fx3 = CreateUsbHandler(); - if (fx3 == nullptr) - { + bool openOK = Fx3->Open(index, SDDC_FX3_img_data, SDDC_FX3_img_size); + if (!openOK) return nullptr; - } - // open the firmware - unsigned char* res_data; - uint32_t res_size; + ret_val->handler = new RadioHandlerClass(); - FILE *fp = fopen(imagefile, "rb"); - if (fp == nullptr) + if (ret_val->handler->Init(Fx3, Callback, nullptr, ret_val)) { - return nullptr; + ret_val->status = SDDC_STATUS_READY; + ret_val->samplerateidx = 0; } - fseek(fp, 0, SEEK_END); - res_size = ftell(fp); - res_data = (unsigned char*)malloc(res_size); - fseek(fp, 0, SEEK_SET); - if (fread(res_data, 1, res_size, fp) != res_size) - return nullptr; + return ret_val; +} + +/* +sddc_t *sddc_open_raw(int index) +{ + auto ret_val = new sddc_t(); + probe_devices(); - bool openOK = fx3->Open(res_data, res_size); + bool openOK = Fx3->Open(index, SDDC_FX3_img_data, SDDC_FX3_img_size); if (!openOK) return nullptr; ret_val->handler = new RadioHandlerClass(); - if (ret_val->handler->Init(fx3, Callback, new rawdata())) + if (ret_val->handler->Init(Fx3, Callback, new rawdata())) { ret_val->status = SDDC_STATUS_READY; ret_val->samplerateidx = 0; @@ -102,6 +166,7 @@ sddc_t *sddc_open(int index, const char* imagefile) return ret_val; } +*/ void sddc_close(sddc_t *that) { @@ -247,12 +312,12 @@ int sddc_set_adc_random(sddc_t *t, int random) } /* HF block functions */ -double sddc_get_hf_attenuation(sddc_t *t) +float sddc_get_hf_attenuation(sddc_t *t) { return 0; } -int sddc_set_hf_attenuation(sddc_t *t, double attenuation) +int sddc_set_hf_attenuation(sddc_t *t, float attenuation) { return 0; } @@ -272,45 +337,44 @@ int sddc_set_hf_bias(sddc_t *t, int bias) /* VHF block and VHF/UHF tuner functions */ double sddc_get_tuner_frequency(sddc_t *t) { - return t->freq; + return (double)t->freq; } int sddc_set_tuner_frequency(sddc_t *t, double frequency) { - t->freq = t->handler->TuneLO((int64_t)frequency); + t->freq = t->handler->TuneLO((uint64_t)frequency); return 0; } -int sddc_get_tuner_rf_attenuations(sddc_t *t, const double *attenuations[]) +int sddc_get_tuner_rf_attenuations(sddc_t *t, const float *attenuations[]) { return 0; } -double sddc_get_tuner_rf_attenuation(sddc_t *t) +float sddc_get_tuner_rf_attenuation(sddc_t *t) { return 0; } -int sddc_set_tuner_rf_attenuation(sddc_t *t, double attenuation) +int sddc_set_tuner_rf_attenuation(sddc_t *t, float attenuation) { - //TODO, convert double to index t->handler->UpdateattRF(5); return 0; } -int sddc_get_tuner_if_attenuations(sddc_t *t, const double *attenuations[]) +int sddc_get_tuner_if_attenuations(sddc_t *t, const float *attenuations[]) { // TODO return 0; } -double sddc_get_tuner_if_attenuation(sddc_t *t) +float sddc_get_tuner_if_attenuation(sddc_t *t) { return 0; } -int sddc_set_tuner_if_attenuation(sddc_t *t, double attenuation) +int sddc_set_tuner_if_attenuation(sddc_t *t, float attenuation) { return 0; } @@ -326,14 +390,19 @@ int sddc_set_vhf_bias(sddc_t *t, int bias) return 0; } -double sddc_get_sample_rate(sddc_t *t) +float sddc_get_sample_rate(sddc_t *t) { return 0; } -int sddc_set_sample_rate(sddc_t *t, double sample_rate) +int sddc_set_sample_rate(sddc_t *t, uint64_t sample_rate) { - switch((int64_t)sample_rate) + if (t->status != SDDC_STATUS_READY) + { + return ERROR_INVALID_STATE; + } + + switch(sample_rate) { case 32000000: t->samplerateidx = 0; diff --git a/libsddc/libsddc.h b/libsddc/libsddc.h index 3f2454cb..68961db5 100644 --- a/libsddc/libsddc.h +++ b/libsddc/libsddc.h @@ -66,6 +66,15 @@ enum LEDColors { BLUE_LED = 0x04 }; +// Success +#define ERROR_SUCCESS 0 + +// The operation failed due to invalid state of the device +#define ERROR_INVALID_STATE -1 + +// The operation failed due to invalid parameter +#define ERROR_INVALID_PARAMETER -2 + /* basic functions */ int sddc_get_device_count(); @@ -73,7 +82,7 @@ int sddc_get_device_info(struct sddc_device_info **sddc_device_infos); int sddc_free_device_info(struct sddc_device_info *sddc_device_infos); -sddc_t *sddc_open(int index, const char* imagefile); +sddc_t *sddc_open(int index); void sddc_close(sddc_t *t); @@ -111,9 +120,9 @@ int sddc_set_adc_random(sddc_t *t, int random); /* HF block functions */ -double sddc_get_hf_attenuation(sddc_t *t); +float sddc_get_hf_attenuation(sddc_t *t); -int sddc_set_hf_attenuation(sddc_t *t, double attenuation); +int sddc_set_hf_attenuation(sddc_t *t, float attenuation); int sddc_get_hf_bias(sddc_t *t); @@ -125,17 +134,17 @@ double sddc_get_tuner_frequency(sddc_t *t); int sddc_set_tuner_frequency(sddc_t *t, double frequency); -int sddc_get_tuner_rf_attenuations(sddc_t *t, const double *attenuations[]); +int sddc_get_tuner_rf_attenuations(sddc_t *t, const float *attenuations[]); -double sddc_get_tuner_rf_attenuation(sddc_t *t); +float sddc_get_tuner_rf_attenuation(sddc_t *t); -int sddc_set_tuner_rf_attenuation(sddc_t *t, double attenuation); +int sddc_set_tuner_rf_attenuation(sddc_t *t, float attenuation); -int sddc_get_tuner_if_attenuations(sddc_t *t, const double *attenuations[]); +int sddc_get_tuner_if_attenuations(sddc_t *t, const float *attenuations[]); -double sddc_get_tuner_if_attenuation(sddc_t *t); +float sddc_get_tuner_if_attenuation(sddc_t *t); -int sddc_set_tuner_if_attenuation(sddc_t *t, double attenuation); +int sddc_set_tuner_if_attenuation(sddc_t *t, float attenuation); int sddc_get_vhf_bias(sddc_t *t); @@ -143,12 +152,12 @@ int sddc_set_vhf_bias(sddc_t *t, int bias); /* streaming functions */ -typedef void (*sddc_read_async_cb_t)(uint32_t data_size, uint8_t *data, +typedef void (*sddc_read_async_cb_t)(uint32_t data_length, const float *data, void *context); -double sddc_get_sample_rate(sddc_t *t); +float sddc_get_sample_rate(sddc_t *t); -int sddc_set_sample_rate(sddc_t *t, double sample_rate); +int sddc_set_sample_rate(sddc_t *t, uint64_t sample_rate); int sddc_set_async_params(sddc_t *t, uint32_t frame_size, uint32_t num_frames, sddc_read_async_cb_t callback, diff --git a/libsddc/sddc_stream_test.c b/libsddc/sddc_stream_test.c index 042edecb..252afbf6 100644 --- a/libsddc/sddc_stream_test.c +++ b/libsddc/sddc_stream_test.c @@ -51,32 +51,36 @@ getFILETIMEoffset() return (t); } -int -clock_gettime(int X, struct timeval* tv) +int clock_gettime(int X, struct timeval *tv) { - LARGE_INTEGER t; - FILETIME f; - double microseconds; - static LARGE_INTEGER offset; - static double frequencyToMicroseconds; - static int initialized = 0; - static BOOL usePerformanceCounter = 0; - - if (!initialized) { + LARGE_INTEGER t; + FILETIME f; + double microseconds; + static LARGE_INTEGER offset; + static double frequencyToMicroseconds; + static int initialized = 0; + static BOOL usePerformanceCounter = 0; + + if (!initialized) + { LARGE_INTEGER performanceFrequency; initialized = 1; usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency); - if (usePerformanceCounter) { + if (usePerformanceCounter) + { QueryPerformanceCounter(&offset); frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.; } - else { + else + { offset = getFILETIMEoffset(); frequencyToMicroseconds = 10.; } } - if (usePerformanceCounter) QueryPerformanceCounter(&t); - else { + if (usePerformanceCounter) + QueryPerformanceCounter(&t); + else + { GetSystemTimeAsFileTime(&f); t.QuadPart = f.dwHighDateTime; t.QuadPart <<= 32; @@ -92,8 +96,7 @@ clock_gettime(int X, struct timeval* tv) } #endif - -static void count_bytes_callback(uint32_t data_size, uint8_t *data, +static void count_bytes_callback(uint32_t data_size, const float *data, void *context); static unsigned long long received_samples = 0; @@ -104,53 +107,58 @@ static int runtime = 3000; static struct timespec clk_start, clk_end; static int stop_reception = 0; -static double clk_diff() { - return ((double)clk_end.tv_sec + 1.0e-9*clk_end.tv_nsec) - - ((double)clk_start.tv_sec + 1.0e-9*clk_start.tv_nsec); +static double clk_diff() +{ + return ((double)clk_end.tv_sec + 1.0e-9 * clk_end.tv_nsec) - + ((double)clk_start.tv_sec + 1.0e-9 * clk_start.tv_nsec); } - int main(int argc, char **argv) { - if (argc < 3) { - fprintf(stderr, "usage: %s [ []\n", argv[0]); + if (argc < 2) + { + fprintf(stderr, "usage: %s [ []\n", argv[0]); return -1; } - char *imagefile = argv[1]; const char *outfilename = 0; double sample_rate = 0.0; - sscanf(argv[2], "%lf", &sample_rate); + sscanf(argv[1], "%lf", &sample_rate); + if (2 < argc) + runtime = atoi(argv[2]); if (3 < argc) - runtime = atoi(argv[3]); - if (4 < argc) - outfilename = argv[4]; + outfilename = argv[3]; - if (sample_rate <= 0) { + if (sample_rate <= 0) + { fprintf(stderr, "ERROR - given samplerate '%f' should be > 0\n", sample_rate); return -1; } int ret_val = -1; - sddc_t *sddc = sddc_open(0, imagefile); - if (sddc == 0) { + sddc_t *sddc = sddc_open(0); + if (sddc == 0) + { fprintf(stderr, "ERROR - sddc_open() failed\n"); return -1; } - if (sddc_set_sample_rate(sddc, sample_rate) < 0) { + if (sddc_set_sample_rate(sddc, sample_rate) < 0) + { fprintf(stderr, "ERROR - sddc_set_sample_rate() failed\n"); goto DONE; } - if (sddc_set_async_params(sddc, 0, 0, count_bytes_callback, sddc) < 0) { + if (sddc_set_async_params(sddc, 0, 0, count_bytes_callback, sddc) < 0) + { fprintf(stderr, "ERROR - sddc_set_async_params() failed\n"); goto DONE; } received_samples = 0; num_callbacks = 0; - if (sddc_start_streaming(sddc) < 0) { + if (sddc_start_streaming(sddc) < 0) + { fprintf(stderr, "ERROR - sddc_start_streaming() failed\n"); return -1; } @@ -159,7 +167,7 @@ int main(int argc, char **argv) total_samples = (unsigned long long)(runtime * sample_rate / 1000.0); if (outfilename) - sampleData = (int16_t*)malloc(total_samples * sizeof(int16_t)); + sampleData = (int16_t *)malloc(total_samples * sizeof(int16_t)); /* todo: move this into a thread */ stop_reception = 0; @@ -168,7 +176,8 @@ int main(int argc, char **argv) sddc_handle_events(sddc); fprintf(stderr, "finished. now stop streaming ..\n"); - if (sddc_stop_streaming(sddc) < 0) { + if (sddc_stop_streaming(sddc) < 0) + { fprintf(stderr, "ERROR - sddc_stop_streaming() failed\n"); return -1; } @@ -176,15 +185,17 @@ int main(int argc, char **argv) double dur = clk_diff(); fprintf(stderr, "received=%llu 16-Bit samples in %d callbacks\n", received_samples, num_callbacks); fprintf(stderr, "run for %f sec\n", dur); - fprintf(stderr, "approx. samplerate is %f kSamples/sec\n", received_samples / (1000.0*dur) ); + fprintf(stderr, "approx. samplerate is %f kSamples/sec\n", received_samples / (1000.0 * dur)); - if (outfilename && sampleData && received_samples) { - FILE * f = fopen(outfilename, "wb"); - if (f) { + if (outfilename && sampleData && received_samples) + { + FILE *f = fopen(outfilename, "wb"); + if (f) + { fprintf(stderr, "saving received real samples to file ..\n"); - waveWriteHeader( (unsigned)(0.5 + sample_rate), 0U /*frequency*/, 16 /*bitsPerSample*/, 1 /*numChannels*/, f); - for ( unsigned long long off = 0; off + 65536 < received_samples; off += 65536 ) - waveWriteSamples(f, sampleData + off, 65536, 0 /*needCleanData*/); + waveWriteHeader((unsigned)(0.5 + sample_rate), 0U /*frequency*/, 16 /*bitsPerSample*/, 1 /*numChannels*/, f); + for (unsigned long long off = 0; off + 65536 < received_samples; off += 65536) + waveWriteSamples(f, sampleData + off, 65536, 0 /*needCleanData*/); waveFinalizeHeader(f); fclose(f); } @@ -200,19 +211,27 @@ int main(int argc, char **argv) } static void count_bytes_callback(uint32_t data_size, - uint8_t *data, + const float *data, void *context) { if (stop_reception) return; ++num_callbacks; - unsigned N = data_size / sizeof(int16_t); - if ( received_samples + N < total_samples ) { + unsigned N = data_size * 2; + if (received_samples + N < total_samples) + { if (sampleData) - memcpy( sampleData+received_samples, data, data_size); + { + for (int i = 0; i < data_size * 2; i++) + { + sampleData[received_samples + i] = (int16_t)(data[i] * INT16_MAX); + } + } + received_samples += N; } - else { + else + { clock_gettime(CLOCK_REALTIME, &clk_end); stop_reception = 1; } diff --git a/libsddc/sddc_test.c b/libsddc/sddc_test.c index 6104e7b1..134f4f0a 100644 --- a/libsddc/sddc_test.c +++ b/libsddc/sddc_test.c @@ -25,25 +25,19 @@ #if _WIN32 #include -#define sleep(x) Sleep(x*1000) +#define sleep(x) Sleep(x * 1000) #else #include #endif static void blink_led(sddc_t *sddc, uint8_t color); - int main(int argc, char **argv) { - if (argc != 2) { - fprintf(stderr, "usage: %s \n", argv[0]); - return -1; - } - char *imagefile = argv[1]; - /* count devices */ int count = sddc_get_device_count(); - if (count < 0) { + if (count < 0) + { fprintf(stderr, "ERROR - sddc_get_device_count() failed\n"); return -1; } @@ -52,11 +46,13 @@ int main(int argc, char **argv) /* get device info */ struct sddc_device_info *sddc_device_infos; count = sddc_get_device_info(&sddc_device_infos); - if (count < 0) { + if (count < 0) + { fprintf(stderr, "ERROR - sddc_get_device_info() failed\n"); return -1; } - for (int i = 0; i < count; ++i) { + for (int i = 0; i < count; ++i) + { printf("%d - manufacturer=\"%s\" product=\"%s\" serial number=\"%s\"\n", i, sddc_device_infos[i].manufacturer, sddc_device_infos[i].product, sddc_device_infos[i].serial_number); @@ -64,8 +60,9 @@ int main(int argc, char **argv) sddc_free_device_info(sddc_device_infos); /* open and close device */ - sddc_t *sddc = sddc_open(0, imagefile); - if (sddc == 0) { + sddc_t *sddc = sddc_open(0); + if (sddc == 0) + { fprintf(stderr, "ERROR - sddc_open() failed\n"); return -1; } @@ -86,15 +83,18 @@ int main(int argc, char **argv) static void blink_led(sddc_t *sddc, uint8_t color) { - for (int i = 0; i < 5; ++i) { + for (int i = 0; i < 5; ++i) + { int ret = sddc_led_on(sddc, color); - if (ret < 0) { + if (ret < 0) + { fprintf(stderr, "ERROR - sddc_led_on(%02x) failed\n", color); return; } sleep(1); ret = sddc_led_off(sddc, color); - if (ret < 0) { + if (ret < 0) + { fprintf(stderr, "ERROR - sddc_led_off(%02x) failed\n", color); return; } diff --git a/libsddc/sddc_vhf_stream_test.c b/libsddc/sddc_vhf_stream_test.c index 4b8cda6a..4d1eb78d 100644 --- a/libsddc/sddc_vhf_stream_test.c +++ b/libsddc/sddc_vhf_stream_test.c @@ -51,32 +51,36 @@ getFILETIMEoffset() return (t); } -int -clock_gettime(int X, struct timeval* tv) +int clock_gettime(int X, struct timeval *tv) { - LARGE_INTEGER t; - FILETIME f; - double microseconds; - static LARGE_INTEGER offset; - static double frequencyToMicroseconds; - static int initialized = 0; - static BOOL usePerformanceCounter = 0; - - if (!initialized) { + LARGE_INTEGER t; + FILETIME f; + double microseconds; + static LARGE_INTEGER offset; + static double frequencyToMicroseconds; + static int initialized = 0; + static BOOL usePerformanceCounter = 0; + + if (!initialized) + { LARGE_INTEGER performanceFrequency; initialized = 1; usePerformanceCounter = QueryPerformanceFrequency(&performanceFrequency); - if (usePerformanceCounter) { + if (usePerformanceCounter) + { QueryPerformanceCounter(&offset); frequencyToMicroseconds = (double)performanceFrequency.QuadPart / 1000000.; } - else { + else + { offset = getFILETIMEoffset(); frequencyToMicroseconds = 10.; } } - if (usePerformanceCounter) QueryPerformanceCounter(&t); - else { + if (usePerformanceCounter) + QueryPerformanceCounter(&t); + else + { GetSystemTimeAsFileTime(&f); t.QuadPart = f.dwHighDateTime; t.QuadPart <<= 32; @@ -92,8 +96,7 @@ clock_gettime(int X, struct timeval* tv) } #endif - -static void count_bytes_callback(uint32_t data_size, uint8_t *data, +static void count_bytes_callback(uint32_t data_size, const float *data, void *context); static unsigned long long received_samples = 0; @@ -104,72 +107,80 @@ static int runtime = 3000; static struct timespec clk_start, clk_end; static int stop_reception = 0; -static double clk_diff() { - return ((double)clk_end.tv_sec + 1.0e-9*clk_end.tv_nsec) - - ((double)clk_start.tv_sec + 1.0e-9*clk_start.tv_nsec); +static double clk_diff() +{ + return ((double)clk_end.tv_sec + 1.0e-9 * clk_end.tv_nsec) - + ((double)clk_start.tv_sec + 1.0e-9 * clk_start.tv_nsec); } - int main(int argc, char **argv) { - if (argc < 3) { - fprintf(stderr, "usage: %s [ []\n", argv[0]); + if (argc < 2) + { + fprintf(stderr, "usage: %s [ []\n", argv[0]); return -1; } - char *imagefile = argv[1]; const char *outfilename = 0; - double sample_rate = 0.0; + uint64_t sample_rate = 0; double vhf_frequency = 100e6; - double vhf_attenuation = 20; /* 20dB attenuation */ + double vhf_attenuation = 20; /* 20dB attenuation */ - sscanf(argv[2], "%lf", &sample_rate); + sscanf(argv[1], "%ld", &sample_rate); if (3 < argc) - runtime = atoi(argv[3]); + runtime = atoi(argv[2]); if (4 < argc) - outfilename = argv[4]; + outfilename = argv[3]; - if (sample_rate <= 0) { - fprintf(stderr, "ERROR - given samplerate '%f' should be > 0\n", sample_rate); + if (sample_rate <= 0) + { + fprintf(stderr, "ERROR - given samplerate '%d' should be > 0\n", sample_rate); return -1; } int ret_val = -1; - sddc_t *sddc = sddc_open(0, imagefile); - if (sddc == 0) { + sddc_t *sddc = sddc_open(0); + if (sddc == 0) + { fprintf(stderr, "ERROR - sddc_open() failed\n"); return -1; } - if (sddc_set_sample_rate(sddc, sample_rate) < 0) { - fprintf(stderr, "ERROR - sddc_set_sample_rate() failed\n"); + if (sddc_set_rf_mode(sddc, VHF_MODE) < 0) + { + fprintf(stderr, "ERROR - sddc_set_rf_mode() failed\n"); goto DONE; } - if (sddc_set_async_params(sddc, 0, 0, count_bytes_callback, sddc) < 0) { - fprintf(stderr, "ERROR - sddc_set_async_params() failed\n"); + if (sddc_set_sample_rate(sddc, sample_rate) < 0) + { + fprintf(stderr, "ERROR - sddc_set_sample_rate() failed\n"); goto DONE; } - if (sddc_set_rf_mode(sddc, VHF_MODE) < 0) { - fprintf(stderr, "ERROR - sddc_set_rf_mode() failed\n"); + if (sddc_set_async_params(sddc, 0, 0, count_bytes_callback, sddc) < 0) + { + fprintf(stderr, "ERROR - sddc_set_async_params() failed\n"); goto DONE; } - if (sddc_set_tuner_frequency(sddc, vhf_frequency) < 0) { + if (sddc_set_tuner_frequency(sddc, vhf_frequency) < 0) + { fprintf(stderr, "ERROR - sddc_set_vhf_frequency() failed\n"); goto DONE; } - if (sddc_set_tuner_rf_attenuation(sddc, vhf_attenuation) < 0) { + if (sddc_set_tuner_rf_attenuation(sddc, vhf_attenuation) < 0) + { fprintf(stderr, "ERROR - sddc_set_tuner_rf_attenuation() failed\n"); goto DONE; } received_samples = 0; num_callbacks = 0; - if (sddc_start_streaming(sddc) < 0) { + if (sddc_start_streaming(sddc) < 0) + { fprintf(stderr, "ERROR - sddc_start_streaming() failed\n"); return -1; } @@ -178,7 +189,7 @@ int main(int argc, char **argv) total_samples = (unsigned long long)(runtime * sample_rate / 1000.0); if (outfilename) - sampleData = (int16_t*)malloc(total_samples * sizeof(int16_t)); + sampleData = (int16_t *)malloc(total_samples * sizeof(int16_t)); /* todo: move this into a thread */ stop_reception = 0; @@ -187,7 +198,8 @@ int main(int argc, char **argv) sddc_handle_events(sddc); fprintf(stderr, "finished. now stop streaming ..\n"); - if (sddc_stop_streaming(sddc) < 0) { + if (sddc_stop_streaming(sddc) < 0) + { fprintf(stderr, "ERROR - sddc_stop_streaming() failed\n"); return -1; } @@ -195,15 +207,17 @@ int main(int argc, char **argv) double dur = clk_diff(); fprintf(stderr, "received=%llu 16-Bit samples in %d callbacks\n", received_samples, num_callbacks); fprintf(stderr, "run for %f sec\n", dur); - fprintf(stderr, "approx. samplerate is %f kSamples/sec\n", received_samples / (1000.0*dur) ); + fprintf(stderr, "approx. samplerate is %f kSamples/sec\n", received_samples / (1000.0 * dur)); - if (outfilename && sampleData && received_samples) { - FILE * f = fopen(outfilename, "wb"); - if (f) { + if (outfilename && sampleData && received_samples) + { + FILE *f = fopen(outfilename, "wb"); + if (f) + { fprintf(stderr, "saving received real samples to file ..\n"); - waveWriteHeader( (unsigned)(0.5 + sample_rate), 0U /*frequency*/, 16 /*bitsPerSample*/, 1 /*numChannels*/, f); - for ( unsigned long long off = 0; off + 65536 < received_samples; off += 65536 ) - waveWriteSamples(f, sampleData + off, 65536, 0 /*needCleanData*/); + waveWriteHeader((unsigned)(0.5 + sample_rate), 0U /*frequency*/, 16 /*bitsPerSample*/, 1 /*numChannels*/, f); + for (unsigned long long off = 0; off + 65536 < received_samples; off += 65536) + waveWriteSamples(f, sampleData + off, 65536, 0 /*needCleanData*/); waveFinalizeHeader(f); fclose(f); } @@ -219,19 +233,27 @@ int main(int argc, char **argv) } static void count_bytes_callback(uint32_t data_size, - uint8_t *data, + const float *data, void *context) { if (stop_reception) return; ++num_callbacks; - unsigned N = data_size / sizeof(int16_t); - if ( received_samples + N < total_samples ) { + unsigned N = data_size * 2; + if (received_samples + N < total_samples) + { if (sampleData) - memcpy( sampleData+received_samples, data, data_size); + { + for (int i = 0; i < data_size * 2; i++) + { + sampleData[received_samples + i] = (int16_t)(data[i] * INT16_MAX); + } + } + received_samples += N; } - else { + else + { clock_gettime(CLOCK_REALTIME, &clk_end); stop_reception = 1; } diff --git a/libsddc/wavewrite.c b/libsddc/wavewrite.c index 0b3fb145..fa9f59d3 100644 --- a/libsddc/wavewrite.c +++ b/libsddc/wavewrite.c @@ -69,16 +69,16 @@ int waveHdrStarted = 0; static void waveSetCurrTime(Wind_SystemTime *p) { - struct timeval tv; + time_t rawtime; struct tm t; - gettimeofday(&tv, NULL); - p->wMilliseconds = tv.tv_usec / 1000; + time(&rawtime); + p->wMilliseconds = 0; #ifdef _WIN32 - t = *gmtime(&tv.tv_sec); + t = *gmtime(&rawtime); #else - gmtime_r(&tv.tv_sec, &t); + gmtime_r(&rawtime, &t); #endif p->wYear = t.tm_year + 1900; /* 1601 through 30827 */ diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index ebb07c78..1d7b8f38 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -17,8 +17,8 @@ file(GLOB UNITTESTS "./*.cpp") add_executable(unittest ${UNITTESTS}) add_dependencies(unittest LIBCPPUNIT) -target_include_directories(unittest PUBLIC "${LIBFFTW_INCLUDE_DIR}") -target_link_directories(unittest PUBLIC "${LIBFFTW_LIBRARY_DIRS}") +target_include_directories(unittest PUBLIC ${LIBFFTW_INCLUDE_DIR}) +target_link_directories(unittest PUBLIC ${LIBFFTW_LIBRARY_DIRS}) include_directories("." "../Core") include_directories(${LIBCPPUNIT_INCLUDE_DIRS}) diff --git a/unittest/core_test.cpp b/unittest/core_test.cpp index 7f30f23b..3d5f21d6 100644 --- a/unittest/core_test.cpp +++ b/unittest/core_test.cpp @@ -12,7 +12,7 @@ using namespace std::chrono; class fx3handler : public fx3class { - bool Open(const uint8_t* fw_data, uint32_t fw_size) + bool Open(int index, const uint8_t* fw_data, uint32_t fw_size) { return true; }