##// END OF EJS Templates
Merge
Merge

File last commit:

r14:7b43cd98469d default
r16:57e3ff45aefd merge tip default
Show More
discovery.py
458 lines | 19.7 KiB | text/x-python | PythonLexer
#!/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 value<self.Min:
raise UserWarning("Parameter "+self.name+" out of bound\nValue="+str(value)+"\nForce to "+str(self.Min))
return self.Min
if value>self.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 val<minVal:
raise self.errors.get(1)
print("Force to "+str(minVal))
return minVal
if val>maxVal:
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))
range,enabled = [ch1range,ch2range],[ch1,ch2]
for ch in (0,1):
self.__libdwf.FDwfAnalogInChannelEnableSet(self.__hdwf, c_int(ch), c_bool(enabled[ch]))
self.__libdwf.FDwfAnalogInChannelRangeSet(self.__hdwf, c_int(ch), c_double(range[ch]))
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()