/**
* @brief

h2 mod 定义

*/

#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				// 无错误
#define APIRETVAL_ERROR_DevModLicFileIsMissing          -601			// 许可证文件缺失，请将xx._mod.lic文件放到/CalFile/文件夹中
#define APIRETVAL_ERROR_DevModLicVerificationFailed     -602			// 许可文件验证失败，通常为许可证内容错误，请联系技术支持人员
#define APIRETVAL_ERROR_DevVerificationFailed        	-603			// 创建设备对象时，设备校验失败，请检查设备是否正常打开，并联系技术支持人员
#define APIRETVAL_ERROR_ObjCreationFailed               -604			// 创建设备对象时，对象创建失败，请检查设备是否正常打开，并联系技术支持人员
#define APIRETVAL_ERROR_ObjReleaseFailed                -605			// 释放设备对象时，对象释放失败，请联系技术支持人员
#define APIRETVAL_ERROR_ModTypeError                    -606			// 生成信号时，输入调制类型错误，请修改调制类型并下发，重新生成信号
#define APIRETVAL_ERROR_ModParameterError               -607			// 生成信号时，输入调制参数错误，请修改调制参数并下发，重新生成信号
#define APIRETVAL_ERROR_NoModLib                        -608			// h2_api库的同路径下没有调制库，请将genSignalWave.dll(Windwos)或libgenSignalWave.so(Linux)放到h2_api库的同路径下
#define APIRETVAL_ERROR_ModProfile_SetError             -609			// 当前参数无法配置，已配置上一次可用参数

	/*数字调制类型*/
	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
	};

	/*滤波器类型*/
	enum mod_filter_type : uint8_t
	{
		FilterType_Rectangular = 1,			// 矩形滤波器
		FilterType_RaisedCosine,			// 升余弦滤波器
		FilterType_RootRaisedCosine,		// 根升余弦滤波器
		FilterType_Gaussian,				// 高斯滤波器
		FilterType_HalfSine					// 半正弦滤波器
	};

	/*调制波形*/
	enum mod_shape_type : uint8_t
	{
		ModShape_Sine = 1,					// 正弦波
		ModShape_Square,					// 方波
		ModShape_Triangle,					// 三角波
		ModShape_Ramp						// 锯齿波
	};


	/*数字调制配置结构体*/
	typedef struct
	{
		mod_digitalmod_type digitalmod_type;				// 数字调制方式
		double symbolrate;									// 符号速率，单位Hz，最小采样率/每个符号样点数 ~ 最大采样率/每个符号样点数
		double fskdeviation;								// FSK频偏，单位Hz,最大为15 * symbolrate
		int32_t pn;											// 伪随机序列，4 ~ 32，建议最大不超过24
		int32_t sequenceseed;								// 伪随机序列初始值，1 ~ 2147483647
		mod_filter_type filter_type;						// 滤波器类型，升余弦、根升余弦、矩形、高斯、HalfSine
		int32_t filter_symbols;								// 滤波器符号数，偶数，2 ~ sps*filter_symbols <= 400, 默认取8
		int32_t sps;										// 每个符号样点数，4 ~ 32的偶数，默认取4
		double alpha;										// 升余弦/根升余弦：0.025 ~ 1，高斯滤波：0.15 ~ 2.5，alpha只对升余弦、根升余弦、高斯滤波有效
	}digitalmod_profile;

	/*AM调制配置结构体*/
	typedef struct
	{
		double rate;										// 调制率，单位Hz
		double depth;										// 调制深度，单位%
		mod_shape_type shape;								// 调制波形
	}am_profile;

	/*FM调制配置结构体*/
	typedef struct
	{
		double rate;										// 调制率，单位Hz
		double deviation;									// 调制频偏，单位Hz
		mod_shape_type shape;								// 调制波形
	}fm_profile;

	/*直接序列扩频配置结构体*/
	typedef struct
	{
		double symbolrate;									// 符号速率，单位Hz
		mod_digitalmod_type digitalmod_type;				// 数字调制方式
		int32_t code;										// 扩频码，取PN值，建议取5
		int32_t filter_symbols;								// 滤波器符号数，偶数，2 ~ sps*filter_symbols <= 400, 默认取8
		int32_t sps;										// 每个符号样点数，4 ~ 32的偶数，默认取4
		double alpha;										// 升余弦/根升余弦：0.025 ~ 1，高斯滤波：0.15 ~ 2.5，alpha只对升余弦、根升余弦、高斯滤波有效
		int32_t sequenceseed;								// 伪随机序列初始值，1 ~ 2147483647
		mod_filter_type filter_type;						// 滤波器类型，升余弦、根升余弦、矩形、高斯、HalfSine
	}dsss_profile;

	/*正交频分复用配置结构体*/
	typedef struct
	{
		double idleinterval;								// 发射突发之间的空闲时间，单位s
		int32_t fftsize;									// FFT个数，支持16、32、64、128、256、512、1024、2048，且fftsize > guardbandcarriers_left + guardbandcarriers_right
		int32_t symbolcount;								// 符号数量
		int32_t guardbandcarriers_left;						// 左侧保护载波个数
		int32_t guardbandcarriers_right;					// 右侧保护载波个数
		int32_t guardinterval;								// 保护间隔，单位为%
		int32_t window_length;								// 窗长度，单位为%
		uint8_t windowed;									// 是否加窗
		mod_digitalmod_type digitalmod_type;				// 数字调制方式，注意，仅支持DigitalModType_BPSK、DigitalModType_QPSK、DigitalModType_PSK8、DigitalModType_PSK16、DigitalModType_QAM16、DigitalModType_QAM64、DigitalModType_QAM256
		uint8_t nulldc;										// 直流是否置空
		double samplerate;									// 采样率 195.3125e3 ~ 125e6，默认20MHz
	}ofdm_profile;

	/*脉冲调制配置结构体*/
	typedef struct
	{
		double width;										// 脉宽，单位s
		double period;										// 周期，单位s，周期一定大于脉宽
	}pulse_profile;

	/*多音配置结构体*/
	typedef struct
	{
		double tonephase;									// 相位，[0，2*pi]
		int32_t tonecount;									// 单音数量
		double freqspacing;									// 频率间隔，单位Hz
	}multitone_profile;

	/*步进扫描配置结构体（把起止频率转换成中心频率和扫宽）*/
	typedef struct
	{
		double center;										// 中心频率，单位Hz
		double span;										// 扫宽，单位Hz
		int32_t points;										// 点数
		double dwelltime;									// 驻留时间，单位s
	}stepsweep_profile;

	/*斜坡扫描配置结构体*/
	typedef struct
	{
		double span;										// 扫宽，单位Hz
		double sweeptime;									// 扫描时间，单位s
		double period;										// 周期，单位s
	}rampsweep_profile;

	/*高斯白噪声配置结构体*/
	typedef struct
	{
		double bandwidth;									// 带宽，单位Hz
		double length;										// 长度，单位s
	}awgn_profile;



	/**
	 * @brief 打开调制功能
	 *
	 * 设备打开后，将设备信息结构体传入函数用于校验设备，检查调制库是否存在，注册函数并创建设备对象，打开调制功能。
	 *
	 * @param device   					      out，返回设备句柄
	 * @param version_o   					  out，调制库版本号
	 *
	 * @return 0 表示成功，非 0 表示失败
	 */
	H2_API int mod_open(void** device, char version_o[50]);

	/**
	 * @brief 关闭调制功能
	 *
	 * 释放对象，对象调用结束后，释放算法开辟的内存空间。
	 *
	 * @param device   					      in，设备句柄
	 * 
	 * @return 0 表示成功，非 0 表示失败
	 */
	H2_API int mod_close(void** device);

	/**
	 * @brief 初始化结构体
	 *
	 * 初始化数字调制配置结构体，将结构体中的每个参数都赋初值。
	 *
	 * @param device   					      in，设备句柄
	 * @param digitalmod_profile_o     		  out，数字调制配置结构体
	 *
	 */
	H2_API void mod_init_digitalmod(void** device, digitalmod_profile* digitalmod_profile_o);

	/**
	 * @brief 初始化结构体
	 *
	 * 初始化AM调制配置结构体，将结构体中的每个参数都赋初值。
	 *
	 * @param device   					      in，设备句柄
	 * @param am_profile_o     		  		  out，AM调制配置结构体
	 *
	 */
	H2_API void mod_init_am(void** device, am_profile* am_profile_o);

	/**
	 * @brief 初始化结构体
	 *
	 * 初始化AM调制配置结构体，将结构体中的每个参数都赋初值。
	 *
	 * @param device   					      in，设备句柄
	 * @param fm_profile_o     		  		  out，FM调制配置结构体
	 *
	 */
	H2_API void mod_init_fm(void** device, fm_profile* fm_profile_o);

	/**
	 * @brief 初始化结构体
	 *
	 * 初始化直接序列扩频配置结构体，将结构体中的每个参数都赋初值。
	 *
	 * @param device   					      in，设备句柄
	 * @param dsss_profile_o     	  		  out，直接序列扩频配置结构体
	 *
	 */
	H2_API void mod_init_dsss(void** device, dsss_profile* dsss_profile_o);

	/**
	 * @brief 初始化结构体
	 *
	 * 初始化脉冲调制配置结构体，将结构体中的每个参数都赋初值。
	 * 
	 * @param device   					      in，设备句柄
	 * @param pulse_profile_o       	  	  out，脉冲调制配置结构体
	 *
	 */
	H2_API void mod_init_pulse(void** device, pulse_profile* pulse_profile_o);

	/**
	 * @brief 初始化结构体
	 *
	 * 初始化多音配置结构体，将结构体中的每个参数都赋初值
	 *
	 * @param device   					      in，设备句柄
	 * @param multitone_profile_o      		  out，多音配置结构体
	 *
	 */
	H2_API void mod_init_multitone(void** device, multitone_profile* multitone_profile_o);

	/**
	 * @brief 初始化结构体
	 *
	 * 初始化步进扫描配置结构体，将结构体中的每个参数都赋初值
	 *
	 * @param device   					      in，设备句柄
	 * @param stepsweep_profile_o      		  out，步进扫描配置结构体
	 *
	 */
	H2_API void mod_init_stepsweep(void** device, stepsweep_profile* stepsweep_profile_o);

	/**
	 * @brief 初始化结构体
	 *
	 * 初始化斜坡扫描配置结构体，将结构体中的每个参数都赋初值
	 *
	 * @param device   					      in，设备句柄
	 * @param rampsweep_profile_o      		  out，斜坡扫描配置结构体
	 *
	 */
	H2_API void mod_init_rampsweep(void** device, rampsweep_profile* rampsweep_profile_o);

	/**
	 * @brief 初始化结构体
	 *
	 * 初始化正交频分复用配置结构体，将结构体中的每个参数都赋初值
	 *
	 * @param device   					      in，设备句柄
	 * @param ofdm_profile_o           		  out，正交频分复用配置结构体
	 *
	 */
	H2_API void mod_init_ofdm(void** device, ofdm_profile* ofdm_profile_o);

	/**
	 * @brief 初始化结构体
	 *
	 * 初始化高斯白噪声配置结构体，将结构体中的每个参数都赋初值
	 *
	 * @param device   					      in，设备句柄
	 * @param awgn_profile_o           		  out，高斯白噪声配置结构体
	 *
	 */
	H2_API void mod_init_awgn(void** device, awgn_profile* awgn_profile_o);



	/**
	 * @brief 配置结构体
	 *
	 * 配置数字调制结构体参数，若输入配置不合理，将回写输出配置结构体为合理参数
	 *
	 * @param device   					    in，设备句柄
	 * @param digitalmod_profile_in     	in，输入数字调制配置结构体
	 * @param digitalmod_profile_o     		out，输出数字调制配置结构体
	 *
	 * @return 0 表示成功，非 0 表示失败
	 */
	H2_API int mod_config_digitalmod(void** device, const digitalmod_profile* digitalmod_profile_in, digitalmod_profile* digitalmod_profile_o);

	/**
	 * @brief 配置结构体
	 *
	 * 配置配置AM调制参数，若输入配置不合理，将回写输出配置结构体为合理参数
	 *
	 * @param device   					    in，设备句柄
	 * @param am_profile_in     			in，输入AM调制配置结构体
	 * @param am_profile_o     				out，输出AM调制配置结构体
	 *
	 * @return 0 表示成功，非 0 表示失败
	 */
	H2_API int mod_config_am(void** device, const am_profile* am_profile_in, am_profile* am_profile_o);

	/**
	 * @brief 配置结构体
	 *
	 * 配置配置FM调制参数，若输入配置不合理，将回写输出配置结构体为合理参数
	 *
	 * @param device   					    in，设备句柄
	 * @param fm_profile_in     			in，输入FM调制配置结构体
	 * @param fm_profile_o     				out，输出FM调制配置结构体
	 *
	 * @return 0 表示成功，非 0 表示失败
	 */
	H2_API int mod_config_fm(void** device, const fm_profile* fm_profile_in, fm_profile* fm_profile_o);

	/**
	 * @brief 配置结构体
	 *
	 * 配置直接序列扩频参数，若输入配置不合理，将回写输出配置结构体为合理参数
	 *
	 * @param device   					    in，设备句柄
	 * @param dsss_profile_in     			in，输入直接序列扩频配置结构体
	 * @param dsss_profile_o     			out，输出直接序列扩频配置结构体
	 *
	 * @return 0 表示成功，非 0 表示失败
	 */
	H2_API int mod_config_dsss(void** device, const dsss_profile* dsss_profile_in, dsss_profile* dsss_profile_o);

	/**
	 * @brief 配置结构体
	 *
	 * 配置脉冲调制参数，若输入配置不合理，将回写输出配置结构体为合理参数
	 *
	 * @param device   					    in，设备句柄
	 * @param pulse_profile_in     			in，输入脉冲调制配置结构体
	 * @param pulse_profile_o     			out，输出脉冲调制配置结构体
	 *
	 * @return 0 表示成功，非 0 表示失败
	 */
	H2_API int mod_config_pulse(void** device, const pulse_profile* pulse_profile_in, pulse_profile* pulse_profile_o);

	/**
	 * @brief 配置结构体
	 *
	 * 配置多音参数，若输入配置不合理，将回写输出配置结构体为合理参数
	 *
	 * @param device   					    in，设备句柄
	 * @param multitone_profile_in     		in，输入多音配置结构体
	 * @param multitone_profile_o     		out，输出多音配置结构体
	 *
	 * @return 0 表示成功，非 0 表示失败
	 */
	H2_API int mod_config_multitone(void** device, const multitone_profile* multitone_profile_in, multitone_profile* multitone_profile_o);

	/**
	 * @brief 配置结构体
	 *
	 * 配置步进扫描参数，若输入配置不合理，将回写输出配置结构体为合理参数
	 *
	 * @param device   					    in，设备句柄
	 * @param stepsweep_profile_in     		in，输入步进扫描配置结构体
	 * @param stepsweep_profile_o     		out，输出步进扫描配置结构体
	 *
	 * @return 0 表示成功，非 0 表示失败
	 */
	H2_API int mod_config_stepsweep(void** device, const stepsweep_profile* stepsweep_profile_in, stepsweep_profile* stepsweep_profile_o);

	/**
	 * @brief 配置结构体
	 *
	 * 配置斜坡扫描参数，若输入配置不合理，将回写输出配置结构体为合理参数
	 *
	 * @param device   					    in，设备句柄
	 * @param rampsweep_profile_in     		in，输入斜坡扫描配置结构体
	 * @param rampsweep_profile_o     		out，输出斜坡扫描配置结构体
	 *
	 * @return 0 表示成功，非 0 表示失败
	 */
	H2_API int mod_config_rampsweep(void** device, const rampsweep_profile* rampsweep_profile_in, rampsweep_profile* rampsweep_profile_o);

	/**
	 * @brief 配置结构体
	 *
	 * 配置正交频分复用参数，若输入配置不合理，将回写输出配置结构体为合理参数
	 *
	 * @param device   					    in，设备句柄
	 * @param ofdm_profile_in     			in，输入正交频分复用配置结构体
	 * @param ofdm_profile_o     			out，输出正交频分复用配置结构体
	 *
	 * @return 0 表示成功，非 0 表示失败
	 */
	H2_API int mod_config_ofdm(void** device, const ofdm_profile* ofdm_profile_in, ofdm_profile* ofdm_profile_o);

	/**
	 * @brief 配置结构体
	 *
	 * 配置高斯白噪声参数，若输入配置不合理，将回写输出配置结构体为合理参数
	 *
	 * @param device   					    in，设备句柄
	 * @param awgn_profile_in     			in，输入高斯白噪声配置结构体
	 * @param awgn_profile_o     			out，输出高斯白噪声配置结构体
	 *
	 * @return 0 表示成功，非 0 表示失败
	 */
	H2_API int mod_config_awgn(void** device, const awgn_profile* awgn_profile_in, awgn_profile* awgn_profile_o);



	/**
	 * @brief 生成信号数据
	 *
	 * 打开调制功能后，调用初始化函数赋初值，然后通过配置结构体函数下发参数，生成信号数据
	 *
	 * @param device   						in，设备句柄
	 * @param symbol_length					in，符号长度，用于数字调制、直接序列扩频调制
	 * @param iq_o     						out，输出信号数据
	 * @param length_o     					out，输出数据长度
	 * @param sample_rate_o     			out，当前生成数据所用的采样率
	 *
	 * @return 0 表示成功，非 0 表示失败
	 */
	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