#ifndef H2_API_H
#define H2_API_H

#define Major_Version        2
#define Minor_Version        0
#define Increamental_Version 18

#define API_Version ((Major_Version << 16) | (Minor_Version << 8) | (Increamental_Version))

#include <stdint.h>
#include "h2_typedef.h"

#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

/* ========================================================================== */
/* Device APIs                                                                */
/* ========================================================================== */

/**
 * @brief 列举挂载在主机上的USB设备。
 *
 * @param[out] model      返回的USB设备类型
 * @param[out] uid_l64    返回的USB设备低64位ID
 * @param[out] uid_h32    返回的USB设备高32位ID
 * @param[out] count      挂载的USB设备总数量
 *
 * @return 0 成功，非 0 失败
 */
H2_API int device_list_usb(device_info* devInfo, uint32_t *count);

/**
 * @brief 强行指定通过USB进行供电，需在device_open_usb之前调用。
 *
 * @param[in] dnum  USB设备序号
 *
 * @return 0 成功，非 0 失败
 */
H2_API int device_powered_by_usb(uint8_t dnum);

/**
 * @brief 打开设备并获取通道信息。
 *
 * @param[out] device      返回设备句柄
 * @param[in]  boot        设备启动配置
 * @param[out] ch_o        返回通道数组
 * @param[out] chn         返回通道数量
 * @param[out] deviceInfo  返回设备信息
 *
 * @return 0 成功，非 0 失败
 */
H2_API int device_open_usb(void** device, uint8_t dnum, channel ch_o[], uint16_t* chn, device_info* dinfo);
//H2_API int device_open(void** device, BootSetting boot, channel ch_o[], uint16_t* chn, device_info* deviceInfo);

/**
 * @brief 打开eth设备并获取通道信息。
 *
 * @param[in] device       返回设备句柄
 * @param[in] settings     eth设备启动配置
 * @param[out] ch_o        返回通道数组
 * @param[out] chn         返回通道数量
 * @param[out] dinfo       返回设备信息
 *
 * @return 0 成功，非 0 失败
 */
H2_API int device_open_eth(void** device, eth_setting settings, channel ch_o[], uint16_t* chn, device_info* dinfo);

/**
 * @brief 关闭设备并释放相关资源。
 *
 * @param[in] device  设备句柄
 *
 * @return 0 成功，非 0 失败
 */
H2_API int device_close(void** device);

/**
 * @brief 设备复位（包含全通道复位）。
 *
 * @param[in] device  设备句柄
 *
 * @return 0 成功，非 0 失败
 */
H2_API int device_preset(void** device);

/**
 * @brief 查询设备当前温度。
 *
 * @param[in]  device  设备句柄
 * @param[out] temp_o  返回设备温度
 *
 * @return 0 成功，非 0 失败
 */
H2_API int device_query_temperature(void** device, float* temp_o);

/**
 * @brief 查询设备当前状态。
 *
 * @return 0 成功，非 0 对应返回值表检查
 */
H2_API int device_query_state(void** device);

/**
 * @brief 设定风扇配置。
 *
 * @param[in]  device  设备句柄
 * @param[in]  mode    风扇模式
 * @param[in]  auto_threshold  自动模式下的温度阈值
 *
 * @return 0 成功，非 0 失败
 */
H2_API int device_config_fan(void**device, fan_mode mode, float auto_threshold);

/**
 * @brief 查询设备当前供电信息。
 *
 * @param[in]  device  设备句柄
 * @param[out] supplyInfo_o  返回设备电压电流
 *
 * @return 0 成功，非 0 失败
 */
H2_API int device_query_supply(void** device, supply_info* supplyInfo_o);

/**
 * @brief 配置设备的GNSS参数。
 *
 * @param[in]  device      设备句柄
 * @param[in]  gnss        GNSS 配置参数
 *
 * @return 0 成功，非 0 失败
 */
H2_API int device_config_gnss(void** device, gnss_setting gnss);

