/**
* @brief

h2 mod definition

*/

#ifndef H2_MOD_
#define H2_MOD_

#include <cmath>
#include <string>
#include <fstream>
#include <stdint.h>

#ifdef _WIN32
#define   MAXPATH MAX_PATH
#define NOMINMAX
#include "windows.h"
#include "tchar.h"
#else
#include <dlfcn.h>
#include <unistd.h>
#include <limits.h>
#include <link.h>
#define  MAXPATH  PATH_MAX
#endif

#ifdef __cplusplus
extern "C" {
#endif

#if defined _WIN32 || defined __CYGWIN__
#ifdef H2_API_EXPORTS
#define H2_API __declspec(dllexport)
#else
#define H2_API
#endif
#else
#ifdef H2_API_EXPORTS
#if __GNUC__ >= 4
#define H2_API __attribute__ ((visibility ("default")))
#else
#define H2_API
#endif
#else
#define H2_API
#endif
#endif

#define APIRETVAL_SUCCESS                                 0				// No error
#define APIRETVAL_ERROR_DevModLicFileIsMissing          -601			// License file is missing. Please place the xx._mod.lic file in the /CalFile/ directory.
#define APIRETVAL_ERROR_DevModLicVerificationFailed     -602			// License file verification failed. This is usually caused by an invalid license file. Please contact technical support.
#define APIRETVAL_ERROR_DevVerificationFailed        	-603			// Device verification failed during device object creation. Please ensure the device is opened properly and contact technical support.
#define APIRETVAL_ERROR_ObjCreationFailed               -604			// Failed to create the device object. Please ensure the device is opened properly and contact technical support.
#define APIRETVAL_ERROR_ObjReleaseFailed                -605			// Failed to release the device object. Please contact technical support.
#define APIRETVAL_ERROR_ModTypeError                    -606			// Invalid modulation type specified when generating the signal. Please correct the modulation type and regenerate the signal.
#define APIRETVAL_ERROR_ModParameterError               -607			// Invalid modulation parameters specified when generating the signal. Please correct the parameters and regenerate the signal.
#define APIRETVAL_ERROR_NoModLib                        -608			// Modulation library not found in the same directory as the h2_api library. Please place genSignalWave.dll (Windows) or libgenSignalWave.so (Linux) in the same directory as the h2_api library.
#define APIRETVAL_ERROR_ModProfile_SetError             -609			// The current parameter configuration is invalid. The previously valid configuration has been retained.

	/* Digital modulation type */
	enum mod_digitalmod_type : uint8_t
	{
		DigitalModType_BPSK = 1,
		DigitalModType_DBPSK,
		DigitalModType_QPSK,
		DigitalModType_DQPSK,
		DigitalModType_OQPSK,
		DigitalModType_Pi4DQPSK,
		DigitalModType_PSK8,
		DigitalModType_D8PSK,
		DigitalModType_PSK16,
		DigitalModType_QAM16,
		DigitalModType_QAM64,
		DigitalModType_QAM256,
		DigitalModType_QAM1024,
		DigitalModType_ASK2,
		DigitalModType_FSK2,
		DigitalModType_FSK4,
		DigitalModType_FSK8,
		DigitalModType_FSK16,
		DigitalModType_ASK4,
		DigitalModType_ASK8,
		DigitalModType_APSK16,
		DigitalModType_QAM8
	};

	/* Filter types */
	enum mod_filter_type : uint8_t
	{
		FilterType_Rectangular = 1,			// Rectangular filter
		FilterType_RaisedCosine,			// Raised Cosine filter
		FilterType_RootRaisedCosine,		// Root Raised Cosine filter
		FilterType_Gaussian,				// Gaussian filter
		FilterType_HalfSine					// Half-Sine filter
	};

	/* Modulation waveform types */
	enum mod_shape_type : uint8_t
	{
		ModShape_Sine = 1,					// Sine wave
		ModShape_Square,					// Square wave
		ModShape_Triangle,					// Triangle wave
		ModShape_Ramp						// Ramp (sawtooth) wave
	};


	/* Digital modulation configuration structure */
	typedef struct
	{
		mod_digitalmod_type digitalmod_type;				// Digital modulation type
		double symbolrate;									// Symbol rate in Hz, Range: minimum sample rate / samples per symbol to maximum sample rate / samples per symbol
		double fskdeviation;								// FSK frequency deviation in Hz, Maximum: 15 × symbol rate
		int32_t pn;											// Pseudo-random sequence order, range: 4 ~ 32, Recommended not to exceed 24
		int32_t sequenceseed;								// Initial seed value for the pseudo-random sequence, Range: 1 ~ 2147483647
		mod_filter_type filter_type;						// Filter type: Raised Cosine, Root Raised Cosine, Rectangular, Gaussian, or Half-Sine
		int32_t filter_symbols;								// Filter span in symbols, Must be an even number, Constraint: 2 ~ (sps * filter_symbols) <= 400, Default: 8
		int32_t sps;										// Samples per symbol (SPS), Even number in the range 4 ~ 32, Default: 4
		double alpha;										// Roll-off factor for Raised Cosine / Root Raised Cosine: 0.025 ~ 1, BT value for Gaussian filter: 0.15 ~ 2.5, Valid only for Raised Cosine, Root Raised Cosine, and Gaussian filters
	}digitalmod_profile;

	/* AM modulation configuration structure */
	typedef struct
	{
		double rate;										// Modulation rate in Hz
		double depth;										// Modulation depth in %
		mod_shape_type shape;								// Modulation waveform type
	}am_profile;

	/* FM modulation configuration structure */
	typedef struct
	{
		double rate;										// Modulation rate in Hz
		double deviation;									// Frequency deviation in Hz
		mod_shape_type shape;								// Modulation waveform type
	}fm_profile;

	/* DSSS configuration structure */
	typedef struct
	{
		double symbolrate;									// Symbol rate in Hz
		mod_digitalmod_type digitalmod_type;				// Digital modulation type
		int32_t code;										// Spreading code (PN code value), Recommended value: 5
		int32_t filter_symbols;								// Filter span in symbols, Must be an even number, Constraint: 2 ~ (sps * filter_symbols) <= 400, Default: 8
		int32_t sps;										// Samples per symbol (SPS), Even number in the range 4 ~ 32, Default: 4
		double alpha;										// Roll-off factor for Raised Cosine, Root Raised Cosine: 0.025 ~ 1, BT value for Gaussian filter: 0.15 ~ 2.5, Valid only for Raised Cosine, Root Raised Cosine, and Gaussian filters
		int32_t sequenceseed;								// Initial seed value for the pseudo-random sequence, Range: 1 ~ 2147483647
		mod_filter_type filter_type;						// Filter type:, Raised Cosine, Root Raised Cosine, Rectangular, Gaussian, or Half-Sine
	}dsss_profile;

	/* Orthogonal Frequency Division Multiplexing (OFDM) configuration structure */
	typedef struct
	{
		double idleinterval;								// Idle time between transmission bursts, in seconds
		int32_t fftsize;									// FFT size, supported values: 16, 32, 64, 128, 256, 512, 1024, 2048, and fftsize > guardbandcarriers_left + guardbandcarriers_right
		int32_t symbolcount;								// Number of OFDM symbols
		int32_t guardbandcarriers_left;						// Number of guard band carriers on the left side
		int32_t guardbandcarriers_right;					// Number of guard band carriers on the right side
		int32_t guardinterval;								// Guard interval, in %
		int32_t window_length;								// Window length, in %
		uint8_t windowed;									// Enable windowing (1 = yes, 0 = no)
		mod_digitalmod_type digitalmod_type;				// Digital modulation type, only supports DigitalModType_BPSK, DigitalModType_QPSK, DigitalModType_PSK8, DigitalModType_PSK16, DigitalModType_QAM16, DigitalModType_QAM64, DigitalModType_QAM256
		uint8_t nulldc;										// Null DC carrier (1 = yes, 0 = no)
		double samplerate;									// Sampling rate, range: 195.3125 kHz ~ 125 MHz, default 20 MHz
	}ofdm_profile;

	/* Pulse modulation configuration structure */
	typedef struct
	{
		double width;										// Pulse width, in seconds
		double period;										// Period, in seconds (must be greater than pulse width)
	}pulse_profile;

	/* Multitone configuration structure */
	typedef struct
	{
		double tonephase;									// Phase, [0, 2*pi]
		int32_t tonecount;									// Number of tones
		double freqspacing;									// Frequency spacing, in Hz
	}multitone_profile;

	/* Step sweep configuration structure (convert start/stop frequency to center frequency and span) */
	typedef struct
	{
		double center;										// Center frequency, in Hz
		double span;										// Span bandwidth, in Hz
		int32_t points;										// Number of points
		double dwelltime;									// Dwell time, in seconds
	}stepsweep_profile;

	/* Ramp sweep configuration structure */
	typedef struct
	{
		double span;										// Span bandwidth, in Hz
		double sweeptime;									// Sweep time, in seconds
		double period;										// Period, in seconds
	}rampsweep_profile;

	/* Additive White Gaussian Noise (AWGN) configuration structure */
	typedef struct
	{
		double bandwidth;									// Bandwidth, in Hz
		double length;										// Duration, in seconds
	}awgn_profile;


	/**
	 * @brief Open modulation function
	 *
 	 * After opening the device, pass the device information structure to this function
 	 * to verify the device, check if the modulation library exists, register functions,
 	 * create the device object, and enable modulation functionality.
	 *
	 * @param device   					      out, Returns the device handle
	 * @param version_o   					  out, Modulation library version string
	 *
	 * @return 0 Success, Non-0 Fail
	 */
	H2_API int mod_open(void** device, char version_o[50]);

	/**
	 * @brief Close modulation functionality
	 *
	 * Releases the device object and frees memory allocated by the modulation algorithm
	 * after the object is no longer needed.
	 *
	 * @param device   					      in, Device handle
	 * 
	 * @return 0 Success, Non-0 Fail
	 */
	H2_API int mod_close(void** device);

	/**
	 * @brief Initialize structure
	 *
	 * Initializes the digital modulation configuration structure by assigning default values
	 * to each parameter within the structure.
	 *
	 * @param device   					      in, Device handle
	 * @param digitalmod_profile_o     		  out, Digital modulation configuration structure
	 *
	 */
	H2_API void mod_init_digitalmod(void** device, digitalmod_profile* digitalmod_profile_o);

	/**
	 * @brief Initialize structure
	 *
	 * Initializes the AM modulation configuration structure by assigning default values
	 * to each parameter within the structure.
	 *
	 * @param device   					      in, Device handle
	 * @param am_profile_o     		  		  out, AM modulation configuration structure
	 *
	 */
	H2_API void mod_init_am(void** device, am_profile* am_profile_o);

	/**
	 * @brief Initialize structure
	 *
	 * Initializes the FM modulation configuration structure by assigning default values
	 * to each parameter within the structure.
	 *
	 * @param device   					      in, Device handle
	 * @param fm_profile_o     		  		  out, FM modulation configuration structure
	 *
	 */
	H2_API void mod_init_fm(void** device, fm_profile* fm_profile_o);

	/**
	 * @brief Initialize structure
	 *
	 * Initializes the Direct-Sequence Spread Spectrum (DSSS) configuration structure
	 * by assigning default values to each parameter within the structure.
	 *
	 * @param device   					      in, Device handle
	 * @param dsss_profile_o     	  		  out, DSSS configuration structure
	 *
	 */
	H2_API void mod_init_dsss(void** device, dsss_profile* dsss_profile_o);

	/**
	 * @brief Initialize structure
	 *
	 * Initializes the pulse modulation configuration structure by assigning default values, to each parameter within the structure.
	 * 
	 * @param device   					      in, Device handle
	 * @param pulse_profile_o       	  	  out, Pulse modulation configuration structure
	 *
	 */
	H2_API void mod_init_pulse(void** device, pulse_profile* pulse_profile_o);

	/**
	 * @brief Initialize structure
	 *
	 * Initializes the multitone configuration structure by assigning default values, to each parameter within the structure.
	 *
	 * @param device   					      in, Device handle
	 * @param multitone_profile_o      		  out, Multitone configuration structure
	 *
	 */
	H2_API void mod_init_multitone(void** device, multitone_profile* multitone_profile_o);

	/**
	 * @brief Initialize structure
	 *
	 * Initializes the step sweep configuration structure by assigning default values to each parameter within the structure.
	 *
	 * @param device   					      in, Device handle
	 * @param stepsweep_profile_o      		  out, Step sweep configuration structure
	 *
	 */
	H2_API void mod_init_stepsweep(void** device, stepsweep_profile* stepsweep_profile_o);

	/**
	 * @brief Initialize structure
	 *
	 * Initializes the ramp sweep configuration structure by assigning default values to each parameter within the structure.
	 *
	 * @param device   					      in, Device handle
	 * @param rampsweep_profile_o      		  out, Ramp sweep configuration structure
	 *
	 */
	H2_API void mod_init_rampsweep(void** device, rampsweep_profile* rampsweep_profile_o);

	/**
	 * @brief Initialize structure
	 *
	 * Initializes the OFDM configuration structure by assigning default values to each parameter within the structure.
	 *
	 * @param device   					      in, Device handle
	 * @param ofdm_profile_o           		  out, OFDM configuration structure
	 *
	 */
	H2_API void mod_init_ofdm(void** device, ofdm_profile* ofdm_profile_o);

	/**
	 * @brief Initialize structure
	 *
	 * Initializes the AWGN (Additive White Gaussian Noise) configuration structure by assigning default values to each parameter within the structure.
	 *
	 * @param device   					      in, Device handle
	 * @param awgn_profile_o           		  out, AWGN configuration structure
	 *
	 */
	H2_API void mod_init_awgn(void** device, awgn_profile* awgn_profile_o);

	/**
	 * @brief Configure structure
	 *
	 * Configures the digital modulation structure parameters. If the input configuration is invalid, a corrected and valid configuration will be returned in the output structure.
	 *
	 * @param device   					    in, Device handle
	 * @param digitalmod_profile_in     	in, Input digital modulation configuration structure
	 * @param digitalmod_profile_o     		out, Output digital modulation configuration structure
	 *
	 * @return 0 Success, Non-0 Fail
	 */
	H2_API int mod_config_digitalmod(void** device, const digitalmod_profile* digitalmod_profile_in, digitalmod_profile* digitalmod_profile_o);

	/**
	 * @brief Configure structure
	 *
	 * Configures the AM modulation parameters. If the input configuration is invalid, a corrected and valid configuration will be returned in the output structure.
	 *
	 * @param device   					    in, Device handle
	 * @param am_profile_in     			in, Input AM modulation configuration structure
	 * @param am_profile_o     				out, Output AM modulation configuration structure
	 *
	 * @return 0 Success, Non-0 Fail
	 */
	H2_API int mod_config_am(void** device, const am_profile* am_profile_in, am_profile* am_profile_o);

	/**
	 * @brief Configure structure
	 *
	 * Configures the FM modulation parameters. If the input configuration is invalid, a corrected and valid configuration will be returned in the output structure.
	 *
	 * @param device   					    in, Device handle
	 * @param fm_profile_in     			in, Input FM modulation configuration structure
	 * @param fm_profile_o     				out, Output FM modulation configuration structure
	 *
	 * @return 0 Success, Non-0 Fail
	 */
	H2_API int mod_config_fm(void** device, const fm_profile* fm_profile_in, fm_profile* fm_profile_o);

	/**
	 * @brief Configuration structure
	 *
	 * Configures the Direct Sequence Spread Spectrum (DSSS) parameters, If the input configuration is invalid, the output configuration structure, will be overwritten with valid parameters.
	 *
	 * @param device   					    in, device handle
	 * @param dsss_profile_in     			in, input DSSS configuration structure
	 * @param dsss_profile_o     			out, output DSSS configuration structure
	 *
	 * @return 0 Success, Non-0 Fail
	 */
	H2_API int mod_config_dsss(void** device, const dsss_profile* dsss_profile_in, dsss_profile* dsss_profile_o);

	/**
	 * @brief Configuration structure
	 *
	 * Configures pulse modulation parameters. 
	 * If the input configuration is invalid, the output configuration structure will be overwritten with valid parameters.
	 *
	 * @param device   					    in, device handle
	 * @param pulse_profile_in     			in, input pulse modulation configuration structure
	 * @param pulse_profile_o     			out, output pulse modulation configuration structure
	 *
	 * @return 0 Success, Non-0 Fail
	 */
	H2_API int mod_config_pulse(void** device, const pulse_profile* pulse_profile_in, pulse_profile* pulse_profile_o);

	/**
	 * @brief Configuration structure
	 *
	 * Configures multitone parameters. If the input configuration is invalid, the output configuration structure will be overwritten with valid parameters.
	 *
	 * @param device   					    in, device handle
	 * @param multitone_profile_in     		in, input multitone configuration structure
	 * @param multitone_profile_o     		out, output multitone configuration structure
	 *
	 * @return 0 Success, Non-0 Fail
	 */
	H2_API int mod_config_multitone(void** device, const multitone_profile* multitone_profile_in, multitone_profile* multitone_profile_o);

	/**
	 * @brief Configuration structure
	 *
	 * Configures step-sweep parameters. If the input configuration is invalid, the output configuration structure will be overwritten with valid parameters.
	 *
	 * @param device   					    in, device handle
	 * @param stepsweep_profile_in     		in, input step-sweep configuration structure
	 * @param stepsweep_profile_o     		out, output step-sweep configuration structure
	 *
	 * @return 0 Success, Non-0 Fail
	 */
	H2_API int mod_config_stepsweep(void** device, const stepsweep_profile* stepsweep_profile_in, stepsweep_profile* stepsweep_profile_o);

	/**
	 * @brief Configuration structure
	 *
	 * Configures ramp-sweep parameters. If the input configuration is invalid, the output configuration structure will be overwritten with valid parameters.
	 *
	 * @param device   					    in, device handle
	 * @param rampsweep_profile_in     		in, input ramp-sweep configuration structure
	 * @param rampsweep_profile_o     		out, output ramp-sweep configuration structure
	 *
	 * @return 0 Success, Non-0 Fail
	 */
	H2_API int mod_config_rampsweep(void** device, const rampsweep_profile* rampsweep_profile_in, rampsweep_profile* rampsweep_profile_o);

	/**
	 * @brief Configuration structure
	 *
	 * Configures orthogonal frequency-division multiplexing (OFDM) parameters. If the input configuration is invalid, the output configuration structure will be overwritten with valid parameters.
	 *
	 * @param device   					    in, device handle
	 * @param ofdm_profile_in     			in, input OFDM configuration structure
	 * @param ofdm_profile_o     			out, output OFDM configuration structure
	 *
	 * @return 0 Success, Non-0 Fail
	 */
	H2_API int mod_config_ofdm(void** device, const ofdm_profile* ofdm_profile_in, ofdm_profile* ofdm_profile_o);

	/**
	 * @brief Configuration structure
	 *
	 * Configures additive white Gaussian noise (AWGN) parameters. If the input configuration is invalid, the output configuration structure will be overwritten with valid parameters.
	 *
	 * @param device   					    in, device handle
	 * @param awgn_profile_in     			in, input AWGN configuration structure
	 * @param awgn_profile_o     			out, output AWGN configuration structure
	 *
	 * @return 0 Success, Non-0 Fail
	 */
	H2_API int mod_config_awgn(void** device, const awgn_profile* awgn_profile_in, awgn_profile* awgn_profile_o);



	/**
	 * @brief Generate signal data
	 *
	 * After enabling the modulation function, call the initialization function to set initial values,
	 * then configure parameters via the configuration structure function to generate signal data.
	 *
	 * @param device   						in, device handle
	 * @param symbol_length					in, symbol length, used for digital modulation and DSSS modulation
	 * @param iq_o     						out, output IQ signal data
	 * @param length_o     					out, output data length
	 * @param sample_rate_o     			out, sampling rate used for the generated data
	 *
	 * @return 0 Success, Non-0 Fail
	 */
	H2_API int mod_generate_stream(void** device, int32_t symbol_length, int16_t** iq_o, int32_t* length_o, double* sample_rate_o);


#ifdef __cplusplus
}
#endif

#endif