from htra_api import *

###打开设备###
Status = 0          #函数的返回。
Device = c_void_p() #当前设备的内存地址。
DevNum = c_int(0)   #指定设备号。

BootProfile = BootProfile_TypeDef() #启动配置结构体，包括物理接口、供电方式等。
BootInfo = BootInfo_TypeDef()       #启动信息结构体，包括设备信息、USB速率等。

BootProfile.DevicePowerSupply = DevicePowerSupply_TypeDef.USBPortAndPowerPort #使用USB数据端口及独立电源端口双供电
BootProfile.PhysicalInterface = PhysicalInterface_TypeDef.USB                 #使用USB接口进行数据传输。

#使用网口设备配置ETH接口
#BootProfile.PhysicalInterface = PhysicalInterface_TypeDef.ETH #使用网口进行数据传输
#BootProfile.ETH_IPVersion = IPVersion_TypeDef.IPv4
#BootProfile.ETH_RemotePort = 5000
#BootProfile.ETH_ReadTimeOut = 10000
#BootProfile.ETH_IPAddress[0] = 192
#BootProfile.ETH_IPAddress[1] = 168
#BootProfile.ETH_IPAddress[2] = 1
#BootProfile.ETH_IPAddress[3] = 100

Status = dll.Device_Open(pointer(Device),DevNum,pointer(BootProfile),pointer(BootInfo)) #打开设备。
if(Status == 0):
    print("Device is opened successfully")
else:
    print("Return other errors Status = {:d}".format(Status))

###配置下发###
IQS_ProfileIn = IQS_Profile_TypeDef()  #IQS输入配置，包括起始频率、终止频率、RBW、参考电平等。
IQS_ProfileOut = IQS_Profile_TypeDef() #IQS输出配置。
StreamInfo = IQS_StreamInfo_TypeDef()  #当前配置下IQ数据信息，包括带宽,IQ单路采样率等。

dll.IQS_ProfileDeInit(pointer(Device),pointer(IQS_ProfileIn)) #初始化配置IQS模式下的相关参数。

IQS_ProfileIn.CenterFreq_Hz = 1e9                           #配置中心频率。
IQS_ProfileIn.RefLevel_dBm = 0                              #配置参考电平。
IQS_ProfileIn.DecimateFactor = 2                            #配置抽取倍数。
IQS_ProfileIn.DataFormat = DataFormat_TypeDef.Complex16bit  #配置IQ数据格式。
IQS_ProfileIn.TriggerSource = IQS_TriggerSource_TypeDef.Bus #配置触发源为内部总线触发。
IQS_ProfileIn.TriggerMode = TriggerMode_TypeDef.FixedPoints
IQS_ProfileIn.TriggerLength = 16242                         #配置单次触发采集的点数，仅当TriggerMode设置为FixedPoints时生效。

Status = dll.IQS_Configuration(pointer(Device),pointer(IQS_ProfileIn),pointer(IQS_ProfileOut),pointer(StreamInfo))  #下发IQS模式的相关配置。

if(Status == 0):
    print("configuration delievery succeeded")
else:
    print("SWP_Configuration call is incorrect Status = {:d}".format(Status))

###获取数据###
IQ_Data = (c_int16 * (StreamInfo.StreamSamples*2))() #存放IQ数据
AlternIQPacket = c_int16_p()                         #指向IQ数据(库函数)临时存放地址的指针
ScaleToV = c_float()                                 #幅度还原成电压的缩放因子
TriggerInfo = IQS_TriggerInfo_TypeDef()              #迹线信息结构体
MeasAuxInfo = MeasAuxInfo_TypeDef()                  #测量辅助信息结构体

try:
    while(True):
        Status = dll.IQS_BusTriggerStart(pointer(Device)) #调用IQS_BusTriggerStart触发设备。若触发源为外部触发，则不需要调用此函数。
        for i in range(0,StreamInfo.PacketCount):
            dll.IQS_GetIQStream(pointer(Device),pointer(AlternIQPacket),pointer(ScaleToV),pointer(TriggerInfo),pointer(MeasAuxInfo)) #获取IQ数据包、触发信息、I路数据最大值及最大值数组下标
            if(i == StreamInfo.PacketCount - 1 and StreamInfo.StreamSamples % StreamInfo.PacketSamples != 0):                        #可能最后一包不满一整包（16242个点）；所以只需要循环不满一包的点数
                IQ_Data[(i*StreamInfo.PacketSamples*2):] = AlternIQPacket[0:(2*(StreamInfo.StreamSamples % StreamInfo.PacketSamples))]
                break
            else:
                IQ_Data[(i*StreamInfo.PacketSamples*2):((i+1)*StreamInfo.PacketSamples*2)] = AlternIQPacket[0:(StreamInfo.PacketSamples*2)]
        I_DATA = IQ_Data[0::2] #I数据分离。
        Q_DATA = IQ_Data[1::2] #Q数据分离。
        #若要乘ScaleToV转为以V为单位的数据，则如以下方式分离
        #scale = float(ScaleToV.value)
        #I_DATA = [x * scale for x in IQ_Data[0::2]]
        #Q_DATA = [x * scale for x in IQ_Data[1::2]]

        
except KeyboardInterrupt:
    print("Stopped by user with Ctrl+C")
finally:
    dll.Device_Close(pointer(Device))
    print("Device closed.")