/**
 * @brief 查询设备当前GNSS配置。
 *
 * @param[in]  device  设备句柄
 * @param[out] gnss_o  返回设备GNSS配置
 *
 * @return 0 成功，非 0 失败
 */
H2_API int device_query_gnss(void** device, gnss_setting* gnss_o);


/**
 * @brief 查询设备当前GNSS信息。
 *
 * @param[in]  device  设备句柄
 * @param[out] gnss_o  返回设备GNSS信息
 *
 * @return 0 成功，非 0 失败
 */
H2_API int device_query_gnss_info(void** device, gnss_info* gnss_o);

/**
 * @brief 查询 API 版本号。
 *
 * @return API 版本号
 */
H2_API uint32_t device_query_apiverion();

/**
 * @brief 配置设备参考时钟。
 *
 * @param device        in，设备句柄
 * @param source        in，参考时钟源
 * @param fref          in，参考时钟频率（单位 Hz）
 * @param out           in，参考时钟输出开关状态
 *
 * @return 执行状态码
 */
H2_API int device_config_clock(void** device, referenceclock_source source, double fref, state out);

/**
 * @brief 查询设备参考时钟配置。
 *
 * @param device        in，设备句柄
 * @param source_o      out，当前参考时钟源
 * @param fref_o        out，当前参考时钟频率（单位 Hz）
 * @param out_o         out，参考时钟输出开关状态
 * @param locked_o      out，时钟监控锁定状态（锁定后可获取当前实际参考时钟频率）
 *
 * @return 执行状态码
 */
H2_API int device_query_clock(void** device, referenceclock_source* source_o, double* fref_o, state* out_o, state* locked_o);

/**
 * @brief 复位 时钟监控。
 *
 * @param[in] device 设备句柄
 */
H2_API int device_reset_clock_monitor(void** device);

/**
 * @brief 清除设备中所有波形数据。
 *
 * @param[in] device  设备句柄
 *
 * @return 0 成功，非 0 失败
 */
H2_API int tx_clear_waveform(void** device);

/**
 * @brief 向设备下载波形数据。
 *
 * @param[in] device    设备句柄
 * @param[in] iq        IQ 数据
 * @param[in] points    IQ 点数
 * @param[out] waveform_o 波形序号
 *
 * @return 0 成功，非 0 失败
 */
H2_API int tx_download_waveform(void** device, int16_t iq[], uint32_t points, uint16_t* waveform_o);

/* ========================================================================== */
/* Channel APIs                                                               */
/* ========================================================================== */

/**
 * @brief 对多个通道执行复位操作。
 *
 * @param[in] ch   通道数组
 * @param[in] chn  通道数量
 *
 * @return 0 成功，非 0 失败
 */
H2_API int channel_preset(channel* ch);
//H2_API int channel_preset_mc(channel ch[], int16_t chn);

/**
 * @brief 启动多个通道运行。
 *
 * @param[in] ch   通道数组
 * @param[in] chn  通道数量
 *
 * @return 0 成功，非 0 失败
 */
H2_API int channel_start(channel* ch);
//H2_API int channel_start_mc(channel ch[], int16_t chn);

/**
 * @brief 停止多个通道运行。
 *
 * @param[in] ch   通道数组
 * @param[in] chn  通道数量
 *
 * @return 0 成功，非 0 失败
 */
H2_API int channel_stop(channel* ch);
//H2_API int channel_stop_mc(channel ch[], int16_t chn);

/**
 * @brief 对多个通道发起一次总线触发。
 *
 * @param[in] ch   通道数组
 * @param[in] chn  通道数量
 *
 * @return 0 成功，非 0 失败
 */
H2_API int channel_trigger_bus(channel* ch);
//H2_API int channel_trigger_bus_mc(channel ch[], int16_t chn);


/* ========================================================================== */
/* TX APIs                                                                    */
/* ========================================================================== */

