#!/usr/bin/env python #-*- coding: utf-8 -*- """Simple python library to drive the analog discovery module from www.digilentinc.com """ from ctypes import * import time import sys import os import matplotlib.pyplot as plt import numpy as np __author__ = "Alexis Jeandet" __copyright__ = "Copyright 2015, Laboratory of Plasma Physics" __credits__ = [] __license__ = "GPLv2" __version__ = "1.0.0" __maintainer__ = "Alexis Jeandet" __email__ = "alexis.jeandet@member.fsf.org" __status__ = "Production" nodev = c_int(0) DwfStateReady = c_byte(0) DwfStateConfig = c_byte(4) DwfStatePrefill = c_byte(5) DwfStateArmed = c_byte(1) DwfStateWait = c_byte(7) DwfStateTriggered = c_byte(3) DwfStateRunning = c_byte(3) DwfStateDone = c_byte(2) DwfStateDict={ DwfStateReady.value:"Ready", DwfStateConfig.value:"Config", DwfStatePrefill.value:"Prefill", DwfStateArmed.value:"Armed", DwfStateWait.value:"Wait", DwfStateTriggered.value:"Triggered", DwfStateRunning.value:"Running", DwfStateDone.value:"Done" } DECIAnalogInChannelCount = c_int(1) DECIAnalogOutChannelCount = c_int(2) DECIAnalogIOChannelCount = c_int(3) DECIDigitalInChannelCount = c_int(4) DECIDigitalOutChannelCount = c_int(5) DECIDigitalIOChannelCount = c_int(6) DECIAnalogInBufferSize = c_int(7) DECIAnalogOutBufferSize = c_int(8) DECIDigitalInBufferSize = c_int(9) DECIDigitalOutBufferSize = c_int(10) trigsrcNone = c_byte(0) trigsrcPC = c_byte(1) trigsrcDetectorAnalogIn = c_byte(2) trigsrcDetectorDigitalIn = c_byte(3) trigsrcAnalogIn = c_byte(4) trigsrcDigitalIn = c_byte(5) trigsrcDigitalOut = c_byte(6) trigsrcAnalogOut1 = c_byte(7) trigsrcAnalogOut2 = c_byte(8) trigsrcAnalogOut3 = c_byte(9) trigsrcAnalogOut4 = c_byte(10) trigsrcExternal1 = c_byte(11) trigsrcExternal2 = c_byte(12) trigsrcExternal3 = c_byte(13) trigsrcExternal4 = c_byte(14) trigAuto = c_byte(254) trigNormal = c_byte(255) AnalogOutNodeCarrier = c_int(0) AnalogOutNodeFM = c_int(1) AnalogOutNodeAM = c_int(2) filterDecimate = c_int(0) filterAverage = c_int(1) filterMinMax = c_int(2) shapes = {'DC' : 0, 'Sine' : 1, 'Square' : 2, 'Triangle' : 3, 'RampUp' : 4, 'RampDown' : 5, 'Noise' : 6, 'Custom' : 30, 'Play' :31, } closed=False opened=True class DiscoveryLimits(object): class limitRange(object): def __init__(self,Min,Max,name="Unknow",unit=""): self.Min = Min self.Max = Max self.name = name self.unit = unit def conform(self,value): if valueself.Max: raise UserWarning("Parameter "+self.name+" out of bound\nValue="+str(value)+"\nForce to "+str(self.Max)) return self.Max return value def __str__(self): return self.name + ":\n Min="+str(self.Min)+" "+self.unit+",Max="+str(self.Max)+" "+self.unit errors = {0: RuntimeError("No card opened"), 1: UserWarning("Parameter out of bound"), } def __init__(self,libdwf,hdwf): self.limits=[] self.ACQ_IN_RANGES=[0.0] if hdwf.value == nodev.value: return self.__hdwf=hdwf self.__libdwf=libdwf Mind=c_double() Maxd=c_double() Mini=c_int() Maxi=c_int() StepsCount=c_int() Steps=(c_double*32)() self.__libdwf.FDwfAnalogInBufferSizeInfo(self.__hdwf, byref(Mini), byref(Maxi)) self.ACQ_BUF=self.limitRange(Mini.value,Maxi.value,"ACQ Buffer Size","Sps") self.limits.append(self.ACQ_BUF) self.__libdwf.FDwfAnalogInFrequencyInfo(self.__hdwf, byref(Mind), byref(Maxd)) self.ACQ_FREQ=self.limitRange(Mind.value,Maxd.value,"ACQ Frequency","Hz") self.limits.append(self.ACQ_FREQ) self.__libdwf.FDwfAnalogInChannelRangeSteps(self.__hdwf, byref(Steps), byref(StepsCount)) self.ACQ_IN_RANGES=Steps[0:StepsCount.value] self.__libdwf.FDwfAnalogOutNodeAmplitudeInfo(self.__hdwf,c_int(0), AnalogOutNodeCarrier, byref(Mind), byref(Maxd)) self.GEN_AMPL=self.limitRange(Mind.value,Maxd.value,"GEN Amplitude","V") self.limits.append(self.GEN_AMPL) self.__libdwf.FDwfAnalogOutNodeFrequencyInfo(self.__hdwf,c_int(0), AnalogOutNodeCarrier, byref(Mind), byref(Maxd)) self.GEN_FREQ=self.limitRange(Mind.value,Maxd.value,"GEN Frequency","Hz") self.limits.append(self.GEN_FREQ) self.__libdwf.FDwfAnalogOutNodeOffsetInfo(self.__hdwf,c_int(0), AnalogOutNodeCarrier, byref(Mind), byref(Maxd)) self.GEN_OFFSET=self.limitRange(Mind.value,Maxd.value,"GEN Offset","V") self.limits.append(self.GEN_OFFSET) self.__libdwf.FDwfAnalogOutNodeDataInfo(self.__hdwf,c_int(0), AnalogOutNodeCarrier, byref(Mini), byref(Maxi)) self.GEN_BUFF=self.limitRange(Mini.value,Maxi.value,"GEN Buffer size","Sps") self.limits.append(self.GEN_BUFF) def __conformParam(self,minVal,maxVal,val): if valmaxVal: raise self.errors.get(1) print("Force to "+str(maxVal)) return maxVal return val def acqFreq(self, value): return self.ACQ_FREQ.conform(value) def acqBufSize(self, value): return self.ACQ_BUF.conform(value) def genFreq(self, value): return self.GEN_FREQ.conform(value) def genAmplitude(self, value): return self.GEN_AMPL.conform(value) def genOffset(self, value): return self.GEN_OFFSET.conform(value) def genBuffSize(self, value): return self.GEN_BUFF.conform(value) def __str__(self): res=str() for i in self.limits: res+=i.__str__()+"\n" res+="ACQ Input ranes: "+str(self.ACQ_IN_RANGES) return res class Discovery(object): errors = {0: RuntimeError("No card opened"), 1: UserWarning("Parameter out of bound"), } def findDevice(self,device): if not self.__opened: raise self.errors.get(0) nbDevices = c_int() self.__libdwf.FDwfEnum(c_int(0), byref(nbDevices)) SN = create_string_buffer(32) for i in range(nbDevices.value): self.__libdwf.FDwfEnumSN(c_int(i), SN) if SN.value.decode("UTF-8") == device: return i return -1 def __init__(self,card=-1): if sys.platform.startswith("win"): self.__libdwf = cdll.dwf elif sys.platform.startswith("darwin"): self.__libdwf = cdll.LoadLibrary("libdwf.dylib") else: self.__libdwf = cdll.LoadLibrary("libdwf.so") self.__opened = True self.__hdwf = c_int() if card != -1: SN=card card = self.findDevice(card) if card == -1: raise RuntimeError( "Card not found "+ SN) self.__libdwf.FDwfDeviceOpen(c_int(card), byref(self.__hdwf)) if self.__hdwf.value == nodev.value: szerr = create_string_buffer(512) self.__libdwf.FDwfGetLastErrorMsg(szerr) print(szerr.value) print("failed to open device") self.__opened=False self.__limits=DiscoveryLimits(self.__libdwf,self.__hdwf) print(self.__limits) @property def opened(self): return self.__opened @property def max_sampling_freq(self): return self.__limits.ACQ_FREQ.Max @property def min_sampling_freq(self): return self.__limits.ACQ_FREQ.Min @property def max_sampling_buffer(self): return self.__limits.ACQ_BUF.Max ############################################################# # Power Supply ############################################################# def set_power(self,fiveVolt=1,minusFiveVolt=1,master=True): if not self.__opened: raise self.errors.get(0) # enable positive supply self.__libdwf.FDwfAnalogIOChannelNodeSet(self.__hdwf, 0, 0, c_double(fiveVolt)) # enable negative supply self.__libdwf.FDwfAnalogIOChannelNodeSet(self.__hdwf, 1, 0, c_double(minusFiveVolt)) # master enable return self.__libdwf.FDwfAnalogIOEnableSet(self.__hdwf, master) def get_power(self): if not self.__opened: raise self.errors.get(0) supplyVoltage = c_double() supplyCurrent = c_double() IsEnabled = c_bool() self.__libdwf.FDwfAnalogIOStatus(self.__hdwf) self.__libdwf.FDwfAnalogIOChannelNodeStatus(self.__hdwf, c_int(3), c_int(0), byref(supplyVoltage)) self.__libdwf.FDwfAnalogIOChannelNodeStatus(self.__hdwf, c_int(3), c_int(1), byref(supplyCurrent)) self.__libdwf.FDwfAnalogIOEnableStatus(self.__hdwf, byref(IsEnabled)) return [IsEnabled.value,supplyVoltage.value,supplyCurrent.value] ############################################################# # AnalogIn ############################################################# def analog_in_read(self,ch1=True,ch2=True,frequency=100000000,samplesCount=100,ch1range=5.0,ch2range=5.0,trigger=trigsrcNone): if not self.__opened: raise self.errors.get(0) cnt=self.__limits.acqBufSize(samplesCount) self.__libdwf.FDwfAnalogInFrequencySet(self.__hdwf, c_double(self.__limits.acqFreq(frequency))) f=c_double() self.__libdwf.FDwfAnalogInFrequencyGet(self.__hdwf, byref(f)) frequency=f.value self.__libdwf.FDwfAnalogInBufferSizeSet(self.__hdwf, c_int(cnt)) for ch in (0,1): self.__libdwf.FDwfAnalogInChannelEnableSet(self.__hdwf, c_int(ch), c_bool(ch2)) self.__libdwf.FDwfAnalogInChannelRangeSet(self.__hdwf, c_int(ch), c_double(ch2range)) self.__libdwf.FDwfAnalogInChannelFilterSet(self.__hdwf,c_int(ch),filterAverage) self.set_analog_in_trigger(trigger) self.__libdwf.FDwfAnalogInConfigure(self.__hdwf, c_bool(False), c_bool(True)) status = c_byte() while True: self.__libdwf.FDwfAnalogInStatus(self.__hdwf, c_int(1), byref(status)) if status.value == DwfStateDone.value : break time.sleep(0.1) if ch1: ch1data = (c_double*cnt)() self.__libdwf.FDwfAnalogInStatusData(self.__hdwf, 0, ch1data, cnt) if ch2: ch2data = (c_double*cnt)() self.__libdwf.FDwfAnalogInStatusData(self.__hdwf, 1, ch2data, cnt) return [np.array([ch1data,ch2data]),frequency] else: return [np.array([ch1data]),frequency] if ch2: ch2data = (c_double*cnt)() self.__libdwf.FDwfAnalogInStatusData(self.__hdwf, 1, ch2data, cnt) return [np.array([ch2data]),frequency] def set_analog_in_trigger(self,trigger=trigAuto,autoTimeout=0.0): if not self.__opened: raise self.errors.get(0) if trigger == trigAuto: self.__libdwf.FDwfAnalogInTriggerSourceSet(self.__hdwf,trigsrcDetectorAnalogIn) self.__libdwf.FDwfAnalogInTriggerAutoTimeoutSet(self.__hdwf,c_double(autoTimeout)) return if trigger == trigNormal: self.__libdwf.FDwfAnalogInTriggerSourceSet(self.__hdwf,trigsrcDetectorAnalogIn) self.__libdwf.FDwfAnalogInTriggerAutoTimeoutSet(self.__hdwf,c_double(0.0)) return self.__libdwf.FDwfAnalogInTriggerSourceSet(self.__hdwf,trigger) ############################################################# # AnalogOut ############################################################# def analog_out_enable(self,channel=0): self.__libdwf.FDwfAnalogOutConfigure(self.__hdwf, c_int(channel), c_bool(True)) def analog_out_disable(self,channel=0): self.__libdwf.FDwfAnalogOutConfigure(self.__hdwf, c_int(channel), c_bool(False)) def analog_out_gen(self,frequency=1000, symmetry=50.0, shape='Sine', channel=0, amplitude=1.0, offset=0.0,phase=0.0, syncOnTrigger=False, triggerFrq=1.0, wait=0.0, runDuration=None): self.__libdwf.FDwfAnalogOutConfigure(self.__hdwf, c_int(channel), c_bool(False)) self.__libdwf.FDwfAnalogOutNodeEnableSet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_bool(True)) self.__libdwf.FDwfAnalogOutNodeFunctionSet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_int(shapes.get(shape))) self.__libdwf.FDwfAnalogOutNodeSymmetrySet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_double(symmetry)) if shape!="DC": self.__libdwf.FDwfAnalogOutNodeFrequencySet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_double(self.__limits.genFreq(frequency))) self.__libdwf.FDwfAnalogOutNodeAmplitudeSet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_double(self.__limits.genAmplitude(amplitude))) self.__libdwf.FDwfAnalogOutNodeOffsetSet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_double(self.__limits.genOffset(offset))) self.__libdwf.FDwfAnalogOutNodePhaseSet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_double(phase)) if syncOnTrigger: self.analog_out_set_trigger(channel) self.__libdwf.FDwfAnalogOutRepeatSet(self.__hdwf, c_int(channel),c_int(0)) if runDuration is None: runDuration = triggerFrq self.__libdwf.FDwfAnalogOutRunSet(self.__hdwf, c_int(channel),c_double(runDuration)) self.__libdwf.FDwfAnalogOutWaitSet(self.__hdwf, c_int(channel), c_double(wait)) self.__libdwf.FDwfAnalogOutConfigure(self.__hdwf, c_int(channel), c_bool(True)) def analog_out_gen_arbit(self,samplesBuffer ,repeatingFrequency=100, channel=0, amplitude=1.0, offset=0.0): self.__libdwf.FDwfAnalogOutConfigure(self.__hdwf, c_int(channel), c_bool(False)) cnt=self.__limits.genBuffSize(len(samplesBuffer)) buf=(c_double*cnt)() buf[:]=samplesBuffer[0:cnt] #repeatingFrequency = self.__limits.genFreq(repeatingFrequency*cnt)/cnt self.__libdwf.FDwfAnalogOutNodeEnableSet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_bool(True)) self.__libdwf.FDwfAnalogOutNodeFunctionSet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_int(shapes.get("Custom"))) self.__libdwf.FDwfAnalogOutNodeFrequencySet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_double(repeatingFrequency)) self.__libdwf.FDwfAnalogOutNodeAmplitudeSet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_double(self.__limits.genAmplitude(amplitude))) self.__libdwf.FDwfAnalogOutNodeOffsetSet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_double(self.__limits.genOffset(offset))) self.__libdwf.FDwfAnalogOutNodeDataSet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, buf, c_int(cnt)) self.__libdwf.FDwfAnalogOutConfigure(self.__hdwf, c_int(channel), c_bool(True)) def analog_out_set_trigger(self, channel=0, trigSrc=trigsrcExternal1, trigRepeat=True): self.__libdwf.FDwfAnalogOutTriggerSourceSet(self.__hdwf, c_int(channel), trigSrc) self.__libdwf.FDwfAnalogOutRepeatTriggerSet(self.__hdwf, c_int(channel), c_bool(trigRepeat)) def __del__(self): if self.__opened: self.__libdwf.FDwfDeviceClose(self.__hdwf) def analog_out_status(self, channel=0): status = c_byte(DwfStateDone.value) self.__libdwf.FDwfAnalogOutStatus(self.__hdwf, c_int(channel), byref(status)) return status # def analog_out_modulation(self, channel=0, # carrier_frequency=10, carrier_shape='Sine', carrier_amplitude=1.0, carrier_offset=0.0, carrier_phase=0.0, carrier_symmetry=0.5, # AM_frequency=0.2857, AM_shape='Square', AM_amplitude=100.0, AM_offset=0.0, AM_phase=0.0, AM_percentageSymmetry=0.2857, # syncOnTrigger=trigsrcExternal1, triggerFrq=1.0, wait=0.0, runDuration=None): # self.__libdwf.FDwfAnalogOutConfigure(self.__hdwf, c_int(channel), c_bool(False)) # self.__libdwf.FDwfAnalogOutNodeEnableSet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_bool(True)) # # self.__libdwf.FDwfAnalogOutNodeFunctionSet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_int(shapes.get(carrier_shape))) # self.__libdwf.FDwfAnalogOutNodeFrequencySet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_double(self.__limits.genFreq(carrier_frequency))) # self.__libdwf.FDwfAnalogOutNodeAmplitudeSet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_double(self.__limits.genAmplitude(carrier_amplitude))) # self.__libdwf.FDwfAnalogOutNodeOffsetSet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_double(self.__limits.genOffset(carrier_offset))) # self.__libdwf.FDwfAnalogOutNodePhaseSet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_double(carrier_phase)) # self.__libdwf.FDwfAnalogOutNodeSymmetrySet(self.__hdwf, c_int(channel), AnalogOutNodeCarrier, c_double(carrier_percentageSymmetry)) # # self.__libdwf.FDwfAnalogOutNodeEnableSet(self.__hdwf, c_int(channel), AnalogOutNodeAM, c_bool(True)) # self.__libdwf.FDwfAnalogOutNodeFunctionSet(self.__hdwf, c_int(channel), AnalogOutNodeAM, c_int(shapes.get(AM_shape))) # self.__libdwf.FDwfAnalogOutNodeFrequencySet(self.__hdwf, c_int(channel), AnalogOutNodeAM, c_double(self.__limits.genFreqAM_frequency))) # self.__libdwf.FDwfAnalogOutNodeAmplitudeSet(self.__hdwf, c_int(channel), AnalogOutNodeAM, c_double(self.__limits.genAmplitude(AM_amplitude))) # self.__libdwf.FDwfAnalogOutNodeOffsetSet(self.__hdwf, c_int(channel), AnalogOutNodeAM, c_double(self.__limits.genOffset(AM_offset))) # self.__libdwf.FDwfAnalogOutNodePhaseSet(self.__hdwf, c_int(channel), AnalogOutNodeAM, c_double(AM_phase)) # self.__libdwf.FDwfAnalogOutNodeSymmetrySet(self.__hdwf, c_int(channel), AnalogOutNodeAM, c_double(AM_percentageSymmetry)) # # if syncOnTrigger: # self.analog_out_set_trigger(channel) # self.__libdwf.FDwfAnalogOutRepeatSet(self.__hdwf, c_int(channel),c_int(0)) # if runDuration is None: # runDuration = triggerFrq # self.__libdwf.FDwfAnalogOutRunSet(self.__hdwf, c_int(channel),c_double(runDuration)) # self.__libdwf.FDwfAnalogOutWaitSet(self.__hdwf, c_int(channel), c_double(wait)) # self.__libdwf.FDwfAnalogOutConfigure(self.__hdwf, c_int(channel), c_bool(True)) def digital_io_output_enable(self, value): self.__libdwf.FDwfDigitalIOOutputEnableSet(self.__hdwf, c_int(value)) def digital_io_get(self): dwRead = c_uint32() self.__libdwf.FDwfDigitalIOStatus (self.__hdwf) self.__libdwf.FDwfDigitalIOInputStatus(self.__hdwf, byref(dwRead)) return dwRead.value def digital_io_set(self,value): self.__libdwf.FDwfDigitalIOOutputSet(self.__hdwf, c_int(value)) @property def digital_io(self): return self.digital_io_get() @digital_io.setter def digital_io(self,value): self.digital_io_set(value) if __name__ == '__main__': print("open first dev") test = Discovery() test.set_power() for i in range(2): time.sleep(0.2) print(test.get_power()) test.analog_out_gen() res=test.analog_in_read(frequency=1000000,samplesCount=1000) print(res) plt.plot(range(len(res[0][0])),res[0][0]) plt.plot(range(len(res[0][0])),res[0][1]) plt.show() test.temp() # del test quit()