diff --git a/.github/workflows/deploy-pypi-testing.yml b/.github/workflows/deploy-pypi-testing.yml index a169605..a72d1bd 100644 --- a/.github/workflows/deploy-pypi-testing.yml +++ b/.github/workflows/deploy-pypi-testing.yml @@ -7,9 +7,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python 3.7 - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: 3.7 diff --git a/.github/workflows/doc.yml b/.github/workflows/doc.yml index 0c5892d..ee09cd5 100644 --- a/.github/workflows/doc.yml +++ b/.github/workflows/doc.yml @@ -7,11 +7,11 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - name: Set up Python 3.7 - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - name: Set up Python 3.10 + uses: actions/setup-python@v5 with: - python-version: 3.7 + python-version: '3.10' - name: Install dependencies run: | @@ -23,6 +23,15 @@ jobs: mkdir -p build cd build cmake .. -DBUILD_DOC=ON + make genalyzer -j4 + sudo make install genalyzer + sudo ldconfig + cd ../bindings/python + pip install ".[tools]" + cd ../../build + sudo rm -rf * + sudo rm ../doc/reference_simplified.md + cmake .. -DBUILD_DOC=ON make Sphinx @@ -32,11 +41,11 @@ jobs: if: github.ref == 'refs/heads/main' steps: - - uses: actions/checkout@v2 - - name: Set up Python 3.7 - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - name: Set up Python 3.10 + uses: actions/setup-python@v5 with: - python-version: 3.7 + python-version: '3.10' - name: Install dependencies run: | diff --git a/.github/workflows/test-win.yml b/.github/workflows/test-win.yml index 704c0a8..d1417ef 100644 --- a/.github/workflows/test-win.yml +++ b/.github/workflows/test-win.yml @@ -7,9 +7,9 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python 3.7 - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: 3.7 @@ -54,7 +54,7 @@ jobs: ctest -V -C Release - name: Archive generated DLLs - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: DLLs path: src\Release\ @@ -63,9 +63,9 @@ jobs: runs-on: windows-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python 3.7 - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: 3.7 @@ -113,13 +113,13 @@ jobs: shell: cmd - name: Archive Windows exe installer - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: EXE-Installer path: C:\genalyzer-setup.exe - name: Download artifact installer - uses: actions/download-artifact@v1 + uses: actions/download-artifact@v4 with: name: EXE-Installer path: win_build diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 94b6835..fce8567 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -20,9 +20,9 @@ jobs: container: image: ${{ matrix.images }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python 3.7 - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: 3.7 @@ -42,11 +42,11 @@ jobs: cp build/bindings/c/src/libgenalyzer.so* libs/ cp build/src/libgenalyzer_plus_plus.a* libs/ cp bindings/c/include/cgenalyzer.h libs/ - cp bindings/c/include/cgenalyzer_advanced.h libs/ + cp bindings/c/include/cgenalyzer_simplified_beta.h libs/ cp bindings/matlab/genalyzer.m libs/ - name: Archive generated SOs - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: ${{ matrix.label }}-Build path: libs/ @@ -61,7 +61,7 @@ jobs: # container: # image: ${{ matrix.images }} # steps: -# - uses: actions/checkout@v2 +# - uses: actions/checkout@v4 # - name: Install dependencies # run: | # bash ./.github/scripts/install_dependencies_rhel.sh @@ -78,11 +78,11 @@ jobs: # cp build/bindings/c/src/libgenalyzer.so* libs/ # cp build/src/libgenalyzer_plus_plus.a* libs/ # cp bindings/c/include/cgenalyzer.h libs/ -# cp bindings/c/include/cgenalyzer_advanced.h libs/ +# cp bindings/c/include/cgenalyzer_simplified_beta.h libs/ # cp bindings/matlab/genalyzer.m libs/ # - name: Archive generated SOs -# uses: actions/upload-artifact@v2 +# uses: actions/upload-artifact@v4 # with: # name: RHEL_7-Build # path: libs/ @@ -91,9 +91,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python 3.7 - uses: actions/setup-python@v2 + uses: actions/setup-python@v3 with: python-version: 3.7 @@ -111,7 +111,7 @@ jobs: make coverage - name: Coveralls - uses: coverallsapp/github-action@v1 + uses: coverallsapp/github-action@v2 with: path-to-lcov: build/main_coverage.info @@ -119,9 +119,9 @@ jobs: runs-on: macos-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python 3.8 - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: 3.8 @@ -143,9 +143,9 @@ jobs: python-version: [3.7, 3.8, 3.9] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} diff --git a/bindings/c/include/CMakeLists.txt b/bindings/c/include/CMakeLists.txt index 76fc3a2..b6425b6 100644 --- a/bindings/c/include/CMakeLists.txt +++ b/bindings/c/include/CMakeLists.txt @@ -1 +1 @@ -install(FILES cgenalyzer.h cgenalyzer_advanced.h DESTINATION include/) +install(FILES cgenalyzer_simplified_beta.h cgenalyzer.h DESTINATION include/) diff --git a/bindings/c/include/cgenalyzer.h b/bindings/c/include/cgenalyzer.h index f1c20cf..4881829 100644 --- a/bindings/c/include/cgenalyzer.h +++ b/bindings/c/include/cgenalyzer.h @@ -2,7 +2,7 @@ * cgenalyzer - genalyzer API header file * * Copyright (C) 2022 Analog Devices, Inc. - * Author: Srikanth Pagadarai + * Author: Peter Derounian * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -22,13 +22,148 @@ #ifndef CGENALYZER_H #define CGENALYZER_H -#include "cgenalyzer_advanced.h" -#include -#include +#include +#include +#include + +/** + * \mainpage Genalyzer Library API Documentation + * \section Overview + * The Genalyzer Library provides analysis routines for data converter testing. The + * library contains routines that analyze waveforms, FFTs, and the output of the traditional code + * density tests: histogram, DNL, and INL. In addition, the library provides basic signal + * generation and processing utilties. + * \section AnalysisRoutines Analysis Routines + * The library provides the following types of analysis: + * \li \ref gn_dnl_analysis "DNL Analysis" + * \li \ref gn_fft_analysis "Fourier Analysis" + * \li \ref gn_hist_analysis "Histogram Analysis" + * \li \ref gn_inl_analysis "INL Analysis" + * \li \ref gn_wf_analysis "Waveform Analysis" + * + * Each analysis routine returns results by filling a Keys array (rkeys) and a corresponding Values + * array (rvalues). Together, rkeys and rvalues represent a set of key-value result pairs: + * rkeys[0] corresponds to rvalues[0], rkeys[1] to rvalues[1], and so on. + */ + +/* Enumerations */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \defgroup Enumerations Enumerations + * @{ + */ + +/** + * @brief GnAnalysisType enumerates analysis types + */ +typedef enum GnAnalysisType { + GnAnalysisTypeDNL, ///< DNL (differential nonlinearity) + GnAnalysisTypeFourier, ///< Fourier (FFT) + GnAnalysisTypeHistogram, ///< Histogram + GnAnalysisTypeINL, ///< INL (integral nonlinearity) + GnAnalysisTypeWaveform ///< Waveform + } GnAnalysisType; + +/** + * @brief GnCodeFormat enumerates binary code formats + */ +typedef enum GnCodeFormat { + GnCodeFormatOffsetBinary, ///< Offset Binary + GnCodeFormatTwosComplement ///< Two's Complement + } GnCodeFormat; + +/** + * @brief GnDnlSignal enumerates signal types for which DNL can be computed + */ +typedef enum GnDnlSignal { + GnDnlSignalRamp, ///< Ramp + GnDnlSignalTone ///< Tone (Sinusoid) + } GnDnlSignal; + +/** + * @brief GnFACompTag enumerates Fourier analysis component tags + */ +typedef enum GnFACompTag { + GnFACompTagDC, ///< DC component (always Bin 0) + GnFACompTagSignal, ///< Signal component + GnFACompTagHD, ///< Harmonic distortion + GnFACompTagIMD, ///< Intermodulation distortion + GnFACompTagILOS, ///< Interleaving offset component + GnFACompTagILGT, ///< Interleaving gain/timing/BW component + GnFACompTagCLK, ///< Clock component + GnFACompTagUserDist, ///< User-designated distortion + GnFACompTagNoise ///< Noise component (e.g. WorstOther) + } GnFACompTag; + +/** + * @brief GnFASsb enumerates the component categories for which the number of single side bins + * (SSB) can be set + */ +typedef enum GnFASsb { + GnFASsbDefault, ///< Default SSB (applies to auto-generated components) + GnFASsbDC, ///< SSB for DC component + GnFASsbSignal, ///< SSB for Signal components + GnFASsbWO, ///< SSB for WorstOther components + } GnFASsb; + +/** + * @brief GnFreqAxisFormat enumerates frequency axis formats + */ +typedef enum GnFreqAxisFormat { + GnFreqAxisFormatBins, ///< Bins + GnFreqAxisFormatFreq, ///< Frequency + GnFreqAxisFormatNorm ///< Normalized + } GnFreqAxisFormat; + +/** + * @brief GnFreqAxisType enumerates frequency axis types + */ +typedef enum GnFreqAxisType { + GnFreqAxisTypeDcCenter, ///< DC centered, e.g. [-fs/2, fs/2) (complex FFT only) + GnFreqAxisTypeDcLeft, ///< DC on left, e.g. [0, fs) (complex FFT only) + GnFreqAxisTypeReal ///< Real axis, e.g. [0, fs/2] (real FFT only) + } GnFreqAxisType; + +/** + * @brief GnInlLineFit enumerates INL line fitting options + */ +typedef enum GnInlLineFit { + GnInlLineFitBestFit, ///< Best fit + GnInlLineFitEndFit, ///< End fit + GnInlLineFitNoFit ///< No fit + } GnInlLineFit; + +/** + * @brief GnRfftScale enumerates real FFT scaling options + */ +typedef enum GnRfftScale { + GnRfftScaleDbfsDc, ///< Full-scale sinusoid measures -3 dBFS + GnRfftScaleDbfsSin, ///< Full-scale sinusoid measures 0 dBFS + GnRfftScaleNative ///< Full-scale sinusoid measures -6 dBFS + } GnRfftScale; + +/** + * @brief GnWindow enumerates window functions + */ +typedef enum GnWindow { + GnWindowBlackmanHarris, ///< Blackman-Harris + GnWindowHann, ///< Hann ("Hanning") + GnWindowNoWindow ///< No window (Rectangular) + } GnWindow; + +/** @} Enumerations */ + +#ifdef __cplusplus +} // extern "C" +#endif + +/* API Utilities */ #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif #ifdef _WIN32 @@ -43,583 +178,1719 @@ extern "C" #else #define __api #endif - - // opaque pointer - typedef struct gn_config_private *gn_config; - typedef enum tone_type - { - REAL_COSINE, - REAL_SINE, - COMPLEX_EXP - } tone_type; +/** + * \defgroup APIUtilities API Utilities + * @{ + */ - /** - * @brief free memory for configuration struct - * @return 0 on success, non-zero otherwise - * @param c genalyzer Configuration struct - */ - __api int gn_config_free( - gn_config *c - ); +/** + * @brief gn_analysis_results_key_sizes + * @return 0 on success, non-zero otherwise + * @details The library string termination setting determines whether or not a null terminator + * is included in the key sizes. See \ref gn_set_string_termination. + */ +__api int gn_analysis_results_key_sizes( + size_t* key_sizes, ///< [out] Key size array pointer + size_t key_sizes_size, ///< [in] Key size array size + GnAnalysisType type ///< [in] Analysis type + ); - /** - * @brief set configuration struct member: tone_type - * @return 0 on success, non-zero otherwise - * @param ttype ENUM value to indicate input tone type. Options: REAL_COSINE, REAL_SINE, COMPLEX_EXP - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_ttype( - tone_type ttype, - gn_config *c - ); +/** + * @brief gn_analysis_results_size + * @return 0 on success, non-zero otherwise + */ +__api int gn_analysis_results_size( + size_t* size, ///< [out] Number of key-value result pairs + GnAnalysisType type ///< [in] Analysis type + ); - /** - * @brief set configuration struct member: npts - * @return 0 on success, non-zero otherwise - * @param npts Number of sample points in the generated waveform - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_npts( - size_t npts, - gn_config *c - ); +/** + * @brief gn_enum_value + * @return 0 on success, non-zero otherwise + */ +__api int gn_enum_value( + int* value, ///< [out] Underlying value of enumeration::enumerator + const char* enumeration, ///< [in] Enumeration name + const char* enumerator ///< [in] Enumerator name + ); - /** - * @brief get configuration struct member: npts - * @return 0 on success, non-zero otherwise - * @param npts Number of sample points in the generated waveform - * @param c genalyzer Configuration struct - */ - __api int gn_config_get_npts( - size_t *npts, - gn_config *c - ); +/** + * @brief gn_error_check + * @return Always returns 0 + */ +__api int gn_error_check( + bool* error ///< [out] true if an error has occurred; false otherwise +); - /** - * @brief set configuration struct member: sample_rate - * @return 0 on success, non-zero otherwise - * @param sample_rate Input Sample rate of the data converter - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_sample_rate( - double sample_rate, - gn_config *c - ); +/** + * @brief gn_error_clear + * @return Always returns 0 + */ +__api int gn_error_clear(); - /** - * @brief get configuration struct member: sample_rate - * @return 0 on success, non-zero otherwise - * @param sample_rate Input Sample rate of the data converter - * @param c genalyzer Configuration struct - */ - __api int gn_config_get_sample_rate( - double *sample_rate, - gn_config *c - ); +/** + * @brief gn_error_string + * @return 0 on success, non-zero otherwise + */ +__api int gn_error_string( + char* buf, ///< [out] Pointer to character array + size_t size ///< [in] Size of character array + ); - /** - * @brief set configuration struct member: data_rate - * @return 0 on success, non-zero otherwise - * @param data_rate Input data rate of the data converter - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_data_rate( - double data_rate, - gn_config *c - ); +/** + * @brief gn_set_string_termination + * @return Always returns 0 + * @details Some functions in this library return strings by filling character buffers (arrays) + * provided by the caller. This function sets a global library setting that determines whether or + * not strings should be null-terminated. If set to true, functions that return strings will + * write a '\0' as the last character. In addition, functions that return the size of a string + * will include the null terminator in the size. + */ +__api int gn_set_string_termination( + bool null_terminated ///< [in] If true, strings are terminated with '\0' +); - /** - * @brief set configuration struct member: shift_freq - * @return 0 on success, non-zero otherwise - * @param shift_freq Shift frequency of the data converter - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_shift_freq( - double shift_freq, - gn_config *c - ); +/** + * @brief gn_version_string + * @return 0 on success, non-zero otherwise + */ +__api int gn_version_string( + char* buf, ///< [in,out] Pointer to character array + size_t size ///< [in] Size of character array + ); - /** - * @brief set configuration struct member: num_tones - * @return 0 on success, non-zero otherwise - * @param num_tones Number of tones to generate - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_num_tones( - size_t num_tones, - gn_config *c - ); +/** + * \defgroup APIUtilityHelpers Helpers + * @{ + */ - /** - * @brief set configuration struct member: tone_freq - * @return 0 on success, non-zero otherwise - * @param tone_freq Input array of tone frequencies to generate - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_tone_freq( - double *tone_freq, - gn_config *c - ); +/** + * @brief gn_error_string_size + * @return Always returns 0 + * @details The library string termination setting determines whether or not a null terminator + * is included in the size. See \ref gn_set_string_termination. + */ +__api int gn_error_string_size( + size_t* size ///< [out] Number of characters in error string +); - /** - * @brief set configuration struct member: tone_ampl - * @return 0 on success, non-zero otherwise - * @param tone_ampl Input array of tone scales to generate - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_tone_ampl( - double *tone_ampl, - gn_config *c - ); +/** + * @brief gn_version_string_size + * @return Always returns 0 + * @details The library string termination setting determines whether or not a null terminator + * is included in the size. See \ref gn_set_string_termination. + */ +__api int gn_version_string_size( + size_t* size ///< [out] Number of characters in version string +); - /** - * @brief set configuration struct member: tone_phase - * @return 0 on success, non-zero otherwise - * @param tone_phase Input array of tone phases to generate - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_tone_phase( - double *tone_phase, - gn_config *c - ); +/** @} APIUtilityHelpers */ - /** - * @brief set configuration struct member: fsr - * @return 0 on success, non-zero otherwise - * @param fsr Full-scale range of the waveform - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_fsr( - double fsr, - gn_config *c - ); +/** @} APIUtilities */ - /** - * @brief set configuration struct member: qres - * @return 0 on success, non-zero otherwise - * @param qres Quantization resolution - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_qres( - int qres, - gn_config *c - ); +#ifdef __cplusplus +} // extern "C" +#endif - /** - * @brief set configuration struct member: noise_rms - * @return 0 on success, non-zero otherwise - * @param qres Quantization noise - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_noise_rms( - double noise_rms, - gn_config *c - ); +/* Array Operations */ +#ifdef __cplusplus +extern "C" { +#endif - /** - * @brief set configuration struct member: code_format - * @return 0 on success, non-zero otherwise - * @param code_format Code format of data - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_code_format( - GnCodeFormat code_format, - gn_config *c - ); +/** + * \defgroup ArrayOperations Array Operations + * @{ + */ - /** - * @brief set configuration struct member: nfft - * @return 0 on success, non-zero otherwise - * @param nfft FFT order - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_nfft( - size_t nfft, - gn_config *c - ); +/** + * @brief gn_abs + * @return 0 on success, non-zero otherwise + */ +__api int gn_abs( + double* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double* in, ///< [in] Input array pointer + size_t in_size ///< [in] Input array size + ); - /** - * @brief get configuration struct member: nfft - * @return 0 on success, non-zero otherwise - * @param nfft FFT order - * @param c genalyzer Configuration struct - */ - __api int gn_config_get_nfft( - size_t *nfft, - gn_config *c - ); - - /** - * @brief set configuration struct member: navg - * @return 0 on success, non-zero otherwise - * @param navg Num. of FFTs to average - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_fft_navg( - size_t fft_navg, - gn_config *c - ); - - /** - * @brief set configuration struct member: win - * @return 0 on success, non-zero otherwise - * @param win Window function used - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_win( - GnWindow win, - gn_config *c - ); - - /** - * @brief set configuration struct member: ssb_fund - * @return 0 on success, non-zero otherwise - * @param ssb_fund Single side bin fundamental - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_ssb_fund( - int ssb_fund, - gn_config *c - ); +/** + * @brief gn_angle + * @return 0 on success, non-zero otherwise + */ +__api int gn_angle( + double* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double* in, ///< [in] Input array pointer + size_t in_size ///< [in] Input array size + ); - /** - * @brief set configuration struct member: ssb_rest - * @return 0 on success, non-zero otherwise - * @param ssb_rest Single side bins rest - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_ssb_rest( - int ssb_rest, - gn_config *c - ); +/** + * @brief gn_db + * @return 0 on success, non-zero otherwise + */ +__api int gn_db( + double* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double* in, ///< [in] Input array pointer + size_t in_size ///< [in] Input array size + ); - /** - * @brief set configuration struct member: max_harm_order - * @return 0 on success, non-zero otherwise - * @param max_harm_order Max order of harmonic - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_max_harm_order( - int max_harm_order, - gn_config *c - ); +/** + * @brief gn_db10 + * @return 0 on success, non-zero otherwise + */ +__api int gn_db10( + double* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double* in, ///< [in] Input array pointer + size_t in_size ///< [in] Input array size + ); - /** - * @brief set configuration struct member: dnla_signal_type - * @return 0 on success, non-zero otherwise - * @param dnla_signal_type DNL analysis signal type - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_dnla_signal_type( - GnDnlSignal dnla_signal_type, - gn_config *c - ); +/** + * @brief gn_db20 + * @return 0 on success, non-zero otherwise + */ +__api int gn_db20( + double* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double* in, ///< [in] Input array pointer + size_t in_size ///< [in] Input array size + ); - /** - * @brief set configuration struct member: inla_fit - * @return 0 on success, non-zero otherwise - * @param inla_fit INL analysis line fit - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_inla_fit( - GnInlLineFit inla_fit, - gn_config *c - ); +/** + * @brief gn_norm + * @return 0 on success, non-zero otherwise + */ +__api int gn_norm( + double* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double* in, ///< [in] Input array pointer + size_t in_size ///< [in] Input array size + ); - /** - * @brief set configuration struct member: ramp_start - * @return 0 on success, non-zero otherwise - * @param ramp_start start value of ramp - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_ramp_start( - double ramp_start, - gn_config *c - ); - - /** - * @brief set configuration struct member: ramp_stop - * @return 0 on success, non-zero otherwise - * @param ramp_stop stop value of ramp - * @param c genalyzer Configuration struct - */ - __api int gn_config_set_ramp_stop( - double ramp_stop, - gn_config *c - ); - - /** - * @brief get configuration struct member: _code_density_size - * @return 0 on success, non-zero otherwise - * @param ramp_stop stop value of ramp - * @param c genalyzer Configuration struct - */ - __api int gn_config_get_code_density_size( - size_t *code_density_size, - gn_config *c - ); +/** @} ArrayOperations */ - /** - * @brief Configure tone parameters to be used in measurement - * @return 0 on success, non-zero otherwise - * @param ttype ENUM value to indicate input tone type. Options: REAL_COSINE, REAL_SINE, COMPLEX_EXP - * @param npts Number of sample points in the generated waveform - * @param sample_rate Input Sample rate of the data converter - * @param num_tones Number of tones to generate - * @param tone_freq Input array of tone frequencies to generate - * @param tone_ampl Input array of tone scales to generate - * @param tone_phase Input array of tone phases to generate - * @param c Configuration struct containing tone parameters - */ - __api int gn_config_gen_tone ( - tone_type ttype, - size_t npts, - double sample_rate, - size_t num_tones, - double *tone_freq, - double *tone_ampl, - double *tone_phase, - gn_config *c - ); +#ifdef __cplusplus +} // extern "C" +#endif - /** - * @brief Configure tone parameters to be used in measurement - * @return 0 on success, non-zero otherwise - * @param npts Number of sample points in the generated waveform - * @param ramp_start Input start value of ramp - * @param ramp_stop Input stop value of ramp - * @param c Configuration struct containing ramp parameters - */ - __api int gn_config_gen_ramp( - size_t npts, - double ramp_start, - double ramp_stop, - gn_config *c - ); +/* Code Density */ +#ifdef __cplusplus +extern "C" { +#endif - /** - * @brief Configure quantization parameters to be used in measurement - * @return 0 on success, non-zero otherwise - * @param npts Number of sample points in the generated waveform - * @param fsr Full-scale range of the waveform - * @param qres Quantization resolution - * @param qnoise Quantization noise - * @param c Configuration structure - */ - __api int gn_config_quantize( - size_t npts, - double fsr, - int qres, - double qnoise, - gn_config *c - ); +/** + * \defgroup CodeDensity Code Density + * @{ + */ - /** - * @brief Configure parameters to compute histogram - * @return 0 on success, non-zero otherwise - * @param npts Number of sample points in the generated waveform - * @param qres Quantization resolution - * @param c Configuration structure - */ - __api int gn_config_histz_nla( - size_t npts, - int qres, - gn_config *c - ); +/** + * @brief gn_code_axis + * @return 0 on success, non-zero otherwise + */ +__api int gn_code_axis( + double* out, ///< [out] Array pointer + size_t size, ///< [in] Array size + int n, ///< [in] Resolution + GnCodeFormat format ///< [in] Code format + ); - /** - * @brief Configure FFT parameters - * @return 0 on success, non-zero otherwise - */ - __api int gn_config_fftz( - size_t npts, ///< [npts] Number of sample points in the input waveform - int qres, ///< [qres] Quantization resolution - size_t navg, ///< [navg] Number of FFT averages - size_t nfft, ///< [nfft] FFT order - GnWindow win, ///< [win] Window function to apply, Options: GnWindowBlackmanHarris, GnWindowHann, GnWindowNoWindow - gn_config *c ///< [c] Configuration structure containing test parameters - ); +/** + * @brief gn_code_axisx + * @return 0 on success, non-zero otherwise + */ +__api int gn_code_axisx( + double* out, ///< [out] Array pointer + size_t size, ///< [in] Array size + int64_t min, ///< [in] Min code + int64_t max ///< [in] Max code + ); - /** - * @brief Generate sinusoidal tone based on supplied configuration. - * @return 0 on success, non-zero otherwise - */ - __api int gn_config_fa( - double fixed_tone_freq, ///< [fixed_tone_freq] Fixed tone frequency - gn_config *c ///< [c] Configuration structure containing test parameters - ); +/** + * @brief gn_dnl + * @return 0 on success, non-zero otherwise + */ +__api int gn_dnl( + double* dnl, ///< [out] Output array pointer + size_t dnl_size, ///< [in] Output array size + const uint64_t* hist, ///< [in] Input array pointer + size_t hist_size, ///< [in] Input array size + GnDnlSignal type ///< [in] Signal type + ); - /** - * @brief Generate sinusoidal tone based on supplied configuration without specifying tone manually. - * @return 0 on success, non-zero otherwise - */ - __api int gn_config_fa_auto( - uint8_t ssb_width, ///< [ssb_width] Number of bins to use for fundamental search and keepout of other tones - gn_config *c ///< [c] Configuration structure containing test parameters - ); - - /** - * @brief Generate ramp based on supplied configuration. - * @param out Output array of ramp generated - * @param c Configuration structure of test and waveform to generate - */ - __api int gn_gen_ramp( - double **out, - gn_config *c - ); - - /** - * @brief Generate sinusoidal tone based on supplied configuration. - * @return 0 on success, non-zero otherwise - * @param out Output array of generated tone - * @param c Configuration structure containing test parameters - */ - __api int gn_gen_real_tone( - double **out, - gn_config *c - ); +/** + * @brief gn_dnl_analysis + * @return 0 on success, non-zero otherwise + * @details The results contain the following key-value pairs (see general description of + * \ref AnalysisRoutines "Analysis Routines"). + * + *
Key Description + *
min Minumum value + *
max Maximum value + *
avg Average value + *
rms RMS value + *
min_index Index of first occurence of minimum value + *
max_index Index of first occurence of maximum value + *
first_nm_index Index of first non-missing code + *
last_nm_index Index of last non-missing code + *
nm_range Non-missing code range (1 + (last_nm_index - first_nm_index)) + *
+ */ +__api int gn_dnl_analysis( + char** rkeys, ///< [out] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + double* rvalues, ///< [out] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const double* dnl, ///< [in] Input array pointer + size_t dnl_size ///< [in] Input array size + ); - /** - * @brief Generate sinusoidal tone based on supplied configuration. - * @return 0 on success, non-zero otherwise - * @param outi In-phase output array of generated tone - * @param outq Quadrature output array of generated tone - * @param c Configuration structure containing test parameters - */ - __api int gn_gen_complex_tone( - double **outi, - double **outq, - gn_config *c - ); +/** + * @brief gn_hist16 + * @return 0 on success, non-zero otherwise + */ +__api int gn_hist16( + uint64_t* hist, ///< [out] Histogram array pointer + size_t hist_size, ///< [in] Histogram array size + const int16_t* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int n, ///< [in] Code width (i.e. ADC resolution) + GnCodeFormat format, ///< [in] Code format + bool preserve ///< [in] If true, hist is not cleared before computing the histogram + ); - /** - * @brief Quantize waveform based on supplied configuration. - * @return 0 on success, non-zero otherwise - */ - __api int gn_quantize( - int32_t **out, ///< [out] Quantized output waveform - const double *in, ///< [in] Input waveform to be quantized - gn_config *c ///< [c] Configuration structure containing test parameters - ); - /** - * @brief Compute FFT of quantized input waveform +/** + * @brief gn_hist32 * @return 0 on success, non-zero otherwise */ - __api int gn_fftz( - double **out, ///< [out] Interleaved Re/Im FFT output - const int32_t *in_i, ///< [in_i] In-phase input - const int32_t *in_q, ///< [in_q] Quadrature input - gn_config *c ///< [c] Configuration structure containing test parameters - ); +__api int gn_hist32( + uint64_t* hist, ///< [out] Histogram array pointer + size_t hist_size, ///< [in] Histogram array size + const int32_t* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int n, ///< [in] Code width (i.e. ADC resolution) + GnCodeFormat format, ///< [in] Code format + bool preserve ///< [in] If true, hist is not cleared before computing the histogram + ); - /** - * @brief Compute histogram of quantized waveform - * @return 0 on success, non-zero otherwise - */ - __api int gn_histz( - uint64_t **hist, ///< [hist] Output - Histogram of input quantized waveform - size_t *hist_len, ///< [hist_len] Output - Histogram size - const int32_t *qwf, ///< [qwf] Input - Quantized input waveform - gn_config *c ///< [c] Input - Configuration structure containing test parameters - ); +/** + * @brief gn_hist64 + * @return 0 on success, non-zero otherwise + */ +__api int gn_hist64( + uint64_t* hist, ///< [out] Histogram array pointer + size_t hist_size, ///< [in] Histogram array size + const int64_t* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int n, ///< [in] Code width (i.e. ADC resolution) + GnCodeFormat format, ///< [in] Code format + bool preserve ///< [in] If true, hist is not cleared before computing the histogram + ); - /** - * @brief Compute histogram of quantized waveform - * @return 0 on success, non-zero otherwise - */ - __api int gn_dnlz( - double **dnl, - size_t *dnl_len, - const uint64_t *hist, - gn_config *c - ); +/** + * @brief gn_histx16 + * @return 0 on success, non-zero otherwise + */ +__api int gn_histx16( + uint64_t* hist, ///< [out] Histogram array pointer + size_t hist_size, ///< [in] Histogram array size + const int16_t* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int64_t min, ///< [in] Min code + int64_t max, ///< [in] Max code + bool preserve ///< [in] If true, hist is not cleared before computing the histogram + ); - /** - * @brief Compute histogram of quantized waveform - * @return 0 on success, non-zero otherwise - */ - - __api int gn_inlz( - double **inl, - size_t *inl_len, - const double *dnl, - gn_config *c - ); - - /** - * @brief Do waveform analysis and all get results - * @return 0 on success, non-zero otherwise - */ - __api int gn_get_wfa_results( - char ***rkeys, - double **rvalues, - size_t *results_size, ///< [results_size] size of results - const int32_t *qwf, ///< [qwf] Input - Quantized input array pointer - gn_config *c ///< [c] Input - Configuration structure containing test parameters - ); - - /** - * @brief Do histogram analysis and get results - * @return 0 on success, non-zero otherwise - */ - __api int gn_get_ha_results( - char ***rkeys, ///< [rkeys] Output - Result keys - double **rvalues, ///< [rvalues] Output - Result values - size_t *results_size, ///< [results_size] Output - Size of results - const uint64_t *hist, ///< [hist] Input - Histogram input to be analyzed - gn_config *c ///< [c] Input - Configuration structure containing test parameters - ); +/** + * @brief gn_histx32 + * @return 0 on success, non-zero otherwise + */ +__api int gn_histx32( + uint64_t* hist, ///< [out] Histogram array pointer + size_t hist_size, ///< [in] Histogram array size + const int32_t* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int64_t min, ///< [in] Min code + int64_t max, ///< [in] Max code + bool preserve ///< [in] If true, hist is not cleared before computing the histogram + ); - /** - * @brief Do DNL analysis and get results - * @return 0 on success, non-zero otherwise - */ - __api int gn_get_dnla_results( - char ***rkeys, ///< [rkeys] Output - Result keys - double **rvalues, ///< [rvalues] Output - Result values - size_t *results_size, ///< [results_size] Output - Size of results - const double *dnl, ///< [dnl] Input - DNL input to be analyzed - gn_config *c ///< [c] Input - Configuration structure containing test parameters - ); +/** + * @brief gn_histx64 + * @return 0 on success, non-zero otherwise + */ +__api int gn_histx64( + uint64_t* hist, ///< [out] Histogram array pointer + size_t hist_size, ///< [in] Histogram array size + const int64_t* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int64_t min, ///< [in] Min code + int64_t max, ///< [in] Max code + bool preserve ///< [in] If true, hist is not cleared before computing the histogram + ); - /** - * @brief Do INL analysis and get results - * @return 0 on success, non-zero otherwise - */ - __api int gn_get_inla_results( - char ***rkeys, ///< [rkeys] Output - Result keys - double **rvalues, ///< [rvalues] Output - Result values - size_t *results_size, ///< [results_size] Output - Size of results - const double *inl, ///< [dnl] Input - INL input to be analyzed - gn_config *c ///< [c] Input - Configuration structure containing test parameters - ); +/** + * @brief gn_hist_analysis + * @return 0 on success, non-zero otherwise + * @details The results contain the following key-value pairs (see general description of + * \ref AnalysisRoutines "Analysis Routines"). + * + *
Key Description + *
sum Sum of all histogram bins + *
first_nz_index First non-zero bin + *
last_nz_index Last non-zero bin + *
nz_range Non-zero bin range (1 + (last_nz_index - first_nz_index)) + *
+ */ +__api int gn_hist_analysis( + char** rkeys, ///< [out] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + double* rvalues, ///< [out] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const uint64_t* hist, ///< [in] Input array pointer + size_t hist_size ///< [in] Input array size + ); - /** - * @brief Do Fourier analysis and get a single result - * @return 0 on success, non-zero otherwise - */ - __api int gn_get_fa_single_result( - double *rvalue, - const char* metric_name, - double *fft_ilv, ///< [fft_ilv] Input - Interleaved Re/Im array pointer - gn_config *c ///< [c] Input - Configuration structure containing test parameters - ); +/** + * @brief gn_inl + * @return 0 on success, non-zero otherwise + */ +__api int gn_inl( + double* inl, ///< [out] Output array pointer + size_t inl_size, ///< [in] Output array size + const double* dnl, ///< [in] Input array pointer + size_t dnl_size, ///< [in] Input array size + GnInlLineFit fit ///< [in] Line fit type + ); + +/** + * @brief gn_inl_analysis + * @return 0 on success, non-zero otherwise + * @details The results contain the following key-value pairs (see general description of + * \ref AnalysisRoutines "Analysis Routines"). + * + *
Key Description + *
min Minumum value + *
max Maximum value + *
min_index Index of first occurence of minimum value + *
max_index Index of first occurence of maximum value + *
+ */ +__api int gn_inl_analysis( + char** rkeys, ///< [out] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + double* rvalues, ///< [out] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const double* inl, ///< [in] Input array pointer + size_t inl_size ///< [in] Input array size + ); + +/** + * \defgroup CodeDensityHelpers Helpers + * @{ + */ + +/** + * @brief gn_code_density_size + * @return 0 on success, non-zero otherwise + */ +__api int gn_code_density_size( + size_t* size, ///< [out] Output array size + int n, ///< [in] Code width (i.e. ADC resolution) + GnCodeFormat format ///< [in] Code format + ); + +/** + * @brief gn_code_densityx_size + * @return 0 on success, non-zero otherwise + */ +__api int gn_code_densityx_size( + size_t* size, ///< [out] Output array size + int64_t min, ///< [in] Min code + int64_t max ///< [in] Max code + ); + +/** @} CodeDensityHelpers */ + +/** @} CodeDensity */ + +#ifdef __cplusplus +} // extern "C" +#endif + +/* Fourier Analysis */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \defgroup FourierAnalysis Fourier Analysis + * @{ + */ + +/** + * @brief gn_fft_analysis returns all Fourier analysis results + * @return 0 on success, non-zero otherwise + * @details The results contain the following key-value pairs (see general description of + * \ref AnalysisRoutines "Analysis Routines"). + * + *
Key Description Units + *
signaltype Signal type: 0=Real, 1=Complex + *
nfft FFT size + *
datasize Data size + *
fbin Frequency bin size Hz + *
fdata Data rate S/s + *
fsample Sample rate S/s + *
fshift Shift frequency Hz + *
fsnr Full-scale-to-noise ratio (a.k.a. "SNRFS") dB + *
snr Signal-to-noise ratio dB + *
sinad Signal-to-noise-and-distortion ratio dB + *
sfdr Spurious-free dynamic range dB + *
abn Average bin noise dBFS + *
nsd Noise spectral density dBFS/Hz + *
carrierindex Order index of the Carrier tone + *
maxspurindex Order index of the MaxSpur tone + *
ab_width Analysis band width Hz + *
ab_i1 Analysis band first index + *
ab_i2 Analysis band last index + *
{PREFIX}_nbins Number of bins associated with PREFIX + *
{PREFIX}_rss Root-sum-square associated with PREFIX + *
{TONEKEY}:orderindex Tone order index + *
{TONEKEY}:freq Tone frequency Hz + *
{TONEKEY}:ffinal Tone final frequency Hz + *
{TONEKEY}:fwavg Tone weighted-average frequency Hz + *
{TONEKEY}:i1 Tone first index + *
{TONEKEY}:i2 Tone last index + *
{TONEKEY}:nbins Tone number of bins + *
{TONEKEY}:inband 0: tone is in-band; 1: tone is out-of-band + *
{TONEKEY}:mag Tone magnitude + *
{TONEKEY}:mag_dbfs Tone magnitude relative to full-scale dBFS + *
{TONEKEY}:mag_dbc Tone magnitude relative to carrier dBc + *
{TONEKEY}:phase Tone phase rad + *
{TONEKEY}:phase_c Tone phase relative to carrier rad + *
+ */ +__api int gn_fft_analysis( + char** rkeys, ///< [out] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + double* rvalues, ///< [out] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const char* cfg_id, ///< [in] Configuration identifier (filename or object key) + const double* in, ///< [in] Interleaved Re/Im input array pointer + size_t in_size, ///< [in] Input array size + size_t nfft, ///< [in] FFT size + GnFreqAxisType axis_type ///< [in] Frequency axis type + ); + +/** + * @brief gn_fft_analysis_select returns select Fourier analysis results + * @return 0 on success, non-zero otherwise + */ +__api int gn_fft_analysis_select( + double* rvalues, ///< [out] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const char* cfg_id, ///< [in] Configuration identifier (filename or object key) + const char** rkeys, ///< [in] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + const double* in, ///< [in] Interleaved Re/Im input array pointer + size_t in_size, ///< [in] Input array size + size_t nfft, ///< [in] FFT size + GnFreqAxisType axis_type ///< [in] Frequency axis type + ); + +/** + * @brief gn_fft_analysis_single returns a single Fourier analysis result + * @return 0 on success, non-zero otherwise + */ +__api int gn_fft_analysis_single( + double* rvalue, ///< [out] Result value + const char* cfg_id, ///< [in] Configuration identifier (filename or object key) + const char* rkey, ///< [in] Result key + const double* in, ///< [in] Interleaved Re/Im input array pointer + size_t in_size, ///< [in] Input array size + size_t nfft, ///< [in] FFT size + GnFreqAxisType axis_type ///< [in] Frequency axis type + ); + +/** + * \defgroup FourierAnalysisConfiguration Configuration + * @{ + */ + +/** + * @brief gn_fa_analysis_band + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_analysis_band( + const char* obj_key, ///< [in] Object key + double center, ///< [in] Analysis band center + double width ///< [in] Analysis band width + ); + +/** + * @brief gn_fa_analysis_band_e + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_analysis_band_e( + const char* obj_key, ///< [in] Object key + const char* center, ///< [in] Analysis band center expression + const char* width ///< [in] Analysis band width expression + ); + +/** + * @brief gn_fa_clk + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_clk( + const char* obj_key, ///< [in] Object key + const int* clk, ///< [in] Pointer to array of clock divisors + size_t clk_size, ///< [in] Size of array of clock divisors + bool as_noise ///< [in] If true, CLK components will be treated as noise + ); + +/** + * @brief gn_fa_conv_offset + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_conv_offset( + const char* obj_key, ///< [in] Object key + bool enable ///< [in] If true, enable converter offset + ); + +/** + * @brief gn_fa_create + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_create( + const char* obj_key ///< [in] Object key + ); + +/** + * @brief gn_fa_dc + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_dc( + const char* obj_key, ///< [in] Object key + bool as_dist ///< [in] If true, treat DC as distortion + ); + +/** + * @brief gn_fa_fdata + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_fdata( + const char* obj_key, ///< [in] Object key + double f ///< [in] fdata + ); + +/** + * @brief gn_fa_fdata_e + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_fdata_e( + const char* obj_key, ///< [in] Object key + const char* f ///< [in] fdata expression + ); + +/** + * @brief gn_fa_fixed_tone + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_fixed_tone( + const char* obj_key, ///< [in] Object key + const char* comp_key, ///< [in] Component key + GnFACompTag tag, ///< [in] Tag + double freq, ///< [in] Frequency + int ssb ///< [in] Number of single-side bins + ); + +/** + * @brief gn_fa_fixed_tone_e + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_fixed_tone_e( + const char* obj_key, ///< [in] Object key + const char* comp_key, ///< [in] Component key + GnFACompTag tag, ///< [in] Tag + const char* freq, ///< [in] Frequency expression + int ssb ///< [in] Number of single-side bins + ); + +/** + * @brief gn_fa_fsample + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_fsample( + const char* obj_key, ///< [in] Object key + double f ///< [in] fsample + ); + +/** + * @brief gn_fa_fsample_e + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_fsample_e( + const char* obj_key, ///< [in] Object key + const char* f ///< [in] fsample expression + ); + +/** + * @brief gn_fa_fshift + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_fshift( + const char* obj_key, ///< [in] Object key + double f ///< [in] fshift + ); + +/** + * @brief gn_fa_fshift_e + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_fshift_e( + const char* obj_key, ///< [in] Object key + const char* f ///< [in] fshift expression + ); + +/** + * @brief gn_fa_fund_images + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_fund_images( + const char* obj_key, ///< [in] Object key + bool enable ///< [in] If true, enable fundamental images + ); + +/** + * @brief gn_fa_hd + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_hd( + const char* obj_key, ///< [in] Object key + int n ///< [in] Order of harmonic distortion, i.e., the maximum harmonic + ); + +/** + * @brief gn_fa_ilv + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_ilv( + const char* obj_key, ///< [in] Object key + const int* ilv, ///< [in] Pointer to array of interleaving factors + size_t ilv_size, ///< [in] Size of array of interleaving factors + bool as_noise ///< [in] If true, ILV components will be treated as noise + ); + +/** + * @brief gn_fa_imd + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_imd( + const char* obj_key, ///< [in] Object key + int n ///< [in] Order of intermodulation distortion + ); + +/** + * @brief gn_fa_load + * @return 0 on success, non-zero otherwise + * @details If obj_key is empty, the object key is derived from filename. + */ +__api int gn_fa_load( + char* buf, ///< [out] Pointer to character array + size_t size, ///< [in] Size of character array + const char* filename, ///< [in] Filename + const char* obj_key ///< [in] Object key + ); + +/** + * @brief gn_fa_max_tone + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_max_tone( + const char* obj_key, ///< [in] Object key + const char* comp_key, ///< [in] Component key + GnFACompTag tag, ///< [in] Tag + int ssb ///< [in] Number of single-side bins + ); + +/** + * @brief gn_fa_preview + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_preview( + char* buf, ///< [out] Pointer to character array + size_t size, ///< [in] Size of character array + const char* cfg_id, ///< [in] Configuration identifier (filename or object key) + bool cplx ///< [in] If true, preview will include complex components + ); + +/** + * @brief gn_fa_quad_errors + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_quad_errors( + const char* obj_key, ///< [in] Object key + bool enable ///< [in] If true, enable quadrature errors + ); + +/** + * @brief gn_fa_remove_comp + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_remove_comp( + const char* obj_key, ///< [in] Object key + const char* comp_key ///< [in] Component key + ); + +/** + * @brief gn_fa_reset + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_reset( + const char* obj_key ///< [in] Object key + ); + +/** + * @brief gn_fa_ssb + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_ssb( + const char* obj_key, ///< [in] Object key + GnFASsb group, ///< [in] SSB group + int ssb ///< [in] Number of single-side bins + ); + +/** + * @brief gn_fa_var + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_var( + const char* obj_key, ///< [in] Object key + const char* name, ///< [in] Variable name + double value ///< [in] Variable value + ); + +/** + * @brief gn_fa_wo + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_wo( + const char* obj_key, ///< [in] Object key + int n ///< [in] Number of worst others + ); + +/** @} FourierAnalysisConfiguration */ + +/** + * \defgroup FourierAnalysisResults Results + * @{ + */ + +/** + * @brief gn_fa_result + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_result( + double* result, ///< [out] Result associated with rkey + const char** rkeys, ///< [in] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + const double* rvalues, ///< [in] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const char* rkey ///< [in] Key of desired result +); + +/** + * @brief gn_fa_result_string + * @return 0 on success, non-zero otherwise + */ +__api int gn_fa_result_string( + char* result, ///< [out] Result string associated with rkey + size_t result_size, ///< [in] Size of result string + const char** rkeys, ///< [in] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + const double* rvalues, ///< [in] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const char* rkey ///< [in] Key of desired result +); + +/** @} FourierAnalysisResults */ + +/** + * \defgroup FourierAnalysisHelpers Helpers + * @{ + */ + +/** + * @brief gn_fa_load_key_size + * @return 0 on success, non-zero otherwise + * @details The library string termination setting determines whether or not a null terminator + * is included in the size. See \ref gn_set_string_termination. + */ +__api int gn_fa_load_key_size( + size_t* size, ///< [out] Number of characters in key + const char* filename, ///< [in] Filename + const char* obj_key ///< [in] Object key + ); + +/** + * @brief gn_fa_preview_size + * @return 0 on success, non-zero otherwise + * @details The library string termination setting determines whether or not a null terminator + * is included in the size. See \ref gn_set_string_termination. + */ +__api int gn_fa_preview_size( + size_t* size, ///< [out] Number of characters in compenent list string + const char* cfg_id, ///< [in] Configuration identifier (filename or object key) + bool cplx ///< [in] If true, list will include complex components + ); + +/** + * @brief gn_fa_result_string_size + * @return 0 on success, non-zero otherwise + * @details The library string termination setting determines whether or not a null terminator + * is included in the size. See \ref gn_set_string_termination. + */ +__api int gn_fa_result_string_size( + size_t* size, ///< [out] Number of characters result string + const char** rkeys, ///< [in] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + const double* rvalues, ///< [in] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const char* rkey ///< [in] Key of desired result + ); + +/** + * @brief gn_fft_analysis_results_key_sizes + * @return 0 on success, non-zero otherwise + * @details The library string termination setting determines whether or not a null terminator + * is included in the key sizes. See \ref gn_set_string_termination. + */ +__api int gn_fft_analysis_results_key_sizes( + size_t* key_sizes, ///< [out] Key size array pointer + size_t key_sizes_size, ///< [in] Key size array size + const char* cfg_id, ///< [in] Configuration identifier (filename or object key) + size_t in_size, ///< [in] Input array size + size_t nfft ///< [in] FFT size + ); + +/** + * @brief gn_fft_analysis_results_size + * @return 0 on success, non-zero otherwise + */ +__api int gn_fft_analysis_results_size( + size_t* size, ///< [out] Number of key-value result pairs + const char* cfg_id, ///< [in] Configuration identifier (filename or object key) + size_t in_size, ///< [in] Input array size + size_t nfft ///< [in] FFT size + ); + +/** @} FourierAnalysisHelpers */ + +/** @} FourierAnalysis */ + +#ifdef __cplusplus +} // extern "C" +#endif + +/* Fourier Transforms */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \defgroup FourierTransforms Fourier Transforms + * @{ + */ /** - * @brief Do Fourier analysis and all get results - * @return 0 on success, non-zero otherwise - */ - __api int gn_get_fa_results( - char ***rkeys, - double **rvalues, - size_t *results_size, ///< [results_size] size of results - double *fft_ilv, ///< [fft_ilv] Input - Interleaved Re/Im array pointer - gn_config *c ///< [c] Input - Configuration structure containing test parameters - ); - + * @brief gn_fft + * @return 0 on success, non-zero otherwise + */ +__api int gn_fft( + double* out, ///< [out] Interleaved Re/Im output array pointer + size_t out_size, ///< [in] Output array size + const double* i, ///< [in] In-phase input array pointer + size_t i_size, ///< [in] In-phase input array size + const double* q, ///< [in] Quadrature input array pointer + size_t q_size, ///< [in] Quadrature input array size + size_t navg, ///< [in] FFT averaging number + size_t nfft, ///< [in] FFT size + GnWindow window ///< [in] Window + ); + +/** + * @brief gn_fft16 + * @return 0 on success, non-zero otherwise + */ +__api int gn_fft16( + double* out, ///< [out] Interleaved Re/Im output array pointer + size_t out_size, ///< [in] Output array size + const int16_t* i, ///< [in] In-phase input array pointer + size_t i_size, ///< [in] In-phase input array size + const int16_t* q, ///< [in] Quadrature input array pointer + size_t q_size, ///< [in] Quadrature input array size + int n, ///< [in] Resolution + size_t navg, ///< [in] FFT averaging number + size_t nfft, ///< [in] FFT size + GnWindow window, ///< [in] Window + GnCodeFormat format ///< [in] Code format + ); + +/** + * @brief gn_fft32 + * @return 0 on success, non-zero otherwise + */ +__api int gn_fft32( + double* out, ///< [out] Interleaved Re/Im output array pointer + size_t out_size, ///< [in] Output array size + const int32_t* i, ///< [in] In-phase input array pointer + size_t i_size, ///< [in] In-phase input array size + const int32_t* q, ///< [in] Quadrature input array pointer + size_t q_size, ///< [in] Quadrature input array size + int n, ///< [in] Resolution + size_t navg, ///< [in] FFT averaging number + size_t nfft, ///< [in] FFT size + GnWindow window, ///< [in] Window + GnCodeFormat format ///< [in] Code format + ); + +/** + * @brief gn_fft64 + * @return 0 on success, non-zero otherwise + */ +__api int gn_fft64( + double* out, ///< [out] Interleaved Re/Im output array pointer + size_t out_size, ///< [in] Output array size + const int64_t* i, ///< [in] In-phase input array pointer + size_t i_size, ///< [in] In-phase input array size + const int64_t* q, ///< [in] Quadrature input array pointer + size_t q_size, ///< [in] Quadrature input array size + int n, ///< [in] Resolution + size_t navg, ///< [in] FFT averaging number + size_t nfft, ///< [in] FFT size + GnWindow window, ///< [in] Window + GnCodeFormat format ///< [in] Code format + ); + +/** + * @brief gn_rfft + * @return 0 on success, non-zero otherwise + * @details This function will be implemented in the future. + */ +__api int gn_rfft( + double* out, ///< [out] Interleaved Re/Im output array pointer + size_t out_size, ///< [in] Output array size + const double* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + size_t navg, ///< [in] FFT averaging number + size_t nfft, ///< [in] FFT size + GnWindow window, ///< [in] Window + GnRfftScale scale ///< [in] Scaling mode + ); + +/** + * @brief gn_rfft16 + * @return 0 on success, non-zero otherwise + */ +__api int gn_rfft16( + double* out, ///< [out] Interleaved Re/Im output array pointer + size_t out_size, ///< [in] Output array size + const int16_t* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int n, ///< [in] Resolution + size_t navg, ///< [in] FFT averaging number + size_t nfft, ///< [in] FFT size + GnWindow window, ///< [in] Window + GnCodeFormat format, ///< [in] Code format + GnRfftScale scale ///< [in] Scaling mode + ); + +/** + * @brief gn_rfft32 + * @return 0 on success, non-zero otherwise + */ +__api int gn_rfft32( + double* out, ///< [out] Interleaved Re/Im output array pointer + size_t out_size, ///< [in] Output array size + const int32_t* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int n, ///< [in] Resolution + size_t navg, ///< [in] FFT averaging number + size_t nfft, ///< [in] FFT size + GnWindow window, ///< [in] Window + GnCodeFormat format, ///< [in] Code format + GnRfftScale scale ///< [in] Scaling mode + ); + +/** + * @brief gn_rfft64 + * @return 0 on success, non-zero otherwise + */ +__api int gn_rfft64( + double* out, ///< [out] Interleaved Re/Im output array pointer + size_t out_size, ///< [in] Output array size + const int64_t* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int n, ///< [in] Resolution + size_t navg, ///< [in] FFT averaging number + size_t nfft, ///< [in] FFT size + GnWindow window, ///< [in] Window + GnCodeFormat format, ///< [in] Code format + GnRfftScale scale ///< [in] Scaling mode + ); + +/** + * \defgroup FourierTransformHelpers Helpers + * @{ + */ + +/** + * @brief gn_fft_size + * @return 0 on success, non-zero otherwise + */ +__api int gn_fft_size( + size_t* out_size, ///< [out] Output array size + size_t i_size, ///< [in] In-phase input array size + size_t q_size, ///< [in] Quadrature input array size + size_t navg, ///< [in] FFT averaging number + size_t nfft ///< [in] FFT size + ); + +/** + * @brief gn_rfft_size + * @return 0 on success, non-zero otherwise + */ +__api int gn_rfft_size( + size_t* out_size, ///< [out] Output array size + size_t in_size, ///< [in] Input array size + size_t navg, ///< [in] FFT averaging number + size_t nfft ///< [in] FFT size + ); + +/** @} FourierTransformHelpers */ + +/** @} FourierTransforms */ + #ifdef __cplusplus -} +} // extern "C" #endif +/* Fourier Utilities */ +#ifdef __cplusplus +extern "C" { #endif + +/** + * \defgroup FourierUtilities Fourier Utilities + * @{ + */ + +/** + * @brief gn_alias + * @return 0 on success, non-zero otherwise + */ +__api int gn_alias( + double* out, ///< [out] Output pointer + double fs, ///< [in] Sample rate (S/s) + double freq, ///< [in] Frequency (Hz) + GnFreqAxisType axis_type ///< [in] Frequency axis type + ); + +/** + * @brief gn_coherent + * @return 0 on success, non-zero otherwise + */ +__api int gn_coherent( + double* out, ///< [out] Output pointer + size_t nfft, ///< [in] FFT size + double fs, ///< [in] Sample rate (S/s) + double freq ///< [in] Desired frequency (Hz) + ); + +/** + * @brief gn_fftshift + * @return 0 on success, non-zero otherwise + */ +__api int gn_fftshift( + double* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double* in, ///< [in] Input array pointer + size_t in_size ///< [in] Input array size + ); + +/** + * @brief gn_freq_axis + * @return 0 on success, non-zero otherwise + */ +__api int gn_freq_axis( + double* out, ///< [out] Array pointer + size_t size, ///< [in] Array size + size_t nfft, ///< [in] FFT size + GnFreqAxisType axis_type, ///< [in] Frequency axis type + double fs, ///< [in] Sample rate (S/s) + GnFreqAxisFormat axis_format ///< [in] Frequency axis format + ); + +/** + * @brief gn_ifftshift + * @return 0 on success, non-zero otherwise + */ +__api int gn_ifftshift( + double* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double* in, ///< [in] Input array pointer + size_t in_size ///< [in] Input array size + ); + +/** + * \defgroup FourierUtilityHelpers Helpers + * @{ + */ + +/** + * @brief gn_freq_axis_size + * @return 0 on success, non-zero otherwise + */ +__api int gn_freq_axis_size( + size_t* size, ///< [out] Output array size + size_t nfft, ///< [in] FFT size + GnFreqAxisType axis_type ///< [in] Frequency axis type + ); + +/** @} FourierUtilityHelpers */ + +/** @} FourierUtilities */ + +#ifdef __cplusplus +} // extern "C" +#endif + +/* Manager */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \defgroup Manager Manager + * @{ + */ + +/** + * @brief gn_mgr_clear + * @return Always returns 0 + */ +__api int gn_mgr_clear(); + +/** + * @brief gn_mgr_compare + * @return 0 on success, non-zero otherwise + */ +__api int gn_mgr_compare( + bool* result, ///< [out] true if the objects are equal, false otherwise + const char* obj_key1, ///< [in] Object key 1 + const char* obj_key2 ///< [in] Object key 2 + ); + +/** + * @brief gn_mgr_contains + * @return Always returns 0 + */ +__api int gn_mgr_contains( + bool* result, ///< [out] true if Manager contains key, false otherwise + const char* obj_key ///< [in] Object key + ); + +/** + * @brief gn_mgr_remove + * @return Always returns 0 + */ +__api int gn_mgr_remove( + const char* obj_key ///< [in] Object key + ); + +/** + * @brief gn_mgr_save + * @return 0 on success, non-zero otherwise + * @details If filename is empty, the filename is derived from obj_key. + */ +__api int gn_mgr_save( + char* buf, ///< [out] Pointer to character array + size_t size, ///< [in] Size of character array + const char* obj_key, ///< [in] Object key + const char* filename ///< [in] Filename + ); + +/** + * @brief gn_mgr_size + * @return Always returns 0 + */ +__api int gn_mgr_size( + size_t* size ///< [out] Number of objects owned by the manager + ); + +/** + * @brief gn_mgr_to_string + * @return 0 on success, non-zero otherwise + */ +__api int gn_mgr_to_string( + char* buf, ///< [out] Pointer to character array + size_t size, ///< [in] Size of character array + const char* obj_key ///< [in] Object key + ); + +/** + * @brief gn_mgr_type + * @return 0 on success, non-zero otherwise + */ +__api int gn_mgr_type( + char* buf, ///< [out] Pointer to character array + size_t size, ///< [in] Size of character array + const char* obj_key ///< [in] Object key + ); + +/** + * \defgroup ManagerHelpers Helpers + * @{ + */ + +/** + * @brief gn_mgr_save_filename_size + * @return 0 on success, non-zero otherwise + * @details The library string termination setting determines whether or not a null terminator + * is included in the size. See \ref gn_set_string_termination. + */ +__api int gn_mgr_save_filename_size( + size_t* size, ///< [out] Number of characters in filename + const char* obj_key, ///< [in] Object key + const char* filename ///< [in] Filename + ); + +/** + * @brief gn_mgr_to_string_size + * @return 0 on success, non-zero otherwise + * @details The library string termination setting determines whether or not a null terminator + * is included in the size. See \ref gn_set_string_termination. + */ +__api int gn_mgr_to_string_size( + size_t* size, ///< [out] Number of characters in the string + const char* obj_key ///< [in] Object key + ); + +/** + * @brief gn_mgr_type_size + * @return 0 on success, non-zero otherwise + * @details The library string termination setting determines whether or not a null terminator + * is included in the size. See \ref gn_set_string_termination. + */ +__api int gn_mgr_type_size( + size_t* size, ///< [out] Number of characters in object type string + const char* obj_key ///< [in] Object key + ); + +/** @} ManagerHelpers */ + +/** @} Manager */ + +#ifdef __cplusplus +} // extern "C" +#endif + +/* Signal Processing */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \defgroup SignalProcessing Signal Processing + * @{ + */ + +/** + * @brief gn_downsample + * @return 0 on success, non-zero otherwise + */ +__api int gn_downsample( + double* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int ratio, ///< [in] Downsample ratio + bool interleaved ///< [in] If true, 'in' is interleaved I/Q data + ); + +/** + * @brief gn_downsample16 + * @return 0 on success, non-zero otherwise + */ +__api int gn_downsample16( + int16_t* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const int16_t* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int ratio, ///< [in] Downsample ratio + bool interleaved ///< [in] If true, 'in' is interleaved I/Q data + ); + +/** + * @brief gn_downsample32 + * @return 0 on success, non-zero otherwise + */ +__api int gn_downsample32( + int32_t* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const int32_t* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int ratio, ///< [in] Downsample ratio + bool interleaved ///< [in] If true, 'in' is interleaved I/Q data + ); + +/** + * @brief gn_downsample64 + * @return 0 on success, non-zero otherwise + */ +__api int gn_downsample64( + int64_t* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const int64_t* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int ratio, ///< [in] Downsample ratio + bool interleaved ///< [in] If true, 'in' is interleaved I/Q data + ); + +/** + * @brief gn_fshift + * @return 0 on success, non-zero otherwise + */ +__api int gn_fshift( + double* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double* i, ///< [in] In-phase input array pointer + size_t i_size, ///< [in] In-phase input array size + const double* q, ///< [in] Quadrature input array pointer + size_t q_size, ///< [in] Quadrature input array size + double fs, ///< [in] Sample rate + double fshift ///< [in] Shift frequency + ); + +/** + * @brief gn_fshift16 + * @return 0 on success, non-zero otherwise + */ +__api int gn_fshift16( + int16_t* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const int16_t* i, ///< [in] In-phase input array pointer + size_t i_size, ///< [in] In-phase input array size + const int16_t* q, ///< [in] Quadrature input array pointer + size_t q_size, ///< [in] Quadrature input array size + int n, ///< [in] Code width + double fs, ///< [in] Sample rate + double fshift, ///< [in] Shift frequency + GnCodeFormat format ///< [in] Code format + ); + +/** + * @brief gn_fshift32 + * @return 0 on success, non-zero otherwise + */ +__api int gn_fshift32( + int32_t* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const int32_t* i, ///< [in] In-phase input array pointer + size_t i_size, ///< [in] In-phase input array size + const int32_t* q, ///< [in] Quadrature input array pointer + size_t q_size, ///< [in] Quadrature input array size + int n, ///< [in] Code width + double fs, ///< [in] Sample rate + double fshift, ///< [in] Shift frequency + GnCodeFormat format ///< [in] Code format + ); + +/** + * @brief gn_fshift64 + * @return 0 on success, non-zero otherwise + */ +__api int gn_fshift64( + int64_t* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const int64_t* i, ///< [in] In-phase input array pointer + size_t i_size, ///< [in] In-phase input array size + const int64_t* q, ///< [in] Quadrature input array pointer + size_t q_size, ///< [in] Quadrature input array size + int n, ///< [in] Code width + double fs, ///< [in] Sample rate + double fshift, ///< [in] Shift frequency + GnCodeFormat format ///< [in] Code format + ); + +/** + * @brief gn_normalize16 + * @return 0 on success, non-zero otherwise + */ +__api int gn_normalize16( + double* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const int16_t* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int n, ///< [in] Resolution + GnCodeFormat format ///< [in] Code format + ); + +/** + * @brief gn_normalize32 + * @return 0 on success, non-zero otherwise + */ +__api int gn_normalize32( + double* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const int32_t* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int n, ///< [in] Resolution + GnCodeFormat format ///< [in] Code format + ); + +/** + * @brief gn_normalize64 + * @return 0 on success, non-zero otherwise + */ +__api int gn_normalize64( + double* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const int64_t* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + int n, ///< [in] Resolution + GnCodeFormat format ///< [in] Code format + ); + +/** + * @brief gn_polyval + * @return 0 on success, non-zero otherwise + */ +__api int gn_polyval( + double* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + const double* c, ///< [in] Coefficient array pointer + size_t c_size ///< [in] Coefficient array size + ); + +/** + * @brief gn_quantize16 + * @return 0 on success, non-zero otherwise + */ +__api int gn_quantize16( + int16_t* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + double fsr, ///< [in] Full-scale range + int n, ///< [in] Resolution + double noise, ///< [in] Input referred RMS noise + GnCodeFormat format ///< [in] Code format +); + +/** + * @brief gn_quantize32 + * @return 0 on success, non-zero otherwise + */ +__api int gn_quantize32( + int32_t* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + double fsr, ///< [in] Full-scale range + int n, ///< [in] Resolution + double noise, ///< [in] Input referred RMS noise + GnCodeFormat format ///< [in] Code format +); + +/** + * @brief gn_quantize64 + * @return 0 on success, non-zero otherwise + */ +__api int gn_quantize64( + int64_t* out, ///< [out] Output array pointer + size_t out_size, ///< [in] Output array size + const double* in, ///< [in] Input array pointer + size_t in_size, ///< [in] Input array size + double fsr, ///< [in] Full-scale range + int n, ///< [in] Resolution + double noise, ///< [in] Input referred RMS noise + GnCodeFormat format ///< [in] Code format +); + +/** + * \defgroup SignalProcessingHelpers Helpers + * @{ + */ + +/** + * @brief gn_downsample_size + * @return 0 on success, non-zero otherwise + */ +__api int gn_downsample_size( + size_t* out_size, ///< [out] Output array size + size_t in_size, ///< [in] Input array size + int ratio, ///< [in] Downsample ratio + bool interleaved ///< [in] If bool, 'in' is interleaved I/Q data + ); + +/** + * @brief gn_fshift_size + * @return 0 on success, non-zero otherwise + */ +__api int gn_fshift_size( + size_t* out_size, ///< [out] Output array size + size_t i_size, ///< [in] In-phase input array size + size_t q_size ///< [in] Quadrature input array size + ); + +/** @} SignalProcessingHelpers */ + +/** @} SignalProcessing */ + +#ifdef __cplusplus +} // extern "C" +#endif + +/* Waveforms */ +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \defgroup Waveforms Waveforms + * @{ + */ + +/** + * @brief gn_cos + * @return 0 on success, non-zero otherwise + */ +__api int gn_cos( + double* out, ///< [out] Array pointer + size_t size, ///< [in] Array size + double fs, ///< [in] Sample rate (S/s) + double ampl, ///< [in] Amplitude + double freq, ///< [in] Frequency (Hz) + double phase, ///< [in] Phase (rad) + double td, ///< [in] Time delay (s) + double tj ///< [in] RMS Aperture jitter (s) + ); + +/** + * @brief gn_gaussian + * @return 0 on success, non-zero otherwise + */ +__api int gn_gaussian( + double* out, ///< [out] Array pointer + size_t size, ///< [in] Array size + double mean, ///< [in] Mean + double sd ///< [in] Standard deviation + ); + +/** + * @brief gn_ramp + * @return 0 on success, non-zero otherwise + */ +__api int gn_ramp( + double* out, ///< [out] Array pointer + size_t size, ///< [in] Array size + double start, ///< [in] Start value + double stop, ///< [in] Stop value + double noise ///< [in] RMS noise + ); + +/** + * @brief gn_sin + * @return 0 on success, non-zero otherwise + */ +__api int gn_sin( + double* out, ///< [out] Array pointer + size_t size, ///< [in] Array size + double fs, ///< [in] Sample rate (S/s) + double ampl, ///< [in] Amplitude + double freq, ///< [in] Frequency (Hz) + double phase, ///< [in] Phase (rad) + double td, ///< [in] Time delay (s) + double tjrms ///< [in] RMS Aperture jitter (s) + ); + +/** + * @brief gn_wf_analysis + * @return 0 on success, non-zero otherwise + * @details The results contain the following key-value pairs (see general description of + * \ref AnalysisRoutines "Analysis Routines"). + * + *
Key Description + *
min Minumum value + *
max Maximum value + *
mid Middle value ((max + min) / 2) + *
range Range (max - min) + *
avg Average value + *
rms RMS value + *
rmsac RMS value with DC removed + *
min_index Index of first occurence of minimum value + *
max_index Index of first occurence of maximum value + *
+ */ +__api int gn_wf_analysis( + char** rkeys, ///< [out] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + double* rvalues, ///< [out] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const double* in, ///< [in] Waveform array pointer + size_t in_size ///< [in] Waveform array size + ); + +/** + * @brief gn_wf_analysis16 + * @return 0 on success, non-zero otherwise + * @details See description of \ref gn_wf_analysis. + */ +__api int gn_wf_analysis16( + char** rkeys, ///< [out] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + double* rvalues, ///< [out] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const int16_t* in, ///< [in] Waveform array pointer + size_t in_size ///< [in] Waveform array size + ); + +/** + * @brief gn_wf_analysis32 + * @return 0 on success, non-zero otherwise + * @details See description of \ref gn_wf_analysis. + */ +__api int gn_wf_analysis32( + char** rkeys, ///< [out] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + double* rvalues, ///< [out] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const int32_t* in, ///< [in] Waveform array pointer + size_t in_size ///< [in] Waveform array size + ); + +/** + * @brief gn_wf_analysis64 + * @return 0 on success, non-zero otherwise + * @details See description of \ref gn_wf_analysis. + */ +__api int gn_wf_analysis64( + char** rkeys, ///< [out] Result keys array pointer + size_t rkeys_size, ///< [in] Result keys array size + double* rvalues, ///< [out] Result values array pointer + size_t rvalues_size, ///< [in] Result values array size + const int64_t* in, ///< [in] Waveform array pointer + size_t in_size ///< [in] Waveform array size + ); + +/** @} Waveforms */ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // CGENALYZER_H \ No newline at end of file diff --git a/bindings/c/include/cgenalyzer_advanced.h b/bindings/c/include/cgenalyzer_advanced.h deleted file mode 100644 index e3c99f4..0000000 --- a/bindings/c/include/cgenalyzer_advanced.h +++ /dev/null @@ -1,1896 +0,0 @@ -/* - * cgenalyzer_advanced - genalyzer (advanced) API header file - * - * Copyright (C) 2022 Analog Devices, Inc. - * Author: Peter Derounian - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * */ - - -#ifndef CGENALYZER_ADVANCED_H -#define CGENALYZER_ADVANCED_H - -#include -#include -#include - -/** - * \mainpage Genalyzer Library API Documentation - * \section Overview - * The Genalyzer Library provides analysis routines for data converter testing. The - * library contains routines that analyze waveforms, FFTs, and the output of the traditional code - * density tests: histogram, DNL, and INL. In addition, the library provides basic signal - * generation and processing utilties. - * \section AnalysisRoutines Analysis Routines - * The library provides the following types of analysis: - * \li \ref gn_dnl_analysis "DNL Analysis" - * \li \ref gn_fft_analysis "Fourier Analysis" - * \li \ref gn_hist_analysis "Histogram Analysis" - * \li \ref gn_inl_analysis "INL Analysis" - * \li \ref gn_wf_analysis "Waveform Analysis" - * - * Each analysis routine returns results by filling a Keys array (rkeys) and a corresponding Values - * array (rvalues). Together, rkeys and rvalues represent a set of key-value result pairs: - * rkeys[0] corresponds to rvalues[0], rkeys[1] to rvalues[1], and so on. - */ - -/* Enumerations */ -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \defgroup Enumerations Enumerations - * @{ - */ - -/** - * @brief GnAnalysisType enumerates analysis types - */ -typedef enum GnAnalysisType { - GnAnalysisTypeDNL, ///< DNL (differential nonlinearity) - GnAnalysisTypeFourier, ///< Fourier (FFT) - GnAnalysisTypeHistogram, ///< Histogram - GnAnalysisTypeINL, ///< INL (integral nonlinearity) - GnAnalysisTypeWaveform ///< Waveform - } GnAnalysisType; - -/** - * @brief GnCodeFormat enumerates binary code formats - */ -typedef enum GnCodeFormat { - GnCodeFormatOffsetBinary, ///< Offset Binary - GnCodeFormatTwosComplement ///< Two's Complement - } GnCodeFormat; - -/** - * @brief GnDnlSignal enumerates signal types for which DNL can be computed - */ -typedef enum GnDnlSignal { - GnDnlSignalRamp, ///< Ramp - GnDnlSignalTone ///< Tone (Sinusoid) - } GnDnlSignal; - -/** - * @brief GnFACompTag enumerates Fourier analysis component tags - */ -typedef enum GnFACompTag { - GnFACompTagDC, ///< DC component (always Bin 0) - GnFACompTagSignal, ///< Signal component - GnFACompTagHD, ///< Harmonic distortion - GnFACompTagIMD, ///< Intermodulation distortion - GnFACompTagILOS, ///< Interleaving offset component - GnFACompTagILGT, ///< Interleaving gain/timing/BW component - GnFACompTagCLK, ///< Clock component - GnFACompTagUserDist, ///< User-designated distortion - GnFACompTagNoise ///< Noise component (e.g. WorstOther) - } GnFACompTag; - -/** - * @brief GnFASsb enumerates the component categories for which the number of single side bins - * (SSB) can be set - */ -typedef enum GnFASsb { - GnFASsbDefault, ///< Default SSB (applies to auto-generated components) - GnFASsbDC, ///< SSB for DC component - GnFASsbSignal, ///< SSB for Signal components - GnFASsbWO, ///< SSB for WorstOther components - } GnFASsb; - -/** - * @brief GnFreqAxisFormat enumerates frequency axis formats - */ -typedef enum GnFreqAxisFormat { - GnFreqAxisFormatBins, ///< Bins - GnFreqAxisFormatFreq, ///< Frequency - GnFreqAxisFormatNorm ///< Normalized - } GnFreqAxisFormat; - -/** - * @brief GnFreqAxisType enumerates frequency axis types - */ -typedef enum GnFreqAxisType { - GnFreqAxisTypeDcCenter, ///< DC centered, e.g. [-fs/2, fs/2) (complex FFT only) - GnFreqAxisTypeDcLeft, ///< DC on left, e.g. [0, fs) (complex FFT only) - GnFreqAxisTypeReal ///< Real axis, e.g. [0, fs/2] (real FFT only) - } GnFreqAxisType; - -/** - * @brief GnInlLineFit enumerates INL line fitting options - */ -typedef enum GnInlLineFit { - GnInlLineFitBestFit, ///< Best fit - GnInlLineFitEndFit, ///< End fit - GnInlLineFitNoFit ///< No fit - } GnInlLineFit; - -/** - * @brief GnRfftScale enumerates real FFT scaling options - */ -typedef enum GnRfftScale { - GnRfftScaleDbfsDc, ///< Full-scale sinusoid measures -3 dBFS - GnRfftScaleDbfsSin, ///< Full-scale sinusoid measures 0 dBFS - GnRfftScaleNative ///< Full-scale sinusoid measures -6 dBFS - } GnRfftScale; - -/** - * @brief GnWindow enumerates window functions - */ -typedef enum GnWindow { - GnWindowBlackmanHarris, ///< Blackman-Harris - GnWindowHann, ///< Hann ("Hanning") - GnWindowNoWindow ///< No window (Rectangular) - } GnWindow; - -/** @} Enumerations */ - -#ifdef __cplusplus -} // extern "C" -#endif - -/* API Utilities */ -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 -#ifdef GENALYZER_EXPORTS -#define __api __declspec(dllexport) -#else -#define __api __declspec(dllimport) -#endif -#elif __GNUC__ >= 4 && !defined(MATLAB_MEX_FILE) \ - && !defined(MATLAB_LOADLIBRARY) -#define __api __attribute__ ((visibility ("default"))) -#else -#define __api -#endif - -/** - * \defgroup APIUtilities API Utilities - * @{ - */ - -/** - * @brief gn_analysis_results_key_sizes - * @return 0 on success, non-zero otherwise - * @details The library string termination setting determines whether or not a null terminator - * is included in the key sizes. See \ref gn_set_string_termination. - */ -__api int gn_analysis_results_key_sizes( - size_t* key_sizes, ///< [out] Key size array pointer - size_t key_sizes_size, ///< [in] Key size array size - GnAnalysisType type ///< [in] Analysis type - ); - -/** - * @brief gn_analysis_results_size - * @return 0 on success, non-zero otherwise - */ -__api int gn_analysis_results_size( - size_t* size, ///< [out] Number of key-value result pairs - GnAnalysisType type ///< [in] Analysis type - ); - -/** - * @brief gn_enum_value - * @return 0 on success, non-zero otherwise - */ -__api int gn_enum_value( - int* value, ///< [out] Underlying value of enumeration::enumerator - const char* enumeration, ///< [in] Enumeration name - const char* enumerator ///< [in] Enumerator name - ); - -/** - * @brief gn_error_check - * @return Always returns 0 - */ -__api int gn_error_check( - bool* error ///< [out] true if an error has occurred; false otherwise -); - -/** - * @brief gn_error_clear - * @return Always returns 0 - */ -__api int gn_error_clear(); - -/** - * @brief gn_error_string - * @return 0 on success, non-zero otherwise - */ -__api int gn_error_string( - char* buf, ///< [out] Pointer to character array - size_t size ///< [in] Size of character array - ); - -/** - * @brief gn_set_string_termination - * @return Always returns 0 - * @details Some functions in this library return strings by filling character buffers (arrays) - * provided by the caller. This function sets a global library setting that determines whether or - * not strings should be null-terminated. If set to true, functions that return strings will - * write a '\0' as the last character. In addition, functions that return the size of a string - * will include the null terminator in the size. - */ -__api int gn_set_string_termination( - bool null_terminated ///< [in] If true, strings are terminated with '\0' -); - -/** - * @brief gn_version_string - * @return 0 on success, non-zero otherwise - */ -__api int gn_version_string( - char* buf, ///< [in,out] Pointer to character array - size_t size ///< [in] Size of character array - ); - -/** - * \defgroup APIUtilityHelpers Helpers - * @{ - */ - -/** - * @brief gn_error_string_size - * @return Always returns 0 - * @details The library string termination setting determines whether or not a null terminator - * is included in the size. See \ref gn_set_string_termination. - */ -__api int gn_error_string_size( - size_t* size ///< [out] Number of characters in error string -); - -/** - * @brief gn_version_string_size - * @return Always returns 0 - * @details The library string termination setting determines whether or not a null terminator - * is included in the size. See \ref gn_set_string_termination. - */ -__api int gn_version_string_size( - size_t* size ///< [out] Number of characters in version string -); - -/** @} APIUtilityHelpers */ - -/** @} APIUtilities */ - -#ifdef __cplusplus -} // extern "C" -#endif - -/* Array Operations */ -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \defgroup ArrayOperations Array Operations - * @{ - */ - -/** - * @brief gn_abs - * @return 0 on success, non-zero otherwise - */ -__api int gn_abs( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size ///< [in] Input array size - ); - -/** - * @brief gn_angle - * @return 0 on success, non-zero otherwise - */ -__api int gn_angle( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size ///< [in] Input array size - ); - -/** - * @brief gn_db - * @return 0 on success, non-zero otherwise - */ -__api int gn_db( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size ///< [in] Input array size - ); - -/** - * @brief gn_db10 - * @return 0 on success, non-zero otherwise - */ -__api int gn_db10( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size ///< [in] Input array size - ); - -/** - * @brief gn_db20 - * @return 0 on success, non-zero otherwise - */ -__api int gn_db20( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size ///< [in] Input array size - ); - -/** - * @brief gn_norm - * @return 0 on success, non-zero otherwise - */ -__api int gn_norm( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size ///< [in] Input array size - ); - -/** @} ArrayOperations */ - -#ifdef __cplusplus -} // extern "C" -#endif - -/* Code Density */ -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \defgroup CodeDensity Code Density - * @{ - */ - -/** - * @brief gn_code_axis - * @return 0 on success, non-zero otherwise - */ -__api int gn_code_axis( - double* out, ///< [out] Array pointer - size_t size, ///< [in] Array size - int n, ///< [in] Resolution - GnCodeFormat format ///< [in] Code format - ); - -/** - * @brief gn_code_axisx - * @return 0 on success, non-zero otherwise - */ -__api int gn_code_axisx( - double* out, ///< [out] Array pointer - size_t size, ///< [in] Array size - int64_t min, ///< [in] Min code - int64_t max ///< [in] Max code - ); - -/** - * @brief gn_dnl - * @return 0 on success, non-zero otherwise - */ -__api int gn_dnl( - double* dnl, ///< [out] Output array pointer - size_t dnl_size, ///< [in] Output array size - const uint64_t* hist, ///< [in] Input array pointer - size_t hist_size, ///< [in] Input array size - GnDnlSignal type ///< [in] Signal type - ); - -/** - * @brief gn_dnl_analysis - * @return 0 on success, non-zero otherwise - * @details The results contain the following key-value pairs (see general description of - * \ref AnalysisRoutines "Analysis Routines"). - * - *
Key Description - *
min Minumum value - *
max Maximum value - *
avg Average value - *
rms RMS value - *
min_index Index of first occurence of minimum value - *
max_index Index of first occurence of maximum value - *
first_nm_index Index of first non-missing code - *
last_nm_index Index of last non-missing code - *
nm_range Non-missing code range (1 + (last_nm_index - first_nm_index)) - *
- */ -__api int gn_dnl_analysis( - char** rkeys, ///< [out] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - double* rvalues, ///< [out] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const double* dnl, ///< [in] Input array pointer - size_t dnl_size ///< [in] Input array size - ); - -/** - * @brief gn_hist16 - * @return 0 on success, non-zero otherwise - */ -__api int gn_hist16( - uint64_t* hist, ///< [out] Histogram array pointer - size_t hist_size, ///< [in] Histogram array size - const int16_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int n, ///< [in] Code width (i.e. ADC resolution) - GnCodeFormat format, ///< [in] Code format - bool preserve ///< [in] If true, hist is not cleared before computing the histogram - ); - -/** - * @brief gn_hist32 - * @return 0 on success, non-zero otherwise - */ -__api int gn_hist32( - uint64_t* hist, ///< [out] Histogram array pointer - size_t hist_size, ///< [in] Histogram array size - const int32_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int n, ///< [in] Code width (i.e. ADC resolution) - GnCodeFormat format, ///< [in] Code format - bool preserve ///< [in] If true, hist is not cleared before computing the histogram - ); - -/** - * @brief gn_hist64 - * @return 0 on success, non-zero otherwise - */ -__api int gn_hist64( - uint64_t* hist, ///< [out] Histogram array pointer - size_t hist_size, ///< [in] Histogram array size - const int64_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int n, ///< [in] Code width (i.e. ADC resolution) - GnCodeFormat format, ///< [in] Code format - bool preserve ///< [in] If true, hist is not cleared before computing the histogram - ); - -/** - * @brief gn_histx16 - * @return 0 on success, non-zero otherwise - */ -__api int gn_histx16( - uint64_t* hist, ///< [out] Histogram array pointer - size_t hist_size, ///< [in] Histogram array size - const int16_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int64_t min, ///< [in] Min code - int64_t max, ///< [in] Max code - bool preserve ///< [in] If true, hist is not cleared before computing the histogram - ); - -/** - * @brief gn_histx32 - * @return 0 on success, non-zero otherwise - */ -__api int gn_histx32( - uint64_t* hist, ///< [out] Histogram array pointer - size_t hist_size, ///< [in] Histogram array size - const int32_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int64_t min, ///< [in] Min code - int64_t max, ///< [in] Max code - bool preserve ///< [in] If true, hist is not cleared before computing the histogram - ); - -/** - * @brief gn_histx64 - * @return 0 on success, non-zero otherwise - */ -__api int gn_histx64( - uint64_t* hist, ///< [out] Histogram array pointer - size_t hist_size, ///< [in] Histogram array size - const int64_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int64_t min, ///< [in] Min code - int64_t max, ///< [in] Max code - bool preserve ///< [in] If true, hist is not cleared before computing the histogram - ); - -/** - * @brief gn_hist_analysis - * @return 0 on success, non-zero otherwise - * @details The results contain the following key-value pairs (see general description of - * \ref AnalysisRoutines "Analysis Routines"). - * - *
Key Description - *
sum Sum of all histogram bins - *
first_nz_index First non-zero bin - *
last_nz_index Last non-zero bin - *
nz_range Non-zero bin range (1 + (last_nz_index - first_nz_index)) - *
- */ -__api int gn_hist_analysis( - char** rkeys, ///< [out] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - double* rvalues, ///< [out] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const uint64_t* hist, ///< [in] Input array pointer - size_t hist_size ///< [in] Input array size - ); - -/** - * @brief gn_inl - * @return 0 on success, non-zero otherwise - */ -__api int gn_inl( - double* inl, ///< [out] Output array pointer - size_t inl_size, ///< [in] Output array size - const double* dnl, ///< [in] Input array pointer - size_t dnl_size, ///< [in] Input array size - GnInlLineFit fit ///< [in] Line fit type - ); - -/** - * @brief gn_inl_analysis - * @return 0 on success, non-zero otherwise - * @details The results contain the following key-value pairs (see general description of - * \ref AnalysisRoutines "Analysis Routines"). - * - *
Key Description - *
min Minumum value - *
max Maximum value - *
min_index Index of first occurence of minimum value - *
max_index Index of first occurence of maximum value - *
- */ -__api int gn_inl_analysis( - char** rkeys, ///< [out] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - double* rvalues, ///< [out] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const double* inl, ///< [in] Input array pointer - size_t inl_size ///< [in] Input array size - ); - -/** - * \defgroup CodeDensityHelpers Helpers - * @{ - */ - -/** - * @brief gn_code_density_size - * @return 0 on success, non-zero otherwise - */ -__api int gn_code_density_size( - size_t* size, ///< [out] Output array size - int n, ///< [in] Code width (i.e. ADC resolution) - GnCodeFormat format ///< [in] Code format - ); - -/** - * @brief gn_code_densityx_size - * @return 0 on success, non-zero otherwise - */ -__api int gn_code_densityx_size( - size_t* size, ///< [out] Output array size - int64_t min, ///< [in] Min code - int64_t max ///< [in] Max code - ); - -/** @} CodeDensityHelpers */ - -/** @} CodeDensity */ - -#ifdef __cplusplus -} // extern "C" -#endif - -/* Fourier Analysis */ -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \defgroup FourierAnalysis Fourier Analysis - * @{ - */ - -/** - * @brief gn_fft_analysis returns all Fourier analysis results - * @return 0 on success, non-zero otherwise - * @details The results contain the following key-value pairs (see general description of - * \ref AnalysisRoutines "Analysis Routines"). - * - *
Key Description Units - *
signaltype Signal type: 0=Real, 1=Complex - *
nfft FFT size - *
datasize Data size - *
fbin Frequency bin size Hz - *
fdata Data rate S/s - *
fsample Sample rate S/s - *
fshift Shift frequency Hz - *
fsnr Full-scale-to-noise ratio (a.k.a. "SNRFS") dB - *
snr Signal-to-noise ratio dB - *
sinad Signal-to-noise-and-distortion ratio dB - *
sfdr Spurious-free dynamic range dB - *
abn Average bin noise dBFS - *
nsd Noise spectral density dBFS/Hz - *
carrierindex Order index of the Carrier tone - *
maxspurindex Order index of the MaxSpur tone - *
ab_width Analysis band width Hz - *
ab_i1 Analysis band first index - *
ab_i2 Analysis band last index - *
{PREFIX}_nbins Number of bins associated with PREFIX - *
{PREFIX}_rss Root-sum-square associated with PREFIX - *
{TONEKEY}:orderindex Tone order index - *
{TONEKEY}:freq Tone frequency Hz - *
{TONEKEY}:ffinal Tone final frequency Hz - *
{TONEKEY}:fwavg Tone weighted-average frequency Hz - *
{TONEKEY}:i1 Tone first index - *
{TONEKEY}:i2 Tone last index - *
{TONEKEY}:nbins Tone number of bins - *
{TONEKEY}:inband 0: tone is in-band; 1: tone is out-of-band - *
{TONEKEY}:mag Tone magnitude - *
{TONEKEY}:mag_dbfs Tone magnitude relative to full-scale dBFS - *
{TONEKEY}:mag_dbc Tone magnitude relative to carrier dBc - *
{TONEKEY}:phase Tone phase rad - *
{TONEKEY}:phase_c Tone phase relative to carrier rad - *
- */ -__api int gn_fft_analysis( - char** rkeys, ///< [out] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - double* rvalues, ///< [out] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const char* cfg_id, ///< [in] Configuration identifier (filename or object key) - const double* in, ///< [in] Interleaved Re/Im input array pointer - size_t in_size, ///< [in] Input array size - size_t nfft, ///< [in] FFT size - GnFreqAxisType axis_type ///< [in] Frequency axis type - ); - -/** - * @brief gn_fft_analysis_select returns select Fourier analysis results - * @return 0 on success, non-zero otherwise - */ -__api int gn_fft_analysis_select( - double* rvalues, ///< [out] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const char* cfg_id, ///< [in] Configuration identifier (filename or object key) - const char** rkeys, ///< [in] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - const double* in, ///< [in] Interleaved Re/Im input array pointer - size_t in_size, ///< [in] Input array size - size_t nfft, ///< [in] FFT size - GnFreqAxisType axis_type ///< [in] Frequency axis type - ); - -/** - * @brief gn_fft_analysis_single returns a single Fourier analysis result - * @return 0 on success, non-zero otherwise - */ -__api int gn_fft_analysis_single( - double* rvalue, ///< [out] Result value - const char* cfg_id, ///< [in] Configuration identifier (filename or object key) - const char* rkey, ///< [in] Result key - const double* in, ///< [in] Interleaved Re/Im input array pointer - size_t in_size, ///< [in] Input array size - size_t nfft, ///< [in] FFT size - GnFreqAxisType axis_type ///< [in] Frequency axis type - ); - -/** - * \defgroup FourierAnalysisConfiguration Configuration - * @{ - */ - -/** - * @brief gn_fa_analysis_band - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_analysis_band( - const char* obj_key, ///< [in] Object key - double center, ///< [in] Analysis band center - double width ///< [in] Analysis band width - ); - -/** - * @brief gn_fa_analysis_band_e - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_analysis_band_e( - const char* obj_key, ///< [in] Object key - const char* center, ///< [in] Analysis band center expression - const char* width ///< [in] Analysis band width expression - ); - -/** - * @brief gn_fa_clk - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_clk( - const char* obj_key, ///< [in] Object key - const int* clk, ///< [in] Pointer to array of clock divisors - size_t clk_size, ///< [in] Size of array of clock divisors - bool as_noise ///< [in] If true, CLK components will be treated as noise - ); - -/** - * @brief gn_fa_conv_offset - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_conv_offset( - const char* obj_key, ///< [in] Object key - bool enable ///< [in] If true, enable converter offset - ); - -/** - * @brief gn_fa_create - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_create( - const char* obj_key ///< [in] Object key - ); - -/** - * @brief gn_fa_dc - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_dc( - const char* obj_key, ///< [in] Object key - bool as_dist ///< [in] If true, treat DC as distortion - ); - -/** - * @brief gn_fa_fdata - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_fdata( - const char* obj_key, ///< [in] Object key - double f ///< [in] fdata - ); - -/** - * @brief gn_fa_fdata_e - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_fdata_e( - const char* obj_key, ///< [in] Object key - const char* f ///< [in] fdata expression - ); - -/** - * @brief gn_fa_fixed_tone - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_fixed_tone( - const char* obj_key, ///< [in] Object key - const char* comp_key, ///< [in] Component key - GnFACompTag tag, ///< [in] Tag - double freq, ///< [in] Frequency - int ssb ///< [in] Number of single-side bins - ); - -/** - * @brief gn_fa_fixed_tone_e - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_fixed_tone_e( - const char* obj_key, ///< [in] Object key - const char* comp_key, ///< [in] Component key - GnFACompTag tag, ///< [in] Tag - const char* freq, ///< [in] Frequency expression - int ssb ///< [in] Number of single-side bins - ); - -/** - * @brief gn_fa_fsample - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_fsample( - const char* obj_key, ///< [in] Object key - double f ///< [in] fsample - ); - -/** - * @brief gn_fa_fsample_e - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_fsample_e( - const char* obj_key, ///< [in] Object key - const char* f ///< [in] fsample expression - ); - -/** - * @brief gn_fa_fshift - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_fshift( - const char* obj_key, ///< [in] Object key - double f ///< [in] fshift - ); - -/** - * @brief gn_fa_fshift_e - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_fshift_e( - const char* obj_key, ///< [in] Object key - const char* f ///< [in] fshift expression - ); - -/** - * @brief gn_fa_fund_images - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_fund_images( - const char* obj_key, ///< [in] Object key - bool enable ///< [in] If true, enable fundamental images - ); - -/** - * @brief gn_fa_hd - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_hd( - const char* obj_key, ///< [in] Object key - int n ///< [in] Order of harmonic distortion, i.e., the maximum harmonic - ); - -/** - * @brief gn_fa_ilv - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_ilv( - const char* obj_key, ///< [in] Object key - const int* ilv, ///< [in] Pointer to array of interleaving factors - size_t ilv_size, ///< [in] Size of array of interleaving factors - bool as_noise ///< [in] If true, ILV components will be treated as noise - ); - -/** - * @brief gn_fa_imd - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_imd( - const char* obj_key, ///< [in] Object key - int n ///< [in] Order of intermodulation distortion - ); - -/** - * @brief gn_fa_load - * @return 0 on success, non-zero otherwise - * @details If obj_key is empty, the object key is derived from filename. - */ -__api int gn_fa_load( - char* buf, ///< [out] Pointer to character array - size_t size, ///< [in] Size of character array - const char* filename, ///< [in] Filename - const char* obj_key ///< [in] Object key - ); - -/** - * @brief gn_fa_max_tone - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_max_tone( - const char* obj_key, ///< [in] Object key - const char* comp_key, ///< [in] Component key - GnFACompTag tag, ///< [in] Tag - int ssb ///< [in] Number of single-side bins - ); - -/** - * @brief gn_fa_preview - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_preview( - char* buf, ///< [out] Pointer to character array - size_t size, ///< [in] Size of character array - const char* cfg_id, ///< [in] Configuration identifier (filename or object key) - bool cplx ///< [in] If true, preview will include complex components - ); - -/** - * @brief gn_fa_quad_errors - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_quad_errors( - const char* obj_key, ///< [in] Object key - bool enable ///< [in] If true, enable quadrature errors - ); - -/** - * @brief gn_fa_remove_comp - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_remove_comp( - const char* obj_key, ///< [in] Object key - const char* comp_key ///< [in] Component key - ); - -/** - * @brief gn_fa_reset - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_reset( - const char* obj_key ///< [in] Object key - ); - -/** - * @brief gn_fa_ssb - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_ssb( - const char* obj_key, ///< [in] Object key - GnFASsb group, ///< [in] SSB group - int ssb ///< [in] Number of single-side bins - ); - -/** - * @brief gn_fa_var - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_var( - const char* obj_key, ///< [in] Object key - const char* name, ///< [in] Variable name - double value ///< [in] Variable value - ); - -/** - * @brief gn_fa_wo - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_wo( - const char* obj_key, ///< [in] Object key - int n ///< [in] Number of worst others - ); - -/** @} FourierAnalysisConfiguration */ - -/** - * \defgroup FourierAnalysisResults Results - * @{ - */ - -/** - * @brief gn_fa_result - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_result( - double* result, ///< [out] Result associated with rkey - const char** rkeys, ///< [in] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - const double* rvalues, ///< [in] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const char* rkey ///< [in] Key of desired result -); - -/** - * @brief gn_fa_result_string - * @return 0 on success, non-zero otherwise - */ -__api int gn_fa_result_string( - char* result, ///< [out] Result string associated with rkey - size_t result_size, ///< [in] Size of result string - const char** rkeys, ///< [in] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - const double* rvalues, ///< [in] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const char* rkey ///< [in] Key of desired result -); - -/** @} FourierAnalysisResults */ - -/** - * \defgroup FourierAnalysisHelpers Helpers - * @{ - */ - -/** - * @brief gn_fa_load_key_size - * @return 0 on success, non-zero otherwise - * @details The library string termination setting determines whether or not a null terminator - * is included in the size. See \ref gn_set_string_termination. - */ -__api int gn_fa_load_key_size( - size_t* size, ///< [out] Number of characters in key - const char* filename, ///< [in] Filename - const char* obj_key ///< [in] Object key - ); - -/** - * @brief gn_fa_preview_size - * @return 0 on success, non-zero otherwise - * @details The library string termination setting determines whether or not a null terminator - * is included in the size. See \ref gn_set_string_termination. - */ -__api int gn_fa_preview_size( - size_t* size, ///< [out] Number of characters in compenent list string - const char* cfg_id, ///< [in] Configuration identifier (filename or object key) - bool cplx ///< [in] If true, list will include complex components - ); - -/** - * @brief gn_fa_result_string_size - * @return 0 on success, non-zero otherwise - * @details The library string termination setting determines whether or not a null terminator - * is included in the size. See \ref gn_set_string_termination. - */ -__api int gn_fa_result_string_size( - size_t* size, ///< [out] Number of characters result string - const char** rkeys, ///< [in] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - const double* rvalues, ///< [in] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const char* rkey ///< [in] Key of desired result - ); - -/** - * @brief gn_fft_analysis_results_key_sizes - * @return 0 on success, non-zero otherwise - * @details The library string termination setting determines whether or not a null terminator - * is included in the key sizes. See \ref gn_set_string_termination. - */ -__api int gn_fft_analysis_results_key_sizes( - size_t* key_sizes, ///< [out] Key size array pointer - size_t key_sizes_size, ///< [in] Key size array size - const char* cfg_id, ///< [in] Configuration identifier (filename or object key) - size_t in_size, ///< [in] Input array size - size_t nfft ///< [in] FFT size - ); - -/** - * @brief gn_fft_analysis_results_size - * @return 0 on success, non-zero otherwise - */ -__api int gn_fft_analysis_results_size( - size_t* size, ///< [out] Number of key-value result pairs - const char* cfg_id, ///< [in] Configuration identifier (filename or object key) - size_t in_size, ///< [in] Input array size - size_t nfft ///< [in] FFT size - ); - -/** @} FourierAnalysisHelpers */ - -/** @} FourierAnalysis */ - -#ifdef __cplusplus -} // extern "C" -#endif - -/* Fourier Transforms */ -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \defgroup FourierTransforms Fourier Transforms - * @{ - */ - - /** - * @brief gn_fft - * @return 0 on success, non-zero otherwise - */ -__api int gn_fft( - double* out, ///< [out] Interleaved Re/Im output array pointer - size_t out_size, ///< [in] Output array size - const double* i, ///< [in] In-phase input array pointer - size_t i_size, ///< [in] In-phase input array size - const double* q, ///< [in] Quadrature input array pointer - size_t q_size, ///< [in] Quadrature input array size - size_t navg, ///< [in] FFT averaging number - size_t nfft, ///< [in] FFT size - GnWindow window ///< [in] Window - ); - -/** - * @brief gn_fft16 - * @return 0 on success, non-zero otherwise - */ -__api int gn_fft16( - double* out, ///< [out] Interleaved Re/Im output array pointer - size_t out_size, ///< [in] Output array size - const int16_t* i, ///< [in] In-phase input array pointer - size_t i_size, ///< [in] In-phase input array size - const int16_t* q, ///< [in] Quadrature input array pointer - size_t q_size, ///< [in] Quadrature input array size - int n, ///< [in] Resolution - size_t navg, ///< [in] FFT averaging number - size_t nfft, ///< [in] FFT size - GnWindow window, ///< [in] Window - GnCodeFormat format ///< [in] Code format - ); - -/** - * @brief gn_fft32 - * @return 0 on success, non-zero otherwise - */ -__api int gn_fft32( - double* out, ///< [out] Interleaved Re/Im output array pointer - size_t out_size, ///< [in] Output array size - const int32_t* i, ///< [in] In-phase input array pointer - size_t i_size, ///< [in] In-phase input array size - const int32_t* q, ///< [in] Quadrature input array pointer - size_t q_size, ///< [in] Quadrature input array size - int n, ///< [in] Resolution - size_t navg, ///< [in] FFT averaging number - size_t nfft, ///< [in] FFT size - GnWindow window, ///< [in] Window - GnCodeFormat format ///< [in] Code format - ); - -/** - * @brief gn_fft64 - * @return 0 on success, non-zero otherwise - */ -__api int gn_fft64( - double* out, ///< [out] Interleaved Re/Im output array pointer - size_t out_size, ///< [in] Output array size - const int64_t* i, ///< [in] In-phase input array pointer - size_t i_size, ///< [in] In-phase input array size - const int64_t* q, ///< [in] Quadrature input array pointer - size_t q_size, ///< [in] Quadrature input array size - int n, ///< [in] Resolution - size_t navg, ///< [in] FFT averaging number - size_t nfft, ///< [in] FFT size - GnWindow window, ///< [in] Window - GnCodeFormat format ///< [in] Code format - ); - -/** - * @brief gn_rfft - * @return 0 on success, non-zero otherwise - * @details This function will be implemented in the future. - */ -__api int gn_rfft( - double* out, ///< [out] Interleaved Re/Im output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - size_t navg, ///< [in] FFT averaging number - size_t nfft, ///< [in] FFT size - GnWindow window, ///< [in] Window - GnRfftScale scale ///< [in] Scaling mode - ); - -/** - * @brief gn_rfft16 - * @return 0 on success, non-zero otherwise - */ -__api int gn_rfft16( - double* out, ///< [out] Interleaved Re/Im output array pointer - size_t out_size, ///< [in] Output array size - const int16_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int n, ///< [in] Resolution - size_t navg, ///< [in] FFT averaging number - size_t nfft, ///< [in] FFT size - GnWindow window, ///< [in] Window - GnCodeFormat format, ///< [in] Code format - GnRfftScale scale ///< [in] Scaling mode - ); - -/** - * @brief gn_rfft32 - * @return 0 on success, non-zero otherwise - */ -__api int gn_rfft32( - double* out, ///< [out] Interleaved Re/Im output array pointer - size_t out_size, ///< [in] Output array size - const int32_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int n, ///< [in] Resolution - size_t navg, ///< [in] FFT averaging number - size_t nfft, ///< [in] FFT size - GnWindow window, ///< [in] Window - GnCodeFormat format, ///< [in] Code format - GnRfftScale scale ///< [in] Scaling mode - ); - -/** - * @brief gn_rfft64 - * @return 0 on success, non-zero otherwise - */ -__api int gn_rfft64( - double* out, ///< [out] Interleaved Re/Im output array pointer - size_t out_size, ///< [in] Output array size - const int64_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int n, ///< [in] Resolution - size_t navg, ///< [in] FFT averaging number - size_t nfft, ///< [in] FFT size - GnWindow window, ///< [in] Window - GnCodeFormat format, ///< [in] Code format - GnRfftScale scale ///< [in] Scaling mode - ); - -/** - * \defgroup FourierTransformHelpers Helpers - * @{ - */ - -/** - * @brief gn_fft_size - * @return 0 on success, non-zero otherwise - */ -__api int gn_fft_size( - size_t* out_size, ///< [out] Output array size - size_t i_size, ///< [in] In-phase input array size - size_t q_size, ///< [in] Quadrature input array size - size_t navg, ///< [in] FFT averaging number - size_t nfft ///< [in] FFT size - ); - -/** - * @brief gn_rfft_size - * @return 0 on success, non-zero otherwise - */ -__api int gn_rfft_size( - size_t* out_size, ///< [out] Output array size - size_t in_size, ///< [in] Input array size - size_t navg, ///< [in] FFT averaging number - size_t nfft ///< [in] FFT size - ); - -/** @} FourierTransformHelpers */ - -/** @} FourierTransforms */ - -#ifdef __cplusplus -} // extern "C" -#endif - -/* Fourier Utilities */ -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \defgroup FourierUtilities Fourier Utilities - * @{ - */ - -/** - * @brief gn_alias - * @return 0 on success, non-zero otherwise - */ -__api int gn_alias( - double* out, ///< [out] Output pointer - double fs, ///< [in] Sample rate (S/s) - double freq, ///< [in] Frequency (Hz) - GnFreqAxisType axis_type ///< [in] Frequency axis type - ); - -/** - * @brief gn_coherent - * @return 0 on success, non-zero otherwise - */ -__api int gn_coherent( - double* out, ///< [out] Output pointer - size_t nfft, ///< [in] FFT size - double fs, ///< [in] Sample rate (S/s) - double freq ///< [in] Desired frequency (Hz) - ); - -/** - * @brief gn_fftshift - * @return 0 on success, non-zero otherwise - */ -__api int gn_fftshift( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size ///< [in] Input array size - ); - -/** - * @brief gn_freq_axis - * @return 0 on success, non-zero otherwise - */ -__api int gn_freq_axis( - double* out, ///< [out] Array pointer - size_t size, ///< [in] Array size - size_t nfft, ///< [in] FFT size - GnFreqAxisType axis_type, ///< [in] Frequency axis type - double fs, ///< [in] Sample rate (S/s) - GnFreqAxisFormat axis_format ///< [in] Frequency axis format - ); - -/** - * @brief gn_ifftshift - * @return 0 on success, non-zero otherwise - */ -__api int gn_ifftshift( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size ///< [in] Input array size - ); - -/** - * \defgroup FourierUtilityHelpers Helpers - * @{ - */ - -/** - * @brief gn_freq_axis_size - * @return 0 on success, non-zero otherwise - */ -__api int gn_freq_axis_size( - size_t* size, ///< [out] Output array size - size_t nfft, ///< [in] FFT size - GnFreqAxisType axis_type ///< [in] Frequency axis type - ); - -/** @} FourierUtilityHelpers */ - -/** @} FourierUtilities */ - -#ifdef __cplusplus -} // extern "C" -#endif - -/* Manager */ -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \defgroup Manager Manager - * @{ - */ - -/** - * @brief gn_mgr_clear - * @return Always returns 0 - */ -__api int gn_mgr_clear(); - -/** - * @brief gn_mgr_compare - * @return 0 on success, non-zero otherwise - */ -__api int gn_mgr_compare( - bool* result, ///< [out] true if the objects are equal, false otherwise - const char* obj_key1, ///< [in] Object key 1 - const char* obj_key2 ///< [in] Object key 2 - ); - -/** - * @brief gn_mgr_contains - * @return Always returns 0 - */ -__api int gn_mgr_contains( - bool* result, ///< [out] true if Manager contains key, false otherwise - const char* obj_key ///< [in] Object key - ); - -/** - * @brief gn_mgr_remove - * @return Always returns 0 - */ -__api int gn_mgr_remove( - const char* obj_key ///< [in] Object key - ); - -/** - * @brief gn_mgr_save - * @return 0 on success, non-zero otherwise - * @details If filename is empty, the filename is derived from obj_key. - */ -__api int gn_mgr_save( - char* buf, ///< [out] Pointer to character array - size_t size, ///< [in] Size of character array - const char* obj_key, ///< [in] Object key - const char* filename ///< [in] Filename - ); - -/** - * @brief gn_mgr_size - * @return Always returns 0 - */ -__api int gn_mgr_size( - size_t* size ///< [out] Number of objects owned by the manager - ); - -/** - * @brief gn_mgr_to_string - * @return 0 on success, non-zero otherwise - */ -__api int gn_mgr_to_string( - char* buf, ///< [out] Pointer to character array - size_t size, ///< [in] Size of character array - const char* obj_key ///< [in] Object key - ); - -/** - * @brief gn_mgr_type - * @return 0 on success, non-zero otherwise - */ -__api int gn_mgr_type( - char* buf, ///< [out] Pointer to character array - size_t size, ///< [in] Size of character array - const char* obj_key ///< [in] Object key - ); - -/** - * \defgroup ManagerHelpers Helpers - * @{ - */ - -/** - * @brief gn_mgr_save_filename_size - * @return 0 on success, non-zero otherwise - * @details The library string termination setting determines whether or not a null terminator - * is included in the size. See \ref gn_set_string_termination. - */ -__api int gn_mgr_save_filename_size( - size_t* size, ///< [out] Number of characters in filename - const char* obj_key, ///< [in] Object key - const char* filename ///< [in] Filename - ); - -/** - * @brief gn_mgr_to_string_size - * @return 0 on success, non-zero otherwise - * @details The library string termination setting determines whether or not a null terminator - * is included in the size. See \ref gn_set_string_termination. - */ -__api int gn_mgr_to_string_size( - size_t* size, ///< [out] Number of characters in the string - const char* obj_key ///< [in] Object key - ); - -/** - * @brief gn_mgr_type_size - * @return 0 on success, non-zero otherwise - * @details The library string termination setting determines whether or not a null terminator - * is included in the size. See \ref gn_set_string_termination. - */ -__api int gn_mgr_type_size( - size_t* size, ///< [out] Number of characters in object type string - const char* obj_key ///< [in] Object key - ); - -/** @} ManagerHelpers */ - -/** @} Manager */ - -#ifdef __cplusplus -} // extern "C" -#endif - -/* Signal Processing */ -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \defgroup SignalProcessing Signal Processing - * @{ - */ - -/** - * @brief gn_downsample - * @return 0 on success, non-zero otherwise - */ -__api int gn_downsample( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int ratio, ///< [in] Downsample ratio - bool interleaved ///< [in] If true, 'in' is interleaved I/Q data - ); - -/** - * @brief gn_downsample16 - * @return 0 on success, non-zero otherwise - */ -__api int gn_downsample16( - int16_t* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const int16_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int ratio, ///< [in] Downsample ratio - bool interleaved ///< [in] If true, 'in' is interleaved I/Q data - ); - -/** - * @brief gn_downsample32 - * @return 0 on success, non-zero otherwise - */ -__api int gn_downsample32( - int32_t* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const int32_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int ratio, ///< [in] Downsample ratio - bool interleaved ///< [in] If true, 'in' is interleaved I/Q data - ); - -/** - * @brief gn_downsample64 - * @return 0 on success, non-zero otherwise - */ -__api int gn_downsample64( - int64_t* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const int64_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int ratio, ///< [in] Downsample ratio - bool interleaved ///< [in] If true, 'in' is interleaved I/Q data - ); - -/** - * @brief gn_fshift - * @return 0 on success, non-zero otherwise - */ -__api int gn_fshift( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* i, ///< [in] In-phase input array pointer - size_t i_size, ///< [in] In-phase input array size - const double* q, ///< [in] Quadrature input array pointer - size_t q_size, ///< [in] Quadrature input array size - double fs, ///< [in] Sample rate - double fshift ///< [in] Shift frequency - ); - -/** - * @brief gn_fshift16 - * @return 0 on success, non-zero otherwise - */ -__api int gn_fshift16( - int16_t* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const int16_t* i, ///< [in] In-phase input array pointer - size_t i_size, ///< [in] In-phase input array size - const int16_t* q, ///< [in] Quadrature input array pointer - size_t q_size, ///< [in] Quadrature input array size - int n, ///< [in] Code width - double fs, ///< [in] Sample rate - double fshift, ///< [in] Shift frequency - GnCodeFormat format ///< [in] Code format - ); - -/** - * @brief gn_fshift32 - * @return 0 on success, non-zero otherwise - */ -__api int gn_fshift32( - int32_t* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const int32_t* i, ///< [in] In-phase input array pointer - size_t i_size, ///< [in] In-phase input array size - const int32_t* q, ///< [in] Quadrature input array pointer - size_t q_size, ///< [in] Quadrature input array size - int n, ///< [in] Code width - double fs, ///< [in] Sample rate - double fshift, ///< [in] Shift frequency - GnCodeFormat format ///< [in] Code format - ); - -/** - * @brief gn_fshift64 - * @return 0 on success, non-zero otherwise - */ -__api int gn_fshift64( - int64_t* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const int64_t* i, ///< [in] In-phase input array pointer - size_t i_size, ///< [in] In-phase input array size - const int64_t* q, ///< [in] Quadrature input array pointer - size_t q_size, ///< [in] Quadrature input array size - int n, ///< [in] Code width - double fs, ///< [in] Sample rate - double fshift, ///< [in] Shift frequency - GnCodeFormat format ///< [in] Code format - ); - -/** - * @brief gn_normalize16 - * @return 0 on success, non-zero otherwise - */ -__api int gn_normalize16( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const int16_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int n, ///< [in] Resolution - GnCodeFormat format ///< [in] Code format - ); - -/** - * @brief gn_normalize32 - * @return 0 on success, non-zero otherwise - */ -__api int gn_normalize32( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const int32_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int n, ///< [in] Resolution - GnCodeFormat format ///< [in] Code format - ); - -/** - * @brief gn_normalize64 - * @return 0 on success, non-zero otherwise - */ -__api int gn_normalize64( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const int64_t* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - int n, ///< [in] Resolution - GnCodeFormat format ///< [in] Code format - ); - -/** - * @brief gn_polyval - * @return 0 on success, non-zero otherwise - */ -__api int gn_polyval( - double* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - const double* c, ///< [in] Coefficient array pointer - size_t c_size ///< [in] Coefficient array size - ); - -/** - * @brief gn_quantize16 - * @return 0 on success, non-zero otherwise - */ -__api int gn_quantize16( - int16_t* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - double fsr, ///< [in] Full-scale range - int n, ///< [in] Resolution - double noise, ///< [in] Input referred RMS noise - GnCodeFormat format ///< [in] Code format -); - -/** - * @brief gn_quantize32 - * @return 0 on success, non-zero otherwise - */ -__api int gn_quantize32( - int32_t* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - double fsr, ///< [in] Full-scale range - int n, ///< [in] Resolution - double noise, ///< [in] Input referred RMS noise - GnCodeFormat format ///< [in] Code format -); - -/** - * @brief gn_quantize64 - * @return 0 on success, non-zero otherwise - */ -__api int gn_quantize64( - int64_t* out, ///< [out] Output array pointer - size_t out_size, ///< [in] Output array size - const double* in, ///< [in] Input array pointer - size_t in_size, ///< [in] Input array size - double fsr, ///< [in] Full-scale range - int n, ///< [in] Resolution - double noise, ///< [in] Input referred RMS noise - GnCodeFormat format ///< [in] Code format -); - -/** - * \defgroup SignalProcessingHelpers Helpers - * @{ - */ - -/** - * @brief gn_downsample_size - * @return 0 on success, non-zero otherwise - */ -__api int gn_downsample_size( - size_t* out_size, ///< [out] Output array size - size_t in_size, ///< [in] Input array size - int ratio, ///< [in] Downsample ratio - bool interleaved ///< [in] If bool, 'in' is interleaved I/Q data - ); - -/** - * @brief gn_fshift_size - * @return 0 on success, non-zero otherwise - */ -__api int gn_fshift_size( - size_t* out_size, ///< [out] Output array size - size_t i_size, ///< [in] In-phase input array size - size_t q_size ///< [in] Quadrature input array size - ); - -/** @} SignalProcessingHelpers */ - -/** @} SignalProcessing */ - -#ifdef __cplusplus -} // extern "C" -#endif - -/* Waveforms */ -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \defgroup Waveforms Waveforms - * @{ - */ - -/** - * @brief gn_cos - * @return 0 on success, non-zero otherwise - */ -__api int gn_cos( - double* out, ///< [out] Array pointer - size_t size, ///< [in] Array size - double fs, ///< [in] Sample rate (S/s) - double ampl, ///< [in] Amplitude - double freq, ///< [in] Frequency (Hz) - double phase, ///< [in] Phase (rad) - double td, ///< [in] Time delay (s) - double tj ///< [in] RMS Aperture jitter (s) - ); - -/** - * @brief gn_gaussian - * @return 0 on success, non-zero otherwise - */ -__api int gn_gaussian( - double* out, ///< [out] Array pointer - size_t size, ///< [in] Array size - double mean, ///< [in] Mean - double sd ///< [in] Standard deviation - ); - -/** - * @brief gn_ramp - * @return 0 on success, non-zero otherwise - */ -__api int gn_ramp( - double* out, ///< [out] Array pointer - size_t size, ///< [in] Array size - double start, ///< [in] Start value - double stop, ///< [in] Stop value - double noise ///< [in] RMS noise - ); - -/** - * @brief gn_sin - * @return 0 on success, non-zero otherwise - */ -__api int gn_sin( - double* out, ///< [out] Array pointer - size_t size, ///< [in] Array size - double fs, ///< [in] Sample rate (S/s) - double ampl, ///< [in] Amplitude - double freq, ///< [in] Frequency (Hz) - double phase, ///< [in] Phase (rad) - double td, ///< [in] Time delay (s) - double tjrms ///< [in] RMS Aperture jitter (s) - ); - -/** - * @brief gn_wf_analysis - * @return 0 on success, non-zero otherwise - * @details The results contain the following key-value pairs (see general description of - * \ref AnalysisRoutines "Analysis Routines"). - * - *
Key Description - *
min Minumum value - *
max Maximum value - *
mid Middle value ((max + min) / 2) - *
range Range (max - min) - *
avg Average value - *
rms RMS value - *
rmsac RMS value with DC removed - *
min_index Index of first occurence of minimum value - *
max_index Index of first occurence of maximum value - *
- */ -__api int gn_wf_analysis( - char** rkeys, ///< [out] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - double* rvalues, ///< [out] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const double* in, ///< [in] Waveform array pointer - size_t in_size ///< [in] Waveform array size - ); - -/** - * @brief gn_wf_analysis16 - * @return 0 on success, non-zero otherwise - * @details See description of \ref gn_wf_analysis. - */ -__api int gn_wf_analysis16( - char** rkeys, ///< [out] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - double* rvalues, ///< [out] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const int16_t* in, ///< [in] Waveform array pointer - size_t in_size ///< [in] Waveform array size - ); - -/** - * @brief gn_wf_analysis32 - * @return 0 on success, non-zero otherwise - * @details See description of \ref gn_wf_analysis. - */ -__api int gn_wf_analysis32( - char** rkeys, ///< [out] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - double* rvalues, ///< [out] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const int32_t* in, ///< [in] Waveform array pointer - size_t in_size ///< [in] Waveform array size - ); - -/** - * @brief gn_wf_analysis64 - * @return 0 on success, non-zero otherwise - * @details See description of \ref gn_wf_analysis. - */ -__api int gn_wf_analysis64( - char** rkeys, ///< [out] Result keys array pointer - size_t rkeys_size, ///< [in] Result keys array size - double* rvalues, ///< [out] Result values array pointer - size_t rvalues_size, ///< [in] Result values array size - const int64_t* in, ///< [in] Waveform array pointer - size_t in_size ///< [in] Waveform array size - ); - -/** @} Waveforms */ - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // CGENALYZER_ADVANCED_H \ No newline at end of file diff --git a/bindings/c/include/cgenalyzer_private.h b/bindings/c/include/cgenalyzer_private.h index 31c0f36..1d0e41a 100644 --- a/bindings/c/include/cgenalyzer_private.h +++ b/bindings/c/include/cgenalyzer_private.h @@ -22,7 +22,7 @@ #ifndef CGENALYZER_PRIVATE_H #define CGENALYZER_PRIVATE_H -#include "cgenalyzer.h" +#include "cgenalyzer_simplified_beta.h" #include #include diff --git a/bindings/c/include/cgenalyzer_simplified_beta.h b/bindings/c/include/cgenalyzer_simplified_beta.h new file mode 100644 index 0000000..d1d9c73 --- /dev/null +++ b/bindings/c/include/cgenalyzer_simplified_beta.h @@ -0,0 +1,625 @@ +/* + * cgenalyzer - genalyzer (beta) simplified API header file + * + * Copyright (C) 2022 Analog Devices, Inc. + * Author: Srikanth Pagadarai + * + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * */ + + +#ifndef CGENALYZER_SIMPLIFIED_BETA_H +#define CGENALYZER_SIMPLIFIED_BETA_H +#include "cgenalyzer.h" +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifdef _WIN32 +#ifdef GENALYZER_EXPORTS +#define __api __declspec(dllexport) +#else +#define __api __declspec(dllimport) +#endif +#elif __GNUC__ >= 4 && !defined(MATLAB_MEX_FILE) \ + && !defined(MATLAB_LOADLIBRARY) +#define __api __attribute__ ((visibility ("default"))) +#else +#define __api +#endif + + // opaque pointer + typedef struct gn_config_private *gn_config; + + typedef enum tone_type + { + REAL_COSINE, + REAL_SINE, + COMPLEX_EXP + } tone_type; + + /** + * @brief free memory for configuration struct + * @return 0 on success, non-zero otherwise + * @param c genalyzer Configuration struct + */ + __api int gn_config_free( + gn_config *c + ); + + /** + * @brief set configuration struct member: tone_type + * @return 0 on success, non-zero otherwise + * @param ttype ENUM value to indicate input tone type. Options: REAL_COSINE, REAL_SINE, COMPLEX_EXP + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_ttype( + tone_type ttype, + gn_config *c + ); + + /** + * @brief set configuration struct member: npts + * @return 0 on success, non-zero otherwise + * @param npts Number of sample points in the generated waveform + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_npts( + size_t npts, + gn_config *c + ); + + /** + * @brief get configuration struct member: npts + * @return 0 on success, non-zero otherwise + * @param npts Number of sample points in the generated waveform + * @param c genalyzer Configuration struct + */ + __api int gn_config_get_npts( + size_t *npts, + gn_config *c + ); + + /** + * @brief set configuration struct member: sample_rate + * @return 0 on success, non-zero otherwise + * @param sample_rate Input Sample rate of the data converter + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_sample_rate( + double sample_rate, + gn_config *c + ); + + /** + * @brief get configuration struct member: sample_rate + * @return 0 on success, non-zero otherwise + * @param sample_rate Input Sample rate of the data converter + * @param c genalyzer Configuration struct + */ + __api int gn_config_get_sample_rate( + double *sample_rate, + gn_config *c + ); + + /** + * @brief set configuration struct member: data_rate + * @return 0 on success, non-zero otherwise + * @param data_rate Input data rate of the data converter + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_data_rate( + double data_rate, + gn_config *c + ); + + /** + * @brief set configuration struct member: shift_freq + * @return 0 on success, non-zero otherwise + * @param shift_freq Shift frequency of the data converter + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_shift_freq( + double shift_freq, + gn_config *c + ); + + /** + * @brief set configuration struct member: num_tones + * @return 0 on success, non-zero otherwise + * @param num_tones Number of tones to generate + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_num_tones( + size_t num_tones, + gn_config *c + ); + + /** + * @brief set configuration struct member: tone_freq + * @return 0 on success, non-zero otherwise + * @param tone_freq Input array of tone frequencies to generate + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_tone_freq( + double *tone_freq, + gn_config *c + ); + + /** + * @brief set configuration struct member: tone_ampl + * @return 0 on success, non-zero otherwise + * @param tone_ampl Input array of tone scales to generate + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_tone_ampl( + double *tone_ampl, + gn_config *c + ); + + /** + * @brief set configuration struct member: tone_phase + * @return 0 on success, non-zero otherwise + * @param tone_phase Input array of tone phases to generate + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_tone_phase( + double *tone_phase, + gn_config *c + ); + + /** + * @brief set configuration struct member: fsr + * @return 0 on success, non-zero otherwise + * @param fsr Full-scale range of the waveform + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_fsr( + double fsr, + gn_config *c + ); + + /** + * @brief set configuration struct member: qres + * @return 0 on success, non-zero otherwise + * @param qres Quantization resolution + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_qres( + int qres, + gn_config *c + ); + + /** + * @brief set configuration struct member: noise_rms + * @return 0 on success, non-zero otherwise + * @param noise_rms RMS Noise + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_noise_rms( + double noise_rms, + gn_config *c + ); + + /** + * @brief set configuration struct member: code_format + * @return 0 on success, non-zero otherwise + * @param code_format Code format of data + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_code_format( + GnCodeFormat code_format, + gn_config *c + ); + + /** + * @brief set configuration struct member: nfft + * @return 0 on success, non-zero otherwise + * @param nfft FFT order + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_nfft( + size_t nfft, + gn_config *c + ); + + /** + * @brief get configuration struct member: nfft + * @return 0 on success, non-zero otherwise + * @param nfft FFT order + * @param c genalyzer Configuration struct + */ + __api int gn_config_get_nfft( + size_t *nfft, + gn_config *c + ); + + /** + * @brief set configuration struct member: navg + * @return 0 on success, non-zero otherwise + * @param fft_navg Num. of FFTs to average + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_fft_navg( + size_t fft_navg, + gn_config *c + ); + + /** + * @brief set configuration struct member: win + * @return 0 on success, non-zero otherwise + * @param win Window function used + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_win( + GnWindow win, + gn_config *c + ); + + /** + * @brief set configuration struct member: ssb_fund + * @return 0 on success, non-zero otherwise + * @param ssb_fund Single side bin fundamental + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_ssb_fund( + int ssb_fund, + gn_config *c + ); + + /** + * @brief set configuration struct member: ssb_rest + * @return 0 on success, non-zero otherwise + * @param ssb_rest Single side bins rest + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_ssb_rest( + int ssb_rest, + gn_config *c + ); + + /** + * @brief set configuration struct member: max_harm_order + * @return 0 on success, non-zero otherwise + * @param max_harm_order Max order of harmonic + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_max_harm_order( + int max_harm_order, + gn_config *c + ); + + /** + * @brief set configuration struct member: dnla_signal_type + * @return 0 on success, non-zero otherwise + * @param dnla_signal_type DNL analysis signal type + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_dnla_signal_type( + GnDnlSignal dnla_signal_type, + gn_config *c + ); + + /** + * @brief set configuration struct member: inla_fit + * @return 0 on success, non-zero otherwise + * @param inla_fit INL analysis line fit + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_inla_fit( + GnInlLineFit inla_fit, + gn_config *c + ); + + /** + * @brief set configuration struct member: ramp_start + * @return 0 on success, non-zero otherwise + * @param ramp_start start value of ramp + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_ramp_start( + double ramp_start, + gn_config *c + ); + + /** + * @brief set configuration struct member: ramp_stop + * @return 0 on success, non-zero otherwise + * @param ramp_stop stop value of ramp + * @param c genalyzer Configuration struct + */ + __api int gn_config_set_ramp_stop( + double ramp_stop, + gn_config *c + ); + + /** + * @brief get configuration struct member: _code_density_size + * @return 0 on success, non-zero otherwise + * @param code_density_size code density size + * @param c genalyzer Configuration struct + */ + __api int gn_config_get_code_density_size( + size_t *code_density_size, + gn_config *c + ); + + /** + * @brief Configure tone parameters to be used in measurement + * @return 0 on success, non-zero otherwise + * @param ttype ENUM value to indicate input tone type. Options: REAL_COSINE, REAL_SINE, COMPLEX_EXP + * @param npts Number of sample points in the generated waveform + * @param sample_rate Input Sample rate of the data converter + * @param num_tones Number of tones to generate + * @param tone_freq Input array of tone frequencies to generate + * @param tone_ampl Input array of tone scales to generate + * @param tone_phase Input array of tone phases to generate + * @param c Configuration struct containing tone parameters + */ + __api int gn_config_gen_tone ( + tone_type ttype, + size_t npts, + double sample_rate, + size_t num_tones, + double *tone_freq, + double *tone_ampl, + double *tone_phase, + gn_config *c + ); + + /** + * @brief Configure tone parameters to be used in measurement + * @return 0 on success, non-zero otherwise + * @param npts Number of sample points in the generated waveform + * @param ramp_start Input start value of ramp + * @param ramp_stop Input stop value of ramp + * @param c Configuration struct containing ramp parameters + */ + __api int gn_config_gen_ramp( + size_t npts, + double ramp_start, + double ramp_stop, + gn_config *c + ); + + /** + * @brief Configure quantization parameters to be used in measurement + * @return 0 on success, non-zero otherwise + * @param npts Number of sample points in the generated waveform + * @param fsr Full-scale range of the waveform + * @param qres Quantization resolution + * @param qnoise Quantization noise + * @param c Configuration structure + */ + __api int gn_config_quantize( + size_t npts, + double fsr, + int qres, + double qnoise, + gn_config *c + ); + + /** + * @brief Configure parameters to compute histogram + * @return 0 on success, non-zero otherwise + * @param npts Number of sample points in the generated waveform + * @param qres Quantization resolution + * @param c Configuration structure + */ + __api int gn_config_histz_nla( + size_t npts, + int qres, + gn_config *c + ); + + /** + * @brief Configure FFT parameters + * @return 0 on success, non-zero otherwise + */ + __api int gn_config_fftz( + size_t npts, ///< [npts] Number of sample points in the input waveform + int qres, ///< [qres] Quantization resolution + size_t navg, ///< [navg] Number of FFT averages + size_t nfft, ///< [nfft] FFT order + GnWindow win, ///< [win] Window function to apply, Options: GnWindowBlackmanHarris, GnWindowHann, GnWindowNoWindow + gn_config *c ///< [c] Configuration structure containing test parameters + ); + + /** + * @brief Generate sinusoidal tone based on supplied configuration. + * @return 0 on success, non-zero otherwise + */ + __api int gn_config_fa( + double fixed_tone_freq, ///< [fixed_tone_freq] Fixed tone frequency + gn_config *c ///< [c] Configuration structure containing test parameters + ); + + /** + * @brief Generate sinusoidal tone based on supplied configuration without specifying tone manually. + * @return 0 on success, non-zero otherwise + */ + __api int gn_config_fa_auto( + uint8_t ssb_width, ///< [ssb_width] Number of bins to use for fundamental search and keepout of other tones + gn_config *c ///< [c] Configuration structure containing test parameters + ); + + /** + * @brief Generate ramp based on supplied configuration. + * @param out Output array of ramp generated + * @param c Configuration structure of test and waveform to generate + */ + __api int gn_gen_ramp( + double **out, + gn_config *c + ); + + /** + * @brief Generate sinusoidal tone based on supplied configuration. + * @return 0 on success, non-zero otherwise + * @param out Output array of generated tone + * @param c Configuration structure containing test parameters + */ + __api int gn_gen_real_tone( + double **out, + gn_config *c + ); + + /** + * @brief Generate sinusoidal tone based on supplied configuration. + * @return 0 on success, non-zero otherwise + * @param outi In-phase output array of generated tone + * @param outq Quadrature output array of generated tone + * @param c Configuration structure containing test parameters + */ + __api int gn_gen_complex_tone( + double **outi, + double **outq, + gn_config *c + ); + + /** + * @brief Quantize waveform based on supplied configuration. + * @return 0 on success, non-zero otherwise + */ + __api int gn_quantize( + int32_t **out, ///< [out] Quantized output waveform + const double *in, ///< [in] Input waveform to be quantized + gn_config *c ///< [c] Configuration structure containing test parameters + ); + /** + * @brief Compute FFT of quantized input waveform + * @return 0 on success, non-zero otherwise + */ + __api int gn_fftz( + double **out, ///< [out] Interleaved Re/Im FFT output + const int32_t *in_i, ///< [in_i] In-phase input + const int32_t *in_q, ///< [in_q] Quadrature input + gn_config *c ///< [c] Configuration structure containing test parameters + ); + + /** + * @brief Compute histogram of quantized waveform + * @return 0 on success, non-zero otherwise + */ + __api int gn_histz( + uint64_t **hist, ///< [hist] Output - Histogram of input quantized waveform + size_t *hist_len, ///< [hist_len] Output - Histogram size + const int32_t *qwf, ///< [qwf] Input - Quantized input waveform + gn_config *c ///< [c] Input - Configuration structure containing test parameters + ); + + /** + * @brief Compute histogram of quantized waveform + * @return 0 on success, non-zero otherwise + */ + __api int gn_dnlz( + double **dnl, + size_t *dnl_len, + const uint64_t *hist, + gn_config *c + ); + + /** + * @brief Compute histogram of quantized waveform + * @return 0 on success, non-zero otherwise + */ + + __api int gn_inlz( + double **inl, + size_t *inl_len, + const double *dnl, + gn_config *c + ); + + /** + * @brief Do waveform analysis and all get results + * @return 0 on success, non-zero otherwise + */ + __api int gn_get_wfa_results( + char ***rkeys, + double **rvalues, + size_t *results_size, ///< [results_size] size of results + const int32_t *qwf, ///< [qwf] Input - Quantized input array pointer + gn_config *c ///< [c] Input - Configuration structure containing test parameters + ); + + /** + * @brief Do histogram analysis and get results + * @return 0 on success, non-zero otherwise + */ + __api int gn_get_ha_results( + char ***rkeys, ///< [rkeys] Output - Result keys + double **rvalues, ///< [rvalues] Output - Result values + size_t *results_size, ///< [results_size] Output - Size of results + const uint64_t *hist, ///< [hist] Input - Histogram input to be analyzed + gn_config *c ///< [c] Input - Configuration structure containing test parameters + ); + + /** + * @brief Do DNL analysis and get results + * @return 0 on success, non-zero otherwise + */ + __api int gn_get_dnla_results( + char ***rkeys, ///< [rkeys] Output - Result keys + double **rvalues, ///< [rvalues] Output - Result values + size_t *results_size, ///< [results_size] Output - Size of results + const double *dnl, ///< [dnl] Input - DNL input to be analyzed + gn_config *c ///< [c] Input - Configuration structure containing test parameters + ); + + /** + * @brief Do INL analysis and get results + * @return 0 on success, non-zero otherwise + */ + __api int gn_get_inla_results( + char ***rkeys, ///< [rkeys] Output - Result keys + double **rvalues, ///< [rvalues] Output - Result values + size_t *results_size, ///< [results_size] Output - Size of results + const double *inl, ///< [dnl] Input - INL input to be analyzed + gn_config *c ///< [c] Input - Configuration structure containing test parameters + ); + + /** + * @brief Do Fourier analysis and get a single result + * @return 0 on success, non-zero otherwise + */ + __api int gn_get_fa_single_result( + double *rvalue, + const char* metric_name, + double *fft_ilv, ///< [fft_ilv] Input - Interleaved Re/Im array pointer + gn_config *c ///< [c] Input - Configuration structure containing test parameters + ); + + /** + * @brief Do Fourier analysis and all get results + * @return 0 on success, non-zero otherwise + */ + __api int gn_get_fa_results( + char ***rkeys, + double **rvalues, + size_t *results_size, ///< [results_size] size of results + double *fft_ilv, ///< [fft_ilv] Input - Interleaved Re/Im array pointer + gn_config *c ///< [c] Input - Configuration structure containing test parameters + ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/bindings/c/src/CMakeLists.txt b/bindings/c/src/CMakeLists.txt index 9974aa3..45c70e7 100644 --- a/bindings/c/src/CMakeLists.txt +++ b/bindings/c/src/CMakeLists.txt @@ -1,5 +1,5 @@ file(GLOB SOURCE_LIST CONFIGURE_DEPENDS "${PROJECT_SOURCE_DIR}/bindings/c/src/*.cpp" "${PROJECT_SOURCE_DIR}/bindings/c/src/*.c") -set(GENALYZER_MAIN_HEADER "${PROJECT_SOURCE_DIR}/bindings/c/include/cgenalyzer.h") +set(GENALYZER_MAIN_HEADER "${PROJECT_SOURCE_DIR}/bindings/c/include/cgenalyzer_simplified_beta.h") add_definitions(-DGENALYZER_EXPORTS) diff --git a/bindings/c/src/cgenalyzer.cpp b/bindings/c/src/cgenalyzer.cpp index e503422..b0c240a 100644 --- a/bindings/c/src/cgenalyzer.cpp +++ b/bindings/c/src/cgenalyzer.cpp @@ -1,1169 +1,1736 @@ #include "cgenalyzer.h" #include "cgenalyzer_private.h" -extern "C" { - int gn_config_free(gn_config *c) +using namespace util; + +namespace util { + + static bool gn_null_terminate = true; + + size_t terminated_size(size_t string_size) { - if ((*c)->obj_key){ - gn_mgr_remove((*c)->obj_key); - free((*c)->obj_key); - } - if ((*c)->comp_key){ - gn_fa_remove_comp((*c)->obj_key, (*c)->comp_key); - free((*c)->comp_key); - } - if (((*c)->_fa_results_size) > 0) - { - for (size_t i = 0; i < (*c)->_fa_results_size; i++) - free((*c)->_fa_result_keys[i]); - free((*c)->_fa_result_keys); - free((*c)->_fa_result_key_sizes); - free((*c)->_fa_result_values); + return string_size + (util::gn_null_terminate ? 1 : 0); + } + + void fill_string_buffer( + const char* src, // Pointer to source + size_t src_size, // Size of source; should not count null-terminator, if it exists + char* dst, // Pointer to destination + size_t dst_size // Size of destination + ) + { + if (nullptr == src) { + throw std::runtime_error("fill_string_buffer : source is NULL"); } - if (((*c)->_wfa_results_size) > 0) - { - for (size_t i = 0; i < (*c)->_wfa_results_size; i++) - free((*c)->_wfa_result_keys[i]); - free((*c)->_wfa_result_keys); - free((*c)->_wfa_result_key_sizes); - free((*c)->_wfa_result_values); + if (nullptr == dst) { + throw std::runtime_error("fill_string_buffer : destination is NULL"); } - if (((*c)->_hist_results_size) > 0) - { - for (size_t i = 0; i < (*c)->_hist_results_size; i++) - free((*c)->_hist_result_keys[i]); - free((*c)->_hist_result_keys); - free((*c)->_hist_result_key_sizes); - free((*c)->_hist_result_values); + if (dst_size < terminated_size(src_size)) { + throw std::runtime_error("fill_string_buffer : destination too small"); } - if (((*c)->_dnl_results_size) > 0) - { - for (size_t i = 0; i < (*c)->_dnl_results_size; i++) - free((*c)->_dnl_result_keys[i]); - free((*c)->_dnl_result_keys); - free((*c)->_dnl_result_key_sizes); - free((*c)->_dnl_result_values); + for (size_t i = 0; i < src_size; ++i) { + dst[i] = src[i]; } - if (((*c)->_inl_results_size) > 0) - { - for (size_t i = 0; i < (*c)->_inl_results_size; i++) - free((*c)->_inl_result_keys[i]); - free((*c)->_inl_result_keys); - free((*c)->_inl_result_key_sizes); - free((*c)->_inl_result_values); + if (gn_null_terminate) { + dst[src_size] = '\0'; } - free(*c); - - return gn_success; } - int gn_config_set_ttype(tone_type ttype, gn_config *c) + std::string get_object_key_from_filename(const std::string& filename) { - if (!((ttype == REAL_COSINE) || (ttype == REAL_SINE) || (ttype == COMPLEX_EXP))) - { - printf("ERROR: Invalid selection of ttype for tone generation\n"); - return gn_failure; - } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; + static const std::regex re {"(" + gn::manager::key_pattern + ")[.]json$", std::regex::icase}; + std::smatch matches; + if (std::regex_search(filename, matches, re)) { + if (1 == matches.size()) { + throw std::runtime_error("unable to derive object key from filename '" + filename + "'"); } - else - *c = c_p; - } - (*c)->ttype = ttype; - - return gn_success; + return matches[1].str(); + } else { + throw std::runtime_error("invalid filename '" + filename + "'"); + } } - int gn_config_set_npts(size_t npts, gn_config *c) - { - if (!(*c)) +} // namespace util + +/**************************************************************************/ +/* API Utilities */ +/**************************************************************************/ + +int gn_analysis_results_key_sizes(size_t* key_sizes, size_t key_sizes_size, GnAnalysisType type) +{ + try { + util::check_pointer(key_sizes); + std::vector keys; + switch (gn::get_enum(type)) { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; + case gn::AnalysisType::DNL : + keys = gn::dnl_analysis_ordered_keys(); + break; + case gn::AnalysisType::Histogram : + keys = gn::hist_analysis_ordered_keys(); + break; + case gn::AnalysisType::INL : + keys = gn::inl_analysis_ordered_keys(); + break; + case gn::AnalysisType::Waveform : + keys = gn::wf_analysis_ordered_keys(); + break; + default : + throw std::runtime_error("Invalid analysis type"); + } + if (keys.size() != key_sizes_size) { + throw std::runtime_error("Number of keys does not match output array size"); + } + for (size_t i = 0; i < key_sizes_size; ++i) { + key_sizes[i] = util::terminated_size(keys[i].size()); } - (*c)->npts = npts; return gn_success; + } catch (const std::exception& e) { + std::fill(key_sizes, key_sizes + key_sizes_size, 0); + return util::return_on_exception("gn_analysis_results_key_sizes : ", e.what()); } +} - int gn_config_get_npts(size_t *npts, gn_config *c) - { - if (!(*c)) +int gn_analysis_results_size(size_t* size, GnAnalysisType type) +{ + try { + util::check_pointer(size); + switch (gn::get_enum(type)) { - printf("config struct is NULL\n"); - return gn_failure; + case gn::AnalysisType::DNL : + *size = gn::dnl_analysis_ordered_keys().size(); + break; + case gn::AnalysisType::Histogram : + *size = gn::hist_analysis_ordered_keys().size(); + break; + case gn::AnalysisType::INL : + *size = gn::inl_analysis_ordered_keys().size(); + break; + case gn::AnalysisType::Waveform : + *size = gn::wf_analysis_ordered_keys().size(); + break; + default : + throw std::runtime_error("Invalid analysis type"); } - *npts = (*c)->npts; return gn_success; + } catch (const std::exception& e) { + *size = 0; + return util::return_on_exception("gn_analysis_results_size : ", e.what()); } +} - int gn_config_set_sample_rate(gn::real_t sample_rate, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->sample_rate = sample_rate; +int gn_enum_value(int* value, const char* enumeration, const char* enumerator) +{ + try { + util::check_pointer(value); + *value = gn::enum_value(enumeration, enumerator); return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_enum_value : ", e.what()); } +} - int gn_config_get_sample_rate(double *sample_rate, gn_config *c) - { - if (!(*c)) - { - printf("config struct is NULL\n"); - return gn_failure; - } - *sample_rate = (*c)->sample_rate; +int gn_error_check(bool* error) +{ + try { + util::check_pointer(error); + *error = util::gn_error_log.check(); return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_error_check : ", e.what()); } - - int gn_config_set_data_rate(gn::real_t data_rate, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->data_rate = data_rate; +} + +int gn_error_clear() +{ + util::gn_error_log.clear(); + return gn_success; +} + +int gn_error_string(char* buf, size_t size) +{ + try { + std::string_view s = util::gn_error_log.get(); + util::fill_string_buffer(s.data(), s.size(), buf, size); + } catch (const std::exception&) { + return gn_failure; + } + return gn_success; +} + +int gn_set_string_termination(bool null_terminated) +{ + util::gn_null_terminate = null_terminated; + return gn_success; +} + +int gn_version_string(char* buf, size_t size) +{ + try { + std::string_view s = gn::version_string(); + util::fill_string_buffer(s.data(), s.size(), buf, size); + } catch (const std::exception& e) { + return util::return_on_exception("gn_version_string : ", e.what()); + } + return gn_success; +} + +/**************************************************************************/ +/* API Utility Helpers */ +/**************************************************************************/ + +int gn_error_string_size(size_t* size) +{ + try { + util::check_pointer(size); + *size = util::terminated_size(util::gn_error_log.size()); return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_error_string_size : ", e.what()); } +} - int gn_config_set_shift_freq(gn::real_t shift_freq, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->shift_freq = shift_freq; +int gn_version_string_size(size_t* size) +{ + try { + util::check_pointer(size); + *size = util::terminated_size(gn::version_string().size()); return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_version_string_size : ", e.what()); } +} - int gn_config_set_num_tones(size_t num_tones, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->num_tones = num_tones; +/**************************************************************************/ +/* Array Operations */ +/**************************************************************************/ + +int gn_abs(double* out, size_t out_size, const double* in, size_t in_size) +{ + try { + gn::abs(in, in_size, out, out_size); return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_abs : ", e.what()); } +} - int gn_config_set_tone_freq(gn::real_t *tone_freq, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->tone_freq = tone_freq; +int gn_angle(double* out, size_t out_size, const double* in, size_t in_size) +{ + try { + gn::angle(in, in_size, out, out_size); return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_angle : ", e.what()); } +} - int gn_config_set_tone_ampl(gn::real_t *tone_ampl, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->tone_ampl = tone_ampl; +int gn_db(double* out, size_t out_size, const double* in, size_t in_size) +{ + try { + gn::db(in, in_size, out, out_size); return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_db : ", e.what()); } +} - int gn_config_set_tone_phase(gn::real_t *tone_phase, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->tone_phase = tone_phase; +int gn_db10(double* out, size_t out_size, const double* in, size_t in_size) +{ + try { + gn::db10(in, in_size, out, out_size); return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_db10 : ", e.what()); } +} - int gn_config_set_fsr(gn::real_t fsr, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->fsr = fsr; +int gn_db20(double* out, size_t out_size, const double* in, size_t in_size) +{ + try { + gn::db20(in, in_size, out, out_size); return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_db20 : ", e.what()); } +} - int gn_config_set_qres(int qres, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->qres = qres; +int gn_norm(double* out, size_t out_size, const double* in, size_t in_size) +{ + try { + gn::norm(in, in_size, out, out_size); return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_norm : ", e.what()); } +} + +/**************************************************************************/ +/* Code Density */ +/**************************************************************************/ + +namespace { - int gn_config_set_noise_rms(gn::real_t noise_rms, gn_config *c) + template + int gn_hist(const char* suffix, uint64_t* hist, size_t hist_size, + const T* in, size_t in_size, int n, GnCodeFormat format, bool preserve) { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; + try { + gn::CodeFormat f = gn::get_enum(format); + gn::hist(hist, hist_size, in, in_size, n, f, preserve); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_hist", suffix, " : ", e.what()); } - (*c)->noise_rms = noise_rms; - return gn_success; } - int gn_config_set_code_format(GnCodeFormat code_format, gn_config *c) + template + int gn_histx(const char* suffix, uint64_t* hist, size_t hist_size, + const T* in, size_t in_size, int64_t min, int64_t max, bool preserve) { - if (!((code_format == GnCodeFormatOffsetBinary) || (code_format == GnCodeFormatTwosComplement))) - { - printf("ERROR: Invalid selection of code format\n"); - return gn_failure; - } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; + try { + gn::histx(hist, hist_size, in, in_size, min, max, preserve); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_histx", suffix, " : ", e.what()); } - (*c)->code_format = code_format; - return gn_success; } - int gn_config_set_nfft(size_t nfft, gn_config *c) - { - if (((*c)->nfft) > ((*c)->npts)) - { - printf("ERROR: FFT order cannot be greater than the number of sample points\n"); - return gn_failure; - } +} // namespace anonymous - double rem = 1.0*(((*c)->npts)%((*c)->nfft)); - if (rem > 0) - { - printf("ERROR: FFT order has to be a multiple of the number of sample points\n"); - return gn_failure; - } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->nfft = nfft; - (*c)->fft_navg = (*c)->npts/(*c)->nfft; +int gn_code_axis(double* out, size_t size, int n, GnCodeFormat format) +{ + try { + gn::CodeFormat f = gn::get_enum(format); + gn::code_axis(out, size, n, f); return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_code_axis : ", e.what()); } - - int gn_config_get_nfft(size_t *nfft, gn_config *c) - { - if (!(*c)) - { - printf("here - config struct is NULL\n"); - return gn_failure; - } - *nfft = (*c)->nfft; +} + +int gn_code_axisx(double* out, size_t size, int64_t min, int64_t max) +{ + try { + gn::code_axisx(out, size, min, max); return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_code_axisx : ", e.what()); } +} - int gn_config_set_fft_navg(size_t fft_navg, gn_config *c) - { - if (((*c)->fft_navg) > ((*c)->npts)) - { - printf("ERROR: Number of FFT averages cannot be greater than the number of sample points\n"); - return gn_failure; +int gn_dnl(double* dnl, size_t dnl_size, const uint64_t* hist, size_t hist_size, GnDnlSignal type) +{ + try { + gn::DnlSignal t = gn::get_enum(type); + gn::dnl(dnl, dnl_size, hist, hist_size, t); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_dnl : ", e.what()); + } +} + +int gn_dnl_analysis(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, + const double* dnl, size_t dnl_size) +{ + try { + util::check_pointer(rkeys); + util::check_pointer(rvalues); + const std::vector& keys = gn::dnl_analysis_ordered_keys(); + if (keys.size() != rkeys_size) { + throw std::runtime_error("Size of result key array is wrong"); } - - double rem = 1.0*(((*c)->npts)%((*c)->fft_navg)); - if (rem > 0) - { - printf("ERROR: Number of FFT averages has to be a multiple of the number of sample points\n"); - return gn_failure; + if (rvalues_size != rkeys_size) { + throw std::runtime_error("Size of result keys does not match size of result values"); } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; + std::map results = gn::dnl_analysis(dnl, dnl_size); + for (size_t i = 0; i < keys.size(); ++i) { + const std::string& src = keys[i]; + char* dst = rkeys[i]; + size_t dst_size = util::terminated_size(src.size()); + util::fill_string_buffer(src.data(), src.size(), dst, dst_size); + rvalues[i] = results.at(src); } - (*c)->fft_navg = fft_navg; - (*c)->nfft = (*c)->npts/(*c)->fft_navg; return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_dnl_analysis : ", e.what()); } - - int gn_config_set_win(GnWindow win, gn_config *c) - { - if (!((win == GnWindowBlackmanHarris) || (win == GnWindowHann) || (win == GnWindowNoWindow))) - { - printf("ERROR: Invalid selection of window function\n"); - return gn_failure; +} + +int gn_hist16(uint64_t* hist, size_t hist_size, const int16_t* in, size_t in_size, + int n, GnCodeFormat format, bool preserve) +{ + return gn_hist("16", hist, hist_size, in, in_size, n, format, preserve); +} + +int gn_hist32(uint64_t* hist, size_t hist_size, const int32_t* in, size_t in_size, + int n, GnCodeFormat format, bool preserve) +{ + return gn_hist("32", hist, hist_size, in, in_size, n, format, preserve); +} + +int gn_hist64(uint64_t* hist, size_t hist_size, const int64_t* in, size_t in_size, + int n, GnCodeFormat format, bool preserve) +{ + return gn_hist("64", hist, hist_size, in, in_size, n, format, preserve); +} + +int gn_histx16(uint64_t* hist, size_t hist_size, const int16_t* in, size_t in_size, + int64_t min, int64_t max, bool preserve) +{ + return gn_histx("16", hist, hist_size, in, in_size, min, max, preserve); +} + +int gn_histx32(uint64_t* hist, size_t hist_size, const int32_t* in, size_t in_size, + int64_t min, int64_t max, bool preserve) +{ + return gn_histx("32", hist, hist_size, in, in_size, min, max, preserve); +} + +int gn_histx64(uint64_t* hist, size_t hist_size, const int64_t* in, size_t in_size, + int64_t min, int64_t max, bool preserve) +{ + return gn_histx("64", hist, hist_size, in, in_size, min, max, preserve); +} + +int gn_hist_analysis(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, + const uint64_t* hist, size_t hist_size) +{ + try { + util::check_pointer(rkeys); + util::check_pointer(rvalues); + const std::vector& keys = gn::hist_analysis_ordered_keys(); + if (keys.size() != rkeys_size) { + throw std::runtime_error("Size of result key array is wrong"); } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; + if (rvalues_size != rkeys_size) { + throw std::runtime_error("Size of result keys does not match size of result values"); } - (*c)->win = win; - return gn_success; - } - - int gn_config_set_ssb_fund(int ssb_fund, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; + std::map results = gn::hist_analysis(hist, hist_size); + for (size_t i = 0; i < keys.size(); ++i) { + const std::string& src = keys[i]; + char* dst = rkeys[i]; + size_t dst_size = util::terminated_size(src.size()); + util::fill_string_buffer(src.data(), src.size(), dst, dst_size); + rvalues[i] = results.at(src); } - (*c)->ssb_fund = ssb_fund; return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_hist_analysis : ", e.what()); } +} - int gn_config_set_ssb_rest(int ssb_rest, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; +int gn_inl(double* inl, size_t inl_size, const double* dnl, size_t dnl_size, GnInlLineFit fit) +{ + try { + gn::InlLineFit f = gn::get_enum(fit); + gn::inl(inl, inl_size, dnl, dnl_size, f); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_inl : ", e.what()); + } +} + +int gn_inl_analysis(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, + const double* inl, size_t inl_size) +{ + try { + util::check_pointer(rkeys); + util::check_pointer(rvalues); + const std::vector& keys = gn::inl_analysis_ordered_keys(); + if (keys.size() != rkeys_size) { + throw std::runtime_error("Size of result key array is wrong"); + } + if (rvalues_size != rkeys_size) { + throw std::runtime_error("Size of result keys does not match size of result values"); } - (*c)->ssb_rest = ssb_rest; + std::map results = gn::inl_analysis(inl, inl_size); + for (size_t i = 0; i < keys.size(); ++i) { + const std::string& src = keys[i]; + char* dst = rkeys[i]; + size_t dst_size = util::terminated_size(src.size()); + util::fill_string_buffer(src.data(), src.size(), dst, dst_size); + rvalues[i] = results.at(src); + } + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_inl_analysis : ", e.what()); + } +} + +/**************************************************************************/ +/* Code Density Helpers */ +/**************************************************************************/ + +int gn_code_density_size(size_t* size, int n, GnCodeFormat format) +{ + try { + util::check_pointer(size); + gn::CodeFormat f = gn::get_enum(format); + *size = gn::code_density_size(n, f); return gn_success; + } catch (const std::exception& e) { + *size = 0; + return util::return_on_exception("gn_code_density_size : ", e.what()); } +} - int gn_config_set_max_harm_order(int max_harm_order, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->max_harm_order = max_harm_order; +int gn_code_densityx_size(size_t* size, int64_t min, int64_t max) +{ + try { + util::check_pointer(size); + *size = gn::code_densityx_size(min, max); return gn_success; + } catch (const std::exception& e) { + *size = 0; + return util::return_on_exception("gn_code_densityx_size : ", e.what()); } +} - int gn_config_set_dnla_signal_type(GnDnlSignal dnla_signal_type, gn_config *c) +/**************************************************************************/ +/* Fourier Analysis */ +/**************************************************************************/ + +namespace { + + using fa_ptr = std::shared_ptr; + + fa_ptr get_fa_object(const std::string& obj_key) { - if (!((dnla_signal_type == GnDnlSignalRamp) || (dnla_signal_type == GnDnlSignalTone))) - { - printf("ERROR: Invalid selection of DNL analysis signal type\n"); - return gn_failure; + gn::object::pointer pobj = gn::manager::get_object(obj_key); + const gn::ObjectType obj_type = gn::ObjectType::FourierAnalysis; + if (obj_type != pobj->object_type()) { + throw std::runtime_error("object '" + obj_key + "' is not of type " + + gn::object_type_map.at(static_cast(obj_type))); } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->dnla_signal_type = dnla_signal_type; - return gn_success; + return std::static_pointer_cast(pobj); } - int gn_config_set_inla_fit(GnInlLineFit inla_fit, gn_config *c) + fa_ptr get_fa_object_or_load_from_file(std::string cfg_id) { - if (!((inla_fit == GnInlLineFitBestFit) || (inla_fit == GnInlLineFitEndFit) || (inla_fit == GnInlLineFitNoFit))) - { - printf("ERROR: Invalid selection of INL line fit\n"); - return gn_failure; - } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; + if (gn::manager::contains(cfg_id)) { + return get_fa_object(cfg_id); + } else { + return gn::fourier_analysis::load(cfg_id); } - (*c)->inla_fit = inla_fit; - return gn_success; } - int gn_config_set_ramp_start(double ramp_start, gn_config *c) + size_t get_fa_result_key_index(const char** rkeys, size_t rkeys_size, const char* rkey) { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; + size_t i = 0; + for (; i < rkeys_size; ++i) { + if (0 == strcmp(rkeys[i], rkey)) { + break; } - else - *c = c_p; } - (*c)->ramp_start = ramp_start; - return gn_success; + if (rkeys_size == i) { + throw std::runtime_error("Result key '" + std::string(rkey) + "' not found"); + } + return i; } - int gn_config_set_ramp_stop(double ramp_stop, gn_config *c) + std::string get_fa_result_string(const char** rkeys, size_t rkeys_size, + const double* rvalues, size_t rvalues_size, const char* rkey) { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; + if (rkeys_size != rvalues_size) { + throw std::runtime_error("Size of result keys does not match size of result values"); + } + if (gn::fa_result_map.contains(rkey, true)) { + gn::FAResult renum = static_cast(gn::fa_result_map.at(rkey)); + if (gn::FAResult::CarrierIndex == renum || + gn::FAResult::MaxSpurIndex == renum) { + // Caller requests the Carrier or MaxSpur tone key. + size_t key_index = get_fa_result_key_index(rkeys, rkeys_size, rkey); + size_t order_index = static_cast(rvalues[key_index]); + int order_index_int = static_cast(gn::FAToneResult::OrderIndex); + std::string search_str = ":" + gn::fa_tone_result_map.at(order_index_int); + const char* search_cstr = search_str.c_str(); + size_t i = 0; + for (; i < rvalues_size; ++i) { + if (strstr(rkeys[i], search_cstr)) { + if (rvalues[i] == order_index) { + break; + } + } + } + if (rvalues_size == i) { + return "Not Found"; + } else { + return gn::fourier_analysis::split_key(rkeys[i]).first; + } } - else - *c = c_p; + } else { + // In the future, there could be a string associated with a tone result. } - (*c)->ramp_stop = ramp_stop; - return gn_success; + throw std::runtime_error("no string associated with result key '" + std::string(rkey) + "'"); } - int gn_config_get_code_density_size(size_t *code_density_size, gn_config *c) + int get_fa_single_result( + const gn::fourier_analysis_results& results, const char* rkey, double* rvalue) { - if (!(*c)) - { - printf("config struct is NULL\n"); - return gn_failure; + *rvalue = 0.0; + std::pair keys = gn::fourier_analysis::split_key(rkey); + if (!keys.first.empty()) { + if (keys.second.empty()) { + if (gn::fa_result_map.contains(keys.first)) { + int i = gn::fa_result_map.at(keys.first); + *rvalue = results.get(static_cast(i)); + return gn_success; + } + } else { + if (results.contains_tone(keys.first)) { + const gn::fa_tone_results& tres = results.get_tone(keys.first); + if (gn::fa_tone_result_map.at(keys.second)) { + int i = gn::fa_tone_result_map.at(keys.second); + *rvalue = tres.get(static_cast(i)); + return gn_success; + } + } + } } - *code_density_size = (*c)->_code_density_size; - return gn_success; + return gn_failure; } - int gn_config_gen_tone(tone_type ttype, size_t npts, gn::real_t sample_rate, size_t num_tones, gn::real_t *tone_freq, gn::real_t *tone_ampl, gn::real_t *tone_phase, gn_config *c) - { - if (!((ttype == REAL_COSINE) || (ttype == REAL_SINE) || (ttype == COMPLEX_EXP))) - { - printf("ERROR: Invalid selection of waveform type for tone generation\n"); - return gn_failure; - } +} // namespace anonymous - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; +int gn_fft_analysis(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, + const char* cfg_id, const double* in, size_t in_size, size_t nfft, GnFreqAxisType axis_type) +{ + try { + if (rkeys_size != rvalues_size) { + throw std::runtime_error("Size of result keys does not match size of result values"); + } + fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); + gn::FreqAxisType at = gn::get_enum(axis_type); + gn::fourier_analysis_results results = obj->analyze(in, in_size, nfft, at); + // The rest of this function flattens results into a key-array and value-array pair + size_t i = 0; // index for rkeys, rvalues + const std::map& rmap = results.results; + for (int j = 0; j < static_cast(gn::FAResult::__SIZE__); ++j) { + const std::string& src = gn::fa_result_map.at(j); + char* dst = rkeys[i]; + size_t dst_size = util::terminated_size(src.size()); + util::fill_string_buffer(src.data(), src.size(), dst, dst_size); + rvalues[i] = rmap.at(static_cast(j)); + i += 1; + } + for (const std::string& tkey : results.tone_keys) { + const gn::fa_tone_results& tone_results = results.get_tone(tkey); + const std::map& trmap = tone_results.results; + for (int j = 0; j < static_cast(gn::FAToneResult::__SIZE__); ++j) { + std::string src = gn::fourier_analysis::flat_tone_key(tkey, j); + char* dst = rkeys[i]; + size_t dst_size = util::terminated_size(src.size()); + util::fill_string_buffer(src.data(), src.size(), dst, dst_size); + rvalues[i] = trmap.at(static_cast(j)); + i += 1; } - else - *c = c_p; } - (*c)->ttype = ttype; - (*c)->npts = npts; - (*c)->sample_rate = sample_rate; - (*c)->num_tones = num_tones; - (*c)->tone_freq = tone_freq; - (*c)->tone_ampl = tone_ampl; - (*c)->tone_phase = tone_phase; - return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_execute : ", e.what()); } - - int gn_config_gen_ramp(size_t npts, double ramp_start, double ramp_stop, gn_config *c) - { - if (ramp_stop < ramp_start) - { - printf("ERROR: ramp stop value cannot be smaller than ramp start value for ramp generation\n"); - return gn_failure; +} + +int gn_fft_analysis_select(double* rvalues, size_t rvalues_size, + const char* cfg_id, const char** rkeys, size_t rkeys_size, + const double* in, size_t in_size, size_t nfft, GnFreqAxisType axis_type) +{ + try { + if (rkeys_size != rvalues_size) { + throw std::runtime_error("Size of result keys does not match size of result values"); } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; + fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); + gn::FreqAxisType at = gn::get_enum(axis_type); + gn::fourier_analysis_results results = obj->analyze(in, in_size, nfft, at); + std::string missing_keys {}; + for (size_t i = 0; i < rkeys_size; ++i) { + int error = get_fa_single_result(results, rkeys[i], &rvalues[i]); + if (error) { + if (!missing_keys.empty()) { + missing_keys += ", "; + } + missing_keys.append("'" + std::string(rkeys[i]) + "'"); } - else - *c = c_p; } - (*c)->npts = npts; - (*c)->ramp_start = ramp_start; - (*c)->ramp_stop = ramp_stop; - (*c)->noise_rms = 0.0; - + if (!missing_keys.empty()) { + throw std::runtime_error("Keys not found: " + missing_keys); + } return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_execute2 : ", e.what()); } - - int gn_config_quantize(size_t npts, gn::real_t fsr, int qres, gn::real_t noise_rms, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; +} + +int gn_fft_analysis_single(double* rvalue, + const char* cfg_id, const char* rkey, + const double* in, size_t in_size, size_t nfft, GnFreqAxisType axis_type) +{ + try { + fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); + gn::FreqAxisType at = gn::get_enum(axis_type); + gn::fourier_analysis_results results = obj->analyze(in, in_size, nfft, at); + int error = get_fa_single_result(results, rkey, rvalue); + if (error) { + throw std::runtime_error("Key '" + std::string(rkey) + "' not found"); } - (*c)->npts = npts; - (*c)->fsr = fsr; - (*c)->qres = qres; - (*c)->noise_rms = noise_rms; - (*c)->code_format = GnCodeFormatTwosComplement; - return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_execute1 : ", e.what()); } - - int gn_config_histz_nla(size_t npts, int qres, gn_config *c) - { - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - (*c)->npts = npts; - (*c)->qres = qres; - (*c)->code_format = GnCodeFormatTwosComplement; - (*c)->inla_fit = GnInlLineFitBestFit; - +} + +/**************************************************************************/ +/* Fourier Analysis Configuration */ +/**************************************************************************/ + +int gn_fa_analysis_band(const char* obj_key, double center, double width) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + std::string center_s = gn::to_string(center, gn::FPFormat::Eng); + std::string width_s = gn::to_string(width, gn::FPFormat::Eng); + obj->set_analysis_band(center_s, width_s); return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_analysis_band : ", e.what()); } +} - int gn_config_fftz(size_t npts, int qres, size_t fft_navg, size_t nfft, GnWindow win, gn_config *c) - { - if (npts != (fft_navg*nfft)) - { - printf("ERROR: Number of samples points in the waveform has to equal FFT order times number of FFT averages\n"); - return gn_failure; - } - - if (!((win == GnWindowBlackmanHarris) || (win == GnWindowHann) || (win == GnWindowNoWindow))) - { - printf("ERROR: Invalid selection of window function\n"); - return gn_failure; - } - - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } - - (*c)->npts = npts; - (*c)->qres = qres; - (*c)->fft_navg = fft_navg; - (*c)->nfft = nfft; - (*c)->win = win; - (*c)->code_format = GnCodeFormatTwosComplement; - +int gn_fa_analysis_band_e(const char* obj_key, const char* center, const char* width) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + obj->set_analysis_band(center, width); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_analysis_band_e : ", e.what()); + } +} + +int gn_fa_clk(const char* obj_key, const int* clk, size_t clk_size, bool as_noise) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + std::set clk2 (clk, clk + clk_size); + obj->set_clk(clk2); + obj->clk_as_noise = as_noise; return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_clk : ", e.what()); } +} - int gn_config_fa_auto(uint8_t ssb_width, gn_config *c) - { - int err_code; +int gn_fa_conv_offset(const char* obj_key, bool enable) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + obj->en_conv_offset = enable; + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_conv_offset : ", e.what()); + } +} - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; - } +int gn_fa_create(const char* obj_key) +{ + try { + gn::manager::add_object(obj_key, gn::fourier_analysis::create(), false); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_create : ", e.what()); + } +} - if ((*c)->sample_rate <= 0) { - printf("ERROR: Sample rate must be set before configuring Fourier analysis\n"); - return gn_failure; - } +int gn_fa_dc(const char* obj_key, bool as_dist) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + obj->dc_as_dist = as_dist; + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_dc : ", e.what()); + } +} + +int gn_fa_fdata(const char* obj_key, double f) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + std::string f_s = gn::to_string(f, gn::FPFormat::Eng); + obj->set_fdata(f_s); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_fdata : ", e.what()); + } +} - (*c)->obj_key = (char *)calloc(3, sizeof(char)); - strcpy((*c)->obj_key, "fa"); - (*c)->comp_key = (char *)calloc(2, sizeof(char)); - strcpy((*c)->comp_key, "A"); +int gn_fa_fdata_e(const char* obj_key, const char* f) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + obj->set_fdata(f); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_fdata_e : ", e.what()); + } +} + +int gn_fa_fixed_tone( + const char* obj_key, const char* comp_key, GnFACompTag tag, double freq, int ssb) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + gn::FACompTag t = gn::get_enum(tag); + std::string freq_s = gn::to_string(freq, gn::FPFormat::Eng); + obj->add_fixed_tone(comp_key, t, freq_s, ssb); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_fixed_tone : ", e.what()); + } +} + +int gn_fa_fixed_tone_e( + const char* obj_key, const char* comp_key, GnFACompTag tag, const char* freq, int ssb) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + gn::FACompTag t = gn::get_enum(tag); + obj->add_fixed_tone(comp_key, t, freq, ssb); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_fixed_tone_e : ", e.what()); + } +} + +int gn_fa_fsample(const char* obj_key, double f) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + std::string f_s = gn::to_string(f, gn::FPFormat::Eng); + obj->set_fsample(f_s); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_fsample : ", e.what()); + } +} - (*c)->ssb_fund = ssb_width; - (*c)->ssb_rest = 0; - (*c)->max_harm_order = 3; - (*c)->axis_type = GnFreqAxisTypeDcCenter; +int gn_fa_fsample_e(const char* obj_key, const char* f) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + obj->set_fsample(f); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_fsample_e : ", e.what()); + } +} + +int gn_fa_fshift(const char* obj_key, double f) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + std::string f_s = gn::to_string(f, gn::FPFormat::Eng); + obj->set_fshift(f_s); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_fshift : ", e.what()); + } +} - // configure object key for Fourier analysis - err_code = gn_fa_create((*c)->obj_key); +int gn_fa_fshift_e(const char* obj_key, const char* f) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + obj->set_fshift(f); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_fshift_e : ", e.what()); + } +} - // configure component key for Fourier analysis - err_code += gn_fa_max_tone((*c)->obj_key, (*c)->comp_key, GnFACompTagSignal, (*c)->ssb_fund); +int gn_fa_fund_images(const char* obj_key, bool enable) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + obj->en_fund_images = enable; + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_fund_images : ", e.what()); + } +} - // configure harmonic order for Fourier analysis - err_code += gn_fa_hd((*c)->obj_key, (*c)->max_harm_order); +int gn_fa_hd(const char* obj_key, int n) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + obj->set_hd(n); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_hd : ", e.what()); + } +} + +int gn_fa_ilv(const char* obj_key, const int* ilv, size_t ilv_size, bool as_noise) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + std::set ilv2 (ilv, ilv + ilv_size); + obj->set_ilv(ilv2); + obj->ilv_as_noise = as_noise; + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_ilv : ", e.what()); + } +} - // configure single-side bins for Fourier analysis - err_code += gn_fa_ssb((*c)->obj_key, GnFASsbDefault, (*c)->ssb_rest); - err_code += gn_fa_ssb((*c)->obj_key, GnFASsbDC, -1); - err_code += gn_fa_ssb((*c)->obj_key, GnFASsbSignal, -1); - err_code += gn_fa_ssb((*c)->obj_key, GnFASsbWO, -1); +int gn_fa_imd(const char* obj_key, int n) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + obj->set_imd(n); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_imd : ", e.what()); + } +} + +int gn_fa_load(char* buf, size_t size, const char* filename, const char* obj_key) +{ + try { + std::string key (obj_key); + if (key.empty()) { + key = util::get_object_key_from_filename(filename); + } + gn::manager::add_object(key, gn::fourier_analysis::load(filename), true); + util::fill_string_buffer(key.data(), key.size(), buf, size); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_load : ", e.what()); + } +} + +int gn_fa_max_tone( + const char* obj_key, + const char* comp_key, + GnFACompTag tag, + int ssb) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + gn::FACompTag t = gn::get_enum(tag); + obj->add_max_tone(comp_key, t, "0.0", "fdata", ssb); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_max_tone : ", e.what()); + } +} + +int gn_fa_preview(char* buf, size_t size, const char* cfg_id, bool cplx) +{ + try { + fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); + std::string s = obj->preview(cplx); + util::fill_string_buffer(s.data(), s.size(), buf, size); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_preview : ", e.what()); + } +} - // configure sample-rate, data-rate, shift frequency, and converter offset - err_code += gn_fa_fsample((*c)->obj_key, (*c)->sample_rate); - err_code += gn_fa_fdata((*c)->obj_key, (*c)->sample_rate); - err_code += gn_fa_fshift((*c)->obj_key, 0.0); - err_code += gn_fa_conv_offset((*c)->obj_key, false); +int gn_fa_quad_errors(const char* obj_key, bool enable) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + obj->en_quad_errors = enable; + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_quad_errors : ", e.what()); + } +} - return (err_code); +int gn_fa_remove_comp(const char* obj_key, const char* comp_key) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + obj->remove_comp(comp_key); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_remove_comp : ", e.what()); } +} +int gn_fa_reset(const char* obj_key) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + obj->reset(); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_reset : ", e.what()); + } +} + +int gn_fa_ssb(const char* obj_key, GnFASsb group, int ssb) +{ + try { + gn::FASsb g = gn::get_enum(group); + fa_ptr obj = get_fa_object(obj_key); + obj->set_ssb(g, ssb); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_ssb_dc : ", e.what()); + } +} - int gn_config_fa(gn::real_t fixed_tone_freq, gn_config *c) - { - int err_code; +int gn_fa_var(const char* obj_key, const char* name, double value) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + obj->set_var(name, value); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_var : ", e.what()); + } +} - if (!(*c)) - { - gn_config c_p; - c_p = (gn_config)calloc(1, sizeof(*c_p)); - if (!(c_p)) - { - printf("insufficient memory\n"); - return ENOMEM; - } - else - *c = c_p; +int gn_fa_wo(const char* obj_key, int n) +{ + try { + fa_ptr obj = get_fa_object(obj_key); + obj->set_wo(n); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_wo : ", e.what()); + } +} + +/**************************************************************************/ +/* Fourier Analysis Results */ +/**************************************************************************/ + +int gn_fa_result(double* result, const char** rkeys, size_t rkeys_size, + const double* rvalues, size_t rvalues_size, const char* rkey) +{ + try { + util::check_pointer(result); + if (rkeys_size != rvalues_size) { + throw std::runtime_error("Size of result keys does not match size of result values"); } - - if ((*c)->sample_rate <= 0) { - printf("ERROR: Sample rate must be set before configuring Fourier analysis\n"); - return gn_failure; + size_t key_index = get_fa_result_key_index(rkeys, rkeys_size, rkey); + *result = rvalues[key_index]; + return gn_success; + } catch (const std::exception& e) { + *result = 0.0; + return util::return_on_exception("gn_fa_result : ", e.what()); + } +} + +int gn_fa_result_string(char* result, size_t result_size, const char** rkeys, size_t rkeys_size, + const double* rvalues, size_t rvalues_size, const char* rkey) +{ + try { + util::check_pointer(result); + std::string rstr = get_fa_result_string(rkeys, rkeys_size, rvalues, rvalues_size, rkey); + util::fill_string_buffer(rstr.data(), rstr.size(), result, result_size); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fa_result_string : ", e.what()); + } +} + +/**************************************************************************/ +/* Fourier Analysis Helpers */ +/**************************************************************************/ + +int gn_fa_load_key_size(size_t* size, const char* filename, const char* obj_key) +{ + try { + util::check_pointer(size); + std::string key (obj_key); + if (key.empty()) { + key = util::get_object_key_from_filename(filename); } - - (*c)->obj_key = (char *)calloc(3, sizeof(char)); - strcpy((*c)->obj_key, "fa"); - (*c)->comp_key = (char *)calloc(2, sizeof(char)); - strcpy((*c)->comp_key, "A"); - - (*c)->ssb_fund = 120; - (*c)->ssb_rest = 0; - (*c)->max_harm_order = 3; - (*c)->axis_type = GnFreqAxisTypeDcCenter; - - // configure object key for Fourier analysis - err_code = gn_fa_create((*c)->obj_key); - - // configure component key for Fourier analysis - err_code += gn_fa_fixed_tone((*c)->obj_key, (*c)->comp_key, GnFACompTagSignal, fixed_tone_freq, (*c)->ssb_fund); - - // configure harmonic order for Fourier analysis - err_code += gn_fa_hd((*c)->obj_key, (*c)->max_harm_order); - - // configure single-side bins for Fourier analysis - err_code += gn_fa_ssb((*c)->obj_key, GnFASsbDefault, (*c)->ssb_rest); - err_code += gn_fa_ssb((*c)->obj_key, GnFASsbDC, -1); - err_code += gn_fa_ssb((*c)->obj_key, GnFASsbSignal, -1); - err_code += gn_fa_ssb((*c)->obj_key, GnFASsbWO, -1); - - // configure sample-rate, data-rate, shift frequency, and converter offset - err_code += gn_fa_fsample((*c)->obj_key, (*c)->sample_rate); - err_code += gn_fa_fdata((*c)->obj_key, (*c)->sample_rate); - err_code += gn_fa_fshift((*c)->obj_key, 0.0); - err_code += gn_fa_conv_offset((*c)->obj_key, false); - - return (err_code); + *size = util::terminated_size(key.size()); + return gn_success; + } catch (const std::exception& e) { + *size = 0; + return util::return_on_exception("gn_fa_load_key_size : ", e.what()); } - - // waveform generation - int gn_gen_ramp(gn::real_t **out, gn_config *c) - { - int err_code; - gn::real_t *awf = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); - err_code = gn_ramp(awf, (*c)->npts, (*c)->ramp_start, (*c)->ramp_stop, (*c)->noise_rms); - *out = awf; - - return err_code; +} + +int gn_fa_preview_size(size_t* size, const char* cfg_id, bool cplx) +{ + try { + util::check_pointer(size); + fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); + std::string s = obj->preview(cplx); + *size = util::terminated_size(s.size()); + return gn_success; + } catch (const std::exception& e) { + *size = 0; + return util::return_on_exception("gn_fa_preview_size : ", e.what()); } - - int gn_gen_real_tone(gn::real_t **out, gn_config *c) - { - int err_code = 0; - gn::real_t *awf = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); - - for (size_t i = 0; i < (*c)->num_tones; i++) - { - gn::real_t *tmp = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); - if ((*c)->ttype == REAL_COSINE) - err_code = gn_cos(tmp, (*c)->npts, (*c)->sample_rate, (*c)->tone_ampl[i], (*c)->tone_freq[i], (*c)->tone_phase[i], 0, 0); - else if ((*c)->ttype == REAL_SINE) - err_code = gn_sin(tmp, (*c)->npts, (*c)->sample_rate, (*c)->tone_ampl[i], (*c)->tone_freq[i], (*c)->tone_phase[i], 0, 0); - if (!err_code) - { - for (size_t j = 0; j < (*c)->npts; j++) - awf[j] = awf[j] + tmp[j]; - } +} + +int gn_fa_result_string_size(size_t* size, const char** rkeys, size_t rkeys_size, + const double* rvalues, size_t rvalues_size, const char* rkey) +{ + try { + util::check_pointer(size); + std::string rstr = get_fa_result_string(rkeys, rkeys_size, rvalues, rvalues_size, rkey); + *size = util::terminated_size(rstr.size()); + return gn_success; + } catch (const std::exception& e) { + *size = 0; + return util::return_on_exception("gn_fa_result_string_size : ", e.what()); + } +} + +int gn_fft_analysis_results_key_sizes(size_t* key_sizes, size_t key_sizes_size, + const char* cfg_id, size_t in_size, size_t nfft) +{ + try { + fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); + std::vector key_sizes_src = obj->result_key_lengths(in_size, nfft); + if (key_sizes_src.size() != key_sizes_size) { + throw std::runtime_error("Number of keys does not match output array size"); + } + for (size_t i = 0; i < key_sizes_size; ++i) { + key_sizes[i] = util::terminated_size(key_sizes_src[i]); } - *out = awf; - - return err_code; + return gn_success; + } catch (const std::exception& e) { + std::fill(key_sizes, key_sizes + key_sizes_size, 0); + return util::return_on_exception("gn_fa_results_key_sizes : ", e.what()); + } +} + +int gn_fft_analysis_results_size(size_t* size, const char* cfg_id, size_t in_size, size_t nfft) +{ + try { + util::check_pointer(size); + fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); + *size = obj->results_size(in_size, nfft); + return gn_success; + } catch (const std::exception& e) { + *size = 0; + return util::return_on_exception("gn_fa_results_size : ", e.what()); } +} + +/**************************************************************************/ +/* Fourier Transforms */ +/**************************************************************************/ + +namespace { - int gn_gen_complex_tone(gn::real_t **outi, gn::real_t **outq, gn_config *c) + template + int gn_fftxx(const char* suffix, double* out, size_t out_size, + const T* i, size_t i_size, const T* q, size_t q_size, + int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format) { - int err_code = 0; - gn::real_t *awfi = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); - gn::real_t *awfq = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); - - for (size_t i = 0; i < (*c)->num_tones; i++) { - gn::real_t *tmp = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); - err_code = gn_cos(tmp, (*c)->npts, (*c)->sample_rate, (*c)->tone_ampl[i], (*c)->tone_freq[i], (*c)->tone_phase[i], 0, 0); - if (!err_code) - { - for (size_t j = 0; j < (*c)->npts; j++) - awfi[j] = awfi[j] + tmp[j]; - } - tmp = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); - err_code = gn_sin(tmp, (*c)->npts, (*c)->sample_rate, (*c)->tone_ampl[i], (*c)->tone_freq[i], (*c)->tone_phase[i], 0, 0); - if (!err_code) - { - for (size_t j = 0; j < (*c)->npts; j++) - awfq[j] = awfq[j] + tmp[j]; - } + try { + gn::Window w = gn::get_enum(window); + gn::CodeFormat f = gn::get_enum(format); + gn::fft(i, i_size, q, q_size, out, out_size, n, navg, nfft, w, f); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fft", suffix, " : ", e.what()); } - *outi = awfi; - *outq = awfq; - - return err_code; } - // processing - int gn_quantize(int32_t **out, const gn::real_t *in, gn_config *c) + template + int gn_rfftxx(const char* suffix, double* out, size_t out_size, + const T* in, size_t in_size, + int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format, GnRfftScale scale) { - int err_code; - int32_t *qwf = (int32_t *)calloc((*c)->npts, sizeof(int32_t)); - - err_code = gn_quantize32(qwf, (*c)->npts, in, (*c)->npts, (*c)->fsr, (*c)->qres, (*c)->noise_rms, (*c)->code_format); - *out = qwf; - - return err_code; + try { + gn::Window w = gn::get_enum(window); + gn::CodeFormat f = gn::get_enum(format); + gn::RfftScale s = gn::get_enum(scale); + gn::rfft(in, in_size, out, out_size, n, navg, nfft, w, f, s); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_rfft", suffix, " : ", e.what()); + } } - int gn_fftz(gn::real_t **out, const int32_t *in_i, const int32_t *in_q, gn_config *c) - { - int err_code; - gn::real_t *fft_of_in = (gn::real_t *)calloc(2*(*c)->nfft, sizeof(gn::real_t)); +} // namespace anonymous - err_code = gn_fft32(fft_of_in, 2*(*c)->nfft, in_i, (*c)->npts, in_q, (*c)->npts, (*c)->qres, (*c)->fft_navg, (*c)->nfft, (*c)->win, (*c)->code_format); - *out = fft_of_in; +int gn_fft(double* out, size_t out_size, + const double* i, size_t i_size, const double* q, size_t q_size, + size_t navg, size_t nfft, GnWindow window) +{ + try { + gn::Window w = gn::get_enum(window); + gn::fft(i, i_size, q, q_size, out, out_size, navg, nfft, w); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fft : ", e.what()); + } +} + +int gn_fft16(double* out, size_t out_size, + const int16_t* i, size_t i_size, const int16_t* q, size_t q_size, + int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format) +{ + return gn_fftxx("16", out, out_size, i, i_size, q, q_size, n, navg, nfft, window, format); +} + +int gn_fft32(double* out, size_t out_size, + const int32_t* i, size_t i_size, const int32_t* q, size_t q_size, + int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format) +{ + return gn_fftxx("32", out, out_size, i, i_size, q, q_size, n, navg, nfft, window, format); +} + +int gn_fft64(double* out, size_t out_size, + const int64_t* i, size_t i_size, const int64_t* q, size_t q_size, + int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format) +{ + return gn_fftxx("64", out, out_size, i, i_size, q, q_size, n, navg, nfft, window, format); +} + +int gn_rfft(double* out, size_t out_size, const double* in, size_t in_size, + size_t navg, size_t nfft, GnWindow window, GnRfftScale scale) +{ + try { + gn::Window w = gn::get_enum(window); + gn::RfftScale s = gn::get_enum(scale); + gn::rfft(in, in_size, out, out_size, navg, nfft, w, s); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_rfft : ", e.what()); + } +} + +int gn_rfft16(double* out, size_t out_size, const int16_t* in, size_t in_size, + int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format, GnRfftScale scale) +{ + return gn_rfftxx("16", out, out_size, in, in_size, n, navg, nfft, window, format, scale); +} + +int gn_rfft32(double* out, size_t out_size, const int32_t* in, size_t in_size, + int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format, GnRfftScale scale) +{ + return gn_rfftxx("32", out, out_size, in, in_size, n, navg, nfft, window, format, scale); +} + +int gn_rfft64(double* out, size_t out_size, const int64_t* in, size_t in_size, + int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format, GnRfftScale scale) +{ + return gn_rfftxx("64", out, out_size, in, in_size, n, navg, nfft, window, format, scale); +} + +/**************************************************************************/ +/* Fourier Transform Helpers */ +/**************************************************************************/ + +int gn_fft_size(size_t* out_size, size_t i_size, size_t q_size, size_t navg, size_t nfft) +{ + try { + util::check_pointer(out_size); + *out_size = gn::fft_size(i_size, q_size, navg, nfft); + return gn_success; + } catch (const std::exception& e) { + *out_size = 0; + return util::return_on_exception("gn_fft_size : ", e.what()); + } +} - return err_code; +int gn_rfft_size(size_t* out_size, size_t in_size, size_t navg, size_t nfft) +{ + try { + util::check_pointer(out_size); + *out_size = gn::rfft_size(in_size, navg, nfft); + return gn_success; + } catch (const std::exception& e) { + *out_size = 0; + return util::return_on_exception("gn_rfft_size : ", e.what()); + } +} + +/**************************************************************************/ +/* Fourier Utilities */ +/**************************************************************************/ + +int gn_alias(double* out, double fs, double freq, GnFreqAxisType axis_type) +{ + try { + util::check_pointer(out); + gn::FreqAxisType at = gn::get_enum(axis_type); + *out = gn::alias(fs, freq, at); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_alias : ", e.what()); } +} - int gn_histz(uint64_t **hist, size_t *hist_len, const int32_t *qwf, gn_config *c) - { - int err_code; - uint64_t *out = NULL; +int gn_coherent(double* out, size_t nfft, double fs, double freq) +{ + try { + util::check_pointer(out); + *out = gn::coherent(nfft, fs, freq); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_coherent : ", e.what()); + } +} - err_code = gn_code_density_size(&((*c)->_code_density_size), (*c)->qres, (*c)->code_format); - out = (uint64_t *)calloc((*c)->_code_density_size, sizeof(uint64_t)); - err_code += gn_hist32(out, (*c)->_code_density_size, qwf, (*c)->npts, (*c)->qres, (*c)->code_format, false); - *hist = out; - *hist_len = (*c)->_code_density_size; +int gn_fftshift(double* out, size_t out_size, const double* in, size_t in_size) +{ + try { + gn::fftshift(in, in_size, out, out_size); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fftshift : ", e.what()); + } +} + +int gn_freq_axis(double* out, size_t size, + size_t nfft, GnFreqAxisType axis_type, double fs, GnFreqAxisFormat axis_format) +{ + try { + gn::FreqAxisType at = gn::get_enum(axis_type); + gn::FreqAxisFormat af = gn::get_enum(axis_format); + gn::freq_axis(out, size, nfft, at, fs, af); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fftshift : ", e.what()); + } +} - return err_code; +int gn_ifftshift(double* out, size_t out_size, const double* in, size_t in_size) +{ + try { + gn::ifftshift(in, in_size, out, out_size); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_ifftshift : ", e.what()); } +} + +/**************************************************************************/ +/* Fourier Utility Helpers */ +/**************************************************************************/ + +int gn_freq_axis_size(size_t* size, size_t nfft, GnFreqAxisType axis_type) +{ + try { + util::check_pointer(size); + gn::FreqAxisType at = gn::get_enum(axis_type); + *size = gn::freq_axis_size(nfft, at); + return gn_success; + } catch (const std::exception& e) { + *size = 0; + return util::return_on_exception("gn_freq_axis_size : ", e.what()); + } +} + +/**************************************************************************/ +/* Manager */ +/**************************************************************************/ + +int gn_mgr_clear() +{ + gn::manager::clear(); + return gn_success; +} + +int gn_mgr_compare(bool* result, const char* obj_key1, const char* obj_key2) +{ + try { + *result = gn::manager::equal(obj_key1, obj_key2); + return gn_success; + } catch (const std::exception& e) { + *result = false; + return util::return_on_exception("gn_mgr_equal : ", e.what()); + } +} + +int gn_mgr_contains(bool* result, const char* obj_key) +{ + *result = gn::manager::contains(obj_key); + return gn_success; +} + +int gn_mgr_remove(const char* obj_key) +{ + gn::manager::remove(obj_key); + return gn_success; +} + +int gn_mgr_save(char* buf, size_t size, const char* obj_key, const char* filename) +{ + try { + std::string fn = gn::manager::save(obj_key, filename); + util::fill_string_buffer(fn.data(), fn.size(), buf, size); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_mgr_save : ", e.what()); + } +} + +int gn_mgr_size(size_t* size) +{ + *size = gn::manager::size(); + return gn_success; +} + +int gn_mgr_to_string(char* buf, size_t size, const char* obj_key) +{ + try { + std::string s = gn::manager::to_string(obj_key); + util::fill_string_buffer(s.data(), s.size(), buf, size); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_mgr_to_string : ", e.what()); + } +} - int gn_dnlz(double **dnl, size_t *dnl_len, const uint64_t *hist, gn_config *c) - { - int err_code; - double *out = NULL; +int gn_mgr_type(char* buf, size_t size, const char* obj_key) +{ + try { + std::string s = gn::manager::type_str(obj_key); + util::fill_string_buffer(s.data(), s.size(), buf, size); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_mgr_type : ", e.what()); + } +} + +/**************************************************************************/ +/* Manager Helpers */ +/**************************************************************************/ + +int gn_mgr_save_filename_size(size_t* size, const char* obj_key, const char* filename) +{ + try { + util::check_pointer(size); + size_t fn_size = gn::manager::get_filename_from_object_key(obj_key, filename).size(); + *size = util::terminated_size(fn_size); + return gn_success; + } catch (const std::exception& e) { + *size = 0; + return util::return_on_exception("gn_mgr_save_filename_size : ", e.what()); + } +} - err_code = gn_code_density_size(&((*c)->_code_density_size), (*c)->qres, (*c)->code_format); - out = (double *)calloc((*c)->_code_density_size, sizeof(double)); - err_code = gn_dnl(out, (*c)->_code_density_size, hist, (*c)->_code_density_size, (*c)->dnla_signal_type); - *dnl = out; - *dnl_len = (*c)->_code_density_size; +int gn_mgr_to_string_size(size_t* size, const char* obj_key) +{ + try { + util::check_pointer(size); + *size = util::terminated_size(gn::manager::to_string(obj_key).size()); + return gn_success; + } catch (const std::exception& e) { + *size = 0; + return util::return_on_exception("gn_mgr_to_string_size : ", e.what()); + } +} - return err_code; +int gn_mgr_type_size(size_t* size, const char* obj_key) +{ + try { + util::check_pointer(size); + *size = util::terminated_size(gn::manager::type_str(obj_key).size()); + return gn_success; + } catch (const std::exception& e) { + *size = 0; + return util::return_on_exception("gn_mgr_type_size : ", e.what()); } +} - int gn_inlz(double **inl, size_t *inl_len, const double *dnl, gn_config *c) - { - int err_code; - double *out = NULL; +/**************************************************************************/ +/* Signal Processing */ +/**************************************************************************/ - err_code = gn_code_density_size(&((*c)->_code_density_size), (*c)->qres, (*c)->code_format); - out = (double *)calloc((*c)->_code_density_size, sizeof(double)); - err_code = gn_inl(out, (*c)->_code_density_size, dnl, (*c)->_code_density_size, (*c)->inla_fit); - *inl = out; - *inl_len = (*c)->_code_density_size; +namespace { - return err_code; + template + int gn_downsamplex(const char* suffix, T* out, size_t out_size, + const T* in, size_t in_size, int ratio, bool interleaved) + { + try { + gn::downsample(in, in_size, out, out_size, ratio, interleaved); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_downsample", suffix, " : ", e.what()); + } } - // Waveform/Histogram/DNL/INL/Fourier Analysis - int gn_get_wfa_results(char ***rkeys, gn::real_t **rvalues, size_t *results_size, const int32_t *qwf, gn_config *c) + template + int gn_fshiftx(const char* suffix, T* out, size_t out_size, + const T* i, size_t i_size, const T* q, size_t q_size, + int n, double fs, double fshift, GnCodeFormat format) { - int err_code = 0; - - // get results size - err_code = gn_analysis_results_size(&((*c)->_wfa_results_size), GnAnalysisTypeWaveform); - - // allocate memory for result keys and values - (*c)->_wfa_result_keys = (char **)calloc(((*c)->_wfa_results_size), sizeof(char*)); - (*c)->_wfa_result_values = (gn::real_t *)calloc(((*c)->_wfa_results_size), sizeof(gn::real_t)); - - // get result key sizes - (*c)->_wfa_result_key_sizes = (size_t *)calloc(((*c)->_wfa_results_size), sizeof(size_t)); - err_code += gn_analysis_results_key_sizes((*c)->_wfa_result_key_sizes, (*c)->_wfa_results_size, GnAnalysisTypeWaveform); - - // allocate memory for each result key - for (size_t i = 0; i < (*c)->_wfa_results_size; ++i) - (*c)->_wfa_result_keys[i] = (char *)calloc((*c)->_wfa_result_key_sizes[i], sizeof(char)); - - // execute analysis - err_code += gn_wf_analysis32((*c)->_wfa_result_keys, (*c)->_wfa_results_size, (*c)->_wfa_result_values, (*c)->_wfa_results_size, qwf, (*c)->npts); - - // copy keys - *rkeys = (char **)calloc(((*c)->_wfa_results_size), sizeof(char*)); - for (size_t i = 0; i < (*c)->_wfa_results_size; ++i) - (*rkeys)[i] = (char *)calloc((*c)->_wfa_result_key_sizes[i], sizeof(char)); - - // copy values - *rvalues = (gn::real_t *)calloc(((*c)->_wfa_results_size), sizeof(gn::real_t)); - for (size_t i = 0; i < (*c)->_wfa_results_size; ++i) - { - strcpy((*rkeys)[i], (*c)->_wfa_result_keys[i]); - (*rvalues)[i] = (*c)->_wfa_result_values[i]; + try { + gn::CodeFormat f = gn::get_enum(format); + gn::fshift(i, i_size, q, q_size, out, out_size, n, fs, fshift, f); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fshift", suffix, " : ", e.what()); } - *results_size = (*c)->_wfa_results_size; - - return(err_code); } - int gn_get_ha_results(char ***rkeys, gn::real_t **rvalues, size_t *results_size, const uint64_t *hist, gn_config *c) + template + int gn_normalize(const char* suffix, double* out, size_t out_size, + const T* in, size_t in_size, int n, GnCodeFormat format) { - int err_code = 0; - - // get results size - err_code = gn_analysis_results_size(&((*c)->_hist_results_size), GnAnalysisTypeHistogram); - - // allocate memory for result keys and values - (*c)->_hist_result_keys = (char **)calloc(((*c)->_hist_results_size), sizeof(char*)); - (*c)->_hist_result_values = (gn::real_t *)calloc(((*c)->_hist_results_size), sizeof(gn::real_t)); - - // get result key sizes - (*c)->_hist_result_key_sizes = (size_t *)calloc(((*c)->_hist_results_size), sizeof(size_t)); - err_code += gn_analysis_results_key_sizes((*c)->_hist_result_key_sizes, (*c)->_hist_results_size, GnAnalysisTypeHistogram); - - // allocate memory for each result key - for (size_t i = 0; i < (*c)->_hist_results_size; ++i) - (*c)->_hist_result_keys[i] = (char *)calloc((*c)->_hist_result_key_sizes[i], sizeof(char)); - - // execute analysis - err_code += gn_hist_analysis((*c)->_hist_result_keys, (*c)->_hist_results_size, (*c)->_hist_result_values, (*c)->_hist_results_size, hist, (*c)->_code_density_size); - - // copy keys - *rkeys = (char **)calloc(((*c)->_hist_results_size), sizeof(char*)); - for (size_t i = 0; i < (*c)->_hist_results_size; ++i) - (*rkeys)[i] = (char *)calloc((*c)->_hist_result_key_sizes[i], sizeof(char)); - - // copy values - *rvalues = (gn::real_t *)calloc(((*c)->_hist_results_size), sizeof(gn::real_t)); - for (size_t i = 0; i < (*c)->_hist_results_size; ++i) - { - strcpy((*rkeys)[i], (*c)->_hist_result_keys[i]); - (*rvalues)[i] = (*c)->_hist_result_values[i]; + try { + gn::CodeFormat f = gn::get_enum(format); + gn::normalize(in, in_size, out, out_size, n, f); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_normalize", suffix, " : ", e.what()); } - *results_size = (*c)->_hist_results_size; - - return(err_code); } - int gn_get_dnla_results(char ***rkeys, gn::real_t **rvalues, size_t *results_size, const gn::real_t *dnl, gn_config *c) + template + int gn_quantize(const char* suffix, T* out, size_t out_size, + const double* in, size_t in_size, double fsr, int n, double noise, GnCodeFormat format) { - int err_code; - - // get results size - err_code = gn_analysis_results_size(&((*c)->_dnl_results_size), GnAnalysisTypeDNL); - - // allocate memory for result keys and values - (*c)->_dnl_result_keys = (char **)calloc(((*c)->_dnl_results_size), sizeof(char*)); - (*c)->_dnl_result_values = (gn::real_t *)calloc(((*c)->_dnl_results_size), sizeof(gn::real_t)); - - // get result key sizes - (*c)->_dnl_result_key_sizes = (size_t *)calloc(((*c)->_dnl_results_size), sizeof(size_t)); - err_code += gn_analysis_results_key_sizes((*c)->_dnl_result_key_sizes, (*c)->_dnl_results_size, GnAnalysisTypeDNL); - - // allocate memory for each result key - for (size_t i = 0; i < (*c)->_dnl_results_size; ++i) - (*c)->_dnl_result_keys[i] = (char *)calloc((*c)->_dnl_result_key_sizes[i], sizeof(char)); - - // execute analysis - err_code += gn_dnl_analysis((*c)->_dnl_result_keys, (*c)->_dnl_results_size, (*c)->_dnl_result_values, (*c)->_dnl_results_size, dnl, (*c)->_code_density_size); - - // copy keys - *rkeys = (char **)calloc(((*c)->_dnl_results_size), sizeof(char*)); - for (size_t i = 0; i < (*c)->_dnl_results_size; ++i) - (*rkeys)[i] = (char *)calloc((*c)->_dnl_result_key_sizes[i], sizeof(char)); - - // copy values - *rvalues = (gn::real_t *)calloc(((*c)->_dnl_results_size), sizeof(gn::real_t)); - for (size_t i = 0; i < (*c)->_dnl_results_size; ++i) - { - strcpy((*rkeys)[i], (*c)->_dnl_result_keys[i]); - (*rvalues)[i] = (*c)->_dnl_result_values[i]; + try { + gn::CodeFormat f = gn::get_enum(format); + gn::quantize(in, in_size, out, out_size, fsr, n, noise, f); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_quantize", suffix, " : ", e.what()); } - *results_size = (*c)->_dnl_results_size; + } - return(err_code); +} // namespace anonymous + +int gn_downsample(double* out, size_t out_size, + const double* in, size_t in_size, int ratio, bool interleaved) +{ + return gn_downsamplex("", out, out_size, in, in_size, ratio, interleaved); +} + +int gn_downsample16(int16_t* out, size_t out_size, + const int16_t* in, size_t in_size, int ratio, bool interleaved) +{ + return gn_downsamplex("16", out, out_size, in, in_size, ratio, interleaved); +} + +int gn_downsample32(int32_t* out, size_t out_size, + const int32_t* in, size_t in_size, int ratio, bool interleaved) +{ + return gn_downsamplex("32", out, out_size, in, in_size, ratio, interleaved); +} + +int gn_downsample64(int64_t* out, size_t out_size, + const int64_t* in, size_t in_size, int ratio, bool interleaved) +{ + return gn_downsamplex("64", out, out_size, in, in_size, ratio, interleaved); +} + +int gn_fshift(double* out, size_t out_size, + const double* i, size_t i_size, const double* q, size_t q_size, double fs, double fshift) +{ + try { + gn::fshift(i, i_size, q, q_size, out, out_size, fs, fshift); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_fshift : ", e.what()); } +} + +int gn_fshift16(int16_t* out, size_t out_size, + const int16_t* i, size_t i_size, const int16_t* q, size_t q_size, + int n, double fs, double fshift, GnCodeFormat format) +{ + return gn_fshiftx("16", out, out_size, i, i_size, q, q_size, n, fs, fshift, format); +} + +int gn_fshift32(int32_t* out, size_t out_size, + const int32_t* i, size_t i_size, const int32_t* q, size_t q_size, + int n, double fs, double fshift, GnCodeFormat format) +{ + return gn_fshiftx("32", out, out_size, i, i_size, q, q_size, n, fs, fshift, format); +} + +int gn_fshift64(int64_t* out, size_t out_size, + const int64_t* i, size_t i_size, const int64_t* q, size_t q_size, + int n, double fs, double fshift, GnCodeFormat format) +{ + return gn_fshiftx("64", out, out_size, i, i_size, q, q_size, n, fs, fshift, format); +} + +int gn_normalize16(double* out, size_t out_size, + const int16_t* in, size_t in_size, int n, GnCodeFormat format) +{ + return gn_normalize("16", out, out_size, in, in_size, n, format); +} + +int gn_normalize32(double* out, size_t out_size, + const int32_t* in, size_t in_size, int n, GnCodeFormat format) +{ + return gn_normalize("32", out, out_size, in, in_size, n, format); +} + +int gn_normalize64(double* out, size_t out_size, + const int64_t* in, size_t in_size, int n, GnCodeFormat format) +{ + return gn_normalize("64", out, out_size, in, in_size, n, format); +} + +int gn_polyval(double* out, size_t out_size, + const double* in, size_t in_size, const double* c, size_t c_size) +{ + try { + gn::polyval(in, in_size, out, out_size, c, c_size); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_polyval : ", e.what()); + } +} + +int gn_quantize16(int16_t* out, size_t out_size, + const double* in, size_t in_size, double fsr, int n, double noise, GnCodeFormat format) +{ + return gn_quantize("16", out, out_size, in, in_size, fsr, n, noise, format); +} + +int gn_quantize32(int32_t* out, size_t out_size, + const double* in, size_t in_size, double fsr, int n, double noise, GnCodeFormat format) +{ + return gn_quantize("32", out, out_size, in, in_size, fsr, n, noise, format); +} + +int gn_quantize64(int64_t* out, size_t out_size, + const double* in, size_t in_size, double fsr, int n, double noise, GnCodeFormat format) +{ + return gn_quantize("64", out, out_size, in, in_size, fsr, n, noise, format); +} + +/**************************************************************************/ +/* Signal Processing Helpers */ +/**************************************************************************/ + +int gn_downsample_size(size_t* out_size, size_t in_size, int ratio, bool interleaved) +{ + try { + util::check_pointer(out_size); + *out_size = gn::downsample_size(in_size, ratio, interleaved); + return gn_success; + } catch (const std::exception& e) { + *out_size = 0; + return util::return_on_exception("gn_downsample_size : ", e.what()); + } +} - int gn_get_inla_results(char ***rkeys, gn::real_t **rvalues, size_t *results_size, const gn::real_t *inl, gn_config *c) +int gn_fshift_size(size_t* out_size, size_t i_size, size_t q_size) +{ + try { + util::check_pointer(out_size); + *out_size = gn::fshift_size(i_size, q_size); + return gn_success; + } catch (const std::exception& e) { + *out_size = 0; + return util::return_on_exception("gn_fshift_size : ", e.what()); + } +} + +/**************************************************************************/ +/* Waveforms */ +/**************************************************************************/ + +namespace { + + template + int gn_wf_analysisx(const char* suffix, + char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, + const T* in, size_t in_size) { - int err_code; - - // get results size - err_code = gn_analysis_results_size(&((*c)->_inl_results_size), GnAnalysisTypeINL); - - // allocate memory for result keys and values - (*c)->_inl_result_keys = (char **)calloc(((*c)->_inl_results_size), sizeof(char*)); - (*c)->_inl_result_values = (gn::real_t *)calloc(((*c)->_inl_results_size), sizeof(gn::real_t)); - - // get result key sizes - (*c)->_inl_result_key_sizes = (size_t *)calloc(((*c)->_inl_results_size), sizeof(size_t)); - err_code += gn_analysis_results_key_sizes((*c)->_inl_result_key_sizes, (*c)->_inl_results_size, GnAnalysisTypeINL); - - // allocate memory for each result key - for (size_t i = 0; i < (*c)->_inl_results_size; ++i) - (*c)->_inl_result_keys[i] = (char *)calloc((*c)->_inl_result_key_sizes[i], sizeof(char)); - - // execute analysis - err_code += gn_inl_analysis((*c)->_inl_result_keys, (*c)->_inl_results_size, (*c)->_inl_result_values, (*c)->_inl_results_size, inl, (*c)->_code_density_size); - - // copy keys - *rkeys = (char **)calloc(((*c)->_inl_results_size), sizeof(char*)); - for (size_t i = 0; i < (*c)->_inl_results_size; ++i) - (*rkeys)[i] = (char *)calloc((*c)->_inl_result_key_sizes[i], sizeof(char)); - - // copy values - *rvalues = (gn::real_t *)calloc(((*c)->_inl_results_size), sizeof(gn::real_t)); - for (size_t i = 0; i < (*c)->_inl_results_size; ++i) - { - strcpy((*rkeys)[i], (*c)->_inl_result_keys[i]); - (*rvalues)[i] = (*c)->_inl_result_values[i]; + try { + util::check_pointer(rkeys); + util::check_pointer(rvalues); + const std::vector& keys = gn::wf_analysis_ordered_keys(); + if (keys.size() != rkeys_size) { + throw std::runtime_error("Size of result key array is wrong"); + } + if (rvalues_size != rkeys_size) { + throw std::runtime_error("Size of result keys does not match size of result values"); + } + std::map results = gn::wf_analysis(in, in_size); + for (size_t i = 0; i < keys.size(); ++i) { + const std::string& src = keys[i]; + char* dst = rkeys[i]; + size_t dst_size = util::terminated_size(src.size()); + util::fill_string_buffer(src.data(), src.size(), dst, dst_size); + rvalues[i] = results.at(src); + } + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_wf_analysis", suffix, " : ", e.what()); } - *results_size = (*c)->_inl_results_size; + } + +} // namespace anonymous - return(err_code); +int gn_cos(double* out, size_t size, + double fs, double ampl, double freq, double phase, double td, double tj) +{ + try { + gn::cos(out, size, fs, ampl, freq, phase, td, tj); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_cos : ", e.what()); } +} - int gn_get_fa_single_result(gn::real_t *rvalue, const char *metric_name, gn::real_t *fft_ilv, gn_config *c) - { - int err_code; - size_t i; - bool metric_found = false; - size_t results_size; - char **rkeys; - double *rvalues; - - // compute all results - err_code = gn_get_fa_results(&rkeys, &rvalues, &results_size, fft_ilv, &(*c)); - for (i = 0; i < results_size; i++) - { - if (!strcmp(metric_name, rkeys[i])) - { - metric_found = true; - break; - } - } - if (!metric_found) - { - printf("ERROR: Invalid selection of metric\n"); - return gn_failure; - } - *rvalue = rvalues[i]; +int gn_gaussian(double* out, size_t size, double mean, double sd) +{ + try { + gn::gaussian(out, size, mean, sd); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_gaussian : ", e.what()); + } +} - return err_code; +int gn_ramp(double* out, size_t size, double start, double stop, double noise) +{ + try { + gn::ramp(out, size, start, stop, noise); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_ramp : ", e.what()); } +} - int gn_get_fa_results(char ***rkeys, gn::real_t **rvalues, size_t *results_size, gn::real_t *fft_ilv, gn_config *c) - { - int err_code = 0; - size_t *result_key_sizes; - - // get results size - err_code = gn_fft_analysis_results_size(results_size, (*c)->obj_key, 2*(*c)->nfft, (*c)->nfft); - - // allocate memory for result keys and values - *rkeys = (char **)calloc(*results_size, sizeof(char*)); - *rvalues = (gn::real_t *)calloc(*results_size, sizeof(gn::real_t)); - - // get result key sizes - result_key_sizes = (size_t *)calloc(*results_size, sizeof(size_t)); - err_code += gn_fft_analysis_results_key_sizes(result_key_sizes, *results_size, (*c)->obj_key, 2*(*c)->nfft, (*c)->nfft); - - // allocate memory for each result key - for (size_t i = 0; i < *results_size; ++i) - (*rkeys)[i] = (char *)calloc(result_key_sizes[i], sizeof(char)); - - // execute analysis - err_code += gn_fft_analysis(*rkeys, *results_size, *rvalues, *results_size, (*c)->obj_key, fft_ilv, 2*(*c)->nfft, (*c)->nfft, (*c)->axis_type); - - return (err_code); +int gn_sin(double* out, size_t size, + double fs, double ampl, double freq, double phase, double td, double tj) +{ + try { + gn::sin(out, size, fs, ampl, freq, phase, td, tj); + return gn_success; + } catch (const std::exception& e) { + return util::return_on_exception("gn_sin : ", e.what()); } +} + +int gn_wf_analysis(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, + const double* in, size_t in_size) +{ + return gn_wf_analysisx("", rkeys, rkeys_size, rvalues, rvalues_size, in, in_size); +} + +int gn_wf_analysis16(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, + const int16_t* in, size_t in_size) +{ + return gn_wf_analysisx("16", rkeys, rkeys_size, rvalues, rvalues_size, in, in_size); +} + +int gn_wf_analysis32(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, + const int32_t* in, size_t in_size) +{ + return gn_wf_analysisx("32", rkeys, rkeys_size, rvalues, rvalues_size, in, in_size); +} + +int gn_wf_analysis64(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, + const int64_t* in, size_t in_size) +{ + return gn_wf_analysisx("64", rkeys, rkeys_size, rvalues, rvalues_size, in, in_size); } \ No newline at end of file diff --git a/bindings/c/src/cgenalyzer_advanced.cpp b/bindings/c/src/cgenalyzer_advanced.cpp deleted file mode 100644 index 1d5f9e0..0000000 --- a/bindings/c/src/cgenalyzer_advanced.cpp +++ /dev/null @@ -1,1736 +0,0 @@ -#include "cgenalyzer_advanced.h" -#include "cgenalyzer_private.h" - -using namespace util; - -namespace util { - - static bool gn_null_terminate = true; - - size_t terminated_size(size_t string_size) - { - return string_size + (util::gn_null_terminate ? 1 : 0); - } - - void fill_string_buffer( - const char* src, // Pointer to source - size_t src_size, // Size of source; should not count null-terminator, if it exists - char* dst, // Pointer to destination - size_t dst_size // Size of destination - ) - { - if (nullptr == src) { - throw std::runtime_error("fill_string_buffer : source is NULL"); - } - if (nullptr == dst) { - throw std::runtime_error("fill_string_buffer : destination is NULL"); - } - if (dst_size < terminated_size(src_size)) { - throw std::runtime_error("fill_string_buffer : destination too small"); - } - for (size_t i = 0; i < src_size; ++i) { - dst[i] = src[i]; - } - if (gn_null_terminate) { - dst[src_size] = '\0'; - } - } - - std::string get_object_key_from_filename(const std::string& filename) - { - static const std::regex re {"(" + gn::manager::key_pattern + ")[.]json$", std::regex::icase}; - std::smatch matches; - if (std::regex_search(filename, matches, re)) { - if (1 == matches.size()) { - throw std::runtime_error("unable to derive object key from filename '" + filename + "'"); - } - return matches[1].str(); - } else { - throw std::runtime_error("invalid filename '" + filename + "'"); - } - } - -} // namespace util - -/**************************************************************************/ -/* API Utilities */ -/**************************************************************************/ - -int gn_analysis_results_key_sizes(size_t* key_sizes, size_t key_sizes_size, GnAnalysisType type) -{ - try { - util::check_pointer(key_sizes); - std::vector keys; - switch (gn::get_enum(type)) - { - case gn::AnalysisType::DNL : - keys = gn::dnl_analysis_ordered_keys(); - break; - case gn::AnalysisType::Histogram : - keys = gn::hist_analysis_ordered_keys(); - break; - case gn::AnalysisType::INL : - keys = gn::inl_analysis_ordered_keys(); - break; - case gn::AnalysisType::Waveform : - keys = gn::wf_analysis_ordered_keys(); - break; - default : - throw std::runtime_error("Invalid analysis type"); - } - if (keys.size() != key_sizes_size) { - throw std::runtime_error("Number of keys does not match output array size"); - } - for (size_t i = 0; i < key_sizes_size; ++i) { - key_sizes[i] = util::terminated_size(keys[i].size()); - } - return gn_success; - } catch (const std::exception& e) { - std::fill(key_sizes, key_sizes + key_sizes_size, 0); - return util::return_on_exception("gn_analysis_results_key_sizes : ", e.what()); - } -} - -int gn_analysis_results_size(size_t* size, GnAnalysisType type) -{ - try { - util::check_pointer(size); - switch (gn::get_enum(type)) - { - case gn::AnalysisType::DNL : - *size = gn::dnl_analysis_ordered_keys().size(); - break; - case gn::AnalysisType::Histogram : - *size = gn::hist_analysis_ordered_keys().size(); - break; - case gn::AnalysisType::INL : - *size = gn::inl_analysis_ordered_keys().size(); - break; - case gn::AnalysisType::Waveform : - *size = gn::wf_analysis_ordered_keys().size(); - break; - default : - throw std::runtime_error("Invalid analysis type"); - } - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_analysis_results_size : ", e.what()); - } -} - -int gn_enum_value(int* value, const char* enumeration, const char* enumerator) -{ - try { - util::check_pointer(value); - *value = gn::enum_value(enumeration, enumerator); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_enum_value : ", e.what()); - } -} - -int gn_error_check(bool* error) -{ - try { - util::check_pointer(error); - *error = util::gn_error_log.check(); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_error_check : ", e.what()); - } -} - -int gn_error_clear() -{ - util::gn_error_log.clear(); - return gn_success; -} - -int gn_error_string(char* buf, size_t size) -{ - try { - std::string_view s = util::gn_error_log.get(); - util::fill_string_buffer(s.data(), s.size(), buf, size); - } catch (const std::exception&) { - return gn_failure; - } - return gn_success; -} - -int gn_set_string_termination(bool null_terminated) -{ - util::gn_null_terminate = null_terminated; - return gn_success; -} - -int gn_version_string(char* buf, size_t size) -{ - try { - std::string_view s = gn::version_string(); - util::fill_string_buffer(s.data(), s.size(), buf, size); - } catch (const std::exception& e) { - return util::return_on_exception("gn_version_string : ", e.what()); - } - return gn_success; -} - -/**************************************************************************/ -/* API Utility Helpers */ -/**************************************************************************/ - -int gn_error_string_size(size_t* size) -{ - try { - util::check_pointer(size); - *size = util::terminated_size(util::gn_error_log.size()); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_error_string_size : ", e.what()); - } -} - -int gn_version_string_size(size_t* size) -{ - try { - util::check_pointer(size); - *size = util::terminated_size(gn::version_string().size()); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_version_string_size : ", e.what()); - } -} - -/**************************************************************************/ -/* Array Operations */ -/**************************************************************************/ - -int gn_abs(double* out, size_t out_size, const double* in, size_t in_size) -{ - try { - gn::abs(in, in_size, out, out_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_abs : ", e.what()); - } -} - -int gn_angle(double* out, size_t out_size, const double* in, size_t in_size) -{ - try { - gn::angle(in, in_size, out, out_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_angle : ", e.what()); - } -} - -int gn_db(double* out, size_t out_size, const double* in, size_t in_size) -{ - try { - gn::db(in, in_size, out, out_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_db : ", e.what()); - } -} - -int gn_db10(double* out, size_t out_size, const double* in, size_t in_size) -{ - try { - gn::db10(in, in_size, out, out_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_db10 : ", e.what()); - } -} - -int gn_db20(double* out, size_t out_size, const double* in, size_t in_size) -{ - try { - gn::db20(in, in_size, out, out_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_db20 : ", e.what()); - } -} - -int gn_norm(double* out, size_t out_size, const double* in, size_t in_size) -{ - try { - gn::norm(in, in_size, out, out_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_norm : ", e.what()); - } -} - -/**************************************************************************/ -/* Code Density */ -/**************************************************************************/ - -namespace { - - template - int gn_hist(const char* suffix, uint64_t* hist, size_t hist_size, - const T* in, size_t in_size, int n, GnCodeFormat format, bool preserve) - { - try { - gn::CodeFormat f = gn::get_enum(format); - gn::hist(hist, hist_size, in, in_size, n, f, preserve); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_hist", suffix, " : ", e.what()); - } - } - - template - int gn_histx(const char* suffix, uint64_t* hist, size_t hist_size, - const T* in, size_t in_size, int64_t min, int64_t max, bool preserve) - { - try { - gn::histx(hist, hist_size, in, in_size, min, max, preserve); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_histx", suffix, " : ", e.what()); - } - } - -} // namespace anonymous - -int gn_code_axis(double* out, size_t size, int n, GnCodeFormat format) -{ - try { - gn::CodeFormat f = gn::get_enum(format); - gn::code_axis(out, size, n, f); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_code_axis : ", e.what()); - } -} - -int gn_code_axisx(double* out, size_t size, int64_t min, int64_t max) -{ - try { - gn::code_axisx(out, size, min, max); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_code_axisx : ", e.what()); - } -} - -int gn_dnl(double* dnl, size_t dnl_size, const uint64_t* hist, size_t hist_size, GnDnlSignal type) -{ - try { - gn::DnlSignal t = gn::get_enum(type); - gn::dnl(dnl, dnl_size, hist, hist_size, t); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_dnl : ", e.what()); - } -} - -int gn_dnl_analysis(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, - const double* dnl, size_t dnl_size) -{ - try { - util::check_pointer(rkeys); - util::check_pointer(rvalues); - const std::vector& keys = gn::dnl_analysis_ordered_keys(); - if (keys.size() != rkeys_size) { - throw std::runtime_error("Size of result key array is wrong"); - } - if (rvalues_size != rkeys_size) { - throw std::runtime_error("Size of result keys does not match size of result values"); - } - std::map results = gn::dnl_analysis(dnl, dnl_size); - for (size_t i = 0; i < keys.size(); ++i) { - const std::string& src = keys[i]; - char* dst = rkeys[i]; - size_t dst_size = util::terminated_size(src.size()); - util::fill_string_buffer(src.data(), src.size(), dst, dst_size); - rvalues[i] = results.at(src); - } - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_dnl_analysis : ", e.what()); - } -} - -int gn_hist16(uint64_t* hist, size_t hist_size, const int16_t* in, size_t in_size, - int n, GnCodeFormat format, bool preserve) -{ - return gn_hist("16", hist, hist_size, in, in_size, n, format, preserve); -} - -int gn_hist32(uint64_t* hist, size_t hist_size, const int32_t* in, size_t in_size, - int n, GnCodeFormat format, bool preserve) -{ - return gn_hist("32", hist, hist_size, in, in_size, n, format, preserve); -} - -int gn_hist64(uint64_t* hist, size_t hist_size, const int64_t* in, size_t in_size, - int n, GnCodeFormat format, bool preserve) -{ - return gn_hist("64", hist, hist_size, in, in_size, n, format, preserve); -} - -int gn_histx16(uint64_t* hist, size_t hist_size, const int16_t* in, size_t in_size, - int64_t min, int64_t max, bool preserve) -{ - return gn_histx("16", hist, hist_size, in, in_size, min, max, preserve); -} - -int gn_histx32(uint64_t* hist, size_t hist_size, const int32_t* in, size_t in_size, - int64_t min, int64_t max, bool preserve) -{ - return gn_histx("32", hist, hist_size, in, in_size, min, max, preserve); -} - -int gn_histx64(uint64_t* hist, size_t hist_size, const int64_t* in, size_t in_size, - int64_t min, int64_t max, bool preserve) -{ - return gn_histx("64", hist, hist_size, in, in_size, min, max, preserve); -} - -int gn_hist_analysis(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, - const uint64_t* hist, size_t hist_size) -{ - try { - util::check_pointer(rkeys); - util::check_pointer(rvalues); - const std::vector& keys = gn::hist_analysis_ordered_keys(); - if (keys.size() != rkeys_size) { - throw std::runtime_error("Size of result key array is wrong"); - } - if (rvalues_size != rkeys_size) { - throw std::runtime_error("Size of result keys does not match size of result values"); - } - std::map results = gn::hist_analysis(hist, hist_size); - for (size_t i = 0; i < keys.size(); ++i) { - const std::string& src = keys[i]; - char* dst = rkeys[i]; - size_t dst_size = util::terminated_size(src.size()); - util::fill_string_buffer(src.data(), src.size(), dst, dst_size); - rvalues[i] = results.at(src); - } - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_hist_analysis : ", e.what()); - } -} - -int gn_inl(double* inl, size_t inl_size, const double* dnl, size_t dnl_size, GnInlLineFit fit) -{ - try { - gn::InlLineFit f = gn::get_enum(fit); - gn::inl(inl, inl_size, dnl, dnl_size, f); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_inl : ", e.what()); - } -} - -int gn_inl_analysis(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, - const double* inl, size_t inl_size) -{ - try { - util::check_pointer(rkeys); - util::check_pointer(rvalues); - const std::vector& keys = gn::inl_analysis_ordered_keys(); - if (keys.size() != rkeys_size) { - throw std::runtime_error("Size of result key array is wrong"); - } - if (rvalues_size != rkeys_size) { - throw std::runtime_error("Size of result keys does not match size of result values"); - } - std::map results = gn::inl_analysis(inl, inl_size); - for (size_t i = 0; i < keys.size(); ++i) { - const std::string& src = keys[i]; - char* dst = rkeys[i]; - size_t dst_size = util::terminated_size(src.size()); - util::fill_string_buffer(src.data(), src.size(), dst, dst_size); - rvalues[i] = results.at(src); - } - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_inl_analysis : ", e.what()); - } -} - -/**************************************************************************/ -/* Code Density Helpers */ -/**************************************************************************/ - -int gn_code_density_size(size_t* size, int n, GnCodeFormat format) -{ - try { - util::check_pointer(size); - gn::CodeFormat f = gn::get_enum(format); - *size = gn::code_density_size(n, f); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_code_density_size : ", e.what()); - } -} - -int gn_code_densityx_size(size_t* size, int64_t min, int64_t max) -{ - try { - util::check_pointer(size); - *size = gn::code_densityx_size(min, max); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_code_densityx_size : ", e.what()); - } -} - -/**************************************************************************/ -/* Fourier Analysis */ -/**************************************************************************/ - -namespace { - - using fa_ptr = std::shared_ptr; - - fa_ptr get_fa_object(const std::string& obj_key) - { - gn::object::pointer pobj = gn::manager::get_object(obj_key); - const gn::ObjectType obj_type = gn::ObjectType::FourierAnalysis; - if (obj_type != pobj->object_type()) { - throw std::runtime_error("object '" + obj_key + "' is not of type " - + gn::object_type_map.at(static_cast(obj_type))); - } - return std::static_pointer_cast(pobj); - } - - fa_ptr get_fa_object_or_load_from_file(std::string cfg_id) - { - if (gn::manager::contains(cfg_id)) { - return get_fa_object(cfg_id); - } else { - return gn::fourier_analysis::load(cfg_id); - } - } - - size_t get_fa_result_key_index(const char** rkeys, size_t rkeys_size, const char* rkey) - { - size_t i = 0; - for (; i < rkeys_size; ++i) { - if (0 == strcmp(rkeys[i], rkey)) { - break; - } - } - if (rkeys_size == i) { - throw std::runtime_error("Result key '" + std::string(rkey) + "' not found"); - } - return i; - } - - std::string get_fa_result_string(const char** rkeys, size_t rkeys_size, - const double* rvalues, size_t rvalues_size, const char* rkey) - { - if (rkeys_size != rvalues_size) { - throw std::runtime_error("Size of result keys does not match size of result values"); - } - if (gn::fa_result_map.contains(rkey, true)) { - gn::FAResult renum = static_cast(gn::fa_result_map.at(rkey)); - if (gn::FAResult::CarrierIndex == renum || - gn::FAResult::MaxSpurIndex == renum) { - // Caller requests the Carrier or MaxSpur tone key. - size_t key_index = get_fa_result_key_index(rkeys, rkeys_size, rkey); - size_t order_index = static_cast(rvalues[key_index]); - int order_index_int = static_cast(gn::FAToneResult::OrderIndex); - std::string search_str = ":" + gn::fa_tone_result_map.at(order_index_int); - const char* search_cstr = search_str.c_str(); - size_t i = 0; - for (; i < rvalues_size; ++i) { - if (strstr(rkeys[i], search_cstr)) { - if (rvalues[i] == order_index) { - break; - } - } - } - if (rvalues_size == i) { - return "Not Found"; - } else { - return gn::fourier_analysis::split_key(rkeys[i]).first; - } - } - } else { - // In the future, there could be a string associated with a tone result. - } - throw std::runtime_error("no string associated with result key '" + std::string(rkey) + "'"); - } - - int get_fa_single_result( - const gn::fourier_analysis_results& results, const char* rkey, double* rvalue) - { - *rvalue = 0.0; - std::pair keys = gn::fourier_analysis::split_key(rkey); - if (!keys.first.empty()) { - if (keys.second.empty()) { - if (gn::fa_result_map.contains(keys.first)) { - int i = gn::fa_result_map.at(keys.first); - *rvalue = results.get(static_cast(i)); - return gn_success; - } - } else { - if (results.contains_tone(keys.first)) { - const gn::fa_tone_results& tres = results.get_tone(keys.first); - if (gn::fa_tone_result_map.at(keys.second)) { - int i = gn::fa_tone_result_map.at(keys.second); - *rvalue = tres.get(static_cast(i)); - return gn_success; - } - } - } - } - return gn_failure; - } - -} // namespace anonymous - -int gn_fft_analysis(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, - const char* cfg_id, const double* in, size_t in_size, size_t nfft, GnFreqAxisType axis_type) -{ - try { - if (rkeys_size != rvalues_size) { - throw std::runtime_error("Size of result keys does not match size of result values"); - } - fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); - gn::FreqAxisType at = gn::get_enum(axis_type); - gn::fourier_analysis_results results = obj->analyze(in, in_size, nfft, at); - // The rest of this function flattens results into a key-array and value-array pair - size_t i = 0; // index for rkeys, rvalues - const std::map& rmap = results.results; - for (int j = 0; j < static_cast(gn::FAResult::__SIZE__); ++j) { - const std::string& src = gn::fa_result_map.at(j); - char* dst = rkeys[i]; - size_t dst_size = util::terminated_size(src.size()); - util::fill_string_buffer(src.data(), src.size(), dst, dst_size); - rvalues[i] = rmap.at(static_cast(j)); - i += 1; - } - for (const std::string& tkey : results.tone_keys) { - const gn::fa_tone_results& tone_results = results.get_tone(tkey); - const std::map& trmap = tone_results.results; - for (int j = 0; j < static_cast(gn::FAToneResult::__SIZE__); ++j) { - std::string src = gn::fourier_analysis::flat_tone_key(tkey, j); - char* dst = rkeys[i]; - size_t dst_size = util::terminated_size(src.size()); - util::fill_string_buffer(src.data(), src.size(), dst, dst_size); - rvalues[i] = trmap.at(static_cast(j)); - i += 1; - } - } - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_execute : ", e.what()); - } -} - -int gn_fft_analysis_select(double* rvalues, size_t rvalues_size, - const char* cfg_id, const char** rkeys, size_t rkeys_size, - const double* in, size_t in_size, size_t nfft, GnFreqAxisType axis_type) -{ - try { - if (rkeys_size != rvalues_size) { - throw std::runtime_error("Size of result keys does not match size of result values"); - } - fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); - gn::FreqAxisType at = gn::get_enum(axis_type); - gn::fourier_analysis_results results = obj->analyze(in, in_size, nfft, at); - std::string missing_keys {}; - for (size_t i = 0; i < rkeys_size; ++i) { - int error = get_fa_single_result(results, rkeys[i], &rvalues[i]); - if (error) { - if (!missing_keys.empty()) { - missing_keys += ", "; - } - missing_keys.append("'" + std::string(rkeys[i]) + "'"); - } - } - if (!missing_keys.empty()) { - throw std::runtime_error("Keys not found: " + missing_keys); - } - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_execute2 : ", e.what()); - } -} - -int gn_fft_analysis_single(double* rvalue, - const char* cfg_id, const char* rkey, - const double* in, size_t in_size, size_t nfft, GnFreqAxisType axis_type) -{ - try { - fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); - gn::FreqAxisType at = gn::get_enum(axis_type); - gn::fourier_analysis_results results = obj->analyze(in, in_size, nfft, at); - int error = get_fa_single_result(results, rkey, rvalue); - if (error) { - throw std::runtime_error("Key '" + std::string(rkey) + "' not found"); - } - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_execute1 : ", e.what()); - } -} - -/**************************************************************************/ -/* Fourier Analysis Configuration */ -/**************************************************************************/ - -int gn_fa_analysis_band(const char* obj_key, double center, double width) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - std::string center_s = gn::to_string(center, gn::FPFormat::Eng); - std::string width_s = gn::to_string(width, gn::FPFormat::Eng); - obj->set_analysis_band(center_s, width_s); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_analysis_band : ", e.what()); - } -} - -int gn_fa_analysis_band_e(const char* obj_key, const char* center, const char* width) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - obj->set_analysis_band(center, width); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_analysis_band_e : ", e.what()); - } -} - -int gn_fa_clk(const char* obj_key, const int* clk, size_t clk_size, bool as_noise) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - std::set clk2 (clk, clk + clk_size); - obj->set_clk(clk2); - obj->clk_as_noise = as_noise; - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_clk : ", e.what()); - } -} - -int gn_fa_conv_offset(const char* obj_key, bool enable) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - obj->en_conv_offset = enable; - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_conv_offset : ", e.what()); - } -} - -int gn_fa_create(const char* obj_key) -{ - try { - gn::manager::add_object(obj_key, gn::fourier_analysis::create(), false); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_create : ", e.what()); - } -} - -int gn_fa_dc(const char* obj_key, bool as_dist) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - obj->dc_as_dist = as_dist; - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_dc : ", e.what()); - } -} - -int gn_fa_fdata(const char* obj_key, double f) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - std::string f_s = gn::to_string(f, gn::FPFormat::Eng); - obj->set_fdata(f_s); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_fdata : ", e.what()); - } -} - -int gn_fa_fdata_e(const char* obj_key, const char* f) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - obj->set_fdata(f); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_fdata_e : ", e.what()); - } -} - -int gn_fa_fixed_tone( - const char* obj_key, const char* comp_key, GnFACompTag tag, double freq, int ssb) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - gn::FACompTag t = gn::get_enum(tag); - std::string freq_s = gn::to_string(freq, gn::FPFormat::Eng); - obj->add_fixed_tone(comp_key, t, freq_s, ssb); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_fixed_tone : ", e.what()); - } -} - -int gn_fa_fixed_tone_e( - const char* obj_key, const char* comp_key, GnFACompTag tag, const char* freq, int ssb) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - gn::FACompTag t = gn::get_enum(tag); - obj->add_fixed_tone(comp_key, t, freq, ssb); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_fixed_tone_e : ", e.what()); - } -} - -int gn_fa_fsample(const char* obj_key, double f) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - std::string f_s = gn::to_string(f, gn::FPFormat::Eng); - obj->set_fsample(f_s); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_fsample : ", e.what()); - } -} - -int gn_fa_fsample_e(const char* obj_key, const char* f) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - obj->set_fsample(f); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_fsample_e : ", e.what()); - } -} - -int gn_fa_fshift(const char* obj_key, double f) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - std::string f_s = gn::to_string(f, gn::FPFormat::Eng); - obj->set_fshift(f_s); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_fshift : ", e.what()); - } -} - -int gn_fa_fshift_e(const char* obj_key, const char* f) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - obj->set_fshift(f); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_fshift_e : ", e.what()); - } -} - -int gn_fa_fund_images(const char* obj_key, bool enable) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - obj->en_fund_images = enable; - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_fund_images : ", e.what()); - } -} - -int gn_fa_hd(const char* obj_key, int n) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - obj->set_hd(n); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_hd : ", e.what()); - } -} - -int gn_fa_ilv(const char* obj_key, const int* ilv, size_t ilv_size, bool as_noise) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - std::set ilv2 (ilv, ilv + ilv_size); - obj->set_ilv(ilv2); - obj->ilv_as_noise = as_noise; - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_ilv : ", e.what()); - } -} - -int gn_fa_imd(const char* obj_key, int n) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - obj->set_imd(n); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_imd : ", e.what()); - } -} - -int gn_fa_load(char* buf, size_t size, const char* filename, const char* obj_key) -{ - try { - std::string key (obj_key); - if (key.empty()) { - key = util::get_object_key_from_filename(filename); - } - gn::manager::add_object(key, gn::fourier_analysis::load(filename), true); - util::fill_string_buffer(key.data(), key.size(), buf, size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_load : ", e.what()); - } -} - -int gn_fa_max_tone( - const char* obj_key, - const char* comp_key, - GnFACompTag tag, - int ssb) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - gn::FACompTag t = gn::get_enum(tag); - obj->add_max_tone(comp_key, t, "0.0", "fdata", ssb); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_max_tone : ", e.what()); - } -} - -int gn_fa_preview(char* buf, size_t size, const char* cfg_id, bool cplx) -{ - try { - fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); - std::string s = obj->preview(cplx); - util::fill_string_buffer(s.data(), s.size(), buf, size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_preview : ", e.what()); - } -} - -int gn_fa_quad_errors(const char* obj_key, bool enable) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - obj->en_quad_errors = enable; - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_quad_errors : ", e.what()); - } -} - -int gn_fa_remove_comp(const char* obj_key, const char* comp_key) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - obj->remove_comp(comp_key); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_remove_comp : ", e.what()); - } -} - -int gn_fa_reset(const char* obj_key) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - obj->reset(); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_reset : ", e.what()); - } -} - -int gn_fa_ssb(const char* obj_key, GnFASsb group, int ssb) -{ - try { - gn::FASsb g = gn::get_enum(group); - fa_ptr obj = get_fa_object(obj_key); - obj->set_ssb(g, ssb); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_ssb_dc : ", e.what()); - } -} - -int gn_fa_var(const char* obj_key, const char* name, double value) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - obj->set_var(name, value); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_var : ", e.what()); - } -} - -int gn_fa_wo(const char* obj_key, int n) -{ - try { - fa_ptr obj = get_fa_object(obj_key); - obj->set_wo(n); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_wo : ", e.what()); - } -} - -/**************************************************************************/ -/* Fourier Analysis Results */ -/**************************************************************************/ - -int gn_fa_result(double* result, const char** rkeys, size_t rkeys_size, - const double* rvalues, size_t rvalues_size, const char* rkey) -{ - try { - util::check_pointer(result); - if (rkeys_size != rvalues_size) { - throw std::runtime_error("Size of result keys does not match size of result values"); - } - size_t key_index = get_fa_result_key_index(rkeys, rkeys_size, rkey); - *result = rvalues[key_index]; - return gn_success; - } catch (const std::exception& e) { - *result = 0.0; - return util::return_on_exception("gn_fa_result : ", e.what()); - } -} - -int gn_fa_result_string(char* result, size_t result_size, const char** rkeys, size_t rkeys_size, - const double* rvalues, size_t rvalues_size, const char* rkey) -{ - try { - util::check_pointer(result); - std::string rstr = get_fa_result_string(rkeys, rkeys_size, rvalues, rvalues_size, rkey); - util::fill_string_buffer(rstr.data(), rstr.size(), result, result_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fa_result_string : ", e.what()); - } -} - -/**************************************************************************/ -/* Fourier Analysis Helpers */ -/**************************************************************************/ - -int gn_fa_load_key_size(size_t* size, const char* filename, const char* obj_key) -{ - try { - util::check_pointer(size); - std::string key (obj_key); - if (key.empty()) { - key = util::get_object_key_from_filename(filename); - } - *size = util::terminated_size(key.size()); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_fa_load_key_size : ", e.what()); - } -} - -int gn_fa_preview_size(size_t* size, const char* cfg_id, bool cplx) -{ - try { - util::check_pointer(size); - fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); - std::string s = obj->preview(cplx); - *size = util::terminated_size(s.size()); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_fa_preview_size : ", e.what()); - } -} - -int gn_fa_result_string_size(size_t* size, const char** rkeys, size_t rkeys_size, - const double* rvalues, size_t rvalues_size, const char* rkey) -{ - try { - util::check_pointer(size); - std::string rstr = get_fa_result_string(rkeys, rkeys_size, rvalues, rvalues_size, rkey); - *size = util::terminated_size(rstr.size()); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_fa_result_string_size : ", e.what()); - } -} - -int gn_fft_analysis_results_key_sizes(size_t* key_sizes, size_t key_sizes_size, - const char* cfg_id, size_t in_size, size_t nfft) -{ - try { - fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); - std::vector key_sizes_src = obj->result_key_lengths(in_size, nfft); - if (key_sizes_src.size() != key_sizes_size) { - throw std::runtime_error("Number of keys does not match output array size"); - } - for (size_t i = 0; i < key_sizes_size; ++i) { - key_sizes[i] = util::terminated_size(key_sizes_src[i]); - } - return gn_success; - } catch (const std::exception& e) { - std::fill(key_sizes, key_sizes + key_sizes_size, 0); - return util::return_on_exception("gn_fa_results_key_sizes : ", e.what()); - } -} - -int gn_fft_analysis_results_size(size_t* size, const char* cfg_id, size_t in_size, size_t nfft) -{ - try { - util::check_pointer(size); - fa_ptr obj = get_fa_object_or_load_from_file(cfg_id); - *size = obj->results_size(in_size, nfft); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_fa_results_size : ", e.what()); - } -} - -/**************************************************************************/ -/* Fourier Transforms */ -/**************************************************************************/ - -namespace { - - template - int gn_fftxx(const char* suffix, double* out, size_t out_size, - const T* i, size_t i_size, const T* q, size_t q_size, - int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format) - { - try { - gn::Window w = gn::get_enum(window); - gn::CodeFormat f = gn::get_enum(format); - gn::fft(i, i_size, q, q_size, out, out_size, n, navg, nfft, w, f); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fft", suffix, " : ", e.what()); - } - } - - template - int gn_rfftxx(const char* suffix, double* out, size_t out_size, - const T* in, size_t in_size, - int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format, GnRfftScale scale) - { - try { - gn::Window w = gn::get_enum(window); - gn::CodeFormat f = gn::get_enum(format); - gn::RfftScale s = gn::get_enum(scale); - gn::rfft(in, in_size, out, out_size, n, navg, nfft, w, f, s); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_rfft", suffix, " : ", e.what()); - } - } - -} // namespace anonymous - -int gn_fft(double* out, size_t out_size, - const double* i, size_t i_size, const double* q, size_t q_size, - size_t navg, size_t nfft, GnWindow window) -{ - try { - gn::Window w = gn::get_enum(window); - gn::fft(i, i_size, q, q_size, out, out_size, navg, nfft, w); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fft : ", e.what()); - } -} - -int gn_fft16(double* out, size_t out_size, - const int16_t* i, size_t i_size, const int16_t* q, size_t q_size, - int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format) -{ - return gn_fftxx("16", out, out_size, i, i_size, q, q_size, n, navg, nfft, window, format); -} - -int gn_fft32(double* out, size_t out_size, - const int32_t* i, size_t i_size, const int32_t* q, size_t q_size, - int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format) -{ - return gn_fftxx("32", out, out_size, i, i_size, q, q_size, n, navg, nfft, window, format); -} - -int gn_fft64(double* out, size_t out_size, - const int64_t* i, size_t i_size, const int64_t* q, size_t q_size, - int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format) -{ - return gn_fftxx("64", out, out_size, i, i_size, q, q_size, n, navg, nfft, window, format); -} - -int gn_rfft(double* out, size_t out_size, const double* in, size_t in_size, - size_t navg, size_t nfft, GnWindow window, GnRfftScale scale) -{ - try { - gn::Window w = gn::get_enum(window); - gn::RfftScale s = gn::get_enum(scale); - gn::rfft(in, in_size, out, out_size, navg, nfft, w, s); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_rfft : ", e.what()); - } -} - -int gn_rfft16(double* out, size_t out_size, const int16_t* in, size_t in_size, - int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format, GnRfftScale scale) -{ - return gn_rfftxx("16", out, out_size, in, in_size, n, navg, nfft, window, format, scale); -} - -int gn_rfft32(double* out, size_t out_size, const int32_t* in, size_t in_size, - int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format, GnRfftScale scale) -{ - return gn_rfftxx("32", out, out_size, in, in_size, n, navg, nfft, window, format, scale); -} - -int gn_rfft64(double* out, size_t out_size, const int64_t* in, size_t in_size, - int n, size_t navg, size_t nfft, GnWindow window, GnCodeFormat format, GnRfftScale scale) -{ - return gn_rfftxx("64", out, out_size, in, in_size, n, navg, nfft, window, format, scale); -} - -/**************************************************************************/ -/* Fourier Transform Helpers */ -/**************************************************************************/ - -int gn_fft_size(size_t* out_size, size_t i_size, size_t q_size, size_t navg, size_t nfft) -{ - try { - util::check_pointer(out_size); - *out_size = gn::fft_size(i_size, q_size, navg, nfft); - return gn_success; - } catch (const std::exception& e) { - *out_size = 0; - return util::return_on_exception("gn_fft_size : ", e.what()); - } -} - -int gn_rfft_size(size_t* out_size, size_t in_size, size_t navg, size_t nfft) -{ - try { - util::check_pointer(out_size); - *out_size = gn::rfft_size(in_size, navg, nfft); - return gn_success; - } catch (const std::exception& e) { - *out_size = 0; - return util::return_on_exception("gn_rfft_size : ", e.what()); - } -} - -/**************************************************************************/ -/* Fourier Utilities */ -/**************************************************************************/ - -int gn_alias(double* out, double fs, double freq, GnFreqAxisType axis_type) -{ - try { - util::check_pointer(out); - gn::FreqAxisType at = gn::get_enum(axis_type); - *out = gn::alias(fs, freq, at); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_alias : ", e.what()); - } -} - -int gn_coherent(double* out, size_t nfft, double fs, double freq) -{ - try { - util::check_pointer(out); - *out = gn::coherent(nfft, fs, freq); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_coherent : ", e.what()); - } -} - -int gn_fftshift(double* out, size_t out_size, const double* in, size_t in_size) -{ - try { - gn::fftshift(in, in_size, out, out_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fftshift : ", e.what()); - } -} - -int gn_freq_axis(double* out, size_t size, - size_t nfft, GnFreqAxisType axis_type, double fs, GnFreqAxisFormat axis_format) -{ - try { - gn::FreqAxisType at = gn::get_enum(axis_type); - gn::FreqAxisFormat af = gn::get_enum(axis_format); - gn::freq_axis(out, size, nfft, at, fs, af); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fftshift : ", e.what()); - } -} - -int gn_ifftshift(double* out, size_t out_size, const double* in, size_t in_size) -{ - try { - gn::ifftshift(in, in_size, out, out_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_ifftshift : ", e.what()); - } -} - -/**************************************************************************/ -/* Fourier Utility Helpers */ -/**************************************************************************/ - -int gn_freq_axis_size(size_t* size, size_t nfft, GnFreqAxisType axis_type) -{ - try { - util::check_pointer(size); - gn::FreqAxisType at = gn::get_enum(axis_type); - *size = gn::freq_axis_size(nfft, at); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_freq_axis_size : ", e.what()); - } -} - -/**************************************************************************/ -/* Manager */ -/**************************************************************************/ - -int gn_mgr_clear() -{ - gn::manager::clear(); - return gn_success; -} - -int gn_mgr_compare(bool* result, const char* obj_key1, const char* obj_key2) -{ - try { - *result = gn::manager::equal(obj_key1, obj_key2); - return gn_success; - } catch (const std::exception& e) { - *result = false; - return util::return_on_exception("gn_mgr_equal : ", e.what()); - } -} - -int gn_mgr_contains(bool* result, const char* obj_key) -{ - *result = gn::manager::contains(obj_key); - return gn_success; -} - -int gn_mgr_remove(const char* obj_key) -{ - gn::manager::remove(obj_key); - return gn_success; -} - -int gn_mgr_save(char* buf, size_t size, const char* obj_key, const char* filename) -{ - try { - std::string fn = gn::manager::save(obj_key, filename); - util::fill_string_buffer(fn.data(), fn.size(), buf, size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_mgr_save : ", e.what()); - } -} - -int gn_mgr_size(size_t* size) -{ - *size = gn::manager::size(); - return gn_success; -} - -int gn_mgr_to_string(char* buf, size_t size, const char* obj_key) -{ - try { - std::string s = gn::manager::to_string(obj_key); - util::fill_string_buffer(s.data(), s.size(), buf, size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_mgr_to_string : ", e.what()); - } -} - -int gn_mgr_type(char* buf, size_t size, const char* obj_key) -{ - try { - std::string s = gn::manager::type_str(obj_key); - util::fill_string_buffer(s.data(), s.size(), buf, size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_mgr_type : ", e.what()); - } -} - -/**************************************************************************/ -/* Manager Helpers */ -/**************************************************************************/ - -int gn_mgr_save_filename_size(size_t* size, const char* obj_key, const char* filename) -{ - try { - util::check_pointer(size); - size_t fn_size = gn::manager::get_filename_from_object_key(obj_key, filename).size(); - *size = util::terminated_size(fn_size); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_mgr_save_filename_size : ", e.what()); - } -} - -int gn_mgr_to_string_size(size_t* size, const char* obj_key) -{ - try { - util::check_pointer(size); - *size = util::terminated_size(gn::manager::to_string(obj_key).size()); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_mgr_to_string_size : ", e.what()); - } -} - -int gn_mgr_type_size(size_t* size, const char* obj_key) -{ - try { - util::check_pointer(size); - *size = util::terminated_size(gn::manager::type_str(obj_key).size()); - return gn_success; - } catch (const std::exception& e) { - *size = 0; - return util::return_on_exception("gn_mgr_type_size : ", e.what()); - } -} - -/**************************************************************************/ -/* Signal Processing */ -/**************************************************************************/ - -namespace { - - template - int gn_downsamplex(const char* suffix, T* out, size_t out_size, - const T* in, size_t in_size, int ratio, bool interleaved) - { - try { - gn::downsample(in, in_size, out, out_size, ratio, interleaved); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_downsample", suffix, " : ", e.what()); - } - } - - template - int gn_fshiftx(const char* suffix, T* out, size_t out_size, - const T* i, size_t i_size, const T* q, size_t q_size, - int n, double fs, double fshift, GnCodeFormat format) - { - try { - gn::CodeFormat f = gn::get_enum(format); - gn::fshift(i, i_size, q, q_size, out, out_size, n, fs, fshift, f); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fshift", suffix, " : ", e.what()); - } - } - - template - int gn_normalize(const char* suffix, double* out, size_t out_size, - const T* in, size_t in_size, int n, GnCodeFormat format) - { - try { - gn::CodeFormat f = gn::get_enum(format); - gn::normalize(in, in_size, out, out_size, n, f); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_normalize", suffix, " : ", e.what()); - } - } - - template - int gn_quantize(const char* suffix, T* out, size_t out_size, - const double* in, size_t in_size, double fsr, int n, double noise, GnCodeFormat format) - { - try { - gn::CodeFormat f = gn::get_enum(format); - gn::quantize(in, in_size, out, out_size, fsr, n, noise, f); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_quantize", suffix, " : ", e.what()); - } - } - -} // namespace anonymous - -int gn_downsample(double* out, size_t out_size, - const double* in, size_t in_size, int ratio, bool interleaved) -{ - return gn_downsamplex("", out, out_size, in, in_size, ratio, interleaved); -} - -int gn_downsample16(int16_t* out, size_t out_size, - const int16_t* in, size_t in_size, int ratio, bool interleaved) -{ - return gn_downsamplex("16", out, out_size, in, in_size, ratio, interleaved); -} - -int gn_downsample32(int32_t* out, size_t out_size, - const int32_t* in, size_t in_size, int ratio, bool interleaved) -{ - return gn_downsamplex("32", out, out_size, in, in_size, ratio, interleaved); -} - -int gn_downsample64(int64_t* out, size_t out_size, - const int64_t* in, size_t in_size, int ratio, bool interleaved) -{ - return gn_downsamplex("64", out, out_size, in, in_size, ratio, interleaved); -} - -int gn_fshift(double* out, size_t out_size, - const double* i, size_t i_size, const double* q, size_t q_size, double fs, double fshift) -{ - try { - gn::fshift(i, i_size, q, q_size, out, out_size, fs, fshift); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_fshift : ", e.what()); - } -} - -int gn_fshift16(int16_t* out, size_t out_size, - const int16_t* i, size_t i_size, const int16_t* q, size_t q_size, - int n, double fs, double fshift, GnCodeFormat format) -{ - return gn_fshiftx("16", out, out_size, i, i_size, q, q_size, n, fs, fshift, format); -} - -int gn_fshift32(int32_t* out, size_t out_size, - const int32_t* i, size_t i_size, const int32_t* q, size_t q_size, - int n, double fs, double fshift, GnCodeFormat format) -{ - return gn_fshiftx("32", out, out_size, i, i_size, q, q_size, n, fs, fshift, format); -} - -int gn_fshift64(int64_t* out, size_t out_size, - const int64_t* i, size_t i_size, const int64_t* q, size_t q_size, - int n, double fs, double fshift, GnCodeFormat format) -{ - return gn_fshiftx("64", out, out_size, i, i_size, q, q_size, n, fs, fshift, format); -} - -int gn_normalize16(double* out, size_t out_size, - const int16_t* in, size_t in_size, int n, GnCodeFormat format) -{ - return gn_normalize("16", out, out_size, in, in_size, n, format); -} - -int gn_normalize32(double* out, size_t out_size, - const int32_t* in, size_t in_size, int n, GnCodeFormat format) -{ - return gn_normalize("32", out, out_size, in, in_size, n, format); -} - -int gn_normalize64(double* out, size_t out_size, - const int64_t* in, size_t in_size, int n, GnCodeFormat format) -{ - return gn_normalize("64", out, out_size, in, in_size, n, format); -} - -int gn_polyval(double* out, size_t out_size, - const double* in, size_t in_size, const double* c, size_t c_size) -{ - try { - gn::polyval(in, in_size, out, out_size, c, c_size); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_polyval : ", e.what()); - } -} - -int gn_quantize16(int16_t* out, size_t out_size, - const double* in, size_t in_size, double fsr, int n, double noise, GnCodeFormat format) -{ - return gn_quantize("16", out, out_size, in, in_size, fsr, n, noise, format); -} - -int gn_quantize32(int32_t* out, size_t out_size, - const double* in, size_t in_size, double fsr, int n, double noise, GnCodeFormat format) -{ - return gn_quantize("32", out, out_size, in, in_size, fsr, n, noise, format); -} - -int gn_quantize64(int64_t* out, size_t out_size, - const double* in, size_t in_size, double fsr, int n, double noise, GnCodeFormat format) -{ - return gn_quantize("64", out, out_size, in, in_size, fsr, n, noise, format); -} - -/**************************************************************************/ -/* Signal Processing Helpers */ -/**************************************************************************/ - -int gn_downsample_size(size_t* out_size, size_t in_size, int ratio, bool interleaved) -{ - try { - util::check_pointer(out_size); - *out_size = gn::downsample_size(in_size, ratio, interleaved); - return gn_success; - } catch (const std::exception& e) { - *out_size = 0; - return util::return_on_exception("gn_downsample_size : ", e.what()); - } -} - -int gn_fshift_size(size_t* out_size, size_t i_size, size_t q_size) -{ - try { - util::check_pointer(out_size); - *out_size = gn::fshift_size(i_size, q_size); - return gn_success; - } catch (const std::exception& e) { - *out_size = 0; - return util::return_on_exception("gn_fshift_size : ", e.what()); - } -} - -/**************************************************************************/ -/* Waveforms */ -/**************************************************************************/ - -namespace { - - template - int gn_wf_analysisx(const char* suffix, - char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, - const T* in, size_t in_size) - { - try { - util::check_pointer(rkeys); - util::check_pointer(rvalues); - const std::vector& keys = gn::wf_analysis_ordered_keys(); - if (keys.size() != rkeys_size) { - throw std::runtime_error("Size of result key array is wrong"); - } - if (rvalues_size != rkeys_size) { - throw std::runtime_error("Size of result keys does not match size of result values"); - } - std::map results = gn::wf_analysis(in, in_size); - for (size_t i = 0; i < keys.size(); ++i) { - const std::string& src = keys[i]; - char* dst = rkeys[i]; - size_t dst_size = util::terminated_size(src.size()); - util::fill_string_buffer(src.data(), src.size(), dst, dst_size); - rvalues[i] = results.at(src); - } - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_wf_analysis", suffix, " : ", e.what()); - } - } - -} // namespace anonymous - -int gn_cos(double* out, size_t size, - double fs, double ampl, double freq, double phase, double td, double tj) -{ - try { - gn::cos(out, size, fs, ampl, freq, phase, td, tj); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_cos : ", e.what()); - } -} - -int gn_gaussian(double* out, size_t size, double mean, double sd) -{ - try { - gn::gaussian(out, size, mean, sd); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_gaussian : ", e.what()); - } -} - -int gn_ramp(double* out, size_t size, double start, double stop, double noise) -{ - try { - gn::ramp(out, size, start, stop, noise); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_ramp : ", e.what()); - } -} - -int gn_sin(double* out, size_t size, - double fs, double ampl, double freq, double phase, double td, double tj) -{ - try { - gn::sin(out, size, fs, ampl, freq, phase, td, tj); - return gn_success; - } catch (const std::exception& e) { - return util::return_on_exception("gn_sin : ", e.what()); - } -} - -int gn_wf_analysis(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, - const double* in, size_t in_size) -{ - return gn_wf_analysisx("", rkeys, rkeys_size, rvalues, rvalues_size, in, in_size); -} - -int gn_wf_analysis16(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, - const int16_t* in, size_t in_size) -{ - return gn_wf_analysisx("16", rkeys, rkeys_size, rvalues, rvalues_size, in, in_size); -} - -int gn_wf_analysis32(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, - const int32_t* in, size_t in_size) -{ - return gn_wf_analysisx("32", rkeys, rkeys_size, rvalues, rvalues_size, in, in_size); -} - -int gn_wf_analysis64(char** rkeys, size_t rkeys_size, double* rvalues, size_t rvalues_size, - const int64_t* in, size_t in_size) -{ - return gn_wf_analysisx("64", rkeys, rkeys_size, rvalues, rvalues_size, in, in_size); -} \ No newline at end of file diff --git a/bindings/c/src/cgenalyzer_simplified_beta.cpp b/bindings/c/src/cgenalyzer_simplified_beta.cpp new file mode 100644 index 0000000..264e8ae --- /dev/null +++ b/bindings/c/src/cgenalyzer_simplified_beta.cpp @@ -0,0 +1,1169 @@ +#include "cgenalyzer_simplified_beta.h" +#include "cgenalyzer_private.h" + +extern "C" { + int gn_config_free(gn_config *c) + { + if ((*c)->obj_key){ + gn_mgr_remove((*c)->obj_key); + free((*c)->obj_key); + } + if ((*c)->comp_key){ + gn_fa_remove_comp((*c)->obj_key, (*c)->comp_key); + free((*c)->comp_key); + } + if (((*c)->_fa_results_size) > 0) + { + for (size_t i = 0; i < (*c)->_fa_results_size; i++) + free((*c)->_fa_result_keys[i]); + free((*c)->_fa_result_keys); + free((*c)->_fa_result_key_sizes); + free((*c)->_fa_result_values); + } + if (((*c)->_wfa_results_size) > 0) + { + for (size_t i = 0; i < (*c)->_wfa_results_size; i++) + free((*c)->_wfa_result_keys[i]); + free((*c)->_wfa_result_keys); + free((*c)->_wfa_result_key_sizes); + free((*c)->_wfa_result_values); + } + if (((*c)->_hist_results_size) > 0) + { + for (size_t i = 0; i < (*c)->_hist_results_size; i++) + free((*c)->_hist_result_keys[i]); + free((*c)->_hist_result_keys); + free((*c)->_hist_result_key_sizes); + free((*c)->_hist_result_values); + } + if (((*c)->_dnl_results_size) > 0) + { + for (size_t i = 0; i < (*c)->_dnl_results_size; i++) + free((*c)->_dnl_result_keys[i]); + free((*c)->_dnl_result_keys); + free((*c)->_dnl_result_key_sizes); + free((*c)->_dnl_result_values); + } + if (((*c)->_inl_results_size) > 0) + { + for (size_t i = 0; i < (*c)->_inl_results_size; i++) + free((*c)->_inl_result_keys[i]); + free((*c)->_inl_result_keys); + free((*c)->_inl_result_key_sizes); + free((*c)->_inl_result_values); + } + free(*c); + + return gn_success; + } + + int gn_config_set_ttype(tone_type ttype, gn_config *c) + { + if (!((ttype == REAL_COSINE) || (ttype == REAL_SINE) || (ttype == COMPLEX_EXP))) + { + printf("ERROR: Invalid selection of ttype for tone generation\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->ttype = ttype; + + return gn_success; + } + + int gn_config_set_npts(size_t npts, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->npts = npts; + return gn_success; + } + + int gn_config_get_npts(size_t *npts, gn_config *c) + { + if (!(*c)) + { + printf("config struct is NULL\n"); + return gn_failure; + } + *npts = (*c)->npts; + return gn_success; + } + + int gn_config_set_sample_rate(gn::real_t sample_rate, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->sample_rate = sample_rate; + return gn_success; + } + + int gn_config_get_sample_rate(double *sample_rate, gn_config *c) + { + if (!(*c)) + { + printf("config struct is NULL\n"); + return gn_failure; + } + *sample_rate = (*c)->sample_rate; + return gn_success; + } + + int gn_config_set_data_rate(gn::real_t data_rate, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->data_rate = data_rate; + return gn_success; + } + + int gn_config_set_shift_freq(gn::real_t shift_freq, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->shift_freq = shift_freq; + return gn_success; + } + + int gn_config_set_num_tones(size_t num_tones, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->num_tones = num_tones; + return gn_success; + } + + int gn_config_set_tone_freq(gn::real_t *tone_freq, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->tone_freq = tone_freq; + return gn_success; + } + + int gn_config_set_tone_ampl(gn::real_t *tone_ampl, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->tone_ampl = tone_ampl; + return gn_success; + } + + int gn_config_set_tone_phase(gn::real_t *tone_phase, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->tone_phase = tone_phase; + return gn_success; + } + + int gn_config_set_fsr(gn::real_t fsr, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->fsr = fsr; + return gn_success; + } + + int gn_config_set_qres(int qres, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->qres = qres; + return gn_success; + } + + int gn_config_set_noise_rms(gn::real_t noise_rms, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->noise_rms = noise_rms; + return gn_success; + } + + int gn_config_set_code_format(GnCodeFormat code_format, gn_config *c) + { + if (!((code_format == GnCodeFormatOffsetBinary) || (code_format == GnCodeFormatTwosComplement))) + { + printf("ERROR: Invalid selection of code format\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->code_format = code_format; + return gn_success; + } + + int gn_config_set_nfft(size_t nfft, gn_config *c) + { + if (((*c)->nfft) > ((*c)->npts)) + { + printf("ERROR: FFT order cannot be greater than the number of sample points\n"); + return gn_failure; + } + + double rem = 1.0*(((*c)->npts)%((*c)->nfft)); + if (rem > 0) + { + printf("ERROR: FFT order has to be a multiple of the number of sample points\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->nfft = nfft; + (*c)->fft_navg = (*c)->npts/(*c)->nfft; + return gn_success; + } + + int gn_config_get_nfft(size_t *nfft, gn_config *c) + { + if (!(*c)) + { + printf("here - config struct is NULL\n"); + return gn_failure; + } + *nfft = (*c)->nfft; + return gn_success; + } + + int gn_config_set_fft_navg(size_t fft_navg, gn_config *c) + { + if (((*c)->fft_navg) > ((*c)->npts)) + { + printf("ERROR: Number of FFT averages cannot be greater than the number of sample points\n"); + return gn_failure; + } + + double rem = 1.0*(((*c)->npts)%((*c)->fft_navg)); + if (rem > 0) + { + printf("ERROR: Number of FFT averages has to be a multiple of the number of sample points\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->fft_navg = fft_navg; + (*c)->nfft = (*c)->npts/(*c)->fft_navg; + return gn_success; + } + + int gn_config_set_win(GnWindow win, gn_config *c) + { + if (!((win == GnWindowBlackmanHarris) || (win == GnWindowHann) || (win == GnWindowNoWindow))) + { + printf("ERROR: Invalid selection of window function\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->win = win; + return gn_success; + } + + int gn_config_set_ssb_fund(int ssb_fund, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->ssb_fund = ssb_fund; + return gn_success; + } + + int gn_config_set_ssb_rest(int ssb_rest, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->ssb_rest = ssb_rest; + return gn_success; + } + + int gn_config_set_max_harm_order(int max_harm_order, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->max_harm_order = max_harm_order; + return gn_success; + } + + int gn_config_set_dnla_signal_type(GnDnlSignal dnla_signal_type, gn_config *c) + { + if (!((dnla_signal_type == GnDnlSignalRamp) || (dnla_signal_type == GnDnlSignalTone))) + { + printf("ERROR: Invalid selection of DNL analysis signal type\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->dnla_signal_type = dnla_signal_type; + return gn_success; + } + + int gn_config_set_inla_fit(GnInlLineFit inla_fit, gn_config *c) + { + if (!((inla_fit == GnInlLineFitBestFit) || (inla_fit == GnInlLineFitEndFit) || (inla_fit == GnInlLineFitNoFit))) + { + printf("ERROR: Invalid selection of INL line fit\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->inla_fit = inla_fit; + return gn_success; + } + + int gn_config_set_ramp_start(double ramp_start, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->ramp_start = ramp_start; + return gn_success; + } + + int gn_config_set_ramp_stop(double ramp_stop, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->ramp_stop = ramp_stop; + return gn_success; + } + + int gn_config_get_code_density_size(size_t *code_density_size, gn_config *c) + { + if (!(*c)) + { + printf("config struct is NULL\n"); + return gn_failure; + } + *code_density_size = (*c)->_code_density_size; + return gn_success; + } + + int gn_config_gen_tone(tone_type ttype, size_t npts, gn::real_t sample_rate, size_t num_tones, gn::real_t *tone_freq, gn::real_t *tone_ampl, gn::real_t *tone_phase, gn_config *c) + { + if (!((ttype == REAL_COSINE) || (ttype == REAL_SINE) || (ttype == COMPLEX_EXP))) + { + printf("ERROR: Invalid selection of waveform type for tone generation\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->ttype = ttype; + (*c)->npts = npts; + (*c)->sample_rate = sample_rate; + (*c)->num_tones = num_tones; + (*c)->tone_freq = tone_freq; + (*c)->tone_ampl = tone_ampl; + (*c)->tone_phase = tone_phase; + + return gn_success; + } + + int gn_config_gen_ramp(size_t npts, double ramp_start, double ramp_stop, gn_config *c) + { + if (ramp_stop < ramp_start) + { + printf("ERROR: ramp stop value cannot be smaller than ramp start value for ramp generation\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->npts = npts; + (*c)->ramp_start = ramp_start; + (*c)->ramp_stop = ramp_stop; + (*c)->noise_rms = 0.0; + + return gn_success; + } + + int gn_config_quantize(size_t npts, gn::real_t fsr, int qres, gn::real_t noise_rms, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->npts = npts; + (*c)->fsr = fsr; + (*c)->qres = qres; + (*c)->noise_rms = noise_rms; + (*c)->code_format = GnCodeFormatTwosComplement; + + return gn_success; + } + + int gn_config_histz_nla(size_t npts, int qres, gn_config *c) + { + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + (*c)->npts = npts; + (*c)->qres = qres; + (*c)->code_format = GnCodeFormatTwosComplement; + (*c)->inla_fit = GnInlLineFitBestFit; + + return gn_success; + } + + int gn_config_fftz(size_t npts, int qres, size_t fft_navg, size_t nfft, GnWindow win, gn_config *c) + { + if (npts != (fft_navg*nfft)) + { + printf("ERROR: Number of samples points in the waveform has to equal FFT order times number of FFT averages\n"); + return gn_failure; + } + + if (!((win == GnWindowBlackmanHarris) || (win == GnWindowHann) || (win == GnWindowNoWindow))) + { + printf("ERROR: Invalid selection of window function\n"); + return gn_failure; + } + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + + (*c)->npts = npts; + (*c)->qres = qres; + (*c)->fft_navg = fft_navg; + (*c)->nfft = nfft; + (*c)->win = win; + (*c)->code_format = GnCodeFormatTwosComplement; + + return gn_success; + } + + int gn_config_fa_auto(uint8_t ssb_width, gn_config *c) + { + int err_code; + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + + if ((*c)->sample_rate <= 0) { + printf("ERROR: Sample rate must be set before configuring Fourier analysis\n"); + return gn_failure; + } + + (*c)->obj_key = (char *)calloc(3, sizeof(char)); + strcpy((*c)->obj_key, "fa"); + (*c)->comp_key = (char *)calloc(2, sizeof(char)); + strcpy((*c)->comp_key, "A"); + + (*c)->ssb_fund = ssb_width; + (*c)->ssb_rest = 0; + (*c)->max_harm_order = 3; + (*c)->axis_type = GnFreqAxisTypeDcCenter; + + // configure object key for Fourier analysis + err_code = gn_fa_create((*c)->obj_key); + + // configure component key for Fourier analysis + err_code += gn_fa_max_tone((*c)->obj_key, (*c)->comp_key, GnFACompTagSignal, (*c)->ssb_fund); + + // configure harmonic order for Fourier analysis + err_code += gn_fa_hd((*c)->obj_key, (*c)->max_harm_order); + + // configure single-side bins for Fourier analysis + err_code += gn_fa_ssb((*c)->obj_key, GnFASsbDefault, (*c)->ssb_rest); + err_code += gn_fa_ssb((*c)->obj_key, GnFASsbDC, -1); + err_code += gn_fa_ssb((*c)->obj_key, GnFASsbSignal, -1); + err_code += gn_fa_ssb((*c)->obj_key, GnFASsbWO, -1); + + // configure sample-rate, data-rate, shift frequency, and converter offset + err_code += gn_fa_fsample((*c)->obj_key, (*c)->sample_rate); + err_code += gn_fa_fdata((*c)->obj_key, (*c)->sample_rate); + err_code += gn_fa_fshift((*c)->obj_key, 0.0); + err_code += gn_fa_conv_offset((*c)->obj_key, false); + + return (err_code); + } + + + int gn_config_fa(gn::real_t fixed_tone_freq, gn_config *c) + { + int err_code; + + if (!(*c)) + { + gn_config c_p; + c_p = (gn_config)calloc(1, sizeof(*c_p)); + if (!(c_p)) + { + printf("insufficient memory\n"); + return ENOMEM; + } + else + *c = c_p; + } + + if ((*c)->sample_rate <= 0) { + printf("ERROR: Sample rate must be set before configuring Fourier analysis\n"); + return gn_failure; + } + + (*c)->obj_key = (char *)calloc(3, sizeof(char)); + strcpy((*c)->obj_key, "fa"); + (*c)->comp_key = (char *)calloc(2, sizeof(char)); + strcpy((*c)->comp_key, "A"); + + (*c)->ssb_fund = 120; + (*c)->ssb_rest = 0; + (*c)->max_harm_order = 3; + (*c)->axis_type = GnFreqAxisTypeDcCenter; + + // configure object key for Fourier analysis + err_code = gn_fa_create((*c)->obj_key); + + // configure component key for Fourier analysis + err_code += gn_fa_fixed_tone((*c)->obj_key, (*c)->comp_key, GnFACompTagSignal, fixed_tone_freq, (*c)->ssb_fund); + + // configure harmonic order for Fourier analysis + err_code += gn_fa_hd((*c)->obj_key, (*c)->max_harm_order); + + // configure single-side bins for Fourier analysis + err_code += gn_fa_ssb((*c)->obj_key, GnFASsbDefault, (*c)->ssb_rest); + err_code += gn_fa_ssb((*c)->obj_key, GnFASsbDC, -1); + err_code += gn_fa_ssb((*c)->obj_key, GnFASsbSignal, -1); + err_code += gn_fa_ssb((*c)->obj_key, GnFASsbWO, -1); + + // configure sample-rate, data-rate, shift frequency, and converter offset + err_code += gn_fa_fsample((*c)->obj_key, (*c)->sample_rate); + err_code += gn_fa_fdata((*c)->obj_key, (*c)->sample_rate); + err_code += gn_fa_fshift((*c)->obj_key, 0.0); + err_code += gn_fa_conv_offset((*c)->obj_key, false); + + return (err_code); + } + + // waveform generation + int gn_gen_ramp(gn::real_t **out, gn_config *c) + { + int err_code; + gn::real_t *awf = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); + err_code = gn_ramp(awf, (*c)->npts, (*c)->ramp_start, (*c)->ramp_stop, (*c)->noise_rms); + *out = awf; + + return err_code; + } + + int gn_gen_real_tone(gn::real_t **out, gn_config *c) + { + int err_code = 0; + gn::real_t *awf = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); + + for (size_t i = 0; i < (*c)->num_tones; i++) + { + gn::real_t *tmp = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); + if ((*c)->ttype == REAL_COSINE) + err_code = gn_cos(tmp, (*c)->npts, (*c)->sample_rate, (*c)->tone_ampl[i], (*c)->tone_freq[i], (*c)->tone_phase[i], 0, 0); + else if ((*c)->ttype == REAL_SINE) + err_code = gn_sin(tmp, (*c)->npts, (*c)->sample_rate, (*c)->tone_ampl[i], (*c)->tone_freq[i], (*c)->tone_phase[i], 0, 0); + if (!err_code) + { + for (size_t j = 0; j < (*c)->npts; j++) + awf[j] = awf[j] + tmp[j]; + } + } + *out = awf; + + return err_code; + } + + int gn_gen_complex_tone(gn::real_t **outi, gn::real_t **outq, gn_config *c) + { + int err_code = 0; + gn::real_t *awfi = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); + gn::real_t *awfq = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); + + for (size_t i = 0; i < (*c)->num_tones; i++) { + gn::real_t *tmp = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); + err_code = gn_cos(tmp, (*c)->npts, (*c)->sample_rate, (*c)->tone_ampl[i], (*c)->tone_freq[i], (*c)->tone_phase[i], 0, 0); + if (!err_code) + { + for (size_t j = 0; j < (*c)->npts; j++) + awfi[j] = awfi[j] + tmp[j]; + } + tmp = (gn::real_t *)calloc((*c)->npts, sizeof(gn::real_t)); + err_code = gn_sin(tmp, (*c)->npts, (*c)->sample_rate, (*c)->tone_ampl[i], (*c)->tone_freq[i], (*c)->tone_phase[i], 0, 0); + if (!err_code) + { + for (size_t j = 0; j < (*c)->npts; j++) + awfq[j] = awfq[j] + tmp[j]; + } + } + *outi = awfi; + *outq = awfq; + + return err_code; + } + + // processing + int gn_quantize(int32_t **out, const gn::real_t *in, gn_config *c) + { + int err_code; + int32_t *qwf = (int32_t *)calloc((*c)->npts, sizeof(int32_t)); + + err_code = gn_quantize32(qwf, (*c)->npts, in, (*c)->npts, (*c)->fsr, (*c)->qres, (*c)->noise_rms, (*c)->code_format); + *out = qwf; + + return err_code; + } + + int gn_fftz(gn::real_t **out, const int32_t *in_i, const int32_t *in_q, gn_config *c) + { + int err_code; + gn::real_t *fft_of_in = (gn::real_t *)calloc(2*(*c)->nfft, sizeof(gn::real_t)); + + err_code = gn_fft32(fft_of_in, 2*(*c)->nfft, in_i, (*c)->npts, in_q, (*c)->npts, (*c)->qres, (*c)->fft_navg, (*c)->nfft, (*c)->win, (*c)->code_format); + *out = fft_of_in; + + return err_code; + } + + int gn_histz(uint64_t **hist, size_t *hist_len, const int32_t *qwf, gn_config *c) + { + int err_code; + uint64_t *out = NULL; + + err_code = gn_code_density_size(&((*c)->_code_density_size), (*c)->qres, (*c)->code_format); + out = (uint64_t *)calloc((*c)->_code_density_size, sizeof(uint64_t)); + err_code += gn_hist32(out, (*c)->_code_density_size, qwf, (*c)->npts, (*c)->qres, (*c)->code_format, false); + *hist = out; + *hist_len = (*c)->_code_density_size; + + return err_code; + } + + int gn_dnlz(double **dnl, size_t *dnl_len, const uint64_t *hist, gn_config *c) + { + int err_code; + double *out = NULL; + + err_code = gn_code_density_size(&((*c)->_code_density_size), (*c)->qres, (*c)->code_format); + out = (double *)calloc((*c)->_code_density_size, sizeof(double)); + err_code = gn_dnl(out, (*c)->_code_density_size, hist, (*c)->_code_density_size, (*c)->dnla_signal_type); + *dnl = out; + *dnl_len = (*c)->_code_density_size; + + return err_code; + } + + int gn_inlz(double **inl, size_t *inl_len, const double *dnl, gn_config *c) + { + int err_code; + double *out = NULL; + + err_code = gn_code_density_size(&((*c)->_code_density_size), (*c)->qres, (*c)->code_format); + out = (double *)calloc((*c)->_code_density_size, sizeof(double)); + err_code = gn_inl(out, (*c)->_code_density_size, dnl, (*c)->_code_density_size, (*c)->inla_fit); + *inl = out; + *inl_len = (*c)->_code_density_size; + + return err_code; + } + + // Waveform/Histogram/DNL/INL/Fourier Analysis + int gn_get_wfa_results(char ***rkeys, gn::real_t **rvalues, size_t *results_size, const int32_t *qwf, gn_config *c) + { + int err_code = 0; + + // get results size + err_code = gn_analysis_results_size(&((*c)->_wfa_results_size), GnAnalysisTypeWaveform); + + // allocate memory for result keys and values + (*c)->_wfa_result_keys = (char **)calloc(((*c)->_wfa_results_size), sizeof(char*)); + (*c)->_wfa_result_values = (gn::real_t *)calloc(((*c)->_wfa_results_size), sizeof(gn::real_t)); + + // get result key sizes + (*c)->_wfa_result_key_sizes = (size_t *)calloc(((*c)->_wfa_results_size), sizeof(size_t)); + err_code += gn_analysis_results_key_sizes((*c)->_wfa_result_key_sizes, (*c)->_wfa_results_size, GnAnalysisTypeWaveform); + + // allocate memory for each result key + for (size_t i = 0; i < (*c)->_wfa_results_size; ++i) + (*c)->_wfa_result_keys[i] = (char *)calloc((*c)->_wfa_result_key_sizes[i], sizeof(char)); + + // execute analysis + err_code += gn_wf_analysis32((*c)->_wfa_result_keys, (*c)->_wfa_results_size, (*c)->_wfa_result_values, (*c)->_wfa_results_size, qwf, (*c)->npts); + + // copy keys + *rkeys = (char **)calloc(((*c)->_wfa_results_size), sizeof(char*)); + for (size_t i = 0; i < (*c)->_wfa_results_size; ++i) + (*rkeys)[i] = (char *)calloc((*c)->_wfa_result_key_sizes[i], sizeof(char)); + + // copy values + *rvalues = (gn::real_t *)calloc(((*c)->_wfa_results_size), sizeof(gn::real_t)); + for (size_t i = 0; i < (*c)->_wfa_results_size; ++i) + { + strcpy((*rkeys)[i], (*c)->_wfa_result_keys[i]); + (*rvalues)[i] = (*c)->_wfa_result_values[i]; + } + *results_size = (*c)->_wfa_results_size; + + return(err_code); + } + + int gn_get_ha_results(char ***rkeys, gn::real_t **rvalues, size_t *results_size, const uint64_t *hist, gn_config *c) + { + int err_code = 0; + + // get results size + err_code = gn_analysis_results_size(&((*c)->_hist_results_size), GnAnalysisTypeHistogram); + + // allocate memory for result keys and values + (*c)->_hist_result_keys = (char **)calloc(((*c)->_hist_results_size), sizeof(char*)); + (*c)->_hist_result_values = (gn::real_t *)calloc(((*c)->_hist_results_size), sizeof(gn::real_t)); + + // get result key sizes + (*c)->_hist_result_key_sizes = (size_t *)calloc(((*c)->_hist_results_size), sizeof(size_t)); + err_code += gn_analysis_results_key_sizes((*c)->_hist_result_key_sizes, (*c)->_hist_results_size, GnAnalysisTypeHistogram); + + // allocate memory for each result key + for (size_t i = 0; i < (*c)->_hist_results_size; ++i) + (*c)->_hist_result_keys[i] = (char *)calloc((*c)->_hist_result_key_sizes[i], sizeof(char)); + + // execute analysis + err_code += gn_hist_analysis((*c)->_hist_result_keys, (*c)->_hist_results_size, (*c)->_hist_result_values, (*c)->_hist_results_size, hist, (*c)->_code_density_size); + + // copy keys + *rkeys = (char **)calloc(((*c)->_hist_results_size), sizeof(char*)); + for (size_t i = 0; i < (*c)->_hist_results_size; ++i) + (*rkeys)[i] = (char *)calloc((*c)->_hist_result_key_sizes[i], sizeof(char)); + + // copy values + *rvalues = (gn::real_t *)calloc(((*c)->_hist_results_size), sizeof(gn::real_t)); + for (size_t i = 0; i < (*c)->_hist_results_size; ++i) + { + strcpy((*rkeys)[i], (*c)->_hist_result_keys[i]); + (*rvalues)[i] = (*c)->_hist_result_values[i]; + } + *results_size = (*c)->_hist_results_size; + + return(err_code); + } + + int gn_get_dnla_results(char ***rkeys, gn::real_t **rvalues, size_t *results_size, const gn::real_t *dnl, gn_config *c) + { + int err_code; + + // get results size + err_code = gn_analysis_results_size(&((*c)->_dnl_results_size), GnAnalysisTypeDNL); + + // allocate memory for result keys and values + (*c)->_dnl_result_keys = (char **)calloc(((*c)->_dnl_results_size), sizeof(char*)); + (*c)->_dnl_result_values = (gn::real_t *)calloc(((*c)->_dnl_results_size), sizeof(gn::real_t)); + + // get result key sizes + (*c)->_dnl_result_key_sizes = (size_t *)calloc(((*c)->_dnl_results_size), sizeof(size_t)); + err_code += gn_analysis_results_key_sizes((*c)->_dnl_result_key_sizes, (*c)->_dnl_results_size, GnAnalysisTypeDNL); + + // allocate memory for each result key + for (size_t i = 0; i < (*c)->_dnl_results_size; ++i) + (*c)->_dnl_result_keys[i] = (char *)calloc((*c)->_dnl_result_key_sizes[i], sizeof(char)); + + // execute analysis + err_code += gn_dnl_analysis((*c)->_dnl_result_keys, (*c)->_dnl_results_size, (*c)->_dnl_result_values, (*c)->_dnl_results_size, dnl, (*c)->_code_density_size); + + // copy keys + *rkeys = (char **)calloc(((*c)->_dnl_results_size), sizeof(char*)); + for (size_t i = 0; i < (*c)->_dnl_results_size; ++i) + (*rkeys)[i] = (char *)calloc((*c)->_dnl_result_key_sizes[i], sizeof(char)); + + // copy values + *rvalues = (gn::real_t *)calloc(((*c)->_dnl_results_size), sizeof(gn::real_t)); + for (size_t i = 0; i < (*c)->_dnl_results_size; ++i) + { + strcpy((*rkeys)[i], (*c)->_dnl_result_keys[i]); + (*rvalues)[i] = (*c)->_dnl_result_values[i]; + } + *results_size = (*c)->_dnl_results_size; + + return(err_code); + } + + int gn_get_inla_results(char ***rkeys, gn::real_t **rvalues, size_t *results_size, const gn::real_t *inl, gn_config *c) + { + int err_code; + + // get results size + err_code = gn_analysis_results_size(&((*c)->_inl_results_size), GnAnalysisTypeINL); + + // allocate memory for result keys and values + (*c)->_inl_result_keys = (char **)calloc(((*c)->_inl_results_size), sizeof(char*)); + (*c)->_inl_result_values = (gn::real_t *)calloc(((*c)->_inl_results_size), sizeof(gn::real_t)); + + // get result key sizes + (*c)->_inl_result_key_sizes = (size_t *)calloc(((*c)->_inl_results_size), sizeof(size_t)); + err_code += gn_analysis_results_key_sizes((*c)->_inl_result_key_sizes, (*c)->_inl_results_size, GnAnalysisTypeINL); + + // allocate memory for each result key + for (size_t i = 0; i < (*c)->_inl_results_size; ++i) + (*c)->_inl_result_keys[i] = (char *)calloc((*c)->_inl_result_key_sizes[i], sizeof(char)); + + // execute analysis + err_code += gn_inl_analysis((*c)->_inl_result_keys, (*c)->_inl_results_size, (*c)->_inl_result_values, (*c)->_inl_results_size, inl, (*c)->_code_density_size); + + // copy keys + *rkeys = (char **)calloc(((*c)->_inl_results_size), sizeof(char*)); + for (size_t i = 0; i < (*c)->_inl_results_size; ++i) + (*rkeys)[i] = (char *)calloc((*c)->_inl_result_key_sizes[i], sizeof(char)); + + // copy values + *rvalues = (gn::real_t *)calloc(((*c)->_inl_results_size), sizeof(gn::real_t)); + for (size_t i = 0; i < (*c)->_inl_results_size; ++i) + { + strcpy((*rkeys)[i], (*c)->_inl_result_keys[i]); + (*rvalues)[i] = (*c)->_inl_result_values[i]; + } + *results_size = (*c)->_inl_results_size; + + return(err_code); + } + + int gn_get_fa_single_result(gn::real_t *rvalue, const char *metric_name, gn::real_t *fft_ilv, gn_config *c) + { + int err_code; + size_t i; + bool metric_found = false; + size_t results_size; + char **rkeys; + double *rvalues; + + // compute all results + err_code = gn_get_fa_results(&rkeys, &rvalues, &results_size, fft_ilv, &(*c)); + for (i = 0; i < results_size; i++) + { + if (!strcmp(metric_name, rkeys[i])) + { + metric_found = true; + break; + } + } + if (!metric_found) + { + printf("ERROR: Invalid selection of metric\n"); + return gn_failure; + } + *rvalue = rvalues[i]; + + return err_code; + } + + int gn_get_fa_results(char ***rkeys, gn::real_t **rvalues, size_t *results_size, gn::real_t *fft_ilv, gn_config *c) + { + int err_code = 0; + size_t *result_key_sizes; + + // get results size + err_code = gn_fft_analysis_results_size(results_size, (*c)->obj_key, 2*(*c)->nfft, (*c)->nfft); + + // allocate memory for result keys and values + *rkeys = (char **)calloc(*results_size, sizeof(char*)); + *rvalues = (gn::real_t *)calloc(*results_size, sizeof(gn::real_t)); + + // get result key sizes + result_key_sizes = (size_t *)calloc(*results_size, sizeof(size_t)); + err_code += gn_fft_analysis_results_key_sizes(result_key_sizes, *results_size, (*c)->obj_key, 2*(*c)->nfft, (*c)->nfft); + + // allocate memory for each result key + for (size_t i = 0; i < *results_size; ++i) + (*rkeys)[i] = (char *)calloc(result_key_sizes[i], sizeof(char)); + + // execute analysis + err_code += gn_fft_analysis(*rkeys, *results_size, *rvalues, *results_size, (*c)->obj_key, fft_ilv, 2*(*c)->nfft, (*c)->nfft, (*c)->axis_type); + + return (err_code); + } +} \ No newline at end of file diff --git a/bindings/matlab/genalyzer.m b/bindings/matlab/genalyzer.m index f23335d..9fa8bed 100644 --- a/bindings/matlab/genalyzer.m +++ b/bindings/matlab/genalyzer.m @@ -1,6 +1,6 @@ classdef (Sealed) genalyzer < handle properties (Constant) % C Library Interface - header_name = 'cgenalyzer_advanced.h'; + header_name = 'cgenalyzer.h'; nixbin_name = 'libgenalyzer.so'; winbin_name = 'libgenalyzer.dll'; lib_alias = 'gn'; diff --git a/bindings/python/examples/do_histogram_analysis.py b/bindings/python/examples/do_histogram_analysis.py deleted file mode 100644 index 74900f2..0000000 --- a/bindings/python/examples/do_histogram_analysis.py +++ /dev/null @@ -1,11 +0,0 @@ -import genalyzer, pprint - -c = genalyzer.config_gen_ramp(8192, 0, 2) -genalyzer.config_quantize(8192, 3.0, 12, pow(10.0, -60.0 / 20.0), c) - -awf = genalyzer.gen_ramp(c) -qwf = genalyzer.quantize(awf, c) -hist = genalyzer.histz(qwf, c) -ha_results = genalyzer.get_ha_results(hist, c) -pprint.pprint(ha_results) -genalyzer.config_free(c) diff --git a/bindings/python/examples/do_waveform_analysis.py b/bindings/python/examples/do_waveform_analysis.py deleted file mode 100644 index da1f69b..0000000 --- a/bindings/python/examples/do_waveform_analysis.py +++ /dev/null @@ -1,10 +0,0 @@ -import genalyzer, pprint - -c = genalyzer.config_gen_tone(0, 8192, 5000000.0, 1, [50000.0], [0.5], [0.2]) -genalyzer.config_quantize(8192, 3.0, 12, pow(10.0, -60.0 / 20.0), c) - -awf = genalyzer.gen_real_tone(c) -qwf = genalyzer.quantize(awf, c) -wfa_results = genalyzer.get_wfa_results(qwf, c) -pprint.pprint(wfa_results) -genalyzer.config_free(c) diff --git a/bindings/python/examples/fft_analysis_advanced.py b/bindings/python/examples/fft_analysis.py similarity index 99% rename from bindings/python/examples/fft_analysis_advanced.py rename to bindings/python/examples/fft_analysis.py index ec22fe2..7e3b6d6 100644 --- a/bindings/python/examples/fft_analysis_advanced.py +++ b/bindings/python/examples/fft_analysis.py @@ -1,6 +1,6 @@ def main(): import numpy as np - import genalyzer.advanced as gn + import genalyzer as gn # print("Library path: {}".format(gn._genalyzer._libpath)) # print("Version: {}\n".format(gn.__version__)) diff --git a/bindings/python/examples/gn_doc_fft.py b/bindings/python/examples/gn_doc_fft.py new file mode 100644 index 0000000..d5e2e8e --- /dev/null +++ b/bindings/python/examples/gn_doc_fft.py @@ -0,0 +1,58 @@ +import numpy as np +import genalyzer as gn +import matplotlib.pyplot as pl + +# +# Signal +# +npts = 30000 # number of points in the signal +fs = 3e6 # sample-rate of the data +freq = 300000 # tone frequency +phase = 0.0 # tone phase +ampl_dbfs = -1.0 # amplitude of the tone in dBFS +qnoise_dbfs = -60.0 # quantizer noise in dBFS +fsr = 2.0 # full-scale range of I/Q components of the complex tone +ampl = (fsr / 2) * 10 ** (ampl_dbfs / 20) # amplitude of the tone in linear scale +qnoise = 10 ** (qnoise_dbfs / 20) # quantizer noise in linear scale +qres = 12 # data resolution +code_fmt = gn.CodeFormat.TWOS_COMPLEMENT # integer data format + +# +# Genarate signal for analysis +# +awfi = gn.cos(npts, fs, ampl, freq, phase) +awfq = gn.sin(npts, fs, ampl, freq, phase) +qwfi = gn.quantize(awfi, fsr, qres, qnoise, code_fmt) +qwfq = gn.quantize(awfq, fsr, qres, qnoise, code_fmt) + +# +# FFT configuration +# +navg = 1 # number of FFT averages +nfft = int(npts/navg) # FFT-order +window = gn.Window.NO_WINDOW # window function to apply +axis_type = gn.FreqAxisType.DC_CENTER # axis type +axis_fmt = gn.FreqAxisFormat.FREQ # axis-format + +# +# Compute FFT +# +fft_cplx = gn.fft(qwfi, qwfq, qres, navg, nfft, window, code_fmt) +freq_axis = gn.freq_axis(nfft, axis_type, fs, axis_fmt) +fft_db = gn.db(fft_cplx) +if gn.FreqAxisType.DC_CENTER == axis_type: + fft_db = gn.fftshift(fft_db) + +# +# Plot +# +scale_MHz = 1e-6 +fig = pl.figure(1) +fig.clf() +pl.plot(freq_axis*scale_MHz, fft_db) +pl.grid(True) +pl.xlabel('frequency (MHz)') +pl.ylabel('magnitude (dBFs)') +pl.xlim(freq_axis[0]*scale_MHz, freq_axis[-1]*scale_MHz) +pl.ylim(-140.0, 20.0) +pl.savefig('fft.png') \ No newline at end of file diff --git a/bindings/python/examples/gn_doc_spectral_analysis1.py b/bindings/python/examples/gn_doc_spectral_analysis1.py new file mode 100644 index 0000000..3bd40e0 --- /dev/null +++ b/bindings/python/examples/gn_doc_spectral_analysis1.py @@ -0,0 +1,213 @@ +import numpy as np +import genalyzer as gn +import pprint +import matplotlib.pyplot as pl +from matplotlib.patches import Rectangle as MPRect +from tabulate import tabulate + +# +# Signal +# +npts = 30000 # number of points in the signal +freq = 300000 # tone frequency +phase = 0.0 # tone phase +ampl_dbfs = -1.0 # amplitude of the tone in dBFS +qnoise_dbfs = -60.0 # quantizer noise in dBFS +fsr = 2.0 # full-scale range of I/Q components of the complex tone +ampl = (fsr / 2) * 10 ** (ampl_dbfs / 20) # amplitude of the tone in linear scale +qnoise = 10 ** (qnoise_dbfs / 20) # quantizer noise in linear scale + +# +# FFT configuration +# +navg = 1 # number of FFT averages +nfft = int(npts/navg) # FFT-order +qres = 12 # data resolution +code_fmt = gn.CodeFormat.TWOS_COMPLEMENT # integer data format +window = gn.Window.NO_WINDOW # window function to apply +ssb_fund = 0 # number of single-side bins +axis_type = gn.FreqAxisType.DC_CENTER # axis type +fs = 3e6 # sample-rate of the data +axis_fmt = gn.FreqAxisFormat.FREQ # axis-format +num_harmonics = 3 # number of harmonics to analyze +ssb_rest = 0 # default number of single-side bins for non-signal components +ssb_dc = 0 # number of single-side bins for the DC-component +ssb_wo = 0 # number of single-side bins for the WO-component + +# +# Genarate signal for analysis +# +awfi = gn.cos(npts, fs, ampl, freq, phase) +awfq = gn.sin(npts, fs, ampl, freq, phase) +qwfi = gn.quantize(awfi, fsr, qres, qnoise, code_fmt) +qwfq = gn.quantize(awfq, fsr, qres, qnoise, code_fmt) + +# +# Compute FFT +# +fft_cplx = gn.fft(qwfi, qwfq, qres, navg, nfft, window, code_fmt) + +# +# Fourier analysis configuration +# +test_label = "fa" +gn.fa_create(test_label) +signal_component_label = 'A' +gn.fa_max_tone(test_label, signal_component_label, gn.FaCompTag.SIGNAL, ssb_fund) +gn.fa_fsample(test_label, fs) +gn.fa_hd(test_label, num_harmonics) +gn.fa_ssb(test_label, gn.FaSsb.DEFAULT, ssb_rest) +gn.fa_ssb(test_label, gn.FaSsb.DC, ssb_dc) +gn.fa_ssb(test_label, gn.FaSsb.WO, ssb_wo) + +# +# Fourier analysis execution +# +results = gn.fft_analysis(test_label, fft_cplx, nfft, axis_type) + +# +# Print results and plot +# +freq_axis = gn.freq_axis(nfft, axis_type, fs, axis_fmt) +fft_db = gn.db(fft_cplx) +if gn.FreqAxisType.DC_CENTER == axis_type: + fft_db = gn.fftshift(fft_db) + +annots = gn.fa_annotations(results, axis_type, axis_fmt) +print('annots["labels"]: ') +labels_head = ('frequency (Hz)', 'magnitude (dBFs)', 'component label') +labels_table = tabulate(annots["labels"], headers=labels_head, tablefmt="grid") +print(labels_table, "\n") + +print('annots["tone_boxes"]: ') +c1 = [x[0] for x in annots["tone_boxes"]] +c2 = [x[2] for x in annots["tone_boxes"]] +tone_boxes_head = ('box left boundary (Hz)', 'width (Hz)') +tone_boxes_table = tabulate(map(list, zip(*(c1, c2))), headers=tone_boxes_head, tablefmt="grid") +print(tone_boxes_table, "\n") + +print('+----------------+') +print("results dictionary") +print('+----------------+') +pprint.pprint(results) + +# plot +toneDC_Hz = annots["labels"][0][0] +toneDC_bin = toneDC_Hz/(fs/nfft) +toneDC_mag = fft_db[int(toneDC_bin+0.5*nfft)] +toneA_Hz = annots["labels"][1][0] +toneA_bin = toneA_Hz/(fs/nfft) +toneA_mag = fft_db[int(toneA_bin+0.5*nfft)] +toneA_im_Hz = annots["labels"][2][0] +toneA_im_bin = toneA_im_Hz/(fs/nfft) +toneA_im_mag = fft_db[int(toneA_im_bin+0.5*nfft)] +tone2A_Hz = annots["labels"][3][0] +tone2A_bin = tone2A_Hz/(fs/nfft) +tone2A_mag = fft_db[int(tone2A_bin+0.5*nfft)] +tone2A_im_Hz = annots["labels"][4][0] +tone2A_im_bin = tone2A_im_Hz/(fs/nfft) +tone2A_im_mag = fft_db[int(tone2A_im_bin+0.5*nfft)] +tone3A_im_Hz = annots["labels"][5][0] +tone3A_im_bin = tone3A_im_Hz/(fs/nfft) +tone3A_im_mag = fft_db[int(tone3A_im_bin+0.5*nfft)] +toneWO_Hz = annots["labels"][6][0] +toneWO_bin = toneWO_Hz/(fs/nfft) +toneWO_mag = fft_db[int(toneWO_bin+0.5*nfft)] + +sfdr = results["sfdr"] +nsd = results["nsd"] +abn = results["abn"] +snr = results["snr"] +fsnr = results["fsnr"] +sinad = results["sinad"] +scale_MHz = 1e-6 +fig, ax = pl.subplots() +fig.clf() +pl.plot(freq_axis*scale_MHz, fft_db) +pl.grid(True) +pl.xlabel('frequency (MHz)') +pl.ylabel('magnitude (dBFs)') +pl.xlim(freq_axis[0]*scale_MHz, freq_axis[-1]*scale_MHz) +pl.ylim(-140.0, 20.0) +for x, y, label in annots["labels"]: + if label == 'dc': + pl.annotate(label+": ["+f"{toneDC_Hz:.2f}"+" ,"+f"{toneDC_mag:.2f}"+"]", + xy=(x*scale_MHz, toneDC_mag), + xytext=(x*scale_MHz, -10), + color = 'red', + horizontalalignment="center", + arrowprops=dict(arrowstyle='->',color='red',lw=1)) + elif label == 'A': + pl.annotate(label+": ["+f"{toneA_Hz:.2f}"+" ,"+f"{toneA_mag:.2f}"+"]", + xy=(x*scale_MHz, toneA_mag), + xytext=(x*scale_MHz, 10), + color = 'black', + horizontalalignment="center", + arrowprops=dict(arrowstyle='->',color='black',lw=1)) + elif label == '-A': + pl.annotate(label+": ["+f"{toneA_im_Hz:.2f}"+" ,"+f"{toneA_im_mag:.2f}"+"]", + xy=(x*scale_MHz, toneA_im_mag), + xytext=(x*scale_MHz, -20), + color = 'black', + horizontalalignment="center", + arrowprops=dict(arrowstyle='->',color='black',lw=1)) + elif label == '2A': + pl.annotate(label+": ["+f"{tone2A_Hz:.2f}"+" ,"+f"{tone2A_mag:.2f}"+"]", + xy=(x*scale_MHz, tone2A_mag), + xytext=(x*scale_MHz, -40), + color = 'green', + horizontalalignment="center", + arrowprops=dict(arrowstyle='->',color='green',lw=1)) + elif label == '-2A': + pl.annotate(label+": ["+f"{tone2A_im_Hz:.2f}"+" ,"+f"{tone2A_im_mag:.2f}"+"]", + xy=(x*scale_MHz, tone2A_im_mag), + xytext=(x*scale_MHz, -40), + color = 'green', + horizontalalignment="center", + arrowprops=dict(arrowstyle='->',color='green',lw=1)) + elif label == '-3A': + pl.annotate(label+": ["+f"{tone3A_im_Hz:.2f}"+" ,"+f"{tone3A_im_mag:.2f}"+"]", + xy=(x*scale_MHz, tone3A_im_mag), + xytext=(x*scale_MHz, -60), + color = 'magenta', + horizontalalignment="center", + arrowprops=dict(arrowstyle='->',color='magenta',lw=1)) + elif label == 'wo': + pl.annotate(label+": ["+f"{toneWO_Hz:.2f}"+" ,"+f"{toneWO_mag:.2f}"+"]", + xy=(x*scale_MHz, toneWO_mag), + xytext=(x*scale_MHz, -80), + color = 'magenta', + horizontalalignment="center", + arrowprops=dict(arrowstyle='->',color='magenta',lw=1)) + else: + pl.annotate(label, xy=(x*scale_MHz, y), ha="center", va="bottom") +pl.axhline(y = toneA_mag, color = 'k', linestyle = '-') +pl.axhline(y = toneWO_mag, color = 'k', linestyle = '-') +pl.annotate('', + xy=(1.25,toneWO_mag), + xytext=(1.25,toneA_mag), + arrowprops=dict(arrowstyle='<->',color='black',lw=1)) +pl.annotate('SFDR'+": "+f"{sfdr:.2f}"+' dB', + xy=(1.25, -40), + xytext=(1.25, -40), + verticalalignment="center", + rotation=270) +pl.axhline(y = abn, color = 'r', linestyle = '-') +pl.annotate('ABN'+": "+f"{abn:.2f}"+' dB', + xy=(0.5, -100), + xytext=(0.5, -100), + color = 'red', + ha="center") +pl.axhline(y = nsd, color = 'r', linestyle = '-') +pl.annotate('NSD'+": "+f"{nsd:.2f}"+' dB', + xy=(0.5, -120), + xytext=(0.5, -120), + color = 'red', + ha="center") +textstr = '\n'.join(( + 'SNR'+": "+f"{snr:.2f}"+' dB', + 'FSNR'+": "+f"{fsnr:.2f}"+' dB', + 'SINAD'+": "+f"{sinad:.2f}"+' dB')) +props = dict(boxstyle='round', facecolor='wheat', alpha=0) +ax.text(0.5, 0.5, textstr, fontsize=14, bbox=props) +pl.savefig('spectral_analysis_summary.png') \ No newline at end of file diff --git a/bindings/python/examples/gn_doc_tone_gen.py b/bindings/python/examples/gn_doc_tone_gen.py new file mode 100644 index 0000000..03c64cc --- /dev/null +++ b/bindings/python/examples/gn_doc_tone_gen.py @@ -0,0 +1,52 @@ +import numpy as np +import genalyzer as gn +import matplotlib.pyplot as pl +import pprint + +# +# Signal +# +npts = 30000 # number of points in the signal +fs = 3e6 # sample-rate of the data +freq = 300000 # tone frequency +phase = 0.0 # tone phase +ampl_dbfs = -1.0 # amplitude of the tone in dBFS +qnoise_dbfs = -60.0 # quantizer noise in dBFS +fsr = 2.0 # full-scale range of I/Q components of the complex tone +ampl = (fsr / 2) * 10 ** (ampl_dbfs / 20) # amplitude of the tone in linear scale +qnoise = 10 ** (qnoise_dbfs / 20) # quantizer noise in linear scale +qres = 12 # data resolution +code_fmt = gn.CodeFormat.TWOS_COMPLEMENT # integer data format + +# +# Genarate signal for analysis +# +awfi = gn.cos(npts, fs, ampl, freq, phase) +awfq = gn.sin(npts, fs, ampl, freq, phase) +qwfi = gn.quantize(awfi, fsr, qres, qnoise, code_fmt) +qwfq = gn.quantize(awfq, fsr, qres, qnoise, code_fmt) + +# Plot +time_axis = np.arange(0, npts*1/fs, 1/fs) +fig = pl.figure(1) +fig.clf() +pl.plot(time_axis*1e6, awfi, 'r+-', label="cosine") +pl.plot(time_axis*1e6, awfq, 'b.-', label="sine") +pl.grid(True) +pl.xlabel('time (us)') +pl.ylabel('magnitude') +pl.xlim(time_axis[0], time_axis[50]*1e6) +pl.ylim(-1.2, 1.2) +pl.legend(loc="upper right") +pl.savefig('complex_sinusoidal_waveform.png') + +wfa_results_i = gn.wf_analysis(qwfi) +wfa_results_q = gn.wf_analysis(qwfq) +print('+---------------------------+') +print("waveform-analysis results (I)") +print('+---------------------------+') +pprint.pprint(wfa_results_i) +print('+---------------------------+') +print("waveform-analysis results (Q)") +print('+---------------------------+') +pprint.pprint(wfa_results_q) \ No newline at end of file diff --git a/bindings/python/examples/real_analysis_advanced.py b/bindings/python/examples/real_analysis.py similarity index 96% rename from bindings/python/examples/real_analysis_advanced.py rename to bindings/python/examples/real_analysis.py index 3814a0d..f532f64 100644 --- a/bindings/python/examples/real_analysis_advanced.py +++ b/bindings/python/examples/real_analysis.py @@ -1,5 +1,5 @@ def main(): - import genalyzer.advanced as gn + import genalyzer as gn # print("Library path: {}".format(gn._genalyzer._libpath)) # print("Version: {}\n".format(gn.__version__)) diff --git a/bindings/python/examples/compute_fft.py b/bindings/python/examples/simplified_beta/compute_fft.py similarity index 70% rename from bindings/python/examples/compute_fft.py rename to bindings/python/examples/simplified_beta/compute_fft.py index ce0dcb0..5c3230c 100644 --- a/bindings/python/examples/compute_fft.py +++ b/bindings/python/examples/simplified_beta/compute_fft.py @@ -1,7 +1,7 @@ import genalyzer, os, json, glob import matplotlib.pyplot as plt -test_dir = os.path.join(*["..", "..", "..", "tests", "test_vectors"]) +test_dir = os.path.join(*["..", "..", "..", "..", "tests", "test_vectors"]) loc = os.path.dirname(__file__) f = glob.glob(os.path.join(loc, test_dir, "test_fft_tone_1655478044632.json")) @@ -16,10 +16,10 @@ qwfi = [int(i) for i in qwfi] qwfq = data["test_vecq_q"] qwfq = [int(i) for i in qwfq] -c = genalyzer.config_fftz( +c = genalyzer.simplified_beta.config_fftz( data["npts"], data["qres"], data["navg"], data["nfft"], data["win"] - 1 ) -fft_out_i, fft_out_q = genalyzer.fftz(qwfi, qwfq, c) +fft_out_i, fft_out_q = genalyzer.simplified_beta.fftz(qwfi, qwfq, c) plt.plot(fft_out_i[:1000]) plt.plot(fft_out_q[:1000]) -genalyzer.config_free(c) +genalyzer.simplified_beta.config_free(c) diff --git a/bindings/python/examples/do_fourier_analysis.py b/bindings/python/examples/simplified_beta/do_fourier_analysis.py similarity index 55% rename from bindings/python/examples/do_fourier_analysis.py rename to bindings/python/examples/simplified_beta/do_fourier_analysis.py index 4253c6c..503595f 100644 --- a/bindings/python/examples/do_fourier_analysis.py +++ b/bindings/python/examples/simplified_beta/do_fourier_analysis.py @@ -1,7 +1,7 @@ import genalyzer, os, json, glob, pprint import matplotlib.pyplot as plt -test_dir = os.path.join(*["..", "..", "..", "tests", "test_vectors"]) +test_dir = os.path.join(*["..", "..", "..", "..", "tests", "test_vectors"]) loc = os.path.dirname(__file__) f = glob.glob(os.path.join(loc, test_dir, "test_fft_tone_1655478044632.json")) @@ -16,15 +16,15 @@ qwfi = [int(i) for i in qwfi] qwfq = data["test_vecq_q"] qwfq = [int(i) for i in qwfq] -c = genalyzer.config_fftz( +c = genalyzer.simplified_beta.config_fftz( data["npts"], data["qres"], data["navg"], data["nfft"], data["win"] - 1 ) -fft_out_i, fft_out_q = genalyzer.fftz(qwfi, qwfq, c) +fft_out_i, fft_out_q = genalyzer.simplified_beta.fftz(qwfi, qwfq, c) fft_out = [val for pair in zip(fft_out_i, fft_out_q) for val in pair] -genalyzer.config_set_sample_rate(data["fs"], c) -genalyzer.config_fa(freq_list[0], c) -all_results = genalyzer.get_fa_results(fft_out, c) +genalyzer.simplified_beta.config_set_sample_rate(data["fs"], c) +genalyzer.simplified_beta.config_fa(freq_list[0], c) +all_results = genalyzer.simplified_beta.get_fa_results(fft_out, c) pprint.pprint(all_results) -sfdr = genalyzer.get_fa_single_result("sfdr", fft_out, c) -genalyzer.config_free(c) +sfdr = genalyzer.simplified_beta.get_fa_single_result("sfdr", fft_out, c) +genalyzer.simplified_beta.config_free(c) print(sfdr) diff --git a/bindings/python/examples/do_fourier_analysis_pluto.py b/bindings/python/examples/simplified_beta/do_fourier_analysis_pluto.py similarity index 74% rename from bindings/python/examples/do_fourier_analysis_pluto.py rename to bindings/python/examples/simplified_beta/do_fourier_analysis_pluto.py index adb5453..2ab0dac 100644 --- a/bindings/python/examples/do_fourier_analysis_pluto.py +++ b/bindings/python/examples/simplified_beta/do_fourier_analysis_pluto.py @@ -2,7 +2,7 @@ import matplotlib.pyplot as plt import numpy as np -test_dir = os.path.join(*["..", "..", "..", "tests", "test_vectors"]) +test_dir = os.path.join(*["..", "..", "..", "..", "tests", "test_vectors"]) loc = os.path.dirname(__file__) f = glob.glob(os.path.join(loc, test_dir, "test_Pluto_DDS_data_1658159639196.json")) @@ -19,14 +19,14 @@ qwfq = [int(i) for i in qwfq] # configure -c = genalyzer.config_fftz( +c = genalyzer.simplified_beta.config_fftz( data["npts"], data["qres"], data["navg"], data["nfft"], data["win"] - 1 ) -genalyzer.config_set_sample_rate(data["fs"], c) -genalyzer.config_fa(freq_list[0], c) +genalyzer.simplified_beta.config_set_sample_rate(data["fs"], c) +genalyzer.simplified_beta.config_fa(freq_list[0], c) # compute FFT -fft_out_i, fft_out_q = genalyzer.fftz(qwfi, qwfq, c) +fft_out_i, fft_out_q = genalyzer.simplified_beta.fftz(qwfi, qwfq, c) fft_out = [val for pair in zip(fft_out_i, fft_out_q) for val in pair] # plot FFT @@ -44,10 +44,10 @@ plt.show() # get a single Fourier analysis result -sfdr = genalyzer.get_fa_single_result("sfdr", fft_out, c) +sfdr = genalyzer.simplified_beta.get_fa_single_result("sfdr", fft_out, c) # display results print("SFDR - ", sfdr) # free memory -genalyzer.config_free(c) +genalyzer.simplified_beta.config_free(c) diff --git a/bindings/python/examples/do_fourier_analysis_pluto_auto.py b/bindings/python/examples/simplified_beta/do_fourier_analysis_pluto_auto.py similarity index 77% rename from bindings/python/examples/do_fourier_analysis_pluto_auto.py rename to bindings/python/examples/simplified_beta/do_fourier_analysis_pluto_auto.py index 3ddfaf0..9f5d7aa 100644 --- a/bindings/python/examples/do_fourier_analysis_pluto_auto.py +++ b/bindings/python/examples/simplified_beta/do_fourier_analysis_pluto_auto.py @@ -6,7 +6,7 @@ import matplotlib.pyplot as plt import numpy as np -test_dir = os.path.join(*["..", "..", "..", "tests", "test_vectors"]) +test_dir = os.path.join(*["..", "..", "..", "..", "tests", "test_vectors"]) loc = os.path.dirname(__file__) f = glob.glob(os.path.join(loc, test_dir, "test_Pluto_DDS_data_1658159639196.json")) @@ -23,20 +23,20 @@ qwfq = [int(i) for i in qwfq] # configure -c = genalyzer.config_fftz( +c = genalyzer.simplified_beta.config_fftz( data["npts"], data["qres"], data["navg"], data["nfft"], data["win"] - 1 ) -genalyzer.config_set_sample_rate(data["fs"], c) +genalyzer.simplified_beta.config_set_sample_rate(data["fs"], c) # Find tones -genalyzer.config_fa_auto(ssb_width=120, c=c) +genalyzer.simplified_beta.config_fa_auto(ssb_width=120, c=c) # compute FFT -fft_out_i, fft_out_q = genalyzer.fftz(qwfi, qwfq, c) +fft_out_i, fft_out_q = genalyzer.simplified_beta.fftz(qwfi, qwfq, c) fft_out = [val for pair in zip(fft_out_i, fft_out_q) for val in pair] # get all Fourier analysis results -all_results = genalyzer.get_fa_results(fft_out, c) +all_results = genalyzer.simplified_beta.get_fa_results(fft_out, c) # plot FFT fft_cp = np.empty(data["nfft"], dtype=np.complex128) @@ -63,11 +63,11 @@ plt.show() # get a single Fourier analysis result -sfdr = genalyzer.get_fa_single_result("sfdr", fft_out, c) +sfdr = genalyzer.simplified_beta.get_fa_single_result("sfdr", fft_out, c) # display results pprint.pprint(all_results) print("SFDR - ", sfdr) # free memory -genalyzer.config_free(c) +genalyzer.simplified_beta.config_free(c) diff --git a/bindings/python/examples/simplified_beta/do_histogram_analysis.py b/bindings/python/examples/simplified_beta/do_histogram_analysis.py new file mode 100644 index 0000000..aaf439b --- /dev/null +++ b/bindings/python/examples/simplified_beta/do_histogram_analysis.py @@ -0,0 +1,11 @@ +import genalyzer, pprint + +c = genalyzer.simplified_beta.config_gen_ramp(8192, 0, 2) +genalyzer.simplified_beta.config_quantize(8192, 3.0, 12, pow(10.0, -60.0 / 20.0), c) + +awf = genalyzer.simplified_beta.gen_ramp(c) +qwf = genalyzer.simplified_beta.quantize(awf, c) +hist = genalyzer.simplified_beta.histz(qwf, c) +ha_results = genalyzer.simplified_beta.get_ha_results(hist, c) +pprint.pprint(ha_results) +genalyzer.simplified_beta.config_free(c) \ No newline at end of file diff --git a/bindings/python/examples/simplified_beta/do_waveform_analysis.py b/bindings/python/examples/simplified_beta/do_waveform_analysis.py new file mode 100644 index 0000000..968ae6a --- /dev/null +++ b/bindings/python/examples/simplified_beta/do_waveform_analysis.py @@ -0,0 +1,10 @@ +import genalyzer, pprint + +c = genalyzer.simplified_beta.config_gen_tone(0, 8192, 5000000.0, 1, [50000.0], [0.5], [0.2]) +genalyzer.simplified_beta.config_quantize(8192, 3.0, 12, pow(10.0, -60.0 / 20.0), c) + +awf = genalyzer.simplified_beta.gen_real_tone(c) +qwf = genalyzer.simplified_beta.quantize(awf, c) +wfa_results = genalyzer.simplified_beta.get_wfa_results(qwf, c) +pprint.pprint(wfa_results) +genalyzer.simplified_beta.config_free(c) diff --git a/bindings/python/examples/gen_tone_and_quantize.py b/bindings/python/examples/simplified_beta/gen_tone_and_quantize.py similarity index 52% rename from bindings/python/examples/gen_tone_and_quantize.py rename to bindings/python/examples/simplified_beta/gen_tone_and_quantize.py index f830a4e..9b59df8 100644 --- a/bindings/python/examples/gen_tone_and_quantize.py +++ b/bindings/python/examples/simplified_beta/gen_tone_and_quantize.py @@ -13,22 +13,22 @@ qres = 12 qnoise = 0.0 -c = genalyzer.config_gen_tone( +c = genalyzer.simplified_beta.config_gen_tone( ttype, npts, sample_rate, num_tones, tone_freq, tone_ampl, tone_phase ) -awf1 = genalyzer.gen_real_tone(c) -genalyzer.config_quantize(npts, fsr, qres, qnoise, c) -qwf1 = genalyzer.quantize(awf1, c) +awf1 = genalyzer.simplified_beta.gen_real_tone(c) +genalyzer.simplified_beta.config_quantize(npts, fsr, qres, qnoise, c) +qwf1 = genalyzer.simplified_beta.quantize(awf1, c) plt.plot(awf1[:1000]) plt.plot(qwf1[:1000]) -c = genalyzer.config_gen_tone( +c = genalyzer.simplified_beta.config_gen_tone( ttype, npts, sample_rate, num_tones, tone_freq, tone_ampl, tone_phase ) -awf2_i, awf2_q = genalyzer.gen_complex_tone(c) -genalyzer.config_quantize(npts, fsr, qres, qnoise, c) -qwf2_i = genalyzer.quantize(awf2_i, c) -qwf2_q = genalyzer.quantize(awf2_q, c) +awf2_i, awf2_q = genalyzer.simplified_beta.gen_complex_tone(c) +genalyzer.simplified_beta.config_quantize(npts, fsr, qres, qnoise, c) +qwf2_i = genalyzer.simplified_beta.quantize(awf2_i, c) +qwf2_q = genalyzer.simplified_beta.quantize(awf2_q, c) plt.plot(awf2_i[:1000]) plt.plot(awf2_q[:1000]) plt.plot(qwf2_i[:1000]) @@ -39,4 +39,4 @@ print(qwf2_i[:10]) print(qwf2_q[:10]) -genalyzer.config_free(c) +genalyzer.simplified_beta.config_free(c) diff --git a/bindings/python/genalyzer/__init__.py b/bindings/python/genalyzer/__init__.py index 4e49e74..11ca7f2 100644 --- a/bindings/python/genalyzer/__init__.py +++ b/bindings/python/genalyzer/__init__.py @@ -5,27 +5,88 @@ __author__ = "Analog Devices, Inc." -from .simplified import ( - config_free, - config_gen_ramp, - config_gen_tone, - config_quantize, - config_histz_nla, - config_fftz, - config_fa, - config_fa_auto, - gen_ramp, - gen_real_tone, - gen_complex_tone, +from .pygenalyzer import ( + abs, + angle, + db, + db10, + db20, + norm, + code_axis, + code_axisx, + dnl, + dnl_analysis, + hist, + histx, + hist_analysis, + inl, + inl_analysis, + fft_analysis, + fa_analysis_band, + fa_clk, + fa_conv_offset, + fa_create, + fa_dc, + fa_fdata, + fa_fixed_tone, + fa_fsample, + fa_fshift, + fa_fund_images, + fa_hd, + fa_ilv, + fa_imd, + fa_load, + fa_max_tone, + fa_preview, + fa_quad_errors, + fa_remove_comp, + fa_reset, + fa_ssb, + fa_ssb_dc, + fa_ssb_def, + fa_ssb_wo, + fa_var, + fa_wo, + fa_annotations, + fa_result_string, + fft, + rfft, + alias, + coherent, + fftshift, + freq_axis, + ifftshift, + mgr_clear, + mgr_compare, + mgr_contains, + mgr_remove, + mgr_save, + mgr_size, + mgr_to_string, + mgr_type, + downsample, + fshift, + normalize, + polyval, + quantize16, + quantize32, + quantize64, quantize, - fftz, - histz, - get_ha_results, - get_wfa_results, - get_fa_single_result, - get_fa_results, - config_set_sample_rate, - config_code_format, + cos, + gaussian, + ramp, + sin, + wf_analysis, + CodeFormat, + DnlSignal, + FaCompTag, + FaSsb, + FreqAxisFormat, + FreqAxisType, + InlLineFit, + RfftScale, + Window, ) -import genalyzer.advanced as advanced + +import genalyzer.simplified_beta as simplified_beta import genalyzer.helpers as helpers diff --git a/bindings/python/genalyzer/advanced/__init__.py b/bindings/python/genalyzer/advanced/__init__.py deleted file mode 100644 index 57dc5c6..0000000 --- a/bindings/python/genalyzer/advanced/__init__.py +++ /dev/null @@ -1,82 +0,0 @@ -from .advanced import ( - abs, - angle, - db, - db10, - db20, - norm, - code_axis, - code_axisx, - dnl, - dnl_analysis, - hist, - histx, - hist_analysis, - inl, - inl_analysis, - fft_analysis, - fa_analysis_band, - fa_clk, - fa_conv_offset, - fa_create, - fa_dc, - fa_fdata, - fa_fixed_tone, - fa_fsample, - fa_fshift, - fa_fund_images, - fa_hd, - fa_ilv, - fa_imd, - fa_load, - fa_max_tone, - fa_preview, - fa_quad_errors, - fa_remove_comp, - fa_reset, - fa_ssb, - fa_ssb_dc, - fa_ssb_def, - fa_ssb_wo, - fa_var, - fa_wo, - fa_annotations, - fa_result_string, - fft, - rfft, - alias, - coherent, - fftshift, - freq_axis, - ifftshift, - mgr_clear, - mgr_compare, - mgr_contains, - mgr_remove, - mgr_save, - mgr_size, - mgr_to_string, - mgr_type, - downsample, - fshift, - normalize, - polyval, - quantize16, - quantize32, - quantize64, - quantize, - cos, - gaussian, - ramp, - sin, - wf_analysis, - CodeFormat, - DnlSignal, - FaCompTag, - FaSsb, - FreqAxisFormat, - FreqAxisType, - InlLineFit, - RfftScale, - Window, -) diff --git a/bindings/python/genalyzer/helpers/waveform_gen.py b/bindings/python/genalyzer/helpers/waveform_gen.py index 1bf7328..883d697 100644 --- a/bindings/python/genalyzer/helpers/waveform_gen.py +++ b/bindings/python/genalyzer/helpers/waveform_gen.py @@ -1,4 +1,4 @@ -from .. import ( +from ..simplified_beta import ( config_gen_tone, gen_real_tone, config_quantize, @@ -148,43 +148,54 @@ def __del__(self): self._data = [] def gen_sine_wave(self): - """Generate sine wave data + """ + Generate sine wave data - :return: waveform as list of ints + Returns: + Waveform as list of ints """ return self.__gen_sine_cosine(1) def gen_cosine_wave(self): - """Generate cosine wave data + """ + Generate cosine wave data - :return: waveform as list of ints + Returns: + Waveform as list of ints """ return self.__gen_sine_cosine(0) def gen_triangular_wave(self): - """Generate triangular wave data + """ + Generate triangular wave data - :return: waveform as list of ints + Returns: + Waveform as list of ints """ self.__prepare_waveform_gen() self._data = signal.sawtooth(2 * np.pi * self.freq * self.__t, 0.5) return self.__gen_other_waveforms() def gen_square_wave(self): - """Generate square wave data + """ + Generate square wave data - :return: waveform as list of ints + Returns: + Waveform as list of ints """ self.__prepare_waveform_gen() self._data = signal.square(2 * np.pi * self.freq * self.__t, 0.5) return self.__gen_other_waveforms() def gen_pwm_wave(self, duty_cycle): - """Generate pwm wave data - :param duty_cycle: Duty cycle required - Must be in between 0 and 1 with a precision of unto two decimals. - e.g. 0.25 for 25% duty-cycle - :return: waveform as list of ints + """ + Generate pwm wave data + + Args: + ``duty_cycle`` (``float``): Duty cycle required. Must be in between 0 and 1. + + Returns: + Waveform as list of ints """ self.__prepare_waveform_gen() self._data = signal.square(2 * np.pi * self.freq * self.__t, duty_cycle) diff --git a/bindings/python/genalyzer/advanced/advanced.py b/bindings/python/genalyzer/pygenalyzer.py similarity index 65% rename from bindings/python/genalyzer/advanced/advanced.py rename to bindings/python/genalyzer/pygenalyzer.py index 52eccac..c1517b8 100644 --- a/bindings/python/genalyzer/advanced/advanced.py +++ b/bindings/python/genalyzer/pygenalyzer.py @@ -1,5 +1,5 @@ """ -* cgenalyzer_advanced - genalyzer (advanced) API header file +* pygenalyzer - genalyzer API header file * * Copyright (C) 2022 Analog Devices, Inc. * Author: Peter Derounian @@ -20,7 +20,7 @@ """ """ -Python wrapper for Data Converter Analysis Library (genalyzer_plus_plus) +Python wrapper for Genalyzer Library (genalyzer_plus_plus) """ import ctypes as _ctypes from ctypes.util import find_library as _find_library @@ -56,21 +56,15 @@ _module_dir = _os.path.dirname(__file__) if "linux" == _sys.platform: _libpath = _find_library("genalyzer") - _lib = _ctypes.cdll.LoadLibrary(_libpath) elif "win32" == _sys.platform: _libpath = _find_library(_os.path.join(_module_dir, "genalyzer")) - if not _libpath: - _libpath = _find_library("libgenalyzer.dll") - try: - _lib = _ctypes.cdll.LoadLibrary(_libpath) # seems to work for Python3.9 - except OSError: - if "add_dll_directory" in dir(_os): - _os.add_dll_directory(_module_dir) # for Python3.8 (?) - else: - _os.environ["PATH"] += ";" + _module_dir # for Python3.7 and earlier - _lib = _ctypes.cdll.LoadLibrary(_libpath) else: raise Exception("Platform '{}' is not supported.".format(_sys.platform)) + +if _libpath is None: + raise OSError(2, "Could not find genalyzer C library") +_lib = _ctypes.cdll.LoadLibrary(_libpath) + del _find_library, _os, _sys _lib.gn_set_string_termination(True) @@ -176,16 +170,51 @@ class _AnalysisType(_IntEnum): # Intentionally private class CodeFormat(_IntEnum): + """Enumerates binary code formats + + Attributes: + ``OFFSET_BINARY`` : Offset Binary + + ``TWOS_COMPLEMENT`` : Two's Complement + """ OFFSET_BINARY = _enum_value("CodeFormat", "OffsetBinary") TWOS_COMPLEMENT = _enum_value("CodeFormat", "TwosComplement") class DnlSignal(_IntEnum): + """Enumerates signal types for which DNL can be computed + + Attributes: + ``RAMP`` : Ramp + + ``TONE`` : Tone (Sinusoid) + """ RAMP = _enum_value("DnlSignal", "Ramp") TONE = _enum_value("DnlSignal", "Tone") class FaCompTag(_IntEnum): + """Enumerates Fourier analysis component tags + + Attributes: + ``DC`` : DC component (always Bin 0) + + ``SIGNAL`` : Signal component + + ``HD`` : Harmonic distortion + + ``IMD`` : Intermodulation distortion + + ``ILOS`` : Interleaving offset component + + ``ILGT`` : Interleaving gain/timing/BW component + + ``CLK`` : Clock component + + ``USERDIST`` : User-designated distortion + + ``NOISE`` : Noise component (e.g. WorstOther) + """ DC = _enum_value("FACompTag", "DC") SIGNAL = _enum_value("FACompTag", "Signal") HD = _enum_value("FACompTag", "HD") @@ -198,6 +227,17 @@ class FaCompTag(_IntEnum): class FaSsb(_IntEnum): + """Enumerates the component categories for which the number of single side bins (SSB) can be set + + Attributes: + ``DEFAULT`` : Default SSB (applies to auto-generated components) + + ``DC`` : SSB for DC component + + ``SIGNAL`` : SSB for Signal components + + ``WO`` : SSB for WorstOther components + """ DEFAULT = _enum_value("FASsb", "Default") DC = _enum_value("FASsb", "DC") SIGNAL = _enum_value("FASsb", "Signal") @@ -205,30 +245,75 @@ class FaSsb(_IntEnum): class FreqAxisFormat(_IntEnum): + """Enumerates frequency axis formats + + Attributes: + ``BINS`` : Bins + + ``FREQ`` : Frequency + + ``NORM`` : Normalized + """ BINS = _enum_value("FreqAxisFormat", "Bins") FREQ = _enum_value("FreqAxisFormat", "Freq") NORM = _enum_value("FreqAxisFormat", "Norm") class FreqAxisType(_IntEnum): + """Enumerates frequency axis types + + Attributes: + ``DC_CENTER`` : DC centered, e.g. [-fs/2, fs/2) (complex FFT only) + + ``DC_LEFT`` : DC on left, e.g. [0, fs) (complex FFT only) + + ``REAL`` : Real axis, e.g. [0, fs/2] (real FFT only) + """ DC_CENTER = _enum_value("FreqAxisType", "DcCenter") DC_LEFT = _enum_value("FreqAxisType", "DcLeft") REAL = _enum_value("FreqAxisType", "Real") class InlLineFit(_IntEnum): + """Enumerates INL line fitting options + + Attributes: + ``BEST_FIT`` : Best fit + + ``END_FIT`` : End fit + + ``NO_FIT`` : No fit + """ BEST_FIT = _enum_value("InlLineFit", "BestFit") END_FIT = _enum_value("InlLineFit", "EndFit") NO_FIT = _enum_value("InlLineFit", "NoFit") class RfftScale(_IntEnum): + """Enumerates real FFT scaling options + + Attributes: + ``DBFS_DC`` : Full-scale sinusoid measures -3 dBFS + + ``DBFS_SIN`` : Full-scale sinusoid measures 0 dBFS + + ``NATIVE`` : Full-scale sinusoid measures -6 dBFS + """ DBFS_DC = _enum_value("RfftScale", "DbfsDc") DBFS_SIN = _enum_value("RfftScale", "DbfsSin") NATIVE = _enum_value("RfftScale", "Native") class Window(_IntEnum): + """Enumerates window functions + + Attributes: + ``BLACKMAN_HARRIS`` : Blackman-Harris + + ``HANN`` : Hann ("Hanning") + + ``NO_WINDOW`` : No window (Rectangular) + """ BLACKMAN_HARRIS = _enum_value("Window", "BlackmanHarris") HANN = _enum_value("Window", "Hann") NO_WINDOW = _enum_value("Window", "NoWindow") @@ -753,73 +838,105 @@ def inl_analysis(a): ] -def fft_analysis(cfg_id, a, nfft, axis_type=FreqAxisType.DC_LEFT): - """ - fft_analysis +def fft_analysis(test_key, a, nfft, axis_type=FreqAxisType.DC_LEFT): + """Returns all Fourier analysis results - Parameters - ---------- - cfg_id - a - nfft - axis_type + Args: + ``test_key`` (``string``) : Key value to the Fourier Analysis object created (through gn_fa_create) - Returns - ------- - results : dict - Every Key:Value pair in the dictionary is str:float. + ``a`` (``ndarray``) : FFT data of type 'complex128' or 'float64' + + ``nfft`` (``int``) : FFT size + + axis_type (``FreqAxisType``) : Frequency axis type + + Returns: + ``results`` (``dict``) : Dictionary containing all Fourier analysis results + + Notes: + Every Key:Value pair in the dictionary is ``str``:``float``. + + The dictionary contains the following keys: + ``signaltype`` : Signal type: 0=Real, 1=Complex + + ``nfft`` : FFT size + + ``datasize`` : Data size + + ``fbin`` : Frequency bin size (Hz) + + ``fdata`` : Data rate (S/s) + + ``fsample`` : Sample rate (S/s) + + ``fshift`` : Shift frequency (Hz) + + ``fsnr`` : Full-scale-to-noise ratio (a.k.a. "SNRFS") (dB) + + ``snr`` : Signal-to-noise ratio (dB) + + ``sinad`` : Signal-to-noise-and-distortion ratio (dB) + + ``sfdr`` : Spurious-free dynamic range (dB) + + ``abn`` : Average bin noise (dBFS) + + ``nsd`` : Noise spectral density (dBFS/Hz) + + ``carrierindex`` : Order index of the Carrier tone + + ``maxspurindex`` : Order index of the MaxSpur tone + + ``ab_width`` : Analysis band width (Hz) - =================================================================================== - Key | Description | Units - =================================================================================== - signaltype | Signal type: 0=Real, 1=Complex | - nfft | FFT size | - datasize | Data size | - fbin | Frequency bin size | Hz - fdata | Data rate | S/s - fsample | Sample rate | S/s - fshift | Shift frequency | Hz - fsnr | Full-scale-to-noise ratio (a.k.a. "SNRFS") | dB - snr | Signal-to-noise ratio | dB - sinad | Signal-to-noise-and-distortion ratio | dB - sfdr | Spurious-free dynamic range | dB - abn | Average bin noise | dBFS - nsd | Noise spectral density | dBFS/Hz - carrierindex | Order index of the Carrier tone | - maxspurindex | Order index of the MaxSpur tone | - ab_width | Analysis band width | Hz - ab_i1 | Analysis band first index | - ab_i2 | Analysis band last index | - {PREFIX}_nbins | Number of bins associated with PREFIX | - {PREFIX}_rss | Root-sum-square associated with PREFIX | - {TONEKEY}:orderindex | Tone order index | - {TONEKEY}:freq | Tone frequency | Hz - {TONEKEY}:ffinal | Tone final frequency | Hz - {TONEKEY}:fwavg | Tone weighted-average frequency | Hz - {TONEKEY}:i1 | Tone first index | - {TONEKEY}:i2 | Tone last index | - {TONEKEY}:nbins | Tone number of bins | - {TONEKEY}:inband | 0: tone is in-band; 1: tone is out-of-band | - {TONEKEY}:mag | Tone magnitude | - {TONEKEY}:mag_dbfs | Tone magnitude relative to full-scale | dBFS - {TONEKEY}:mag_dbc | Tone magnitude relative to carrier | dBc - {TONEKEY}:phase | Tone phase | rad - {TONEKEY}:phase_c | Tone phase relative to carrier | rad - =================================================================================== - - """ - cfg_id = bytes(cfg_id, "utf-8") + ``ab_i1`` : Analysis band first index + + ``ab_i2`` : Analysis band last index + + ``{PREFIX}_nbins`` : Number of bins associated with PREFIX + + ``{PREFIX}_rss`` : Root-sum-square associated with PREFIX + + ``{TONEKEY}:ffinal`` : Tone final frequency (Hz) + + ``{TONEKEY}:freq`` : Tone frequency (Hz) + + ``{TONEKEY}:fwavg`` : Tone weighted-average frequency (Hz) + + ``{TONEKEY}:i1`` : Tone first index + + ``{TONEKEY}:i2`` : Tone last index + + ``{TONEKEY}:inband`` : 1: tone is in-band; 0: tone is out-of-band + + ``{TONEKEY}:mag`` : Tone magnitude + + ``{TONEKEY}:mag_dbc`` : Tone magnitude relative to carrier (dBc) + + ``{TONEKEY}:mag_dbfs`` : Tone magnitude relative to full-scale (dBFS) + + ``{TONEKEY}:nbins`` : Tone number of bins + + ``{TONEKEY}:orderindex`` : Tone order index + + ``{TONEKEY}:phase`` : Tone phase (rad) + + ``{TONEKEY}:phase_c`` : Tone phase relative to carrier (rad) + + ``{TONEKEY}:tag`` : Tone tag + """ + test_key = bytes(test_key, "utf-8") dtype = _check_ndarray(a, ["complex128", "float64"]) af64 = a.view("float64") if "complex128" == dtype else a size = _c_size_t(0) result = _lib.gn_fft_analysis_results_size( - _ctypes.byref(size), cfg_id, af64.size, nfft + _ctypes.byref(size), test_key, af64.size, nfft ) _raise_exception_on_failure(result) size = size.value key_sizes = (_c_size_t * size)() result = _lib.gn_fft_analysis_results_key_sizes( - key_sizes, size, cfg_id, af64.size, nfft + key_sizes, size, test_key, af64.size, nfft ) _raise_exception_on_failure(result) keys = (_c_char_p * size)() @@ -829,7 +946,7 @@ def fft_analysis(cfg_id, a, nfft, axis_type=FreqAxisType.DC_LEFT): _ctypes.create_string_buffer(int(key_sizes[i])), _c_char_p ) result = _lib.gn_fft_analysis( - keys, size, values, size, cfg_id, af64, af64.size, nfft, axis_type + keys, size, values, size, test_key, af64, af64.size, nfft, axis_type ) _raise_exception_on_failure(result) results = _make_results_dict(keys, values) @@ -860,194 +977,416 @@ def fft_analysis(cfg_id, a, nfft, axis_type=FreqAxisType.DC_LEFT): _lib.gn_fa_var.argtypes = [_c_char_p, _c_char_p, _c_double] -def fa_analysis_band(obj_key, center, width): - obj_key = bytes(obj_key, "utf-8") +def fa_analysis_band(test_key, center, width): + """ + Configure analysis band + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``center`` (``float``) : Analysis band center (Hz) + + ``width`` (``float``) : Analysis band width (Hz) + """ + test_key = bytes(test_key, "utf-8") if isinstance(center, str) and isinstance(width, str): center = bytes(center, "utf-8") width = bytes(width, "utf-8") - result = _lib.gn_fa_analysis_band_e(obj_key, center, width) + result = _lib.gn_fa_analysis_band_e(test_key, center, width) else: - result = _lib.gn_fa_analysis_band(obj_key, center, width) + result = _lib.gn_fa_analysis_band(test_key, center, width) _raise_exception_on_failure(result) -def fa_clk(obj_key, x, as_noise=False): - obj_key = bytes(obj_key, "utf-8") +def fa_clk(test_key, x, as_noise=False): + """ + Treat clock components as noise + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``x`` (``list``) : Array of clock divisors + + ``as_noise`` (``bool``) : If true, CLK components will be treated as noise + """ + test_key = bytes(test_key, "utf-8") x = _np.array(x, dtype="int32") - result = _lib.gn_fa_clk(obj_key, x, x.size, as_noise) + result = _lib.gn_fa_clk(test_key, x, x.size, as_noise) _raise_exception_on_failure(result) -def fa_conv_offset(obj_key, enable): - obj_key = bytes(obj_key, "utf-8") - result = _lib.gn_fa_conv_offset(obj_key, enable) +def fa_conv_offset(test_key, enable): + """ + Enable converter offset + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``enable`` (``bool``) : If true, enable converter offset + """ + test_key = bytes(test_key, "utf-8") + result = _lib.gn_fa_conv_offset(test_key, enable) _raise_exception_on_failure(result) -def fa_create(obj_key): - obj_key = bytes(obj_key, "utf-8") - result = _lib.gn_fa_create(obj_key) +def fa_create(test_key): + """ + Create ``fourier_analysis`` object + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + """ + test_key = bytes(test_key, "utf-8") + result = _lib.gn_fa_create(test_key) _raise_exception_on_failure(result) -def fa_dc(obj_key, as_dist): - obj_key = bytes(obj_key, "utf-8") - result = _lib.gn_fa_dc(obj_key, as_dist) +def fa_dc(test_key, as_dist): + """ + Treat DC as distortion + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``as_dist`` (``bool``) : If true, treat DC as distortion + """ + test_key = bytes(test_key, "utf-8") + result = _lib.gn_fa_dc(test_key, as_dist) _raise_exception_on_failure(result) -def fa_fdata(obj_key, f): - obj_key = bytes(obj_key, "utf-8") +def fa_fdata(test_key, f): + """ + Configure fdata + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``f`` (``float``) : fdata + """ + test_key = bytes(test_key, "utf-8") if isinstance(f, str): f = bytes(f, "utf-8") - result = _lib.gn_fa_fdata_e(obj_key, f) + result = _lib.gn_fa_fdata_e(test_key, f) else: - result = _lib.gn_fa_fdata(obj_key, f) + result = _lib.gn_fa_fdata(test_key, f) _raise_exception_on_failure(result) -def fa_fixed_tone(obj_key, comp_key, tag, freq, ssb=-1): - obj_key = bytes(obj_key, "utf-8") +def fa_fixed_tone(test_key, comp_key, tag, freq, ssb=-1): + """ + Configure fixed tone + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``comp_key`` (``str``) : Component key + + ``tag`` (``FACompTag``) : Component tag + + ``freq`` (``float``) : Frequency (Hz) + + ``ssb`` (``int``) : Single side bin + """ + test_key = bytes(test_key, "utf-8") comp_key = bytes(comp_key, "utf-8") if isinstance(freq, str): freq = bytes(freq, "utf-8") - result = _lib.gn_fa_fixed_tone_e(obj_key, comp_key, tag, freq, ssb) + result = _lib.gn_fa_fixed_tone_e(test_key, comp_key, tag, freq, ssb) else: - result = _lib.gn_fa_fixed_tone(obj_key, comp_key, tag, freq, ssb) + result = _lib.gn_fa_fixed_tone(test_key, comp_key, tag, freq, ssb) _raise_exception_on_failure(result) -def fa_fsample(obj_key, f): - obj_key = bytes(obj_key, "utf-8") +def fa_fsample(test_key, f): + """ + Configure fsample + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``f`` (``float``) : fsample + """ + test_key = bytes(test_key, "utf-8") if isinstance(f, str): f = bytes(f, "utf-8") - result = _lib.gn_fa_fsample_e(obj_key, f) + result = _lib.gn_fa_fsample_e(test_key, f) else: - result = _lib.gn_fa_fsample(obj_key, f) + result = _lib.gn_fa_fsample(test_key, f) _raise_exception_on_failure(result) -def fa_fshift(obj_key, f): - obj_key = bytes(obj_key, "utf-8") +def fa_fshift(test_key, f): + """ + Configure fshift + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``f`` (``float``) : fshift + """ + test_key = bytes(test_key, "utf-8") if isinstance(f, str): f = bytes(f, "utf-8") - result = _lib.gn_fa_fshift_e(obj_key, f) + result = _lib.gn_fa_fshift_e(test_key, f) else: - result = _lib.gn_fa_fshift(obj_key, f) + result = _lib.gn_fa_fshift(test_key, f) _raise_exception_on_failure(result) -def fa_fund_images(obj_key, enable): - obj_key = bytes(obj_key, "utf-8") - result = _lib.gn_fa_fund_images(obj_key, enable) +def fa_fund_images(test_key, enable): + """ + Enable fundamental images + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``enable`` (``bool``) : If true, enable fundamental images + """ + test_key = bytes(test_key, "utf-8") + result = _lib.gn_fa_fund_images(test_key, enable) _raise_exception_on_failure(result) -def fa_hd(obj_key, n): - obj_key = bytes(obj_key, "utf-8") - result = _lib.gn_fa_hd(obj_key, n) +def fa_hd(test_key, n): + """ + Configure maximum harmonic order + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``n`` (``int``) : Order of harmonic distortion, i.e., the maximum harmonic + """ + test_key = bytes(test_key, "utf-8") + result = _lib.gn_fa_hd(test_key, n) _raise_exception_on_failure(result) -def fa_ilv(obj_key, x, as_noise=False): - obj_key = bytes(obj_key, "utf-8") +def fa_ilv(test_key, x, as_noise=False): + """ + Configure interleaving factors + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``x`` (``list``) : Array of interleaving factors + + ``as_noise`` (``bool``) : If true, interleaving factors will be treated as noise + """ + + test_key = bytes(test_key, "utf-8") x = _np.array(x, dtype="int32") - result = _lib.gn_fa_ilv(obj_key, x, x.size, as_noise) + result = _lib.gn_fa_ilv(test_key, x, x.size, as_noise) _raise_exception_on_failure(result) -def fa_imd(obj_key, n): - obj_key = bytes(obj_key, "utf-8") - result = _lib.gn_fa_imd(obj_key, n) +def fa_imd(test_key, n): + """ + Configure maximum intermodulation order + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``n`` (``int``) : Order of intermodulation distortion + """ + test_key = bytes(test_key, "utf-8") + result = _lib.gn_fa_imd(test_key, n) _raise_exception_on_failure(result) -def fa_load(filename, obj_key=""): +def fa_load(filename, test_key=""): + """ + Load object-key from file + + Args: + ``filename`` (``str``) : File name + + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + """ filename = bytes(filename, "utf-8") - obj_key = bytes(obj_key, "utf-8") + test_key = bytes(test_key, "utf-8") size = _c_size_t(0) - result = _lib.gn_fa_load_key_size(_ctypes.byref(size), filename, obj_key) + result = _lib.gn_fa_load_key_size(_ctypes.byref(size), filename, test_key) _raise_exception_on_failure(result) buf = _ctypes.create_string_buffer(size.value) - result = _lib.gn_fa_load(buf, len(buf), filename, obj_key) + result = _lib.gn_fa_load(buf, len(buf), filename, test_key) _raise_exception_on_failure(result) return buf.value.decode("utf-8") -def fa_max_tone(obj_key, comp_key, tag, ssb=-1): - obj_key = bytes(obj_key, "utf-8") +def fa_max_tone(test_key, comp_key, tag, ssb=-1): + """ + Configure component-key to select peak tone + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``comp_key`` (``str``) : Component key + + ``tag`` (``FACompTag``) : Tag + + ``ssb`` (``int``) : Number of single-side bins + """ + test_key = bytes(test_key, "utf-8") comp_key = bytes(comp_key, "utf-8") - result = _lib.gn_fa_max_tone(obj_key, comp_key, tag, ssb) + result = _lib.gn_fa_max_tone(test_key, comp_key, tag, ssb) _raise_exception_on_failure(result) -def fa_preview(cfg_id, cplx=False): - cfg_id = bytes(cfg_id, "utf-8") +def fa_preview(test_key, cplx=False): + """ + Preview ``fourier_analysis`` object + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``cplx`` (``bool``) : If true, preview will include complex components + """ + test_key = bytes(test_key, "utf-8") size = _c_size_t(0) - result = _lib.gn_fa_preview_size(_ctypes.byref(size), cfg_id, cplx) + result = _lib.gn_fa_preview_size(_ctypes.byref(size), test_key, cplx) _raise_exception_on_failure(result) buf = _ctypes.create_string_buffer(size.value) - result = _lib.gn_fa_preview(buf, len(buf), cfg_id, cplx) + result = _lib.gn_fa_preview(buf, len(buf), test_key, cplx) _raise_exception_on_failure(result) return buf.value.decode("utf-8") -def fa_quad_errors(obj_key, enable): - obj_key = bytes(obj_key, "utf-8") - result = _lib.gn_fa_quad_errors(obj_key, enable) +def fa_quad_errors(test_key, enable): + """ + Enable quadrature errors + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``enable`` (``bool``) : If true, enable quadrature errors + """ + test_key = bytes(test_key, "utf-8") + result = _lib.gn_fa_quad_errors(test_key, enable) _raise_exception_on_failure(result) -def fa_remove_comp(obj_key, comp_key): - obj_key = bytes(obj_key, "utf-8") +def fa_remove_comp(test_key, comp_key): + """ + Remove component + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``comp_key`` (``str``) : Component key + """ + test_key = bytes(test_key, "utf-8") comp_key = bytes(comp_key, "utf-8") - result = _lib.gn_fa_remove_comp(obj_key, comp_key) + result = _lib.gn_fa_remove_comp(test_key, comp_key) _raise_exception_on_failure(result) -def fa_reset(obj_key): - obj_key = bytes(obj_key, "utf-8") - result = _lib.gn_fa_reset(obj_key) +def fa_reset(test_key): + """ + Reset object + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + """ + test_key = bytes(test_key, "utf-8") + result = _lib.gn_fa_reset(test_key) _raise_exception_on_failure(result) -def fa_ssb(obj_key, group, n): - obj_key = bytes(obj_key, "utf-8") - result = _lib.gn_fa_ssb(obj_key, group, n) +def fa_ssb(test_key, group, n): + """ + Configure number of single-sideband bins + + Args: + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``group`` (``FASsb``) : SSB Group + + ``n`` (``int``) : Number of single-sideband bins + """ + test_key = bytes(test_key, "utf-8") + result = _lib.gn_fa_ssb(test_key, group, n) _raise_exception_on_failure(result) -def fa_ssb_dc(obj_key, n): - print("fa_ssb_dc(obj_key, n) is deprecated; use fa_ssb(obj_key, FaSsb.DC, n)") - obj_key = bytes(obj_key, "utf-8") - result = _lib.gn_fa_ssb(obj_key, FaSsb.DC, n) +def fa_ssb_dc(test_key, n): + """ + Configure number of single-sideband bins for DC + + Args: + + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``n`` (``int``) : Number of single-sideband bins + """ + print("fa_ssb_dc(test_key, n) is deprecated; use fa_ssb(test_key, FaSsb.DC, n)") + test_key = bytes(test_key, "utf-8") + result = _lib.gn_fa_ssb(test_key, FaSsb.DC, n) _raise_exception_on_failure(result) -def fa_ssb_def(obj_key, n): - print("fa_ssb_def(obj_key, n) is deprecated; use fa_ssb(obj_key, FaSsb.DEFAULT, n)") - obj_key = bytes(obj_key, "utf-8") - result = _lib.gn_fa_ssb(obj_key, FaSsb.DEFAULT, n) +def fa_ssb_def(test_key, n): + """ + Configure default number of single-sideband bins for auto-generated components + + Args: + + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``n`` (``int``) : Number of single-sideband bins + """ + print("fa_ssb_def(test_key, n) is deprecated; use fa_ssb(test_key, FaSsb.DEFAULT, n)") + test_key = bytes(test_key, "utf-8") + result = _lib.gn_fa_ssb(test_key, FaSsb.DEFAULT, n) _raise_exception_on_failure(result) -def fa_ssb_wo(obj_key, n): - print("fa_ssb_wo(obj_key, n) is deprecated; use fa_ssb(obj_key, FaSsb.WO, n)") - obj_key = bytes(obj_key, "utf-8") - result = _lib.gn_fa_ssb(obj_key, FaSsb.WO, n) +def fa_ssb_wo(test_key, n): + """ + Configure number of single-sideband bins for WO component + + Args: + + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``n`` (``int``) : Number of single-sideband bins + """ + print("fa_ssb_wo(test_key, n) is deprecated; use fa_ssb(test_key, FaSsb.WO, n)") + test_key = bytes(test_key, "utf-8") + result = _lib.gn_fa_ssb(test_key, FaSsb.WO, n) _raise_exception_on_failure(result) -def fa_var(obj_key, name, value): - obj_key = bytes(obj_key, "utf-8") +def fa_var(test_key, name, value): + """ + Set value of variable in object + + Args: + + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``name`` (``str``) : Variable name + + ``value`` (``float``) : Variable value + """ + test_key = bytes(test_key, "utf-8") name = bytes(name, "utf-8") - result = _lib.gn_fa_var(obj_key, name, value) + result = _lib.gn_fa_var(test_key, name, value) _raise_exception_on_failure(result) -def fa_wo(obj_key, n): - obj_key = bytes(obj_key, "utf-8") - result = _lib.gn_fa_wo(obj_key, n) +def fa_wo(test_key, n): + """ + Configure number of WO components + + Args: + + ``test_key`` (``str``) : Test key (key to a Fourier Analysis object) + + ``n`` (``int``) : Number of worst others + """ + test_key = bytes(test_key, "utf-8") + result = _lib.gn_fa_wo(test_key, n) _raise_exception_on_failure(result) @@ -1309,31 +1648,66 @@ def fa_result_string(result_dict, result_key): def fft(a, *args): """ - 1. fft(iq, navg=1, nfft=0, window=Window.NoWindow) - Computes the FFT of interleaved normalized samples. dtype of iq is 'float64' or - 'complex128'. + Compute FFT - 2. fft(i, q, navg=1, nfft=0, window=Window.NoWindow) - Computes the FFT of split normalized samples. dtype of i and q is 'float64'. + Args: + ``a`` (``ndarray``) : Input array of type ``complex128``, ``float64``, ``int16``, ``int32``, or ``int64`` - 3. fft(iq, n, navg=1, nfft=0, window=Window.NoWindow, fmt=CodeFormat.TwosComplement) - Computes the FFT of interleaved quantized samples. dtype of iq is 'int16', 'int32', or - 'int64'. Requires the second argument, n, which specifies code width, i.e., quantizer - resolution. + ``args`` (``list``) : Additional arguments + 1. If ``a`` is of type ``complex128`` or ``float64``, then compute the FFT of interleaved normalized samples with the following interpretation. - 4. fft(i, q, n, navg=1, nfft=0, window=Window.NoWindow, fmt=CodeFormat.TwosComplement) - Computes the FFT of split quantized samples. dtype of i and q is 'int16', 'int32', or - 'int64'. Requires the third argument, n, which represents code width, i.e., quantizer - resolution. + ``navg`` (``int``) : FFT averaging number - Parameters - ---------- - a : ndarray - Input array, the dtype determines the interpretation of args. + ``nfft`` (``int``) : FFT size - Returns - ------- - out : complex ndarray + ``window`` (``Window``): Window + + In this case, if ``a`` is not complex, then a is interpreted to contain interleaved I/Q samples with the following interpretation. + + 2. If ``a`` is of type ``float64``, then compute the FFT of split normalized samples. + + ``q`` (``float64``) : Quadrature component + + ``navg`` (``int``) : FFT averaging number + + ``nfft`` (``int``) : FFT size + + ``window`` (``Window``): Window + + In this case, ``a`` is interpreted to be the In-phase component. + + 3. If ``a`` is of type ``int16``, ``int32``, or ``int64``, then compute the FFT of interleaved quantized samples with the following interpretation. + + ``n`` (``int``) : Resolution (Bitwidth of a) + + ``navg`` (``int``) : FFT averaging number + + ``nfft`` (``int``) : FFT size + + ``window`` (``Window``): Window + + ``fmt`` (``CodeFormat``): Code format + + In this case, ``a`` is interpreted to contain interleaved quantized samples. + + 4. If ``a`` is of type ``int16``, ``int32``, or ``int64``, then compute the FFT of split quantized samples with the following interpretation. + + ``q`` (``int16``, ``int32``, or ``int64``) : Quadrature component + + ``n`` (``int``) : Resolution (Bitwidth of ``a``) + + ``navg`` (``int``) : FFT averaging number + + ``nfft`` (``int``) : FFT size + + ``window`` (``Window``): Window + + ``fmt`` (``CodeFormat``): Code format + + In this case, ``a`` is interpreted to to be the In-phase component. + + Returns: + ``out`` (``ndarray``) : FFT result of type ``float64`` with interleaved Re/Im components """ dtype = _check_ndarray(a, ["complex128", "float64", "int16", "int32", "int64"]) @@ -1436,35 +1810,38 @@ def fft(a, *args): def rfft(a, *args): """ - 1. rfft(a, navg=1, nfft=0, window=Window.NoWindow, scale=RfftScale.DbfsSin) - Computes the FFT of real normalized samples. + Compute Real-FFT - 2. rfft(a, n, navg=1, nfft=0, window=Window.NoWindow, fmt=CodeFormat.TwosComplement, scale=RfftScale.DbfsSin) - Computes the FFT of real quantized samples. Requires the second argument, n, which specifies - code width, i.e., quantizer resolution. + Args: + ``a`` (``ndarray``) : Input array of type ``float64``, ``int16``, ``int32``, or ``int64`` - Parameters - ---------- - a : ndarray - Input array, the dtype determines the interpretation of args. - args : - a.dtype = 'float64' : - arg[0] : navg - arg[1] : nfft - arg[2] : window - arg[3] : scale - a.dtype = 'int16', 'int32', 'int64' : - arg[0] : n - arg[1] : navg - arg[2] : nfft - arg[3] : window - arg[4] : fmt - arg[5] : scale + ``args`` (``list``) : Additional arguments + 1. If ``a`` is of type ``float64``, then compute the real-FFT of normalized samples with the following interpretation. - Returns - ------- - out : complex ndarray + ``navg`` (``int``) : FFT averaging number + + ``nfft`` (``int``) : FFT size + + ``window`` (``Window``): Window + + ``scale`` (``RfftScale``): Scaling mode + + 2. If ``a`` is of type ``int16``, ``int32``, or ``int64``, then compute the FFT of interleaved quantized samples with the following interpretation. + + ``n`` (``int``) : Resolution (Bitwidth of a) + + ``navg`` (``int``) : FFT averaging number + + ``nfft`` (``int``) : FFT size + + ``window`` (``Window``): Window + + ``fmt`` (``CodeFormat``): Code format + ``scale`` (``RfftScale``): Scaling mode + + Returns: + ``out`` (``ndarray``) : FFT result of type ``float64`` with interleaved Re/Im components """ dtype = _check_ndarray(a, ["float64", "int16", "int32", "int64"]) nargs = len(args) @@ -1861,7 +2238,20 @@ def mgr_type(key): ] -def downsample(a, ratio, interleaved=False): +def downsample(a, ratio, interleaved=False): + """ + Downsample a waveform + + Args: + ``a`` (``ndarray``) : Input array of type ``complex128``, ``int16``, ``int32``, or ``int64`` + + ``ratio`` (``int``) : Downsample ratio + + ``interleaved`` (``double``) : If true, ``a`` is interleaved I/Q data + + Returns: + ``out`` (``ndarray``) : ``float64``, ``int16``, ``int32``, or ``int64`` ``numpy`` array consisting of downsampled waveform + """ dtype = _check_ndarray(a, ["complex128", "float64", "int16", "int32", "int64"]) ratio = int(ratio) if ( @@ -1899,30 +2289,58 @@ def downsample(a, ratio, interleaved=False): def fshift(a, *args): """ - 1. fshift(iq, fs, fshift_) - Performs frequency shift on interleaved normalized samples. dtype of iq is 'float64' or - 'complex128'. + Perform frequency shift - 2. fshift(i, q, fs, fshift_) - Performs frequency shift on split normalized samples. dtype of i and q is 'float64'. + Args: + ``a`` (``ndarray``) : Input array of type ``complex128``, ``float64``, ``int16``, ``int32``, or ``int64`` - 3. fshift(iq, n, fs, fshift_, fmt=CodeFormat.TWOS_COMPLEMENT) - Performs frequency shift on interleaved quantized samples. dtype of iq is 'int16', - 'int32', or 'int64'. + ``args`` (``list``) : Additional arguments + 1. If ``a`` is of type ``complex128`` or ``float64``, then perform frequency shift of interleaved normalized samples with the following interpretation. - 4. fshift(i, q, n, fs, fshift_, fmt=CodeFormat.TWOS_COMPLEMENT) - Performs frequency shift on split quantized samples. dtype of i and q is 'int16', 'int32', - or 'int64'. + ``fs`` (``double``) : Sample rate - Parameters - ---------- - a : ndarray - Input array, the dtype determines the interpretation of args. + ``fshift_`` (``double``) : Shift frequency - Returns - ------- - out : ndarray - The output is always interleaved. The output dtype is the same as the input dtype. + In this case, if ``a`` is not complex, then a is interpreted to contain interleaved I/Q samples. + + 2. If ``a`` is of type ``float64``, then perform frequency shift of split normalized samples. + + ``q`` (``float64``) : Quadrature component + + ``fs`` (``double``) : Sample rate + + ``fshift_`` (``double``) : Shift frequency + + In this case, ``a`` is interpreted to be the In-phase component. + + 3. If ``a`` is of type ``int16``, ``int32``, or ``int64``, then perform frequency shift of interleaved quantized samples with the following interpretation. + + ``n`` (``int``) : Resolution (Bitwidth of a) + + ``fs`` (``double``) : Sample rate + + ``fshift_`` (``double``) : Shift frequency + + ``fmt`` (``CodeFormat``): Code format + + In this case, ``a`` is interpreted to contain interleaved quantized samples. + + 4. If ``a`` is of type ``int16``, ``int32``, or ``int64``, then perform frequency shift of split quantized samples with the following interpretation. + + ``q`` (``int16``, ``int32``, or ``int64``) : Quadrature component + + ``n`` (``int``) : Resolution (Bitwidth of ``a``) + + ``fs`` (``double``) : Sample rate + + ``fshift_`` (``double``) : Shift frequency + + ``fmt`` (``CodeFormat``): Code format + + In this case, ``a`` is interpreted to to be the In-phase component. + + Returns: + ``out`` (``ndarray``) : Frequency-shifted input waveform. The output datatype is the same as the input datatype. """ dtype = _check_ndarray(a, ["complex128", "float64", "int16", "int32", "int64"]) @@ -2000,18 +2418,17 @@ def fshift(a, *args): def normalize(a, n, fmt=CodeFormat.TWOS_COMPLEMENT): """ - normalize + Normalize a waveform - Parameters - ---------- - a : - n : - fmt : + Args: + ``a`` (``ndarray``) : Input array of type ``int16``, ``int32``, or ``int64`` + + ``n`` (``int``) : Resolution (Bitwidth of ``a``) - Returns - ------- - out : + ``fmt`` (``CodeFormat``): Code format + Returns: + ``out`` (``ndarray``) : ``float64`` ``numpy`` array consisting of normalized input waveform """ dtype = _check_ndarray(a, ["int16", "int32", "int64"]) out = _np.empty(a.size, dtype="float64") @@ -2027,17 +2444,15 @@ def normalize(a, n, fmt=CodeFormat.TWOS_COMPLEMENT): def polyval(a, c): """ - polyval + Apply distortion as a polynomial function - Parameters - ---------- - a : - c : - - Returns - ------- - out : + Args: + ``a`` (``ndarray``) : Input array of type ``float64`` + + ``c`` (``ndarray``) : Polynomial coefficient array of type ``float64`` + Returns: + ``out`` (``ndarray``) : ``float64`` ``numpy`` array consisting of distorted input waveform """ _check_ndarray(a, "float64") c = _np.array(c, dtype="float64") @@ -2049,20 +2464,21 @@ def polyval(a, c): def quantize16(a, fsr, n, noise=0.0, fmt=CodeFormat.TWOS_COMPLEMENT): """ - quantize16 + Quantize a floating-point waveform - Parameters - ---------- - a : - fsr : - n : - noise : - fmt : + Args: + ``a`` (``ndarray``) : Input array of type ``float64`` - Returns - ------- - out : + ``fsr`` (``double``) : Full-scale range of the waveform + + ``n`` (``int``) : Resolution (Bitwidth of ``a``) + ``noise`` (``double``) : Quantization Noise RMS level + + ``fmt`` (``CodeFormat``): Code format + + Returns: + ``out`` (``ndarray``) : ``int16`` ``numpy`` array consisting of quantized input waveform """ _check_ndarray(a, "float64") out = _np.empty(a.size, dtype="int16") @@ -2073,20 +2489,21 @@ def quantize16(a, fsr, n, noise=0.0, fmt=CodeFormat.TWOS_COMPLEMENT): def quantize32(a, fsr, n, noise=0.0, fmt=CodeFormat.TWOS_COMPLEMENT): """ - quantize32 + Quantize a floating-point waveform - Parameters - ---------- - a : - fsr : - n : - noise : - fmt : + Args: + ``a`` (``ndarray``) : Input array of type ``float64`` - Returns - ------- - out : + ``fsr`` (``double``) : Full-scale range of the waveform + + ``n`` (``int``) : Resolution (Bitwidth of ``a``) + + ``noise`` (``double``) : Quantization Noise RMS level + + ``fmt`` (``CodeFormat``): Code format + Returns: + ``out`` (``ndarray``) : ``int32`` ``numpy`` array consisting of quantized input waveform """ _check_ndarray(a, "float64") out = _np.empty(a.size, dtype="int32") @@ -2097,20 +2514,21 @@ def quantize32(a, fsr, n, noise=0.0, fmt=CodeFormat.TWOS_COMPLEMENT): def quantize64(a, fsr, n, noise=0.0, fmt=CodeFormat.TWOS_COMPLEMENT): """ - quantize64 + Quantize a floating-point waveform - Parameters - ---------- - a : - fsr : - n : - noise : - fmt : + Args: + ``a`` (``ndarray``) : Input array of type ``float64`` - Returns - ------- - out : + ``fsr`` (``double``) : Full-scale range of the waveform + + ``n`` (``int``) : Resolution (Bitwidth of ``a``) + + ``noise`` (``double``) : Quantization Noise RMS level + ``fmt`` (``CodeFormat``): Code format + + Returns: + ``out`` (``ndarray``) : ``int64`` ``numpy`` array consisting of quantized input waveform """ _check_ndarray(a, "float64") out = _np.empty(a.size, dtype="int64") @@ -2121,20 +2539,21 @@ def quantize64(a, fsr, n, noise=0.0, fmt=CodeFormat.TWOS_COMPLEMENT): def quantize(a, fsr, n, noise=0.0, fmt=CodeFormat.TWOS_COMPLEMENT): """ - quantize + Quantize a floating-point waveform - Parameters - ---------- - a : - fsr : - n : - noise : - fmt : + Args: + ``a`` (``ndarray``) : Input array of type ``float64`` - Returns - ------- - out : + ``fsr`` (``double``) : Full-scale range of the waveform + + ``n`` (``int``) : Resolution (Bitwidth of ``a``) + ``noise`` (``double``) : Quantization Noise RMS level + + ``fmt`` (``CodeFormat``): Code format + + Returns: + ``out`` (``ndarray``) : ``numpy`` array consisting of quantized input waveform of datatype ``int16`` if ``n <= 16``, ``int32`` otherwise """ if n < 16 or 16 == n and CodeFormat.TWOS_COMPLEMENT == fmt: return quantize16(a, fsr, n, noise, fmt) @@ -2202,126 +2621,138 @@ def quantize(a, fsr, n, noise=0.0, fmt=CodeFormat.TWOS_COMPLEMENT): ] -def cos(size, fs, ampl, freq, phase=0.0, td=0.0, tj=0.0): +def cos(nsamples, fs, ampl, freq, phase=0.0, td=0.0, tj=0.0): """ - cos + Generate cosine waveform - Parameters - ---------- - size : - fs : - ampl : - freq : - phase : - td : - tj : + Args: + ``nsamples`` (``int``) : Number of samples - Returns - ------- - out : + ``fs`` (``double``) : Sample rate (S/s) + ``ampl`` (``double``) : Amplitude + + ``freq`` (``double``) : Frequency (Hz) + + ``phase`` (``double``) : Phase (rad) + + ``td`` (``double``) : Time delay (s) + + ``tj`` (``double``) : RMS Aperture jitter (s) + + Returns: + ``out`` (``ndarray``) : ``float64`` ``numpy`` array consisting of Cosine waveform """ - out = _np.empty(size, "float64") + out = _np.empty(nsamples, "float64") result = _lib.gn_cos(out, out.size, fs, ampl, freq, phase, td, tj) _raise_exception_on_failure(result) return out -def gaussian(size, mean, sd): +def gaussian(nsamples, mean, sd): """ - ramp + Generate Gaussian random samples - Parameters - ---------- - size : - mean : - sd : + Args: + ``nsamples`` (``int``) : Number of samples - Returns - ------- - out : + ``mean`` (``double``) : Mean + + ``sd`` (``double``) : Standard deviation + Returns: + ``out`` (``ndarray``) : ``float64`` ``numpy`` array consisting of Gaussian random samples """ - out = _np.empty(size, "float64") + out = _np.empty(nsamples, "float64") result = _lib.gn_gaussian(out, out.size, mean, sd) _raise_exception_on_failure(result) return out -def ramp(size, start, stop, noise): +def ramp(nsamples, start, stop, noise): """ - ramp + Generate ramp waveform - Parameters - ---------- - size : - start : - stop : - noise : + Args: + ``nsamples`` (``int``) : Number of samples - Returns - ------- - out : + ``start`` (``double``) : Start value + + ``stop`` (``double``) : Stop value + + ``noise`` (``double``) : RMS noise + Returns: + ``out`` (``ndarray``) : ``float64`` ``numpy`` array consisting of ramp waveform """ - out = _np.empty(size, "float64") + out = _np.empty(nsamples, "float64") result = _lib.gn_ramp(out, out.size, start, stop, noise) _raise_exception_on_failure(result) return out -def sin(size, fs, ampl, freq, phase=0.0, td=0.0, tj=0.0): +def sin(nsamples, fs, ampl, freq, phase=0.0, td=0.0, tj=0.0): """ - sin + Generate sine waveform - Parameters - ---------- - size : - fs : - ampl : - freq : - phase : - td : - tj : + Args: + ``nsamples`` (``int``) : Number of samples - Returns - ------- - out : + ``fs`` (``double``) : Sample rate (S/s) + + ``ampl`` (``double``) : Amplitude + + ``freq`` (``double``) : Frequency (Hz) + + ``phase`` (``double``) : Phase (rad) + + ``td`` (``double``) : Time delay (s) + + ``tj`` (``double``) : RMS Aperture jitter (s) + Returns: + ``out`` (``ndarray``) : ``float64`` ``numpy`` array consisting of Sine waveform """ - out = _np.empty(size, "float64") + out = _np.empty(nsamples, "float64") result = _lib.gn_sin(out, out.size, fs, ampl, freq, phase, td, tj) _raise_exception_on_failure(result) return out -def wf_analysis(a): +def wf_analysis(a): """ - wf_analysis + Run waveform analysis - Parameters - ---------- - a : + Args: + ``a`` (``ndarray``) : Input array of type ``int16``, ``int32``, or ``int64`` + + Returns: + Returns: + ``results`` (``dict``) : Dictionary containing all waveform analysis results - Returns - ------- - results : dict - Every Key:Value pair in the dictionary is str:float. + Notes: + Every Key:Value pair in the dictionary is ``str``:``float``. - =========================================================== - Key | Description - =========================================================== - min | Minumum value - max | Maximum value - mid | Middle value ((max + min) / 2) - range | Range (max - min) - avg | Average value - rms | RMS value - rmsac | RMS value with DC removed - min_index | Index of first occurence of minimum value - max_index | Index of first occurence of maximum value - =========================================================== + The dictionary contains the following keys: + ``signaltype`` : Signal type: 0=Real, 1=Complex + + ``min`` : Minumum value + + ``max`` : Maximum value + + ``mid`` : Middle value ((max + min) / 2) + + ``range`` : Range (max - min) + + ``avg`` : Average value + + ``rms`` : RMS value + + ``rmsac`` : RMS value with DC removed + + ``min_index`` : Index of first occurence of minimum value + ``max_index`` : Index of first occurence of maximum value """ dtype = _check_ndarray(a, ["float", "int16", "int32", "int64"]) keys, values = _get_analysis_containers(_AnalysisType.WAVEFORM) diff --git a/bindings/python/genalyzer/simplified_beta/__init__.py b/bindings/python/genalyzer/simplified_beta/__init__.py new file mode 100644 index 0000000..89a94fb --- /dev/null +++ b/bindings/python/genalyzer/simplified_beta/__init__.py @@ -0,0 +1,22 @@ +from .simplified_beta import ( + config_free, + config_gen_ramp, + config_gen_tone, + config_quantize, + config_histz_nla, + config_fftz, + config_fa, + config_fa_auto, + gen_ramp, + gen_real_tone, + gen_complex_tone, + quantize, + fftz, + histz, + get_ha_results, + get_wfa_results, + get_fa_single_result, + get_fa_results, + config_set_sample_rate, + config_code_format, +) diff --git a/bindings/python/genalyzer/simplified.py b/bindings/python/genalyzer/simplified_beta/simplified_beta.py similarity index 81% rename from bindings/python/genalyzer/simplified.py rename to bindings/python/genalyzer/simplified_beta/simplified_beta.py index 451e8c9..1e233b3 100644 --- a/bindings/python/genalyzer/simplified.py +++ b/bindings/python/genalyzer/simplified_beta/simplified_beta.py @@ -46,8 +46,6 @@ from ctypes.util import find_library import os -# import genalyzer_advanced as advanced - if "Windows" in _system(): _libgen = "libgenalyzer.dll" else: @@ -465,12 +463,6 @@ def config_free( def config_gen_ramp(npts: int, ramp_start: int, ramp_stop: int, c: GNConfig = None) -> GNConfig: - """Configure GNConfig struct to generate tone. - :param npts: number of sample points in the waveform - :param ramp_start: Input start value of ramp - :param ramp_stop: Input stop value of ramp - :return: GNConfig object - """ if c is None: c = GNConfig() @@ -494,16 +486,6 @@ def config_gen_tone( tone_phase: float, c: GNConfig = None ) -> GNConfig: - """Configure GNConfig struct to generate tone. - :param ttype: tone type - :param npts: number of sample points in the waveform - :param sample_rate: sampling frequency - :param num_tones: number of tones - :param tone_freq: tone frequency - :param tone_ampl: tone amplitude - :param tone_phase: tone phase - :return: GNConfig object - """ if c is None: c = GNConfig() @@ -532,13 +514,6 @@ def config_gen_tone( def config_quantize(npts: int, fsr: float, qres: int, qnoise: float, c: GNConfig = None) -> GNConfig: - """Configure GNConfig struct to perform quantization. - :param npts: number of sample points in the waveform - :param fsr: full-scale range - :param qres: quantization resolution - :param qnoise: quantization noise - :return: GNConfig object - """ if c is None: c = GNConfig() @@ -554,13 +529,6 @@ def config_quantize(npts: int, fsr: float, qres: int, qnoise: float, c: GNConfig def config_histz_nla(npts: int, qres: int, c: GNConfig = None) -> GNConfig: - """Configure GNConfig struct to compute histogram or perform non-linearity analysis. - :param npts: number of sample points in the waveform - :param fsr: full-scale range - :param qres: quantization resolution - :param qnoise: quantization noise - :return: GNConfig object - """ if c is None: c = GNConfig() @@ -576,13 +544,6 @@ def config_histz_nla(npts: int, qres: int, c: GNConfig = None) -> GNConfig: def config_fftz( npts: int, qres: int, navg: int, nfft: int, win: int, c: GNConfig = None ) -> GNConfig: - """Configure GNConfig struct to compute FFT. - :param npts: number of sample points in the waveform - :param fsr: full-scale range - :param qres: quantization resolution - :param qnoise: quantization noise - :return: GNConfig object - """ if c is None: c = GNConfig() @@ -599,10 +560,6 @@ def config_fftz( def config_fa(fixed_tone_freq: float, c: GNConfig = None) -> GNConfig: - """Configure GNConfig struct for Fourier analysis. - :param fixed_tone_freq: fixed tone frequency - :return: GNConfig object - """ if c is None: c = GNConfig() @@ -615,11 +572,6 @@ def config_fa(fixed_tone_freq: float, c: GNConfig = None) -> GNConfig: def config_fa_auto(ssb_width: int, c: GNConfig = None): - """Configure GNConfig struct for Fourier analysis where tones are - automatically found. - :param ssb_width: SSB width - :param c: GNConfig object - """ if c is None: c = GNConfig() ssb_width = c_uint8(ssb_width) @@ -631,10 +583,6 @@ def config_fa_auto(ssb_width: int, c: GNConfig = None): def gen_ramp(c: GNConfig) -> List[float]: - """Generate floating-point ramp waveform - :param c: GNConfig object - :return: real ramp waveform as list of floats - """ awf = POINTER(c_double)() wf_len = c_ulong(0) _gn_config_get_npts(byref(wf_len), byref(c._struct)) @@ -643,10 +591,6 @@ def gen_ramp(c: GNConfig) -> List[float]: def gen_real_tone(c: GNConfig) -> List[float]: - """Generate single-tone or multi-tone floating-point waveform - :param c: GNConfig object - :return: single-/multi-tone real waveform as list of floats - """ awf = POINTER(c_double)() wf_len = c_ulong(0) _gn_config_get_npts(byref(wf_len), byref(c._struct)) @@ -655,10 +599,6 @@ def gen_real_tone(c: GNConfig) -> List[float]: def gen_complex_tone(c: GNConfig) -> List[float]: - """Generate single-tone or multi-tone complex waveform - :param c: GNConfig object - :return: single-/multi-tone complex waveform as (I and Q) lists of floats - """ awf_i = POINTER(c_double)() awf_q = POINTER(c_double)() wf_len = c_ulong(0) @@ -668,10 +608,6 @@ def gen_complex_tone(c: GNConfig) -> List[float]: def quantize(in_awf: list, c: GNConfig) -> List[int]: - """Quantize real waveform - :param c: GNConfig object - :return: Quantized floating-point waveform as list of ints - """ qwf = POINTER(c_int32)() wf_len = c_ulong(0) _gn_config_get_npts(byref(wf_len), byref(c._struct)) @@ -682,12 +618,6 @@ def quantize(in_awf: list, c: GNConfig) -> List[int]: def fftz(in_qwfi: int, in_qwfq: int, c: GNConfig) -> List[float]: - """Compute FFT - :param in_qwfi: Input quantized waveform (I) - :param in_qwfq: Input quantized waveform (Q) - :param c: GNConfig object - :return: FFT of the input waveform as list of floats - """ fft_out = POINTER(c_double)() wf_len = c_ulong(0) _gn_config_get_npts(byref(wf_len), byref(c._struct)) @@ -704,11 +634,6 @@ def fftz(in_qwfi: int, in_qwfq: int, c: GNConfig) -> List[float]: def histz(in_qwf: int, c: GNConfig) -> List[int]: - """Compute histogram - :param in_qwf: Input quantized waveform - :param c: GNConfig object - :return: Histogram of the input waveform as list of floats - """ hist_out = POINTER(c_uint64)() wf_len = c_ulong(0) _gn_config_get_npts(byref(wf_len), byref(c._struct)) @@ -720,11 +645,6 @@ def histz(in_qwf: int, c: GNConfig) -> List[int]: def get_ha_results(hist_in: int, c: GNConfig) -> dict: - """Get Fourier analysis results. - :param hist_in: Input histogram data - :param: GNConfig object - :return: Results as dict - """ cd_len = c_ulong(0) _gn_config_get_code_density_size(byref(cd_len), byref(c._struct)) uint64_array = c_uint64 * cd_len.value @@ -742,11 +662,6 @@ def get_ha_results(hist_in: int, c: GNConfig) -> dict: def get_wfa_results(in_qwf: int, c: GNConfig) -> dict: - """Get Fourier analysis results. - :param hist_in: Input histogram data - :param: GNConfig object - :return: Results as dict - """ wf_len = c_ulong(0) _gn_config_get_npts(byref(wf_len), byref(c._struct)) int32_array = c_int32 * wf_len.value @@ -764,11 +679,6 @@ def get_wfa_results(in_qwf: int, c: GNConfig) -> dict: def get_fa_single_result(metric_name: str, fft_ilv: float, c: GNConfig) -> float: - """Get Fourier analysis results. - :param fixed_tone_freq: fixed tone frequency - :param: GNConfig object - :return: Results as dict - """ fft_len = c_ulong(0) _gn_config_get_nfft(byref(fft_len), byref(c._struct)) fft_ilv_len = 2 * fft_len.value @@ -781,10 +691,16 @@ def get_fa_single_result(metric_name: str, fft_ilv: float, c: GNConfig) -> float def get_fa_results(fft_ilv: float, c: GNConfig) -> dict: - """Get Fourier analysis results. - :param fixed_tone_freq: fixed tone frequency - :param: GNConfig object - :return: Results as dict + """ + Get Fourier analysis results. + + Args: + ``fixed_tone_freq``: fixed tone frequency + + ``c``: GNConfig object + + Returns: + Results as dict """ fft_len = c_ulong(0) _gn_config_get_nfft(byref(fft_len), byref(c._struct)) @@ -804,24 +720,34 @@ def get_fa_results(fft_ilv: float, c: GNConfig) -> dict: def config_set_sample_rate(sample_rate: float, c: GNConfig) -> None: - """Set sample rate. - :param sample_rate: Sample rate in Hz - :param c: GNConfig object + """ + Set sample rate. + + Args: + ``sample_rate``: Sample rate in Hz + + ``c``: GNConfig object """ _gn_config_set_sample_rate(sample_rate, byref(c._struct)) def config_code_format(code_format: int, c: GNConfig) -> None: - """Configure code format. - :param code_format: code format (Offset binary, Twos complement) - :param c: GNConfig object + """ + Configure code format. + + Args: + ``code_format``: code format (Offset binary, Twos complement) + + ``c``: GNConfig object """ code_format = c_uint(code_format) _gn_config_set_code_format(code_format, byref(c._struct)) class WaveformGen: - """Waveform data generation for transmit devices""" + """ + Waveform data generation for transmit devices + """ _tone_phase = [0, 0, 0] # tone phase _noise = 0.0 @@ -837,21 +763,35 @@ def __init__( v_min: float, v_max: float, ): - """Constructor for WaveformGen class. - - :param npts: number of points required per waveform cycle - :param freq: output frequency required in hz - :param code_fmt: code format to get data in - 0: for binary offset - 1: for 2's complement - :param res: code resolution - :param v_ref_n: negative reference voltage - Can be zero(0) for unipolar device - :param v_ref_p: positive reference voltage - :param v_min: minimum required voltage to generate - Must be in the accepted reference voltage range - :param v_max: maximum required voltage to generate - Must be in the accepted reference voltage range + """ + Constructor for WaveformGen class. + + Args: + ``npts`` (``int``): number of points required per waveform cycle + + ``freq`` (``int``): output frequency required in hz + + ``code_fmt`` (``int``): code format to get data in + + 0: for binary offset + + 1: for 2's complement + + ``res`` (``int``): code resolution + + ``v_ref_n`` (``float``): negative reference voltage + + Can be zero(0) for unipolar device + + ``v_ref_p`` (``float``): positive reference voltage + + ``v_min`` (``float``): minimum required voltage to generate + + Must be in the accepted reference voltage range + + ``v_max`` (``float``): maximum required voltage to generate + + Must be in the accepted reference voltage range """ self._data = [] @@ -866,12 +806,19 @@ def __init__( @property def v_min(self): - """v_min: Lower required voltage limit""" + """ + Lower required voltage limit + """ return self._v_min @v_min.setter def v_min(self, value): - """v_min: Set Lower required voltage limit""" + """ + Set Lower required voltage limit + + Args: + ``value`` (``float``): Lower required voltage limit + """ if value < self._v_ref_n: raise Exception( "required lower voltage cannot be less than lower voltage reference" @@ -880,12 +827,19 @@ def v_min(self, value): @property def v_max(self): - """v_max: Upper required voltage limit""" + """ + Upper required voltage limit + """ return self._v_max @v_max.setter def v_max(self, value): - """v_max: Set Upper required voltage limit""" + """ + Set Upper required voltage limit + + Args: + ``value`` (``float``): Upper required voltage limit + """ if value > self._v_ref_p: raise Exception( "required upper voltage cannot be greater than upper voltage reference" @@ -958,43 +912,54 @@ def __del__(self): self._data = [] def gen_sine_wave(self): - """Generate sine wave data + """ + Generate sine wave data - :return: waveform as list of ints + Returns: + Waveform as list of ints """ return self.__gen_sine_cosine(1) def gen_cosine_wave(self): - """Generate cosine wave data + """ + Generate cosine wave data - :return: waveform as list of ints + Returns: + Waveform as list of ints """ return self.__gen_sine_cosine(0) def gen_triangular_wave(self): - """Generate triangular wave data + """ + Generate triangular wave data - :return: waveform as list of ints + Returns: + Waveform as list of ints """ self.__prepare_waveform_gen() self._data = signal.sawtooth(2 * np.pi * self.freq * self.__t, 0.5) return self.__gen_other_waveforms() def gen_square_wave(self): - """Generate square wave data + """ + Generate square wave data - :return: waveform as list of ints + Returns: + Waveform as list of ints """ self.__prepare_waveform_gen() self._data = signal.square(2 * np.pi * self.freq * self.__t, 0.5) return self.__gen_other_waveforms() def gen_pwm_wave(self, duty_cycle): - """Generate pwm wave data - :param duty_cycle: Duty cycle required - Must be in between 0 and 1 with a precision of unto two decimals. - e.g. 0.25 for 25% duty-cycle - :return: waveform as list of ints + """ + Generate pwm wave data + + Args: + ``duty_cycle`` (``float``): Duty cycle required. Must be in between 0 and 1. + + Returns: + Waveform as list of ints """ self.__prepare_waveform_gen() self._data = signal.square(2 * np.pi * self.freq * self.__t, duty_cycle) diff --git a/bindings/python/tests/test_genalyzer.py b/bindings/python/tests/test_genalyzer.py index f282c39..e5dca5c 100644 --- a/bindings/python/tests/test_genalyzer.py +++ b/bindings/python/tests/test_genalyzer.py @@ -37,7 +37,7 @@ def test_gen_real_tone(filename): scale_list = data["scale"] phase_list = data["phase"] - c = genalyzer.config_gen_tone( + c = genalyzer.simplified_beta.simplified_beta.config_gen_tone( data["wf_type"], data["npts"], data["fs"], @@ -46,8 +46,8 @@ def test_gen_real_tone(filename): scale_list, phase_list, ) - awf = genalyzer.gen_real_tone(c) - genalyzer.config_free(c) + awf = genalyzer.simplified_beta.simplified_beta.gen_real_tone(c) + genalyzer.simplified_beta.simplified_beta.config_free(c) assert len(awf) != 0, "the list is non empty" @@ -64,7 +64,7 @@ def test_gen_complex_tone(filename): scale_list = data["scale"] phase_list = data["phase"] - c = genalyzer.config_gen_tone( + c = genalyzer.simplified_beta.simplified_beta.config_gen_tone( data["wf_type"], data["npts"], data["fs"], @@ -73,8 +73,8 @@ def test_gen_complex_tone(filename): scale_list, phase_list, ) - awfi, awfq = genalyzer.gen_complex_tone(c) - genalyzer.config_free(c) + awfi, awfq = genalyzer.simplified_beta.simplified_beta.gen_complex_tone(c) + genalyzer.simplified_beta.simplified_beta.config_free(c) assert len(awfi) != 0, "the list is non empty" assert len(awfq) != 0, "the list is non empty" @@ -84,11 +84,11 @@ def test_quantize_real_tone(filename): with open(filename) as f: data = json.load(f) awf = data["test_vec"] - c = genalyzer.config_quantize( + c = genalyzer.simplified_beta.simplified_beta.config_quantize( data["npts"], data["fsr"], data["qres"], data["qnoise"] ) - qwf = genalyzer.quantize(awf, c) - genalyzer.config_free(c) + qwf = genalyzer.simplified_beta.simplified_beta.quantize(awf, c) + genalyzer.simplified_beta.simplified_beta.config_free(c) assert qwf != 0, "the list is non empty" @@ -98,12 +98,12 @@ def test_quantize_complex_tone(filename): data = json.load(f) awfi = data["test_vec_i"] awfq = data["test_vec_q"] - c = genalyzer.config_quantize( + c = genalyzer.simplified_beta.simplified_beta.config_quantize( data["npts"], data["fsr"], data["qres"], data["qnoise"] ) - qwfi = genalyzer.quantize(awfi, c) - qwfq = genalyzer.quantize(awfq, c) - genalyzer.config_free(c) + qwfi = genalyzer.simplified_beta.simplified_beta.quantize(awfi, c) + qwfq = genalyzer.simplified_beta.quantize(awfq, c) + genalyzer.simplified_beta.simplified_beta.config_free(c) assert qwfi != 0, "the list is non empty" assert qwfq != 0, "the list is non empty" @@ -116,11 +116,11 @@ def test_fft(filename): qwfi = [int(i) for i in qwfi] qwfq = data["test_vecq_q"] qwfq = [int(i) for i in qwfq] - c = genalyzer.config_fftz( + c = genalyzer.simplified_beta.simplified_beta.config_fftz( data["npts"], data["qres"], data["navg"], data["nfft"], data["win"] - 1 ) - out = genalyzer.fftz(qwfi, qwfq, c) - genalyzer.config_free(c) + out = genalyzer.simplified_beta.simplified_beta.fftz(qwfi, qwfq, c) + genalyzer.simplified_beta.simplified_beta.config_free(c) assert out != 0, "the list is non empty" @@ -137,15 +137,15 @@ def test_get_fa_results(filename): qwfi = [int(i) for i in qwfi] qwfq = data["test_vecq_q"] qwfq = [int(i) for i in qwfq] - c = genalyzer.config_fftz( + c = genalyzer.simplified_beta.simplified_beta.config_fftz( data["npts"], data["qres"], data["navg"], data["nfft"], data["win"] - 1 ) - fft_out_i, fft_out_q = genalyzer.fftz(qwfi, qwfq, c) + fft_out_i, fft_out_q = genalyzer.simplified_beta.simplified_beta.fftz(qwfi, qwfq, c) fft_out = [val for pair in zip(fft_out_i, fft_out_q) for val in pair] - genalyzer.config_set_sample_rate(data["fs"], c) - genalyzer.config_fa(freq_list[0], c) - fa_results = genalyzer.get_fa_results(fft_out, c) - genalyzer.config_free(c) + genalyzer.simplified_beta.simplified_beta.config_set_sample_rate(data["fs"], c) + genalyzer.simplified_beta.simplified_beta.config_fa(freq_list[0], c) + fa_results = genalyzer.simplified_beta.simplified_beta.get_fa_results(fft_out, c) + genalyzer.simplified_beta.simplified_beta.config_free(c) assert bool(fa_results), "the dict is non empty" @@ -162,15 +162,15 @@ def test_get_fa_single_result(filename): qwfi = [int(i) for i in qwfi] qwfq = data["test_vecq_q"] qwfq = [int(i) for i in qwfq] - c = genalyzer.config_fftz( + c = genalyzer.simplified_beta.config_fftz( data["npts"], data["qres"], data["navg"], data["nfft"], data["win"] - 1 ) - fft_out_i, fft_out_q = genalyzer.fftz(qwfi, qwfq, c) + fft_out_i, fft_out_q = genalyzer.simplified_beta.fftz(qwfi, qwfq, c) fft_out = [val for pair in zip(fft_out_i, fft_out_q) for val in pair] - genalyzer.config_set_sample_rate(data["fs"], c) - genalyzer.config_fa(freq_list[0], c) - sfdr = genalyzer.get_fa_single_result("sfdr", fft_out, c) - genalyzer.config_free(c) + genalyzer.simplified_beta.config_set_sample_rate(data["fs"], c) + genalyzer.simplified_beta.config_fa(freq_list[0], c) + sfdr = genalyzer.simplified_beta.get_fa_single_result("sfdr", fft_out, c) + genalyzer.simplified_beta.config_free(c) assert sfdr != 0, "the value is non zero" @@ -180,12 +180,12 @@ def test_get_ha_results(filename): data = json.load(f) qwf = data["test_vecq"] qwf = [int(i) for i in qwf] - c = genalyzer.config_quantize( + c = genalyzer.simplified_beta.config_quantize( data["npts"], data["fsr"], data["qres"], data["qnoise"] ) - hist_qwf = genalyzer.histz(qwf, c) - ha_results = genalyzer.get_ha_results(hist_qwf, c) - genalyzer.config_free(c) + hist_qwf = genalyzer.simplified_beta.histz(qwf, c) + ha_results = genalyzer.simplified_beta.get_ha_results(hist_qwf, c) + genalyzer.simplified_beta.config_free(c) assert bool(ha_results), "the dict is non empty" @@ -195,11 +195,11 @@ def test_get_wfa_results(filename): data = json.load(f) qwf = data["test_vecq"] qwf = [int(i) for i in qwf] - c = genalyzer.config_quantize( + c = genalyzer.simplified_beta.config_quantize( data["npts"], data["fsr"], data["qres"], data["qnoise"] ) - wfa_results = genalyzer.get_wfa_results(qwf, c) - genalyzer.config_free(c) + wfa_results = genalyzer.simplified_beta.get_wfa_results(qwf, c) + genalyzer.simplified_beta.config_free(c) assert bool(wfa_results), "the dict is non empty" diff --git a/doc/02_using_genalyzer.rst b/doc/02_using_genalyzer.rst deleted file mode 100644 index b4ad28e..0000000 --- a/doc/02_using_genalyzer.rst +++ /dev/null @@ -1,27 +0,0 @@ -Using Genalyzer -=============== -As mentioned previously, Genalyzer is a C++ library designed to support computation of RF performance metrics using either simulation data or data captured from a physical instrument. Bindings are provided to enable users to write C- or Python-based scripts to compute the desired performance metrics. In both cases, the overall structure of a C-example script that links to genalyzer library is similar, as shown in the next section. The overall structure in a simulation-only scenario consists of three stages: - -* Test Configuration -* Waveform Generation -* Metric Computation - -In the data-capture scenario, where the response of a data-converter is available in the form of text files, the structure would be - -* Test Configuration -* Waveform Loading -* Metric Computation - -That is, only the second step in the procedure involved would change. The overall structure of a C-example that utilizes genalyzer library in the simulation-only scenario is shown by the following example. - -.. literalinclude:: general_example_skelton1.c - :language: C - -Similarly, the overall structure of a C-example in the data-capture scenario is shown by the following example. - -.. literalinclude:: general_example_skelton2.c - :language: C - -.. include:: 02a_test_configuration.rst -.. include:: 02b_waveform_generation.rst -.. include:: 02c_perf_metric_computation.rst \ No newline at end of file diff --git a/doc/02a_test_configuration.rst b/doc/02a_test_configuration.rst deleted file mode 100644 index 0f9e5da..0000000 --- a/doc/02a_test_configuration.rst +++ /dev/null @@ -1,30 +0,0 @@ -Test Configuration ------------------- -.. As indicated in the overall skelton C-script that interfaces with genalyzer, the first stage involves configuring an opaque struct that is provided to the users in order to describe the measurement scenario. Here, users can select between three ``config_*_meas()'' function calls in order to select between tone-, ramp- and noise-based performance metric calculations. The opaque struct maintains the state of the test scenario and is passed to the waveform generation and performance metric computation stages subsequently. - -Tone-based Test Configuration -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -In tone-based test configuration, ``config_tone_meas()`` allows users to indicate test settings such as, number of tones, their frequencies, phases, scales, whether real sinusoidal or complex-exponential waveforms are to be generated, the sample-rate, full-scale range of the converter, its resolution etc. Similarly, users can indicate whether the data that will be loaded in the second stage is time-series data or interleaved FFT samples. Moreover, in data-capture scenario i.e., when FFT data is provided to Genalyzer in the second step, the tone frequency, scale and phase information is not required. This test configuration is used for measurements such as SFDR, THD, TIL etc. - -An example of the ``config_tone_meas()`` function call is shown by the following example. - -.. literalinclude:: general_example_tone_configuration.c - :language: C - -Ramp-based Test Configuration -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -In ramp-based test configuration, ``config_ramp_meas()`` allows users to indicate test settings such as, the starting and ending values of the ramp waveform in addition to the full-scale range and the resolution of the data converter under test. This test configuration is primarily used in non-linearity based measurements. - -An example of the ``config_ramp_meas()`` function call is shown by the following example. - -.. literalinclude:: general_example_ramp_configuration.c - :language: C - -Noise-based Test Configuration -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -In noise-based test configuration, ``config_noise_meas()`` allows users to indicate test settings such as, the noise power level in addition to the full-scale range and the resolution of the data converter under test. This test configuration is primarily used for computing noise spectral density. - -An example of the ``config_noise_meas()`` function call is shown by the following example. - -.. literalinclude:: general_example_noise_configuration.c - :language: C \ No newline at end of file diff --git a/doc/02b_waveform_generation.rst b/doc/02b_waveform_generation.rst deleted file mode 100644 index 1d0b8b3..0000000 --- a/doc/02b_waveform_generation.rst +++ /dev/null @@ -1,14 +0,0 @@ -Waveform Generation -------------------- -The second step, as shown previously, involves either generating the waveform and quantizing it or loading the waveform from a file. The following options are currently supported. - -- cosine/sine and complex exponential waveforms of arbitrary frequency and sample rate -- ramp waveform -- Gaussian noise waveform of desired noise power spectral density level - -In all three cases, the waveform generation functions take two arguments, the opaque configuration struct that has been populated in the first step and a double pointer that will contain the analog waveform generated. The subsequent call to quantize() takes the configuration struct, the analog input waveform and the output quantized waveform obtained from quantizeing the analog waveform based on the resolution contained in the configuration struct. - -Alternatively, if data is loaded from a file, the configuration struct generated in the first stage will serve as a descriptor of that data. Note that indicating whether time or frequency data is loaded is indicated simply by an argument to the ``config_tone_meas()`` call in the first step. - -.. literalinclude:: general_example_skelton3.c - :language: C diff --git a/doc/02c_perf_metric_computation.rst b/doc/02c_perf_metric_computation.rst deleted file mode 100644 index 3fa1db3..0000000 --- a/doc/02c_perf_metric_computation.rst +++ /dev/null @@ -1,17 +0,0 @@ -Performance Metric Computation ------------------------------- -The final stage involves simply computing the desired performance metric. Metric computation is done by a call to ``metric()`` where, the last argument is one of: - -.. hlist:: - :columns: 5 - - * ``"FSNR"`` - * ``"NSD"`` - * ``"SFDR"`` - * ``"SINAD"`` - * ``"SNR"`` - * ``"TD"`` - * ``"THD"`` - * ``"TIL`` - -Again, the test configuration contained in the opaque struct obtained from the first step is helpful in determinging whether the \ No newline at end of file diff --git a/doc/03_examples.rst b/doc/03_examples.rst deleted file mode 100644 index 3c7d574..0000000 --- a/doc/03_examples.rst +++ /dev/null @@ -1,11 +0,0 @@ -Examples -======== -A complete working example to generate and compute a tone-based data-converter performance metric is shown below. - -.. literalinclude:: working_example_tone_sim.c - :language: C - -Similarly, a complete working example that utilizes recorded waveforms from a data-converter to characterize its performance is shown by the following example. - -.. literalinclude:: working_example_tone_instr.c - :language: C \ No newline at end of file diff --git a/doc/conf.py b/doc/conf.py index 9b0e248..417fd78 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -35,7 +35,10 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ["breathe", "sphinx.ext.autodoc", "myst_parser", "sphinx_inline_tabs", "sphinx.ext.graphviz"] +extensions = ["breathe", "sphinx.ext.autodoc", "myst_parser", "sphinx_inline_tabs", "sphinx.ext.graphviz", "sphinxcontrib.mermaid", "sphinx_togglebutton"] + +# Fix use of autogenerated cross-reference warning +myst_heading_anchors = 2 # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] diff --git a/doc/examples.md b/doc/examples.md deleted file mode 100644 index 8ff4cb1..0000000 --- a/doc/examples.md +++ /dev/null @@ -1,326 +0,0 @@ -# Language Examples - -## Fourier Analysis - -In the following working example, data from an ADALM-PLUTO is used to perform a Fourier analysis as shown below. Note that in the following example, it is assumed that the data is available in the form of a json file. It can be replaced by any other means of loading this data. - -````{tab} C -```C -#include "cgenalyzer.h" -#include "../tests/test_genalyzer.h" -#include - -int main(int argc, const char* argv[]) -{ - // read test waveform filename - const char* test_filename = "../tests/test_vectors/test_Pluto_DDS_data_1658159639196.json"; - - int err_code; - int32_t *ref_qwfi, *ref_qwfq; - double *fft_out; - size_t results_size; - char **rkeys; - double *rvalues, sfdr; - - // read parameters - tone_type ttype; - int qres; - unsigned long long npts, navg, nfft, tmp_win, num_tones; - double *freq; - GnWindow win; - err_code = read_scalar_from_json_file(test_filename, "wf_type", (void*)(&ttype), UINT64); - err_code = read_scalar_from_json_file(test_filename, "qres", (void*)(&qres), INT32); - err_code = read_scalar_from_json_file(test_filename, "npts", (void*)(&npts), UINT64); - err_code = read_scalar_from_json_file(test_filename, "navg", (void*)(&navg), UINT64); - err_code = read_scalar_from_json_file(test_filename, "nfft", (void*)(&nfft), UINT64); - err_code = read_scalar_from_json_file(test_filename, "num_tones", (void*)(&num_tones), UINT64); - freq = (double*)calloc(num_tones, sizeof(double)); - if (num_tones > 1) - err_code = read_array_from_json_file(test_filename, "freq", freq, DOUBLE, num_tones); - else - err_code = read_scalar_from_json_file(test_filename, "freq", (void*)(freq), DOUBLE); - err_code = read_scalar_from_json_file(test_filename, "win", (void*)(&tmp_win), UINT64); - if (tmp_win==1) - win = GnWindowBlackmanHarris; - else if (tmp_win==2) - win = GnWindowHann; - else if (tmp_win==3) - win = GnWindowNoWindow; - - // read reference waveforms - ref_qwfi = (int32_t*)malloc(npts*sizeof(int32_t)); - err_code = read_array_from_json_file(test_filename, "test_vec_i", ref_qwfi, INT32, npts); - ref_qwfq = (int32_t*)malloc(npts*sizeof(int32_t)); - err_code = read_array_from_json_file(test_filename, "test_vec_q", ref_qwfq, INT32, npts); - - // configuration - gn_config c = NULL; - err_code = gn_config_fftz(npts, qres, navg, nfft, win, &c); - - // FFT of waveform - err_code = gn_fftz(&fft_out, ref_qwfi, ref_qwfq, &c); - - // Configure Fourier analysis - err_code = gn_config_fa(freq[0], &c); - err_code = gn_get_fa_results(&rkeys, &rvalues, &results_size, fft_out, &c); - - printf("\nAll Fourier Analysis Results:\n"); - for (size_t i = 0; i < results_size; i++) - printf("%4zu%20s%20.6f\n", i, rkeys[i], rvalues[i]); - - err_code = gn_get_fa_single_result(&sfdr, "sfdr", fft_out, &c); - printf("SFDR - %20.6f\n", sfdr); - - // free memory - free(ref_qwfi); - free(ref_qwfq); - free(fft_out); - free(rvalues); - for (size_t i = 0; i < results_size; ++i) - free(rkeys[i]); - free(rkeys); - gn_config_free(&c); - - return 0; -} -``` -```` -````{tab} Python -```python -import genalyzer, os, json, glob, pprint -import matplotlib.pyplot as plt - -test_dir = os.path.join(*["..", "..", "..", "tests", "test_vectors"]) -loc = os.path.dirname(__file__) - -f = glob.glob(os.path.join(loc, test_dir, "test_Pluto_DDS_data_1658159639196.json")) -a = open(f[0]) -data = json.load(a) -if data['num_tones'] == 1: - freq_list = [data['freq']] -else: - freq_list = data['freq'] - -qwfi = data['test_vec_i'] -qwfi = [int(i) for i in qwfi] -qwfq = data['test_vec_q'] -qwfq = [int(i) for i in qwfq] - -# configure -c = genalyzer.config_fftz(data['npts'], data['qres'], data['navg'], data['nfft'], data['win']-1) -genalyzer.config_fa(freq_list[0], c) - -# compute FFT -fft_out_i, fft_out_q = genalyzer.fftz(qwfi, qwfq, c) -fft_out = [val for pair in zip(fft_out_i, fft_out_q) for val in pair] - -# get all Fourier analysis results -all_results = genalyzer.get_fa_results(fft_out, c) - -# get a single Fourier analysis result -sfdr = genalyzer.get_fa_single_result("sfdr", fft_out, c) - -# display results -pprint.pprint(all_results) -print('SFDR - ', sfdr) - -# free memory -genalyzer.config_free(c) -``` -```` - -A summary of the most important results displayed and a brief explanation is as follows: - -| Result Name | Description| -|:-----------:|:-----------:| -| fsnr| Full-scale Signal-to-Noise Ratio | -| snr| Signal-to-Noise Ratio | -| sinad| Signal-to-Noise and Distortion Ratio | -| sfdr| Spurious Free Dynamic Range | -| abn| Analysis Band Noise Power | -| nsd| Noise Spectral Density | -| carrierindex| Index of carrier tone | -| maxspurindex| Index of max. spur tone | -| ab_nbins| # of bins in analysis band | -| ab_rss| Analysis band received signal strength | -| hd_nbins| # of bins in used in computing harmonic distortion | -| hd_rss| Harmonic distortion band received signal strength | -| imd_nbins| # of bins in used in computing inter-modulation distortion | -| imd_rss| Inter-modulation distortion band received signal strength | -| thd_nbins| # of bins in used in computing total harmonic distortion | -| thd_rss| Total harmonic distortion band received signal strength | - -Waveform Analysis ------------------ -In the following working example, genalyzer is used to generate a cosine-tone waveform, then the effect of a data-converter on this waveform is simulated and a basic waveform analysis is performed as shown below. - -````{tab} C -```C -#include "cgenalyzer.h" -#include - -int main(int argc, const char* argv[]) -{ - // parameters - tone_type ttype = REAL_COSINE; - double fsr = 3.0, qnoise = pow(10.0, -60.0 / 20.0); - int qres = 12; - double fs = 5000000.0; - unsigned long long npts = 8192, num_tones = 1; - double freq[] = {50000.0}, scale[] = {0.5}, phase[] = {0.2}; - - // waveforms - double *awf; - int32_t *qwf; - - // results - size_t results_size; - char **rkeys; - double *rvalues; - - // configuration - int err_code; - gn_config c = NULL; - err_code = gn_config_gen_tone(ttype, npts, fs, num_tones, freq, scale, phase, &c); - err_code = gn_config_quantize(npts, fsr, qres, qnoise, &c); - - // generate waveform - err_code = gn_gen_real_tone(&awf, &c); - - // quantize waveform - err_code = gn_quantize(&qwf, awf, &c); - - // do waveform analysis - err_code = gn_get_wfa_results(&rkeys, &rvalues, &results_size, qwf, &c); - - // print results - printf("All Waveform Analysis Results:\n"); - for (size_t i = 0; i < results_size; i++) - printf("%4zu%20s%20.6f\n", i, rkeys[i], rvalues[i]); - - // free memory - free(qwf); - free(awf); - for (size_t i = 0; i < results_size; i++) - free(rkeys[i]); - free(rkeys); - gn_config_free(&c); - - return 0; -} -```` -````{tab} Python -```python -import genalyzer, pprint - -c = genalyzer.config_gen_tone(0, 8192, 5000000.0, 1, [50000.0], [0.5], [0.2]) -genalyzer.config_quantize(8192, 3.0, 12, pow(10.0, -60.0 / 20.0), c) - -awf = genalyzer.gen_real_tone(c) -qwf = genalyzer.quantize(awf, c) -wfa_results = genalyzer.get_wfa_results(qwf, c) -pprint.pprint(wfa_results) -genalyzer.config_free(c) -``` -```` - -A summary of the results displayed and a brief explanation is as follows: - -| Result Name | Description| Notes -|:-----------:|:-----------:|:-----------:| -| min| Min. value | -| max| Max. value | -| mid| Mid value | -| range| Numerical range | max-min| -| avg| Mean value | | -| rms| RMS value | | -| rmsac| RMS (AC) | Evaluated as rms2-avg2| -| min_index| Index of min. value | | -| max_index| Index of max. value | | - -Histogram Analysis ------------------- -In the following working example, genalyzer is used to generate a ramp waveform, then the effect of a data-converter on this waveform is simulated and a basic histogram analysis is performed as shown below. - -````{tab} C -```C -#include "cgenalyzer.h" -#include -#include - -int main(int argc, const char* argv[]) -{ - // parameters - double fsr = 3.0, qnoise = pow(10.0, -60.0 / 20.0); - int qres = 12; - unsigned long long npts = 8192, ramp_start = 0, ramp_stop = 2; - - // waveforms - double *awf; - int32_t *qwf; - - // results - uint64_t *hist; - size_t results_size, hist_len; - char **rkeys; - double *rvalues; - - // configuration - int err_code; - gn_config c = NULL; - err_code = gn_config_gen_ramp(npts, ramp_start, ramp_stop, &c); - err_code = gn_config_quantize(npts, fsr, qres, qnoise, &c); - - // generate waveform - err_code = gn_gen_ramp(&awf, &c); - - // quantize waveform - err_code = gn_quantize(&qwf, awf, &c); - - // compute histogram - err_code = gn_histz(&hist, &hist_len, qwf, &c); - - // do waveform analysis - err_code = gn_get_ha_results(&rkeys, &rvalues, &results_size, hist, &c); - - // print results - printf("All Waveform Analysis Results:\n"); - for (size_t i = 0; i < results_size; i++) - printf("%4zu%20s%20.6f\n", i, rkeys[i], rvalues[i]); - - // free memory - free(qwf); - free(awf); - for (size_t i = 0; i < results_size; i++) - free(rkeys[i]); - free(rkeys); - gn_config_free(&c); - - return 0; -} -``` -```` -````{tab} Python -```python -import genalyzer, pprint - -c = genalyzer.config_gen_ramp(8192, 0, 2) -genalyzer.config_quantize(8192, 3.0, 12, pow(10.0, -60.0 / 20.0), c) - -awf = genalyzer.gen_ramp(c) -qwf = genalyzer.quantize(awf, c) -hist = genalyzer.histz(qwf, c) -ha_results = genalyzer.get_ha_results(hist, c) -pprint.pprint(ha_results) -genalyzer.config_free(c) -``` -```` - -A summary of the results displayed and a brief explanation is as follows: - -| Result Name | Description| -|:-----------:|:-----------:| -| sum| Sum of histogram hits | -| first_nz_index| First non-zero bin index | -| last_nz_index| Last non-zero bin index | -| nz_range| Non-zero bin range| \ No newline at end of file diff --git a/doc/figures/complex_sinusoidal_waveform.png b/doc/figures/complex_sinusoidal_waveform.png new file mode 100644 index 0000000..00eb21d Binary files /dev/null and b/doc/figures/complex_sinusoidal_waveform.png differ diff --git a/doc/figures/fft.png b/doc/figures/fft.png new file mode 100644 index 0000000..bad3b5d Binary files /dev/null and b/doc/figures/fft.png differ diff --git a/doc/figures/spectral_analysis_summary.png b/doc/figures/spectral_analysis_summary.png new file mode 100644 index 0000000..d44a532 Binary files /dev/null and b/doc/figures/spectral_analysis_summary.png differ diff --git a/doc/gen_api_page.py b/doc/gen_api_page.py index b4fcac3..01147be 100644 --- a/doc/gen_api_page.py +++ b/doc/gen_api_page.py @@ -3,7 +3,7 @@ def gen_pages(): header = os.path.join( - os.path.dirname(__file__), "..", "bindings", "c", "include", "cgenalyzer.h" + os.path.dirname(__file__), "..", "bindings", "c", "include", "cgenalyzer_simplified_beta.h" ) if not os.path.exists(header): @@ -64,8 +64,8 @@ def gen_pages(): # Generate md file for breathe page = "\n\n" - page += "# API Reference\n\n" - page += "This page contains the API reference for the Genalyzer library.\n\n" + page += "# (Beta) Simplified API Reference\n\n" + page += "This page contains the (beta) simplified API reference for the Genalyzer library.\n\n" # Table of contents @@ -76,7 +76,7 @@ def gen_pages(): page += "- [Generate Functions](#generate-functions)\n" page += "- [Operation Functions](#operation-functions)\n\n" - page += "## Structs\n\n" + #page += "## Structs\n\n" def gen_functions(functions): @@ -107,7 +107,7 @@ def gen_functions(functions): page += "## Operation Functions\n\n" page += gen_functions(operation_functions) - with open("reference.md", "w") as f: + with open("reference_simplified.md", "w") as f: f.write(page) print("API page generated") diff --git a/doc/index.rst b/doc/index.rst index 6c59127..bb03c53 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -20,16 +20,12 @@ Reference :maxdepth: 2 :caption: Contents: - .. c/configs - 01_introduction + introduction setup - theory - sim - examples.md - .. 02_using_genalyzer - 03_examples + spectral_analysis reference - reference_advanced + reference_simplified + python/genalyzer diff --git a/doc/01_introduction.rst b/doc/introduction.rst similarity index 100% rename from doc/01_introduction.rst rename to doc/introduction.rst diff --git a/doc/python/enumerations.rst b/doc/python/enumerations.rst new file mode 100644 index 0000000..b2c9411 --- /dev/null +++ b/doc/python/enumerations.rst @@ -0,0 +1,20 @@ +Enumerations +------------ + +.. autofunction:: genalyzer.CodeFormat + +.. autofunction:: genalyzer.DnlSignal + +.. autofunction:: genalyzer.FaCompTag + +.. autofunction:: genalyzer.FaSsb + +.. autofunction:: genalyzer.FreqAxisFormat + +.. autofunction:: genalyzer.FreqAxisType + +.. autofunction:: genalyzer.InlLineFit + +.. autofunction:: genalyzer.RfftScale + +.. autofunction:: genalyzer.Window diff --git a/doc/python/fourier_analysis.rst b/doc/python/fourier_analysis.rst new file mode 100644 index 0000000..685c321 --- /dev/null +++ b/doc/python/fourier_analysis.rst @@ -0,0 +1,4 @@ +Fourier Analysis +---------------- + +.. autofunction:: genalyzer.fft_analysis \ No newline at end of file diff --git a/doc/python/fourier_configuration.rst b/doc/python/fourier_configuration.rst new file mode 100644 index 0000000..d1db919 --- /dev/null +++ b/doc/python/fourier_configuration.rst @@ -0,0 +1,52 @@ +Fourier Analysis Configuration +------------------------------ + +.. autofunction:: genalyzer.fa_analysis_band + +.. autofunction:: genalyzer.fa_clk + +.. autofunction:: genalyzer.fa_conv_offset + +.. autofunction:: genalyzer.fa_create + +.. autofunction:: genalyzer.fa_dc + +.. autofunction:: genalyzer.fa_fdata + +.. autofunction:: genalyzer.fa_fixed_tone + +.. autofunction:: genalyzer.fa_fsample + +.. autofunction:: genalyzer.fa_fshift + +.. autofunction:: genalyzer.fa_fund_images + +.. autofunction:: genalyzer.fa_hd + +.. autofunction:: genalyzer.fa_ilv + +.. autofunction:: genalyzer.fa_imd + +.. autofunction:: genalyzer.fa_load + +.. autofunction:: genalyzer.fa_max_tone + +.. autofunction:: genalyzer.fa_preview + +.. autofunction:: genalyzer.fa_quad_errors + +.. autofunction:: genalyzer.fa_remove_comp + +.. autofunction:: genalyzer.fa_reset + +.. autofunction:: genalyzer.fa_ssb + +.. autofunction:: genalyzer.fa_ssb_dc + +.. autofunction:: genalyzer.fa_ssb_def + +.. autofunction:: genalyzer.fa_ssb_wo + +.. autofunction:: genalyzer.fa_var + +.. autofunction:: genalyzer.fa_wo \ No newline at end of file diff --git a/doc/python/fourier_transforms.rst b/doc/python/fourier_transforms.rst new file mode 100644 index 0000000..380ff03 --- /dev/null +++ b/doc/python/fourier_transforms.rst @@ -0,0 +1,6 @@ +Fourier Transforms +------------------ + +.. autofunction:: genalyzer.fft + +.. autofunction:: genalyzer.rfft \ No newline at end of file diff --git a/doc/python/genalyzer.rst b/doc/python/genalyzer.rst new file mode 100644 index 0000000..4c5540f --- /dev/null +++ b/doc/python/genalyzer.rst @@ -0,0 +1,12 @@ +Python Bindings +=============== + +Component APIs +-------------- + +.. toctree:: + :maxdepth: 4 + + pygenalyzer + pygenalyzer.simplified + diff --git a/doc/python/pygenalyzer.rst b/doc/python/pygenalyzer.rst new file mode 100644 index 0000000..75c81e2 --- /dev/null +++ b/doc/python/pygenalyzer.rst @@ -0,0 +1,13 @@ +pygenalizer +=========== + +.. toctree:: + :maxdepth: 2 + :caption: Table of Contents + + enumerations + fourier_analysis + fourier_configuration + fourier_transforms + waveforms + signal_processing \ No newline at end of file diff --git a/doc/python/pygenalyzer.simplified.rst b/doc/python/pygenalyzer.simplified.rst new file mode 100644 index 0000000..91e43fb --- /dev/null +++ b/doc/python/pygenalyzer.simplified.rst @@ -0,0 +1,7 @@ +pygenalizer.simplified (Beta) +============================= + +.. automodule:: genalyzer.simplified_beta.simplified_beta + :members: + :undoc-members: + :show-inheritance: \ No newline at end of file diff --git a/doc/python/signal_processing.rst b/doc/python/signal_processing.rst new file mode 100644 index 0000000..159a94c --- /dev/null +++ b/doc/python/signal_processing.rst @@ -0,0 +1,18 @@ +Signal Processing +----------------- + +.. autofunction:: genalyzer.downsample + +.. autofunction:: genalyzer.fshift + +.. autofunction:: genalyzer.normalize + +.. autofunction:: genalyzer.polyval + +.. autofunction:: genalyzer.quantize16 + +.. autofunction:: genalyzer.quantize32 + +.. autofunction:: genalyzer.quantize64 + +.. autofunction:: genalyzer.quantize diff --git a/doc/python/waveforms.rst b/doc/python/waveforms.rst new file mode 100644 index 0000000..29aa3c7 --- /dev/null +++ b/doc/python/waveforms.rst @@ -0,0 +1,12 @@ +Waveforms +--------- + +.. autofunction:: genalyzer.cos + +.. autofunction:: genalyzer.gaussian + +.. autofunction:: genalyzer.ramp + +.. autofunction:: genalyzer.sin + +.. autofunction:: genalyzer.wf_analysis diff --git a/doc/reference_advanced.md b/doc/reference.md similarity index 99% rename from doc/reference_advanced.md rename to doc/reference.md index 1cbc00b..6806c23 100644 --- a/doc/reference_advanced.md +++ b/doc/reference.md @@ -12,6 +12,7 @@ Advanced API Reference for Genalyzer library. This API is meant for advanced use ```{eval-rst} .. doxygengroup:: Enumerations + :no-link: ``` ## API Utilities diff --git a/doc/sim.md b/doc/sim.md deleted file mode 100644 index bd1c7c2..0000000 --- a/doc/sim.md +++ /dev/null @@ -1,202 +0,0 @@ - -# Simulation Based Testing - -A number of tests that genalyzer supports assume that the waveform that is analyzed contain one tone or two tones. genalyzer does not support analysis of generic waveforms, which can be decomposed into multiple tone frequencies. In this section, a demonstration of single-tone based measurements supported by genalyzer are described. MATLAB and Python bindings are used to describe the results using the computed FFT and its analysis. First a brief overview of configuring ADALM-PLUTO is shown. For more details, see [this](https://analogdevicesinc.github.io/TransceiverToolbox/mkdocs/streaming/) page on streaming samples from a supported device using ADI Transceiver Toolbox for MATLAB and [this](https://analogdevicesinc.github.io/pyadi-iio/buffers/index.html#buffer-examples) page for the corresponding details when using PyADI-IIO. - -

Configuring ADALM-PLUTO for Tone-Based Measurement in RF Loopback

- -An ADALM-PLUTO is connected in RF loopback and is configured to transmit a 2 MHz complex tone, with the sample rate set to 15.36 MSPS. -

MATLAB

- -The MATLAB and Python code snippets are shown below. - - -````{tab} MATLAB - -```matlab -%% Tx set up -tx = adi.Pluto.Tx; -tx.uri = 'ip:pluto'; -tx.DataSource = 'DDS'; -tx.DDSFrequencies = [2e6 2e6; 0 0]; % set DDS complex tone freq to 2 MHz -tx.DDSPhases = [90e3 0; 0 0]; % expressed in millidegrees -tx.DDSScales = [1 1; 0 0]; -tx.CenterFrequency = 2.4e9; -tx.EnableCustomFilter = true; -tx.CustomFilterFileName = 'LTE10_MHz.ftr'; % sets PlutoSDR sample-rate to 15.36 MSPS -tx.AttenuationChannel0 = -10; -tx(); -pause(1); - -%% Rx set up -rx = adi.Pluto.Rx('uri','ip:pluto'); -rx.CenterFrequency = tx.CenterFrequency; -rx.EnableCustomFilter = true; -rx.CustomFilterFileName = 'LTE10_MHz.ftr'; -rx.GainControlModeChannel0 = 'fast_attack'; -y = rx(); -y_re = real(y); -y_im = imag(y); - -tx.release(); -rx.release(); -``` -```` - -````{tab} Python - -```python -# Create radio -sdr = adi.Pluto() - -# Configure properties -sdr.rx_lo = 2400000000 -sdr.tx_lo = 2400000000 -sdr.tx_cyclic_buffer = True -sdr.tx_hardwaregain_chan0 = -10 -sdr.gain_control_mode_chan0 = "fast_attack" -sdr.filter = "LTE10_MHz.ftr" - -fs = int(sdr.sample_rate) -tone_freq_hz = 2000000 # In Hz -tone_scale = 1.0 # Range: 0-1.0 -tx_channel = 0 # Starts at 0 -sdr.dds_single_tone(tone_freq_hz, tone_scale, tx_channel) - -# Collect data -x = sdr.rx() -``` - -```` - -

Using genalyzer and ADALM-PLUTO to Compute Tone-Based Measurements for ADALM-PLUTO in RF Loopback

-In this section, an example on how to use genalyzer for calculating Spurious free dynamic range (SFDR) is provided. Doc in progress. - - - -Spurious free dynamic range (SFDR) specifies the capability of the ADC and the system to decipher a carrier signal from other noise or any other spurious frequency. It represents the smallest power signal that can be distinguished from a large interfering signal. Mathematically, it is the ratio between the root mean square (rms) value of the power of a carrier and the rms value of the next most significant spurious signal seen in the frequency domain, such as in a fast Fourier transform (FFT). Hence, by definition, this dynamic range must be free of other spurious frequencies, or spurs. - -SFDR is quantified as the range, in units of power (dBc), relative from the carrier of interest to the power of the next most significant frequency. However, it also could be referenced to a full-scale signal in units of power (dBFS). This is an important distinction since the carrier of interest may be a relatively lower power signal that is well below the full-scale input to the ADC. When this is the case, the SFDR becomes paramount in distinguishing the signal from other noise and spurious frequencies. - -A harmonic frequency is an integer multiple of the fundamental frequency. Hence, the SFDR typically will be dominated by the dynamic range between a carrier frequency and the second or third harmonic of the fundamental frequency of interest. - -In this example, these ideas are demonstrated by using MATLAB's `calllib` interface to genalyzer. A link to the complete MATLAB script is shown at the bottom of this page. - -The first step is to create an opaque configuration struct. Using MATLAB and Python bindings, this is done as shown by the code snippet below. -````{tab} MATLAB - -```matlab -% measurement settings -domain = 0; % 0 - TIME; 1 - FREQ -type = 2; -nfft = length(y); -navg = 1; -fs = 15.36e6; -fsr = 0; -res = 12; -window = 1; % 0 - BlackmanHarris, 1 - Hann, 2 - Rect - -% setup measurement for time-domain measurement -c = libpointer; % create a null pointer -calllib('libgenalyzer', 'gn_config_tone_meas', ... - c, domain, type, nfft, navg, fs, fsr, res, window, false, false, false); -``` -```` - -````{tab} Python -```python -# setup measurement -inputs = dict() -inputs["domain_wf"] = 0 -inputs["type_wf"] = 2 -inputs["nfft"] = len(x) -inputs["navg"] = 1 -inputs["fs"] = fs -inputs["fsr"] = 0 -inputs["res"] = 12 -inputs["win"] = 1 -inputs["freq"] = [0] -inputs["phase"] = [0] -inputs["scale"] = [0] -config_obj = genalyzer.gn_params(**inputs) -c = genalyzer.config_tone_meas(config_obj) -``` -```` - -Now, the configuration struct contains the measurement settings in order to calculate the desired metric. SFDR calculation is done as shown in the following code snippets. -````{tab} MATLAB -```matlab -% calculating SFDR using the time-domain waveform -err_code = libpointer('uint32Ptr',0); -fft_len = libpointer('uint64Ptr',0); -metric = char('SFDR'); -fft_time_re = libpointer('doublePtrPtr', zeros(nfft, 1)); -fft_time_im = libpointer('doublePtrPtr', zeros(nfft, 1)); -y_interleaved = [y_re'; y_im']; -y_interleaved = y_interleaved(:); -y_interleavedPtr = libpointer('int32Ptr', y_interleaved); -sfdr_time = calllib('libgenalyzer', 'gn_metric', c, y_interleavedPtr, metric, fft_time_re, fft_time_im, fft_len, err_code); -``` -```` - -````{tab} Python -```python -# compute SFDR -result, fft_i, fft_q, err_code = genalyzer.metric_t(c, x_intrlv, "SFDR") -``` -```` - -Note that the FFT calculated for analysis and computing the desired metric is returned by genalyzer. Plotting the FFT computed using genalyzer, we can see that the second harmonic at 4 MHz and its image dominate the remaining spurs. Note that the third harmonic and its image are filtered out by the programmable filter coefficients loaded into ADALM-PLUTO. -
- ![ADALM-PLUTO FFT](assets/PlutoSDR_FFT.svg){ width="900" } -
- -Since SFDR is by definition, free of spurious frequencies, by examining the above plot, one can estimate SFDR to be around 50 dBc. This values agrees with the SFDR computed by genalyzer. -``` py -SFDR (time) - 49.742253 -``` - -Note that genalyzer can be configured to compute performance metrics from frequency-domain data as well. In other words, genalyzer can be configured to skip the FFT computation step and only perform analysis of the FFT provided as input. Note that passing a `1` instead of a `0` to the `domain` argument controls this configuration. This is shown by the MATLAB code snippet below. The same can be accomplished using Python bindings as well. - -````{tab} MATLAB -```matlab -% setup measurement for freq-domain measurement -c = libpointer; -domain = 1; % 0 - TIME; 1 - FREQ -calllib('libgenalyzer', 'gn_config_tone_meas', ... - c, domain, type, nfft, navg, fs, fsr, res, window, false, false, false); - -% calculating SFDR using the FFT calculated from time-domain waveform -err_code = libpointer('uint32Ptr',0); -fft_len = libpointer('uint64Ptr',0); -fft_y = fft(hann(length(y)).*y); -ffty_interleaved = [real(fft_y)'; imag(fft_y).']; -ffty_interleaved = ffty_interleaved(:); -ffty_interleavedPtr = libpointer('doublePtr', ffty_interleaved); -fft_freq_re = libpointer('doublePtrPtr', zeros(nfft, 1)); -fft_freq_im = libpointer('doublePtrPtr', zeros(nfft, 1)); -sfdr_freq = calllib('libgenalyzer', 'gn_metric', c, ffty_interleavedPtr, metric, fft_freq_re, fft_freq_im, fft_len, err_code); -``` -```` - -````{tab} Python -```python -# update domain -inputs["domain_wf"] = 1 -config_obj = genalyzer.gn_params(**inputs) -c = genalyzer.config_tone_meas(config_obj) -# compute SFDR -result, fft_i, fft_q, err_code = genalyzer.metric_t(c, x_intrlv, "SFDR") -``` -```` - -The calculated SFDR matches the corresponding result obtained using time-domain waveform closely. -``` -SFDR (freq) - 49.742421 -``` - -Similarly, Signal-to-Noise-and-Distortion (SINAD, or S/(N + D) is the ratio of the rms signal amplitude to the mean value of the root-sum-square (RSS) of all other spectral components, including harmonics, but excluding DC. SINAD is a therefore, an indicator of the overall dynamic performance of an ADC because it includes all components which make up noise and distortion. To compute SINAD, only the - - - - \ No newline at end of file diff --git a/doc/spectral_analysis.md b/doc/spectral_analysis.md new file mode 100644 index 0000000..53673b9 --- /dev/null +++ b/doc/spectral_analysis.md @@ -0,0 +1,537 @@ +# Spectral Analysis +In this tutorial, we will use Genalyzer to conduct spectral analysis of a waveform. The waveform we analyze will be a ``300 KHz`` complex sinusoidal tone sampled at ``3 MSPS``. The only impairment in this waveform will be quantization noise. At the end of this tutorial, the reader will have gained an understanding on how to utilize Genalyzer to compute various RF performance metrics such as SFDR, FSNR, SNR, NSD etc. + +The workflow we follow in this tutorial is generally what is to be followed to use Genalyzer for spectral analysis. It consists of three stages shown in the diagram below. + +```{eval-rst} +.. mermaid:: + + graph LR; + A[Generate/Import Waveform] --> B[Compute FFT]; + B -->C1[Configure Spectral Analysis]; + + subgraph SA[Spectral Analysis] + C1[Configure] -->C2[Run]; + end + + style SA fill:#ffffff +``` + +We first generate (or import) a waveform to be analyzed, compute its FFT, and finally, calculate various performance metrics by running spectral analysis. In this tutorial, we will generate the tone waveform using Genalyzer. In another example, we will import a tone waveform captured using ADALM-PLUTO to perform spectral analysis. Please refer to the [spectral-analysis example](https://github.com/analogdevicesinc/genalyzer/blob/main/bindings/python/examples/gn_doc_spectral_analysis1.py) Python script to follow the discussion on this page. + +## Tone Generation +```{eval-rst} +.. mermaid:: + + graph LR; + A[Generate/Import Waveform] --> B[Compute FFT]; + B -->C1[Configure Spectral Analysis]; + + subgraph SA[Spectral Analysis] + C1[Configure] -->C2[Run]; + end + + style SA fill:#ffffff + + style A fill:#9fa4fc +``` +Genalyzer supports [sine](#genalyzer.sin), [cosine](#genalyzer.cos), [ramp](#genalyzer.ramp), and [Gaussian](#genalyzer.gaussian) random waveforms. It also contains a [waveform analysis](#genalyzer.wf_analysis) utility to summarize a waveform, generated or otherwise. For example, in the [spectral-analysis example](https://github.com/analogdevicesinc/genalyzer/blob/main/bindings/python/examples/gn_doc_spectral_analysis1.py) Python script, to generate a cosine-waveform, we called [``cos()``](#genalyzer.cos) as follows: +```{code-block} python +# signal configuration +npts = 30000 # number of points in the signal +fs = 3e6 # sample-rate of the data +freq = 300000 # tone frequency +phase = 0.0 # tone phase +ampl_dbfs = -1.0 # amplitude of the tone in dBFS +ampl = (fsr / 2) * 10 ** (ampl_dbfs / 20) # amplitude of the tone in linear scale + +# generate signal for analysis +wf = gn.cos(npts, fs, ampl, freq, phase) +``` +Note that we also used [``quantize()``](#genalyzer.quantize) to convert a floating-point waveform to fixed-point. Its usage is as follows: +```{code-block} python +# quantization settings +fsr = 2.0 # full-scale range of I/Q components of the complex tone +qres = 12 # data resolution +qnoise = 10 ** (qnoise_dbfs / 20) # quantizer noise in linear scale +code_fmt = gn.CodeFormat.TWOS_COMPLEMENT # integer data format + +# quantize signal +qwf = gn.quantize(wf, fsr, qres, qnoise, code_fmt) +``` +A time-domain plot of the complex-sinusoidal tone for which we compute FFT in the next step is shown below for reference. + +```{figure} figures/complex_sinusoidal_waveform.png + +Time-domain plot of a ``300 KHz`` complex sinusoidal tone sampled at ``3 MSPS``. +``` + +## Compute FFT +```{eval-rst} +.. mermaid:: + + graph LR; + A[Generate/Import Waveform] --> B[Compute FFT]; + B -->C1[Configure Spectral Analysis]; + + subgraph SA[Spectral Analysis] + C1[Configure] -->C2[Run]; + end + + style SA fill:#ffffff + + style B fill:#9fa4fc +``` +Next, we compute FFT of the sinusoidal tone since spectral analysis of a waveform is in essence an analysis of its FFT. + +Genalyzer's [``fft()``](#genalyzer.fft) supports several usecases depending on whether the samples are represented in floating- or fixed-point, and on whether the samples are represented as complex-valued, or interleaved I/Q, or split into I and Q streams. In the [spectral-analysis example](https://github.com/analogdevicesinc/genalyzer/blob/main/bindings/python/examples/gn_doc_spectral_analysis1.py) Python script, we compute the complex, floating-point FFT of a complex, fixed-point input waveform represented as separate I and Q streams in the following manner: +```{code-block} python +# signal configuration +npts = 30000 # number of points in the signal +fs = 3e6 # sample-rate of the data +freq = 300000 # tone frequency +phase = 0.0 # tone phase +ampl_dbfs = -1.0 # amplitude of the tone in dBFS +qnoise_dbfs = -60.0 # quantizer noise in dBFS +fsr = 2.0 # full-scale range of I/Q components of the complex tone +ampl = (fsr / 2) * 10 ** (ampl_dbfs / 20) # amplitude of the tone in linear scale +qnoise = 10 ** (qnoise_dbfs / 20) # quantizer noise in linear scale +qres = 12 # data resolution +code_fmt = gn.CodeFormat.TWOS_COMPLEMENT # integer data format + +# FFT configuration +navg = 1 # number of FFT averages +nfft = int(npts/navg) # FFT-order +window = gn.Window.NO_WINDOW # window function to apply +axis_type = gn.FreqAxisType.DC_CENTER # axis type + +# generate signal for analysis +awfi = gn.cos(npts, fs, ampl, freq, phase) +awfq = gn.sin(npts, fs, ampl, freq, phase) +qwfi = gn.quantize(awfi, fsr, qres, qnoise, code_fmt) +qwfq = gn.quantize(awfq, fsr, qres, qnoise, code_fmt) + +# compute FFT +fft_cplx = gn.fft(qwfi, qwfq, qres, navg, nfft, window, code_fmt) +``` +More details can be found on the API page for [``fft()``](#genalyzer.fft). +```{note} +Genalyzer supports two fixed-point data formats: offset binary and two's-complement. See [here](#genalyzer.CodeFormat). +``` +```{note} +Genalyzer supports three window types that can be applied to the signal prior to computing FFT: Blackman-Harris, Hanning, and rectangular. See [here](#genalyzer.Window). +``` +```{important} +Genalyzer doesn't support an overlap window between different snapshots that are averaged to generate the FFT. As a result, ``fft()`` expects the number of complex-valued samples in the input to be equal to the product of the number of averages and the FFT order. +``` +```{seealso} +Genalyzer's ``fft()`` computes FFT for complex-valued data only. To compute FFT for real-valued data, use ``rfft()``. Additional details [here](#genalyzer.rfft). +``` + +The FFT plot of the complex-sinusoidal tone in our working example is shown below for reference. +```{figure} figures/fft.png + +FFT plot of a ``300 KHz`` complex sinusoidal tone sampled at ``3 MSPS``. +``` + +## Run Spectral Analysis +```{eval-rst} +.. mermaid:: + + graph LR; + A[Generate/Import Waveform] --> B[Compute FFT]; + B -->C1[Configure Spectral Analysis]; + + subgraph SA[Spectral Analysis] + C1[Configure] -->C2[Run]; + end + + style SA fill:#9fa4fc +``` +Conducting spectral analysis using Genalyzer involves two steps: configuration and analysis. + +### Configure Genalyzer +```{eval-rst} +.. mermaid:: + + graph LR; + A[Generate/Import Waveform] --> B[Compute FFT]; + B -->C1[Configure Spectral Analysis]; + + subgraph SA[Spectral Analysis] + C1[Configure] -->C2[Run]; + end + + style C1 fill:#9fa4fc + style SA fill:#ffffff +``` +We configure Genalyzer for spectral analysis by creating a _test_ followed by associating _components_ to this _test_. +#### Create a _test_ +In the [spectral-analysis example](https://github.com/analogdevicesinc/genalyzer/blob/main/bindings/python/examples/gn_doc_spectral_analysis1.py) Python script, to create a _test_, we called [``fa_create()``](#genalyzer.fa_create) as follows: +```{code-block} python +# Fourier analysis configuration +test_label = "fa" +gn.fa_create(test_label) +``` +The ``test_label`` ``string`` is key to all further configuration, and for computing and retrieving the metrics. +```{admonition} Aside +:class: dropdown + +Under the hood, Genalyzer adds a key-value pair to a ``static`` ``map`` container to manage the metrics to be computed. The key is the string argument passed through ``fa_create()``, and the mapped value is a shared-pointer to an instance of ``fourier_analysis`` class. This key is then used to further configure Genalyzer, and to compute and retrieve the metrics through ``fourier_analysis`` class. The intent behind using a ``map`` container is to be easily able to associate multiple keys to different snapshots of the data being analyzed and to have the metrics for each of those snapshots available. +``` + +#### Add a _component_ to a _test_ +The next step is to identify a tone, give it a label, tag it with a component tag, and add it to the _test_ being run. In this working example, we will consider only the signal tone for illustration purposes. We pick the label, ``A`` for the signal component and associate it with the test labeled ``fa`` from above. To do this, call [``fa_max_tone()``](#genalyzer.fa_max_tone) as follows: +```{code-block} python +# Fourier analysis configuration +test_label = "fa" +gn.fa_create(test_label) +signal_component_label = 'A' +gn.fa_max_tone(test_label, signal_component_label, gn.FaCompTag.SIGNAL, ssb_fund) +``` +As the name indicates, ``fa_max_tone()`` above interprets the tone with the highest magnitude as the signal component. For a more general way of informing Genalyzer to link a certain tone with a tag, use [``fa_fixed_tone()``](#genalyzer.fa_fixed_tone). +```{note} +Genalyzer supports several _tags_ for Fourier analysis. See [here](#genalyzer.FaCompTag). +``` + +The number of single-side bins (SSBs) for a _component_ is an important configuration step, and it will be explained in sufficient detail in another subsection. + +### Run Spectral Analysis +```{eval-rst} +.. mermaid:: + + graph LR; + A[Generate/Import Waveform] --> B[Compute FFT]; + B -->C1[Configure Spectral Analysis]; + + subgraph SA[Spectral Analysis] + C1[Configure] -->C2[Run]; + end + + style C2 fill:#9fa4fc + style SA fill:#ffffff +``` + +In the [spectral-analyis example](https://github.com/analogdevicesinc/genalyzer/blob/main/bindings/python/examples/gn_doc_spectral_analysis1.py) Python script, FFT analysis is run by the following line: +```{code-block} python +# Fourier analysis execution +results = gn.fft_analysis(test_label, fft_cplx, nfft, axis_type) +``` +See more details on ``fft_analysis()`` [here](#genalyzer.fft_analysis). +```{note} +The enumerations for frequency-axis type are [here](#genalyzer.FreqAxisType). +``` + +The Python script prints two tables and a dictionary to the console output. With the help of the tables, we will first see how Genalyzer identifies signal tone, its harmonics (and other components), their locations, and their magnitudes. Next, we will look at the dictionary of key-value pairs that [``fft_analysis()``](#genalyzer.fft_analysis) returns. It contains all the necessary information gathered by Genalyzer to compute various performance metrics. Towards the end of this discussion, we consider one metric, ``snr`` and verify how it is computed by Genalyzer. + +#### Tone labels +The first table we look at is the ``labels`` table. +```{admonition} annots["labels"] from console output +:class: dropdown + +``` console ++------------------+--------------------+-------------------+ +| frequency (Hz) | magnitude (dBFs) | component label | ++==================+====================+===================+ +| 0 | -69.1449 | dc | ++------------------+--------------------+-------------------+ +| 300000 | -1.00002 | A | ++------------------+--------------------+-------------------+ +| -300000 | -96.918 | -A | ++------------------+--------------------+-------------------+ +| 600000 | -102.544 | 2A | ++------------------+--------------------+-------------------+ +| -600000 | -99.6542 | -2A | ++------------------+--------------------+-------------------+ +| -900000 | -104.414 | -3A | ++------------------+--------------------+-------------------+ +| 1.1641e+06 | -91.308 | wo | ++------------------+--------------------+-------------------+ +``` + +Notice that this table shows ``7`` frequencies, their magnitudes, and their labels. In addition to the auto-configured ``dc`` component, with the help of the manually configured signal component, Genalyzer has identified ``4`` others: the image, two second-order harmonics, and one third-order harmonic. We also see a ``wo`` (worst-other) component which, as the name indicates, is the component of the highest magnitude excluding the ones listed so far. By default, Genalyzer identifies harmonics upto the `6`th order. In the [spectral-analysis example](https://github.com/analogdevicesinc/genalyzer/blob/main/bindings/python/examples/gn_doc_spectral_analysis1.py) Python script, we set the the number of harmonics to take into account to ``3`` with the following lines: +```{code-block} python +num_harmonics = 3 # number of harmonics to analyze +... +gn.fa_hd(test_label, num_harmonics) +``` + +```{note} +For odd-ordered harmonics, `3`rd, `5`th, and so on, Genalyzer considers only the maximum of the harmonic and its image, whereas for an even-ordered harmonic, both are taken into account. +``` + +#### Tone boxes +Next, we look at the ``tone_boxes`` table. +```{admonition} annots["tone_boxes"] from console output +:class: dropdown + +``` console ++--------------------------+--------------+ +| box left boundary (Hz) | width (Hz) | ++==========================+==============+ +| -50 | 100 | ++--------------------------+--------------+ +| 299950 | 100 | ++--------------------------+--------------+ +| -300050 | 100 | ++--------------------------+--------------+ +| 599950 | 100 | ++--------------------------+--------------+ +| -600050 | 100 | ++--------------------------+--------------+ +| -900050 | 100 | ++--------------------------+--------------+ +| 401050 | 100 | ++--------------------------+--------------+ +``` + +From this table, we see that each of the ``7`` components spans a width of ``100 Hz``. This value equals sample-rate divided by the FFT order we chose in the working example. Because the tone is coherently sampled and we chose the sample-rate to be an integer multiple of the FFT-order, all the power corresponding to a component is located in exactly one bin. This is the reason why, in [this](https://github.com/analogdevicesinc/genalyzer/blob/main/bindings/python/examples/gn_doc_spectral_analysis1.py) example, we set the number of single-side bins (SSBs) for every component to ``0``. So, Genalyzer takes into account the magnitude value corresponding to exactly one bin (and ``0`` bins on either side) as that component's contribution in various metrics computed. In a subsequent example, we consider the case when it becomes necessary to set the number of SSBs to a value greater than ``0``. +```{caution} +The choice of the number of single-side bins (SSBs) is important when the signal is not coherently sampled and when the sample-rate is not an integer multiple of the FFT-order. +``` + +#### Spectral analysis results +Finally, we take a brief look at the ``results`` dictionary. This dictionary can be thought of as a comprehensive summary gathered by Genalyzer for the snapshot of the sinusoidal tone we wished to analyze. + +The results dictionary printed to the console output is shown below. Note that since a random quantization noise is added to the signal, the console output will be different when you run the Python script. +```{admonition} results +:class: dropdown + +``` console ++----------------+ +results dictionary ++----------------+ +{'-2A:ffinal': -600000.0, + '-2A:freq': -600000.0, + '-2A:fwavg': 0.0, + '-2A:i1': 24000.0, + '-2A:i2': 24000.0, + '-2A:inband': 1.0, + '-2A:mag': 1.0406152385295209e-05, + '-2A:mag_dbc': -98.65417884167778, + '-2A:mag_dbfs': -99.654196373704, + '-2A:nbins': 1.0, + '-2A:orderindex': 4.0, + '-2A:phase': -0.9269628993478889, + '-2A:phase_c': -0.9269652814760975, + '-2A:tag': 2.0, + '-3A:ffinal': -900000.0, + '-3A:freq': -900000.0, + '-3A:fwavg': 0.0, + '-3A:i1': 21000.0, + '-3A:i2': 21000.0, + '-3A:inband': 1.0, + '-3A:mag': 6.016169853525572e-06, + '-3A:mag_dbc': -103.41358068555886, + '-3A:mag_dbfs': -104.41359821758508, + '-3A:nbins': 1.0, + '-3A:orderindex': 5.0, + '-3A:phase': 2.094523867798375, + '-3A:phase_c': 2.0945214856701666, + '-3A:tag': 2.0, + '-A:ffinal': -300000.0, + '-A:freq': -300000.0, + '-A:fwavg': 0.0, + '-A:i1': 27000.0, + '-A:i2': 27000.0, + '-A:inband': 1.0, + '-A:mag': 1.4259315029324203e-05, + '-A:mag_dbc': -95.91800918925517, + '-A:mag_dbfs': -96.9180267212814, + '-A:nbins': 1.0, + '-A:orderindex': 2.0, + '-A:phase': -1.0654410825386686, + '-A:phase_c': -1.0654434646668773, + '-A:tag': 2.0, + '2A:ffinal': 600000.0, + '2A:freq': 600000.0, + '2A:fwavg': 0.0, + '2A:i1': 6000.0, + '2A:i2': 6000.0, + '2A:inband': 1.0, + '2A:mag': 7.461346264425087e-06, + '2A:mag_dbc': -101.54363856607857, + '2A:mag_dbfs': -102.54365609810476, + '2A:nbins': 1.0, + '2A:orderindex': 3.0, + '2A:phase': 1.1796502560980227, + '2A:phase_c': 1.179647873969814, + '2A:tag': 2.0, + 'A:ffinal': 300000.0, + 'A:freq': 300000.0, + 'A:fwavg': 0.0, + 'A:i1': 3000.0, + 'A:i2': 3000.0, + 'A:inband': 1.0, + 'A:mag': 0.8912491391908985, + 'A:mag_dbc': 0.0, + 'A:mag_dbfs': -1.0000175320262066, + 'A:nbins': 1.0, + 'A:orderindex': 1.0, + 'A:phase': 2.3821282085798884e-06, + 'A:phase_c': 0.0, + 'A:tag': 1.0, + 'ab_i1': 0.0, + 'ab_i2': 29999.0, + 'ab_nbins': 30000.0, + 'ab_rss': 0.891250360126791, + 'ab_width': 3000000.0, + 'abn': -101.6440166036007, + 'analysistype': 1.0, + 'carrierindex': 1.0, + 'clk_nbins': 0.0, + 'clk_rss': 0.0, + 'datasize': 30000.0, + 'dc:ffinal': 0.0, + 'dc:freq': 0.0, + 'dc:fwavg': 0.0, + 'dc:i1': 0.0, + 'dc:i2': 0.0, + 'dc:inband': 1.0, + 'dc:mag': 0.00034894329171477126, + 'dc:mag_dbc': -68.14488539563568, + 'dc:mag_dbfs': -69.1449029276619, + 'dc:nbins': 1.0, + 'dc:orderindex': 0.0, + 'dc:phase': -2.3326100677671495, + 'dc:phase_c': -2.332612449895358, + 'dc:tag': 0.0, + 'dist_nbins': 4.0, + 'dist_rss': 2.0086862879892827e-05, + 'fbin': 100.0, + 'fdata': 3000000.0, + 'fsample': 3000000.0, + 'fshift': 0.0, + 'fsnr': 56.873672732238376, + 'hd_nbins': 4.0, + 'hd_rss': 2.0086862879892827e-05, + 'ilgt_nbins': 0.0, + 'ilgt_rss': 0.0, + 'ilos_nbins': 0.0, + 'ilos_rss': 0.0, + 'ilv_nbins': 0.0, + 'ilv_rss': 0.0, + 'imd_nbins': 0.0, + 'imd_rss': 0.0, + 'maxspurindex': 6.0, + 'nad_nbins': 29998.0, + 'nad_rss': 0.0014333723144579046, + 'nfft': 30000.0, + 'noise_nbins': 29994.0, + 'noise_rss': 0.0014332315618189736, + 'nsd': -121.64488527943499, + 'sfdr': 90.30795361676347, + 'signal_nbins': 1.0, + 'signal_rss': 0.8912491391908985, + 'signaltype': 1.0, + 'sinad': 55.87280223137394, + 'snr': 55.87365520021216, + 'thd_nbins': 4.0, + 'thd_rss': 2.0086862879892827e-05, + 'userdist_nbins': 0.0, + 'userdist_rss': 0.0, + 'wo:ffinal': 1164100.0, + 'wo:freq': 1164100.0, + 'wo:fwavg': 0.0, + 'wo:i1': 11641.0, + 'wo:i2': 11641.0, + 'wo:inband': 1.0, + 'wo:mag': 2.7202037974481932e-05, + 'wo:mag_dbc': -90.30795361676347, + 'wo:mag_dbfs': -91.30797114878968, + 'wo:nbins': 1.0, + 'wo:orderindex': 6.0, + 'wo:phase': -2.1560142655481678, + 'wo:phase_c': -2.1560166476763762, + 'wo:tag': 8.0} +``` + +From the results dictionary, we see a number of key-value pairs that are computed by Genalyzer. Among them, ``7`` sets of key-value pairs corresponding to the ``7`` components listed in the third column of the ``labels`` table in the console output above have the following format: + +``{TONEKEY}:ffinal`` : Tone final frequency (Hz) + +``{TONEKEY}:freq`` : Tone frequency (Hz) + +``{TONEKEY}:fwavg`` : Tone weighted-average frequency (Hz) + +``{TONEKEY}:i1`` : Tone first index + +``{TONEKEY}:i2`` : Tone last index + +``{TONEKEY}:inband`` : 1: tone is in-band; 0: tone is out-of-band + +``{TONEKEY}:mag`` : Tone magnitude + +``{TONEKEY}:mag_dbc`` : Tone magnitude relative to carrier (dBc) + +``{TONEKEY}:mag_dbfs`` : Tone magnitude relative to full-scale (dBFS) + +``{TONEKEY}:nbins`` : Tone number of bins + +``{TONEKEY}:orderindex`` : Tone order index + +``{TONEKEY}:phase`` : Tone phase (rad) + +``{TONEKEY}:phase_c`` : Tone phase relative to carrier (rad) + +``{TONEKEY}:tag`` : Tone tag + + +For example, the key-value pairs in the above format for ``-A`` component are as follows: + +``'-A:ffinal': -300000.0,`` + +``'-A:freq': -300000.0,`` + +``'-A:fwavg': 0.0,`` + +``'-A:i1': 27000.0,`` + +``'-A:i2': 27000.0,`` + +``'-A:inband': 1.0,`` + +``'-A:mag': 1.0513032226581935e-05,`` + +``'-A:mag_dbc': -98.56536672200804,`` + +``'-A:mag_dbfs': -99.56544008601296,`` + +``'-A:nbins': 1.0,`` + +``'-A:orderindex': 2.0,`` + +``'-A:phase': 2.2048368960072615,`` + +``'-A:phase_c': 2.2048362928010907,`` + +``'-A:tag': 2.0,`` + +which provide all the relevant information concerning ``-A`` component and how its contribution to the metrics is computed. More details concerning the key-value pairs in the ``results`` dictionary are available [here](#genalyzer.fft_analysis). + +In this manner, Genalyzer collates the information concerning all the components to account for, calculates the various performance metrics, and logs them to the ``results`` dictionary. To give an example of how genalyzer computes ``sfdr``, consider the following key-value pair from the ``results`` dictionary: + +``'noise_nbins': 29994.0,`` + +``'noise_rss': 0.0014332315618189736,`` + +which indicate that aside from ``6`` components (``A``, ``-A``, ``2A``, ``-2A``, ``-3A``, and ``wo``), all other bins have been accumulated and the root-sum-square value was computed to be ``0.0014332315618189736`` (``-56.8737 dB``). In our working example, we set the signal amplitude of the tone to be ``-1 dBFS`` (confirmed by ``'signal_rss': 0.8912491391908985``). Hence, we can verify that ``SNR (dB) = 20*log10(signal_rss/noise_rss) = 55.87365520021216 dB``, which matches the value in the console output above. In a similar manner, we can verify several other metrics as shown below: + +* ``SINAD (dB) = 20*log10(signal_rss/nad_rss)`` + +* ``FSNR (dB) = 20*log10(1.0/noise_rss)`` + +* ``SFDR (dB) = 20*log10(signal_rss/wo:mag)`` + +* ``NSD (dB) = 10*log10(noise_rss*noise_rss/ab_width)`` + +* ``ABN (dB) = 10*log10(noise_ss/noise_nbins)`` + +Please refer to the documentation page for [``fft_analysis()``](#genalyzer.fft_analysis) for further details. + +In summary, the magnitude spectrum plot for the working example considered so far, with DC, signal, and harmonic components labeled, is shown below. + +```{figure} figures/spectral_analysis_summary.png + +Magnitude spectrum of the FFT showing signal, harmonic, DC, and WO components. +``` diff --git a/doc/theory.md b/doc/theory.md deleted file mode 100644 index a7271f9..0000000 --- a/doc/theory.md +++ /dev/null @@ -1,268 +0,0 @@ -Usage Model -=========== -Overview --------- -Within Genalyzer, bindings to the C++ library are provided to enable users to write C-, Python-, or MATLAB-based scripts to compute the desired performance metrics. In all three cases, the overall structure of a script that links to genalyzer is similar, as shown in more detail in the next subsection. The overall structure in a simulation-only scenario consists of three stages: - -* Configure test -* Generate waveform -* Compute metric - -In the scenario where either the ADC codes or the FFT of the captured ADC codes are available, the structure would be - -* Configure test -* Load waveform -* Compute metric - -In other words, only the second step would change. - -The overall structure of a C-example that utilizes genalyzer library in the first scenario is shown by the following example. -``` c -#include "cgenalyzer.h" - -int main(int argc, char *argv[]) { - // opaque config struct that will contain config settings - gn_config c = NULL; - - // configure test - err_code = gn_config_gen_tone(..., &c); - err_code = gn_config_quantize(..., &c); - - // generate waveform and quantize - err_code = gn_gen_real_tone(..., &c); - err_code = gn_quantize(..., &c); - - // compute metrics - err_code = gn_get_fa_single_result(&sfdr, "sfdr", ..., &c); - - // free memory - gn_config_free(&c); - - return 0; -} -``` -As shown in this (incomplete) illustrative example, a configuration struct is passed to various stages without having to pass the same relevant parameters over and over. - -The overall structure of a C-example in the second scenario is shown by the following example. -``` c -#include "cgenalyzer.h" - -int main(int argc, char *argv[]) { - // opaque config struct that will contain config settings - gn_config c = NULL; - - // configure test - err_code = gn_config_fft(..., &c); - - // read ADC codes from file - err_code = read_array_from_json_file(filename, "adc_output_i", adc_i, ...); - err_code = read_array_from_json_file(filename, "adc_output_q", adc_q, ...); - - // compute FFT - err_code = gn_fftz(&fft_out, adc_i, adc_q, &c); - - // compute metrics - err_code = gn_get_fa_single_result(&sfdr, "sfdr", fft_out, &c); - - // free memory - gn_config_free(&c); - - return 0; -} -``` -If on the other hand, the FFT is pre-computed and genalyzer is expected to compute the desired performance metric alone, then only the configuration of FFT related parameters is needed in order for genalyzer to compute the desired performance metric. Note that in the following example, it is assumed that the FFT data is available in the form of a json file. It can be replaced by any other means of loading this data. -``` c -#include "cgenalyzer.h" - -int main(int argc, char *argv[]) { - // opaque config struct that will contain config settings - gn_config c = NULL; - - // configuration - err_code = gn_config_fft(..., &c); - - // read FFT of ADC codes from file - err_code = read_array_from_json_file(filename, "fft_test_vec", fft_out, ...); - - // compute metrics - err_code = gn_get_fa_single_result(&sfdr, "sfdr", fft_out, &c); - - // free memory - gn_config_free(&c); - - return 0; -} -``` -As highlighted by all three illustrative examples above, prior to configuring the test scenario, memory is allocated for the configuration struct by invoking, gn_config_calloc() and to free the allocated memory, gn_config_free() is called. - -Test Configuration ------------------- - -As indicated previously, test configuration is driven through an opaque struct. The public members that are accessible to the user for the purpose of specifying either the waveform or the FFT or the analysis settings are shown in the table below. - -| Catgory | Member Name | Datatype | Description | Notes | -|:-------:|:-----------:|:--------:|:-----------:|:-----:| -| **Waveform and FFT settings** | ttype | ENUM | Tone type | Options:
REAL_COSINE
REAL_SINE
COMPLEX_EXP | -| | npts | size_t | Num. of sample points in the waveform | | -| | sample_rate | double | Sample Rate | Units: samples/second| -| | tone_freq | double* | Tone frequency | Units: Hertz | -| | tone_ampl | double* | Tone amplitude | | -| | tone_phase | double* | Tone phase | | -| | num_tones | size_t | Num. of tones | | -| | fsr | double | ADC full-scale range | Units: Volts| -| | qres | int | Quantization resolution | Units: bits| -| | noise_rms | double | Noise RMS value | | -| | code_format | ENUM | Code format of ADC/DAC codes | Options:
GnCodeFormatOffsetBinary
GnCodeFormatTwosComplement | -| | nfft | size_t | FFT order | | -| | fft_navg | size_t | Num. of FFT averages | | -| | data_rate | double | Data rate | Units: samples/second | -| | shift_freq | double | Shift frequency | Units: Hertz| -| | win | ENUM | Window function | Options:
GnWindowBlackmanHarris
GnWindowHann
GnWindowNoWindow | -| | ramp_start | double | Start value of ramp | | -| | ramp_stop | double | Stop value of ramp | | -| **Fourier analysis settings** | ssb_fund | int | Single side bin - Fundamental | | -| | ssb_fund | int | Single side bin - Fundamental | | -| | max_harm_order | int | Max. order of harmonic | | -| **NL analysis settings** | dnla_signal_type | ENUM | DNL analysis signal type | Options:
GnDnlSignalRamp
GnDnlSignalTone | -| | inla_fit | ENUM | INL analysis fit | Options:
GnInlLineFitBestFit
GnInlLineFitEndFit
GnInlLineFitNoFit | - -As shown by this table, not all parameters are necessary in all use-cases. Consequently, each of the above struct members are accessible through gn_config_set_* functions. For instance, in order to configure sample rate, the function, gn_config_set_sample_rate would be used. Similarly for the other struct members. Additionally, the functions, gn_config_gen_tone, gn_config_gen_ramp, gn_config_quantize, gn_config_fft, and gn_config_fa can be used to configure a set of parameters that are needed in certain specific use-cases. Further details on the function signatures for each of these configuration functions can be found on the API reference page. - -The following table describes a few use-cases and the relevant members of the configuration struct that need to be set in order to generate a waveform or to perform the desired analysis using genalyzer. - -| Use-case | gn_config members to configure | Pre-requite function call | Function call | -|:-------:|:-----------|:-----------:|:-----------:| -| Generate single-/multi-tone waveform |
  • ttype
  • npts
  • sample_rate
  • num_tones
  • tone_freq
  • tone_ampl
  • tone_phase
| gn_config_gen_tone()| gn_gen_tone()| -| Generate ramp waveform |
  • npts
  • ramp_start
  • ramp_stop
| gn_config_gen_ramp()1 | gn_gen_ramp()| -| Quantize waveform |
  • npts
  • fsr
  • qres
  • noise_rms
| gn_config_quantize()2 | gn_quantize()| -| Compute FFT |
  • npts
  • qres
  • fft_navg
  • nfft
  • win
| gn_config_fft()2 | gn_fftz()| -| Compute histogram |
  • npts
  • qres
| gn_config_histz_nla()2 | gn_histz()| -| Compute DNL |
  • npts
  • qres
| gn_config_histz_nla()2 | gn_dnlz()| -| Compute INL |
  • npts
  • qres
| gn_config_histz_nla()2,3 | gn_inlz()| -| Do Fourier analysis |
  • nfft
| gn_config_fa()4 | gn_get_fa_single_result()
or
gn_get_fa_results() | -| Do waveform analysis |
  • npts
| gn_config_set_npts() | gn_get_wfa_results() | -| Do histogram analysis |
  • npts
  • qres
| gn_config_histz_nla()2 | gn_get_ha_results() | -| Do DNL analysis |
  • npts
  • qres
| gn_config_histz_nla()2 | gn_get_dnla_results() | -| Do INL analysis |
  • npts
  • qres
| gn_config_histz_nla()2 | gn_get_inla_results() | - -1noise_rms=0.0 is used. It can be overridden by calling gn_config_set_noise_rms() prior to calling gn_gen_ramp(). - -2code_format=GnCodeFormatTwosComplement is used. It can be overridden by calling gn_config_set_code_format() prior to calling the corresponding pre-requisite function call. - -3inla_fit=GnInlLineFitBestFit is used. It can be overridden by calling gn_config_set_inla_fit() prior to calling gn_config_histz_nla(). - -4The following default settings are used.
  • ssb_fund = 0
  • ssb_rest = 0
  • max_harm_order = 3
  • axis_type=GnFreqAxisTypeDcCenter
They can be overridden by calling gn_config_set_ssb_fund(), gn_config_set_ssb_rest(), gn_config_set_max_harm_order(), gn_config_set_axis_type() prior to calling gn_get_fa_results() or gn_get_fa_single_result(). - -Note that for certain use-cases, the pre-requisite function calls need not be invoked. For instance, given an analog waveform, if the user intends to quantize it and then compute the histogram, calling gn_config_quantize() will set the gn_config struct parameters needed prior to invoking gn_histz(). - -As indicated in the overall skelton C-script that interfaces with genalyzer, the first stage involves configuring an opaque struct that is provided to the users in order to describe the measurement scenario. Here, users can select between three `config_*_meas()` function calls in order to select between tone-, ramp- and noise-based performance metric calculations. The opaque struct maintains the state of the test scenario and is passed to the waveform generation and performance metric computation stages subsequently. - -**Tone-based Test Configuration**
-In tone-based test configuration, `config_tone_meas()` allows users to indicate test settings such as, number of tones, their frequencies, phases, scales, whether real sinusoidal or complex-exponential waveforms are to be generated, the sample-rate, full-scale range of the converter, its resolution etc. Similarly, users can indicate whether the data that will be loaded in the second stage is time-series data or interleaved FFT samples. Moreover, in data-capture scenario i.e., when FFT data is provided to Genalyzer in the second step, the tone frequency, scale and phase information is not required. This test configuration is used for measurements such as SFDR, THD, TIL etc. - -An example of the `config_tone_meas()` function call is shown by the following example. -``` c -// configuration -config_tone_meas(&c, - domain_wf, - type_wf, - nfft, // FFT order - navg, // # of FFTs averaged - fs, // sample rate - fsr, // full-scale range - 0, // ADC resolution: unused configuration setting - freq, // tone frequency, # of array elements = num_tones - scale, // tone scale, # of array elements = num_tones - phase, // tone phase, # of array elements = num_tones - num_tones, // # of tones - false, - false, - false - ); -``` - -**Ramp-based Test Configuration**
-In ramp-based test configuration, `config_ramp_meas()` allows users to indicate test settings such as, the starting and ending values of the ramp waveform in addition to the full-scale range and the resolution of the data converter under test. This test configuration is primarily used in non-linearity based measurements. - -An example of the `config_ramp_meas()` function call is shown by the following example. -``` c -// configuration -config_ramp_nl_meas(&c, - npts, // # of data points - fs, // sample rate - fsr, // full-scale range - res, // ADC resolution: unused configuration setting - start, - stop, - 0.0 - ); -``` - -**Noise-based Test Configuration**
-In noise-based test configuration, `config_noise_meas()` allows users to indicate test settings such as, the noise power level in addition to the full-scale range and the resolution of the data converter under test. This test configuration is primarily used for computing noise spectral density. - -An example of the `config_noise_meas()` function call is shown by the following example. -``` c -// configuration -config_noise_meas(&c, - COMPLEX_NOISE, - nfft, - navg, - fs, - fsr, - res, - noise_pwr_lvl, - update_fsample, - update_fdata, - update_fshift); -``` - -Waveform Generation -------------------- -The second step, as shown previously, involves either generating the waveform and quantizing it or loading the waveform from a file. The following options are currently supported. - -- cosine/sine and complex exponential waveforms of arbitrary frequency and sample rate -- ramp waveform -- Gaussian noise waveform of desired noise power spectral density level - -In all three cases, the waveform generation functions take two arguments, the opaque configuration struct that has been populated in the first step and a double pointer that will contain the analog waveform generated. The subsequent call to `quantize()` takes the configuration struct, the analog input waveform and the output quantized waveform obtained from quantizeing the analog waveform based on the resolution contained in the configuration struct. - -Alternatively, if data is loaded from a file, the configuration struct generated in the first stage will serve as a descriptor of that data. Note that indicating whether time or frequency data is loaded is indicated simply by an argument to the `config_tone_meas()` call in the first step. -``` c -#include -#include -#include -#include "genalyzer_cwrapper.h" - -int main(int argc, char *argv[]) { - // opaque config struct that will contain config settings - // config c = NULL; - - /* configuration */ - // config_tone_meas(&c, FREQ, ...); - // config_tone_meas(&c, TIME,...); - - /* load waveform generation*/ - // read_file_to_array(...); - - /* compute metrics */ - // fsnr_val = metric(..., "FSNR"); - - return 0; -} -``` - -Performance Metric Computation ------------------------------- -The final stage involves simply computing the desired performance metric. Metric computation is done by a call to ``metric()`` where, the last argument is one of: - - * `"FSNR"` - * `"NSD"` - * `"SFDR"` - * `"SINAD"` - * `"SNR"` - * `"TD"` - * `"THD"` - * `"TIL` - -Again, the test configuration contained in the opaque struct obtained from the first step is helpful in determinging whether the diff --git a/examples/do_fa_pluto_example.c b/examples/do_fa_pluto_example.c index 4d8b2cd..ed96e51 100644 --- a/examples/do_fa_pluto_example.c +++ b/examples/do_fa_pluto_example.c @@ -1,4 +1,4 @@ -#include "cgenalyzer.h" +#include "cgenalyzer_simplified_beta.h" #include "../tests/test_genalyzer.h" #include "../tests/cJSON.h" #include diff --git a/examples/do_fa_pluto_example_all_results.c b/examples/do_fa_pluto_example_all_results.c index 9aa1287..4fef108 100644 --- a/examples/do_fa_pluto_example_all_results.c +++ b/examples/do_fa_pluto_example_all_results.c @@ -1,4 +1,4 @@ -#include "cgenalyzer.h" +#include "cgenalyzer_simplified_beta.h" #include "../tests/test_genalyzer.h" #include "../tests/cJSON.h" #include diff --git a/examples/do_ha_sim_example.c b/examples/do_ha_sim_example.c index 7ce98d9..8e92451 100644 --- a/examples/do_ha_sim_example.c +++ b/examples/do_ha_sim_example.c @@ -1,4 +1,4 @@ -#include "cgenalyzer.h" +#include "cgenalyzer_simplified_beta.h" #include #include diff --git a/examples/do_wfa_sim_example.c b/examples/do_wfa_sim_example.c index cf46692..8f24277 100644 --- a/examples/do_wfa_sim_example.c +++ b/examples/do_wfa_sim_example.c @@ -1,4 +1,4 @@ -#include "cgenalyzer.h" +#include "cgenalyzer_simplified_beta.h" #include #include diff --git a/examples/fft_analysis_genalyzer_advanced.c b/examples/fft_analysis_genalyzer_advanced.c index 6483576..42b0a42 100644 --- a/examples/fft_analysis_genalyzer_advanced.c +++ b/examples/fft_analysis_genalyzer_advanced.c @@ -1,5 +1,5 @@ +#include #include -#include #include #include diff --git a/examples/real_analysis_genalyzer_advanced.c b/examples/real_analysis_genalyzer_advanced.c index bedd935..74c0c1f 100644 --- a/examples/real_analysis_genalyzer_advanced.c +++ b/examples/real_analysis_genalyzer_advanced.c @@ -1,5 +1,5 @@ +#include #include -#include #include #include diff --git a/libgenalyzer.iss.cmakein b/libgenalyzer.iss.cmakein index c8089b3..b75ebee 100644 --- a/libgenalyzer.iss.cmakein +++ b/libgenalyzer.iss.cmakein @@ -44,8 +44,8 @@ Source: "D:\a\genalyzer\genalyzer\bindings\c\src\Release\libgenalyzer.dll"; Dest Source: "D:\a\genalyzer\genalyzer\bindings\c\src\Release\libgenalyzer.lib"; DestDir: "{commonpf32}\Microsoft Visual Studio 12.0\VC\lib\amd64"; Check: Is64BitInstallMode Source: "D:\a\genalyzer\genalyzer\src\Release\genalyzer_plus_plus.lib"; DestDir: "{sys}"; Check: Is64BitInstallMode; Flags: replacesameversion +Source: "D:\a\genalyzer\genalyzer\bindings\c\include\cgenalyzer_simplified_beta.h"; DestDir: "{commonpf32}\Microsoft Visual Studio 12.0\VC\include" Source: "D:\a\genalyzer\genalyzer\bindings\c\include\cgenalyzer.h"; DestDir: "{commonpf32}\Microsoft Visual Studio 12.0\VC\include" -Source: "D:\a\genalyzer\genalyzer\bindings\c\include\cgenalyzer_advanced.h"; DestDir: "{commonpf32}\Microsoft Visual Studio 12.0\VC\include" Source: "D:\a\genalyzer\genalyzer\deps\fftw3\libfftw3-3.dll"; DestDir: "{sys}"; Check: Is64BitInstallMode diff --git a/requirements_doc.txt b/requirements_doc.txt index d3670f4..212757f 100644 --- a/requirements_doc.txt +++ b/requirements_doc.txt @@ -5,3 +5,6 @@ myst-parser sphinx-tabs graphviz sphinx_inline_tabs +sphinxcontrib-mermaid +sphinx-togglebutton +numpy \ No newline at end of file diff --git a/requirements_test.txt b/requirements_test.txt index 0e1f2ea..c8526e4 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -6,3 +6,4 @@ pytest-cov numpy setuptools matplotlib +tabulate \ No newline at end of file diff --git a/tasks.py b/tasks.py index 51feff4..cf7ede1 100644 --- a/tasks.py +++ b/tasks.py @@ -13,7 +13,7 @@ def lint(c): files = glob.glob("./**/CMakeLists.txt") + ["CMakeLists.txt"] cmd = ["cmake-format -i"] + files c.run(" ".join(cmd)) - c.run("clang-format -style=file -i bindings/c/include/cgenalyzer.h") + c.run("clang-format -style=file -i bindings/c/include/cgenalyzer_simplified_beta.h") c.run("black bindings/python") @task diff --git a/tests/test_fa_get_all_results.c b/tests/test_fa_get_all_results.c index ddf4db3..deaf2dd 100644 --- a/tests/test_fa_get_all_results.c +++ b/tests/test_fa_get_all_results.c @@ -1,4 +1,4 @@ -#include "cgenalyzer.h" +#include "cgenalyzer_simplified_beta.h" #include "test_genalyzer.h" #include #include diff --git a/tests/test_fa_get_single_result.c b/tests/test_fa_get_single_result.c index bf050a6..58f48a8 100644 --- a/tests/test_fa_get_single_result.c +++ b/tests/test_fa_get_single_result.c @@ -1,4 +1,4 @@ -#include "cgenalyzer.h" +#include "cgenalyzer_simplified_beta.h" #include "test_genalyzer.h" #include #include diff --git a/tests/test_fft.c b/tests/test_fft.c index 6b0ffa1..dff8913 100644 --- a/tests/test_fft.c +++ b/tests/test_fft.c @@ -1,4 +1,4 @@ -#include "cgenalyzer.h" +#include "cgenalyzer_simplified_beta.h" #include "test_genalyzer.h" #include #include diff --git a/tests/test_gen_complex_tone.c b/tests/test_gen_complex_tone.c index 14cddb3..8fb3b3c 100644 --- a/tests/test_gen_complex_tone.c +++ b/tests/test_gen_complex_tone.c @@ -1,4 +1,4 @@ -#include "cgenalyzer.h" +#include "cgenalyzer_simplified_beta.h" #include "test_genalyzer.h" #include #include diff --git a/tests/test_gen_real_tone.c b/tests/test_gen_real_tone.c index 9e84f68..3ce711f 100644 --- a/tests/test_gen_real_tone.c +++ b/tests/test_gen_real_tone.c @@ -1,4 +1,4 @@ -#include "cgenalyzer.h" +#include "cgenalyzer_simplified_beta.h" #include "test_genalyzer.h" #include #include diff --git a/tests/test_genalyzer.h b/tests/test_genalyzer.h index 80bc316..d2afee9 100644 --- a/tests/test_genalyzer.h +++ b/tests/test_genalyzer.h @@ -20,7 +20,7 @@ * */ -#include +#include #include #include #include diff --git a/tests/test_ha_get_all_results.c b/tests/test_ha_get_all_results.c index 2331d39..3ea687b 100644 --- a/tests/test_ha_get_all_results.c +++ b/tests/test_ha_get_all_results.c @@ -1,4 +1,4 @@ -#include "cgenalyzer.h" +#include "cgenalyzer_simplified_beta.h" #include "test_genalyzer.h" #include #include diff --git a/tests/test_histz.c b/tests/test_histz.c index 0ea1e46..3e2c36c 100644 --- a/tests/test_histz.c +++ b/tests/test_histz.c @@ -1,4 +1,4 @@ -#include "cgenalyzer.h" +#include "cgenalyzer_simplified_beta.h" #include "test_genalyzer.h" #include #include diff --git a/tests/test_quantize_complex_tone.c b/tests/test_quantize_complex_tone.c index fca7f20..15bf22c 100644 --- a/tests/test_quantize_complex_tone.c +++ b/tests/test_quantize_complex_tone.c @@ -1,4 +1,4 @@ -#include "cgenalyzer.h" +#include "cgenalyzer_simplified_beta.h" #include "test_genalyzer.h" #include #include diff --git a/tests/test_quantize_real_tone.c b/tests/test_quantize_real_tone.c index 41afff3..06bb2d8 100644 --- a/tests/test_quantize_real_tone.c +++ b/tests/test_quantize_real_tone.c @@ -1,4 +1,4 @@ -#include "cgenalyzer.h" +#include "cgenalyzer_simplified_beta.h" #include "test_genalyzer.h" #include #include diff --git a/tests/test_wfa_get_all_results.c b/tests/test_wfa_get_all_results.c index 93996a0..ddc37a3 100644 --- a/tests/test_wfa_get_all_results.c +++ b/tests/test_wfa_get_all_results.c @@ -1,4 +1,4 @@ -#include "cgenalyzer.h" +#include "cgenalyzer_simplified_beta.h" #include "test_genalyzer.h" #include #include