/**
 * @brief 配置通道的频率和幅度参数（FFM）。
 *
 * @param[in] ch     目标通道
 * @param[in] fc     中心频率
 * @param[in] level  输出幅度
 *
 * @return 0 成功，非 0 失败
 */
H2_API int tx_config_ffm(channel* ch, double fc, float level);

/**
 * @brief 查询通道的频率和幅度参数（FFM）。
 *
 * @param[in]  ch       目标通道
 * @param[out] fc_o     返回中心频率
 * @param[out] level_o  返回输出幅度
 *
 * @return 0 成功，非 0 失败
 */
H2_API int tx_query_ffm(channel* ch, double* fc_o, float* level_o);

/**
 * @brief 配置通道的频率扫描参数（FSCAN）。
 *
 * 在固定功率 level下，从 start 开始，到 stop 为止，以 step 为步进递增频率
 *
 * @param[in] ch      目标通道
 * @param[in] start   扫描起始频率
 * @param[in] stop    扫描终止频率
 * @param[in] step    扫描步进频率
 * @param[in] level   输出幅度
 * @param[in] dwell   单个频点驻留时间（秒）
 *
 * @return 0 成功，非 0 失败
 */
H2_API int tx_config_fscan(channel* ch, double start, double stop, double step, float level, float dwell);

/**
 * @brief 测试通道的频率扫描参数（FSCAN）是否符合限制，用于人机交互UI开发时的参数限值预览
 *
 * 在固定功率 level下，从 start 开始，到 stop 为止，以 step 为步进递增频率
 *
 * @param[in] ch      目标通道
 * @param[inout] start   扫描起始频率
 * @param[inout] stop    扫描终止频率
 * @param[inout] step    扫描步进频率
 * @param[inout] level   输出幅度
 * @param[inout] dwell   单个频点驻留时间（秒）
 *
 * @return 0 成功，非 0 失败
 */
H2_API int tx_test_fscan(channel* ch, double* start, double* stop, double* step, float* level, float* dwell);

/**
 * @brief 查询通道的频率扫描参数（FSCAN）。
 *
 * @param[in]  ch        目标通道
 * @param[out] start_o  返回扫描起始频率
 * @param[out] stop_o   返回扫描终止频率
 * @param[out] step_o   返回扫描步进频率
 * @param[out] level_o  返回输出幅度
 * @param[out] dwell_o  返回单个频点驻留时间（秒）
 *
 * @return 0 成功，非 0 失败
 */
H2_API int tx_query_fscan(channel* ch, double* start_o, double* stop_o, double* step_o, float* level_o, float* dwell_o);

/**
 * @brief 配置通道的幅度扫描参数（LSCAN）。
 *
 * 在固定中心频率 fc 下，从 level_start 开始，到 level_stop 为止，以 level_step 为步进递增幅度，
 *
 * @param[in] ch            目标通道
 * @param[in] fc            中心频率
 * @param[in] level_start   扫描起始幅度
 * @param[in] level_stop    扫描终止幅度
 * @param[in] level_step    扫描步进幅度
 * @param[in] dwell         单个幅度点驻留时间（秒）
 *
 * @return 0 成功，非 0 失败
 */
H2_API int tx_config_lscan(channel* ch, double fc, float level_start, float level_stop, float level_step, float dwell);

/**
 * @brief 测试通道的幅度扫描参数（LSCAN）是否符合限制，用于人机交互UI开发时的参数限值预览
 *
 * 在固定中心频率 fc 下，从 level_start 开始，到 level_stop 为止，以 level_step 为步进递增幅度，
 *
 * @param[in] ch            目标通道
 * @param[inout] fc            中心频率
 * @param[inout] level_start   扫描起始幅度
 * @param[inout] level_stop    扫描终止幅度
 * @param[inout] level_step    扫描步进幅度
 * @param[inout] dwell         单个幅度点驻留时间（秒）
 *
 * @return 0 成功，非 0 失败
 */
H2_API int tx_test_lscan(channel* ch, double* fc, float* level_start, float* level_stop, float* level_step, float* dwell);

/**
 * @brief 查询通道的幅度扫描参数（LSCAN）。
 *
 * @param[in]  ch              目标通道
 * @param[out] fc_o            返回中心频率
 * @param[out] level_start_o   返回扫描起始幅度
 * @param[out] level_stop_o    返回扫描终止幅度
 * @param[out] level_step_o    返回扫描步进幅度
 * @param[out] dwell_o         返回单个幅度点驻留时间（秒）
 *
 * @return 0 成功，非 0 失败
 */
H2_API int tx_query_lscan(channel* ch, double* fc_o, float* level_start_o, float* level_stop_o, float* level_step_o, float* dwell_o);

/**
 * @brief 配置通道的多点扫描参数（MSCAN）。
 *
 * 按数组下标顺序，从第 0 点到第 n-1 点依次扫描，
 * 每个点使用对应的 fc[i] 与 level[i]，
 *
 * @param[in] ch       目标通道
 * @param[in] fc       频率数组，长度为 n
 * @param[in] level    幅度数组，长度为 n
 * @param[in] dwell    驻留时间数组（秒），长度为 n
 * @param[in] n        扫描点个数
 *
 * @return 0 成功，非 0 失败
 */
H2_API int tx_config_mscan(channel* ch, const double fc[], const float level[], const float dwell[], int16_t n);

/**
 * @brief 测试通道的多点扫描参数（MSCAN）是否符合限制，用于人机交互UI开发时的参数限值预览
 *
 * 按数组下标顺序，从第 0 点到第 n-1 点依次扫描，
 * 每个点使用对应的 fc[i] 与 level[i]，
 *
 * @param[in] ch          目标通道
 * @param[inout] fc       频率数组，长度为 n
 * @param[inout] level    幅度数组，长度为 n
 * @param[inout] dwell    驻留时间数组（秒），长度为 n
 * @param[inout] n        扫描点个数
 *
 * @return 0 成功，非 0 失败
 */
H2_API int tx_test_mscan(channel* ch, double fc[], float level[], float dwell[], int16_t* n);

/**
 * @brief 查询通道的多点扫描参数（MSCAN）。
 *
 * 按数组下标顺序返回当前配置的扫描序列。
 *
 * @param[in]  ch       目标通道
 * @param[out] fc_o     返回频率数组，长度为 n
 * @param[out] level_o  返回幅度数组，长度为 n
 * @param[out] dwell_o  返回驻留时间数组（秒），长度为 n
 * @param[in]  n        扫描点个数
 *
 * @return 0 成功，非 0 失败
 */
H2_API int tx_query_mscan(channel* ch, double fc_o[], float level_o[], float dwell_o[], int16_t* n);

/**
 * @brief 配置通道触发参数。
 *
 * @param[in] ch   目标通道
 * @param[in] trg  触发配置参数
 *
 * @return 0 成功，非 0 失败
 */
H2_API int channel_config_trigger(channel* ch, const tx_trigger* trg);

/**
 * @brief 查询通道触发配置。
 *
 * @param[in]  ch     目标通道
 * @param[out] trg_o  返回触发配置
 *
 * @return 0 成功，非 0 失败
 */
H2_API int channel_query_trigger(channel* ch, tx_trigger* trg_o);

/**
 * @brief 配置通道触发输出参数。
 *
 * @param[in] ch   目标通道
 * @param[in] trg  触发输出配置参数
 *
 * @return 0 成功，非 0 失败
 */
H2_API int channel_config_trigger_out(channel* ch, const trigger_out* trg);

/**
 * @brief 查询通道触发输出配置。
 *
 * @param[in]  ch     目标通道
 * @param[out] trg_o  返回触发输出配置
 *
 * @return 0 成功，非 0 失败
 */
H2_API int channel_query_trigger_out(channel* ch, trigger_out* trg_o);

/**
 * @brief 配置通道本振模式。
 *
 * @param[in] ch       目标通道
 * @param[in] lomode   本振模式配置
 *
 * @return 0 成功，非 0 失败
 */
H2_API int channel_config_lo_mode(channel* ch, lomode mode); 

/**
 * @brief 查询通道本振模式。
 *
 * @param[in]  ch         目标通道
 * @param[out] loMode_o   返回本振模式配置
 *
 * @return 0 成功，非 0 失败
 */
H2_API int channel_query_lo_mode(channel* ch, lomode* mode_o);

/**
 * @brief 配置多个通道的输出状态（RFOUT / MOD）。
 *
 * @param[in] ch     通道数组
 * @param[in] rfout  射频输出配置
 * @param[in] mod    调制输出配置
 * @param[in] chn    通道数量
 *
 * @return 0 成功，非 0 失败
 */
H2_API int tx_config_output(channel* ch, state rfout, state mod);

/**
 * @brief 查询多个通道的输出状态（RFOUT / MOD）。
 *
 * @param[in]  ch        通道数组
 * @param[out] rfout_o   返回射频输出状态
 * @param[out] mod_o     返回调制输出状态
 * @param[in]  chn       通道数量
 *
 * @return 0 成功，非 0 失败
 */
H2_API int tx_query_output(channel* ch, state* rfout_o, state* mod_o);
//H2_API int tx_query_output_mc(channel ch[], int8_t* rfout_o, int8_t* mod_o, int16_t chn);

/**
 * @brief 多通道发送连续波（CW）。
 *
 * @param[in] ch   通道数组
 * @param[in] chn  通道数量
 *
 * @return 0 成功，非 0 失败
 */
H2_API int tx_config_cw(channel* ch);
//H2_API int tx_config_cw_mc(channel ch[], int16_t chn);

/**
 * @brief 配置指定通道的流播放参数
 *
 * @param[in] ch          指定通道
 * @param[in] sample_rate 采样率
 *
 * @return 0 成功，非 0 失败
 */
H2_API int tx_config_stream(channel* ch, double sample_rate);

/**
 * @brief 对指定通道发送IQ流实时播放
 *
 * @param[in] ch          指定通道
 * @param[in] iq          IQ 数据
 * @param[in] points      IQ 点数
 *
 * @return 0 成功，非 0 失败
 */H2_API int tx_send_stream(channel* ch, int16_t iq[], uint32_t points);

/**
 * @brief 配置指定通道的波形回放参数。
 *
 * @param[in] ch        目标通道
 * @param[in] waveform  波形索引数组
 * @param[in] repeat    循环播放次数
 * @param[in] sample_rate 采样率数组
 * @param[in] waveforms   播放的波形数量
 *
 * @return 0 成功，非 0 失败
 */
H2_API int tx_config_playback(channel* ch, const int16_t waveform[], const int32_t repeat[], const double sample_rate[], int16_t waveforms);

/**
 * @brief 将 unix Epoch 纳秒时间戳转换为可读的 UTC 时间
 *
 * @param[in]  ns_sinceepoch  从 Epoch 起累计的时间，单位：ns
 * @param[out] year  年（如 2026）
 * @param[out] mon   月（1 ~ 12）
 * @param[out] day   日（1 ~ 31）
 * @param[out] hour  时（0 ~ 23）
 * @param[out] min   分（0 ~ 59）
 * @param[out] sec   秒（0 ~ 59）
 * @param[out] ms    毫秒（0 ~ 999）
 * @param[out] us    微秒（0 ~ 999）
 * @param[out] ns    纳秒（0 ~ 999）
 */
H2_API void device_epoch_to_utc(uint64_t ns_sinceepoch, int16_t* year, int16_t* mon, int16_t* day, int16_t* hour, int16_t* min, int16_t* sec, int16_t* ms, int16_t* us, int16_t* ns);


#ifdef __cplusplus
}
#endif

#endif /* H2_API_H */
