Commit 1ddf74bf authored by Matthieu Cattin's avatar Matthieu Cattin

Change data from ADC to two's complement. Auto detection of ttyUSB devices based…

Change data from ADC to two's complement. Auto detection of ttyUSB devices based on vendor id and product id. test17 calibration is working fine, but calibration data still needs to be stored in EEPROM.
parent 8c0345d2
......@@ -23,8 +23,8 @@ calibr_box: Access to calibration box via USB-UART bridge CP2103
class CCalibr_box:
def __init__(self, dev_num):
self.cp210x = cp210x.CCP210x(dev_num)
def __init__(self, device):
self.cp210x = cp210x.CCP210x(device)
# Select AWG as default output
self.cp210x.gpio_set(0x0)
......
......@@ -6,8 +6,8 @@ import time
import array
class CCP210x:
def __init__(self, usb_number):
self.fd = open('/dev/ttyUSB' + str(usb_number), 'wb')
def __init__(self, device):
self.fd = open(device, 'wb')
def gpio_set(self, mask):
fcntl.ioctl(self.fd.fileno(), 0x8001, mask)
......
......@@ -17,6 +17,22 @@ import si57x
import eeprom_24aa64
# Converts digital value to volts
def digital2volt(value, full_scale, nb_bit):
return float(value) * float(full_scale)/2**nb_bit - full_scale/2.0
# Converts volts to digital value with half full range offset
def volt2digital(value, full_scale, nb_bit):
digital = (value + full_scale/2) * 2**nb_bit/full_scale
if(digital > 2**nb_bit - 1):
digital = 2**nb_bit - 1
if(digital < 0):
digital = 0
#print('volt2digital: %2.9f > %2.9f')%(value,digital)
return int(digital)
class CFmcAdc100Ms:
FMC_SYS_I2C_ADDR = 0x60000
......@@ -290,34 +306,45 @@ class CFmcAdc100Ms:
self.dac_gain_corr = gain
def dac_apply_corr(self, value, gain_corr, offset_corr):
return int((float(value) + offset_corr) * gain_corr)
value = digital2volt(value, 10, 16)
value_corr = (float(value) + offset_corr) * gain_corr
return volt2digital(value_corr, 10, 16)
# Set DC offset with gain and offset correction
# value = DAC unsigned integer value
def set_dc_offset_corrected(self, channel, value):
print_value = False
if(1 == channel):
#print('CH%d DAC uncorrected value: 0x%.4X')%(channel, value)
uncorr_value = value
value = self.dac_apply_corr(value, self.dac_gain_corr[channel-1],self.dac_offset_corr[channel-1])
#print('gain corr: %1.9f offset corr: %1.9f')%(self.dac_gain_corr[channel-1], self.dac_offset_corr[channel-1])
#print('CH%d DAC corrected value : 0x%.4X')%(channel, value)
if(print_value):
print('CH%d DAC uncorrected value: 0x%.4X')%(channel, uncorr_value)
print('CH%d DAC corrected value : 0x%.4X')%(channel, value)
self.dac_ch1.set_offset(value)
elif(2 == channel):
#print('CH%d DAC uncorrected value: 0x%.4X')%(channel, value)
uncorr_value = value
value = self.dac_apply_corr(value, self.dac_gain_corr[channel-1],self.dac_offset_corr[channel-1])
#print('gain corr: %1.9f offset corr: %1.9f')%(self.dac_gain_corr[channel-1], self.dac_offset_corr[channel-1])
#print('CH%d DAC corrected value : 0x%.4X')%(channel, value)
if(print_value):
print('CH%d DAC uncorrected value: 0x%.4X')%(channel, uncorr_value)
print('CH%d DAC corrected value : 0x%.4X')%(channel, value)
self.dac_ch2.set_offset(value)
elif(3 == channel):
#print('CH%d DAC uncorrected value: 0x%.4X')%(channel, value)
uncorr_value = value
value = self.dac_apply_corr(value, self.dac_gain_corr[channel-1],self.dac_offset_corr[channel-1])
#print('gain corr: %1.9f offset corr: %1.9f')%(self.dac_gain_corr[channel-1], self.dac_offset_corr[channel-1])
#print('CH%d DAC corrected value : 0x%.4X')%(channel, value)
if(print_value):
print('CH%d DAC uncorrected value: 0x%.4X')%(channel, uncorr_value)
print('CH%d DAC corrected value : 0x%.4X')%(channel, value)
self.dac_ch3.set_offset(value)
elif(4 == channel):
#print('CH%d DAC uncorrected value: 0x%.4X')%(channel, value)
uncorr_value = value
value = self.dac_apply_corr(value, self.dac_gain_corr[channel-1],self.dac_offset_corr[channel-1])
#print('gain corr: %1.9f offset corr: %1.9f')%(self.dac_gain_corr[channel-1], self.dac_offset_corr[channel-1])
#print('CH%d DAC corrected value : 0x%.4X')%(channel, value)
if(print_value):
print('CH%d DAC uncorrected value: 0x%.4X')%(channel, uncorr_value)
print('CH%d DAC corrected value : 0x%.4X')%(channel, value)
self.dac_ch4.set_offset(value)
else:
raise Exception('Unsupported parameter, channel number from 1 to 4')
......
......@@ -59,7 +59,8 @@ class CLTC217x:
self.spi = spi
self.slave = slave
self.wr_reg(self.R_RST, self.RST)
self.wr_reg(self.R_FMT, 0)
#self.wr_reg(self.R_FMT, 0)
self.wr_reg(self.R_FMT, self.FMT_TWOSCOMP)
#self.wr_reg(self.R_OUTMODE, (self.OUTMODE_ILVDS_4M5 | self.OUTMODE_2L_16B | self.OUTMODE_TERMON))
#self.wr_reg(self.R_OUTMODE, (self.OUTMODE_ILVDS_2M5 | self.OUTMODE_2L_16B | self.OUTMODE_TERMON))
self.wr_reg(self.R_OUTMODE, (self.OUTMODE_ILVDS_4M5 | self.OUTMODE_2L_16B))
......
......@@ -42,7 +42,7 @@ ACQ_TIMEOUT = 10
MAX_FIRMWARE_RELOAD = 10
PRE_TRIG_SAMPLES = 10
POST_TRIG_SAMPLES = 1000
POST_TRIG_SAMPLES = 10000
NB_SHOTS = 1
ACQ_LENGTH = 10000 # in samples
......@@ -51,22 +51,30 @@ DMA_LENGTH = 4096 # in bytes
# col 0: freq
# col 1: expected amplitude (ADC raw data)
# col 2: tolerance on the amplitude
points = [[1E3, 33300, 4000],
[10E3, 33300, 4000],
points = [[10E3, 33300, 4000],
[100E3, 33300, 4000],
[1E6, 33300, 4000],
[5E6, 33300, 4000],
[6E6, 33300, 4000],
[7E6, 33300, 4000],
[8E6, 33300, 4000],
[9E6, 33300, 4000],
[10E6, 21000, 4000],
[11E6, 21000, 4000],
[12E6, 21000, 4000],
[13E6, 21000, 4000],
[14E6, 21000, 4000],
[15E6, 16500, 4000],
[16E6, 15700, 4000],
[17E6, 15000, 4000],
[18E6, 14500, 4000],
[19E6, 14000, 4000],
[20E6, 12500, 4000],
#[20E6, 12500, 4000],
[21E6, 12500, 4000],
[22E6, 12500, 4000],
[23E6, 12000, 4000],
[24E6, 11500, 4000],
[25E6, 10000, 4000],
#[25E6, 10000, 4000],
[30E6, 9000, 4000],
[32E6, 9000, 4000],
[34E6, 9000, 4000],
......@@ -140,7 +148,7 @@ def fmc_adc_init(spec, fmc):
def set_awg_freq(gen, sine, freq):
sine.frequency = freq
gen.play(sine)
print('Sine frequency:%3.3fMHz')%(sine.frequency/1E6)
#print('Sine frequency:%3.3fMHz')%(sine.frequency/1E6)
time.sleep(AWG_SET_SLEEP)
......@@ -167,23 +175,39 @@ def acquisition(gnum, pages, fmc, spec_fmc, channel_nb):
return channels_data[channel_nb-1::4]
def show_result_graph(points, ch_diff):
def show_result_graph(points, ch_diff, ch):
pt = array(points)
freq = pt[:,0]
a_min = pt[:,1] - pt[:,2]
a_max = pt[:,1] + pt[:,2]
semilogx(freq, ch_diff[0::4], 'b', label='Channel 1')
semilogx(freq, ch_diff[1::4], 'g', label='Channel 2')
semilogx(freq, ch_diff[2::4], 'r', label='Channel 3')
semilogx(freq, ch_diff[3::4], 'c', label='Channel 4')
cutoff = [-3] * len(points)
ch_label = 'Channel' + str(ch)
semilogx(freq, ch_diff, 'b', label=ch_label)
#semilogx(freq, ch_diff[1::4], 'g', label='Channel 2')
#semilogx(freq, ch_diff[2::4], 'm', label='Channel 3')
#semilogx(freq, ch_diff[3::4], 'c', label='Channel 4')
#semilogx(freq, a_min, 'r:', label='Lower limit')
#semilogx(freq, a_max, 'r:', label='Upper limit')
semilogx(freq, cutoff, 'r', label='-3dB')
grid(which='both')
legend()
legend(loc='upper left')
show()
return 0
# Converts two's complement hex to signed
def hex2signed(value):
if(value & 0x8000):
return -((~value & 0xFFFF) + 1)
else:
return value
# Converts digital value to volts
def digital2volt(value, full_scale, nb_bit):
return float(value) * float(full_scale)/2**nb_bit
def main (default_directory='.'):
# Load firmware to FPGA
......@@ -225,27 +249,33 @@ def main (default_directory='.'):
# Get physical addresses of the pages for DMA transfer
pages = gnum.get_physical_addr()
ch_sel = int(raw_input('Select a channel [1:4]:'))
print("Channel %d selected.")%ch_sel
# Test frequency response of all channels
ch_diff = []
i = ch_sel
for j in range(len(points)):
set_awg_freq(gen, sine, points[j][0])
for i in range(1,NB_CHANNELS+1):
fmc.set_input_range(i, '1V')
fmc.set_input_term(i, 'ON')
time.sleep(SSR_SET_SLEEP)
channel_data = []
channel_data = acquisition(gnum, pages, fmc, spec_fmc, i)
diff = max(channel_data)-min(channel_data)
#print('CH%d amplitude:%d expected:%d +/-%d')%(i, diff, points[j][1], points[j][2])
ch_diff.append(diff)
fmc.set_input_range(i, 'OPEN')
fmc.set_input_term(i, 'OFF')
#for i in range(1,NB_CHANNELS+1):
fmc.set_input_range(i, '1V')
fmc.set_input_term(i, 'ON')
time.sleep(SSR_SET_SLEEP)
channel_data = []
channel_data = acquisition(gnum, pages, fmc, spec_fmc, i)
channel_data = [hex2signed(item) for item in channel_data]
channel_data_v = [digital2volt(item,1.0,16) for item in channel_data]
diff = max(channel_data_v)-min(channel_data_v)
print('CH%d frequency:%6.0f Hz amplitude:%f V')%(i, points[j][0], diff)
ch_diff.append(diff)
fmc.set_input_range(i, 'OPEN')
fmc.set_input_term(i, 'OFF')
# print freqency response to log
print('Channels frequency response')
print('Frequency, CH1 value, CH2 value, CH3 value, CH4 value')
print('Frequency, CH%d value')%ch_sel
for i in range(len(points)):
print('%2.3f, %d, %d, %d, %d')%(points[i][0]/1E6, ch_diff[i*4], ch_diff[i*4+1], ch_diff[i*4+2], ch_diff[i*4+3])
print('%2.3f, %f')%(points[i][0]/1E6, ch_diff[i])
# print aqcuisition to file
# open test09 log file in read mode
......@@ -253,12 +283,23 @@ def main (default_directory='.'):
if file_name == "":
file_name = "log_test16.txt"
file = open(file_name, 'w')
file.write("Frequency, CH1 amplitude, CH2 amplitude, CH3 amplitude, CH4 amplitude\n")
file.write("Frequency, CH%d amplitude\n"%ch_sel)
for i in range(len(points)):
file.write('%2.3f, %f\n'%(points[i][0]/1E6, ch_diff[i]))
# Convert volts to dB
vref = ch_diff[0]
print('vref=%f')% vref
ch_diff = [(20*log(item/vref)) for item in ch_diff]
# print freqency response to log
print('Channels frequency response in dB')
print('Frequency, CH%d value')%ch_sel
for i in range(len(points)):
file.write('%2.3f, %d, %d, %d, %d\n'%(points[i][0]/1E6, ch_diff[i*4], ch_diff[i*4+1], ch_diff[i*4+2], ch_diff[i*4+3]))
print('%2.3f, %f')%(points[i][0]/1E6, ch_diff[i])
# Plot results
show_result_graph(points, ch_diff)
show_result_graph(points, ch_diff, ch_sel)
# Make sure all switches are OFF
open_all_channels(fmc)
......
......@@ -19,6 +19,7 @@ from ptsexcept import *
import spec_fmc_adc
import fmc_adc
import calibr_box
import find_usb_tty
from PAGE.Agilent33250A import *
from PAGE.SineWaveform import *
......@@ -32,7 +33,14 @@ Note: Requires test00.py to run first to load the firmware!
GN4124_CSR = 0x0
USB_DEVICE = "/dev/ttyUSB0"
# Calibration box vendor and device IDs
BOX_USB_VENDOR_ID = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device
# Agilent AWG serial access vendor and device IDs
AWG_USB_VENDOR_ID = 0x0403 # Future Technology Devices International, Ltd
AWG_USB_DEVICE_ID = 0x6001 # FT232 USB-Serial (UART) IC
RS232_BAUD = 57600
NB_CHANNELS = 4
AWG_SET_SLEEP = 1
......@@ -45,7 +53,7 @@ ACQ_TIMEOUT = 10
MAX_FIRMWARE_RELOAD = 10
PRE_TRIG_SAMPLES = 1000
POST_TRIG_SAMPLES = 50000
POST_TRIG_SAMPLES = 100000
NB_SHOTS = 1
ACQ_LENGTH = 50000 # in samples
......@@ -101,31 +109,6 @@ def set_awg_freq(gen, sine, freq):
time.sleep(AWG_SET_SLEEP)
def acquisition(fmc, spec_fmc, channel_nb):
# Make sure no acquisition is running
fmc.stop_acq()
#print('Acquisition FSM state : %s') % fmc.get_acq_fsm_state()
# Start acquisition
fmc.start_acq()
time.sleep(0.01)
# Trigger
fmc.sw_trig()
# Wait end of acquisition
timeout = 0
while('IDLE' != fmc.get_acq_fsm_state()):
#print fmc.get_acq_fsm_state()
time.sleep(.1)
timeout += 1
if(ACQ_TIMEOUT < timeout):
print('Acquisition timeout. Check that the AWG is switched ON and properly connected.')
return 1
# Retrieve data trough DMA
trig_pos = fmc.get_trig_pos()
#print('Trigger position; 0x%X')%trig_pos
channels_data = spec_fmc.get_data(trig_pos, ACQ_LENGTH*8)
return channels_data[channel_nb-1::4]
def acquisition_all(fmc, spec_fmc):
# Make sure no acquisition is running
fmc.stop_acq()
......@@ -148,12 +131,40 @@ def acquisition_all(fmc, spec_fmc):
trig_pos = fmc.get_trig_pos()
#print('Trigger position; 0x%X')%(trig_pos)
channels_data = spec_fmc.get_data((trig_pos<<3), ACQ_LENGTH*8)
#channels_data = spec_fmc.get_data(0x0, ACQ_LENGTH*8)
return channels_data
def plot_all(data, mean, ylimit):
sample = arange(len(data)/4)
clf()
plot(sample, data[0::4], 'b', label='Channel 1')
plot(sample, data[1::4], 'g', label='Channel 2')
plot(sample, data[2::4], 'c', label='Channel 3')
plot(sample, data[3::4], 'm', label='Channel 4')
plot(sample, [mean[0]]*len(sample), 'r')
plot(sample, [mean[1]]*len(sample), 'r')
plot(sample, [mean[2]]*len(sample), 'r')
plot(sample, [mean[3]]*len(sample), 'r')
ylim(-ylimit-(ylimit/10.0), ylimit+(ylimit/10.0))
grid(which='both')
legend()
draw()
show()
return 0
# Converts two's complement hex to signed
def hex2signed(value):
if(value & 0x8000):
return -((~value & 0xFFFF) + 1)
else:
return value
# Converts digital value to volts
def digital2volt(value, full_scale, nb_bit):
return float(value) * float(full_scale)/2**nb_bit - full_scale/2.0
return float(value) * float(full_scale)/2**nb_bit
# Converts volts to digital value with half full range offset
......@@ -171,18 +182,21 @@ def volt2digital(value, full_scale, nb_bit):
def volt2digital_without_offset(value, full_scale, nb_bit):
digital = (value) * 2**nb_bit/full_scale
if(digital > 2**nb_bit - 1):
digital = 2**nb_bit - 1
digital = ~(1<<nb_bit)
if(digital < 0):
digital = 0
digital = (1<<nb_bit)
#print('volt2digital: %2.9f > %2.9f')%(value,digital)
return int(digital)
def set_offset_dac(fmc, dac_fs, dac_nbits, channel, offset_volt):
def set_offset_dac(fmc, dac_fs, dac_nbits, channel, offset_volt, dac_corr_flag=False):
dac_v = offset_volt
dac_d = volt2digital(dac_v,dac_fs,dac_nbits)
#print('DAC value: 0x%X (%fV)')%(dac_d, dac_v)
fmc.set_dc_offset(channel,dac_d)
if(True == dac_corr_flag):
fmc.set_dc_offset_corrected(channel,dac_d)
else:
fmc.set_dc_offset(channel,dac_d)
time.sleep(DAC_SET_SLEEP)
......@@ -194,6 +208,36 @@ def get_mean_value(adc_fs, adc_nbits, acq):
return mean_v
def set_box_dac_range(box, fmc, box_out, dac_value, in_range, dac_corr_flag=False):
# Set calibration box output
box.select_output(box_out)
time.sleep(BOX_SET_SLEEP)
# Set offset DACs
for channel in range(1,NB_CHANNELS+1):
set_offset_dac(fmc, DAC_FS, DAC_NBITS, channel, dac_value, dac_corr_flag)
# Set channels input range
for channel in range(1,NB_CHANNELS+1):
fmc.set_input_range(channel, in_range)
time.sleep(SSR_SET_SLEEP)
def channels_mean(spec_fmc, fmc, ADC_FS, print_flag, plot_flag=False):
# Measures value on each channel
acq_d = acquisition_all(fmc, spec_fmc)
acq_d = [hex2signed(item) for item in acq_d]
acq_v = [digital2volt(item,ADC_FS,ADC_NBITS) for item in acq_d]
mean_v = get_mean_value(ADC_FS, ADC_NBITS, acq_d)
if(True == print_flag):
print('\n')
for channel in range(1,NB_CHANNELS+1):
print('Channel %d: mean voltage = %2.9fV')%(channel, mean_v[channel-1])
if(True == plot_flag):
plot_all(acq_v, mean_v, ADC_FS/2.0)
return mean_v
# Calculates ADC + input stage gain
def calc_ga(Vm1, Vm2, Vref1):
return ((Vm2-Vm1)/Vref1)
......@@ -211,37 +255,6 @@ def calc_od(Vm1, Vm2, Vm3, Vm4, Vref1):
return ((Vref1*(Vm1-Vm2-Vm3+Vm4))/(Vm1-Vm2))
def plot_acq(data, mean):
sample = arange(len(data))
clf()
plot(sample, data, 'b')
plot(sample, [mean]*len(data), 'r')
ylim(-0.01, 0.01)
grid(which='both')
draw()
show()
return 0
def plot_all(data, mean, ylimit):
sample = arange(len(data)/4)
clf()
plot(sample, data[0::4], 'b', label='Channel 1')
plot(sample, data[1::4], 'g', label='Channel 2')
plot(sample, data[2::4], 'c', label='Channel 3')
plot(sample, data[3::4], 'm', label='Channel 4')
plot(sample, [mean[0]]*len(sample), 'r')
plot(sample, [mean[1]]*len(sample), 'r')
plot(sample, [mean[2]]*len(sample), 'r')
plot(sample, [mean[3]]*len(sample), 'r')
ylim(-ylimit-(ylimit/10.0), ylimit+(ylimit/10.0))
grid(which='both')
legend()
draw()
show()
return 0
def main (default_directory = '.'):
# Load firmware to FPGA
......@@ -251,9 +264,14 @@ def main (default_directory = '.'):
spec = rr.Gennum() # bind to the SPEC board
spec_fmc = spec_fmc_adc.CSpecFmcAdc100Ms(spec)
fmc = fmc_adc.CFmcAdc100Ms(spec)
gen = Agilent33250A(device=USB_DEVICE, bauds=RS232_BAUD)
usb_tty = find_usb_tty.CttyUSB()
awg_tty = usb_tty.find_usb_tty(AWG_USB_VENDOR_ID, AWG_USB_DEVICE_ID)
box_tty = usb_tty.find_usb_tty(BOX_USB_VENDOR_ID, BOX_USB_DEVICE_ID)
#print "AWG:%s"%awg_tty[0]
#print "BOX:%s"%box_tty[0]
gen = Agilent33250A(device=awg_tty[0], bauds=RS232_BAUD)
sine = SineWaveform()
box = calibr_box.CCalibr_box(1)
box = calibr_box.CCalibr_box(box_tty[0])
# Enable "DMA finished" IRQ
spec_fmc.set_irq_en_mask(0x1)
......@@ -288,8 +306,10 @@ def main (default_directory = '.'):
ADC_FS = 0.1
# Reference voltage for calibration
Vref1 = 0.040943 # should be taken from box cailbration data in CP2103 EEPROM
Vref2 = 0.04096
Vref1 = 0.040948 # should be taken from box cailbration data in CP2103 EEPROM
Vref2 = 0.04096 # reference voltage to set offset DAC
REPEAT = 5
#---------------------------------------------------------------------------
# Measure 1
......@@ -298,28 +318,15 @@ def main (default_directory = '.'):
print('\nMeasurement 1: channel input = 0V, offset DAC = 0V')
# Set calibration box to AWG
box.select_output('AWG')
time.sleep(BOX_SET_SLEEP)
# All offset DACs to 0V
for channel in range(1,NB_CHANNELS+1):
set_offset_dac(fmc, DAC_FS, DAC_NBITS, channel, 0.0)
# All channel input opened and grounded
for channel in range(1,NB_CHANNELS+1):
fmc.set_input_range(channel, 'CAL_100mV')
time.sleep(SSR_SET_SLEEP)
set_box_dac_range(box, fmc, 'AWG', 0.0, 'CAL_100mV')
# Measures value on each channel
acq_d = acquisition_all(fmc, spec_fmc)
acq_v = [digital2volt(item,ADC_FS,ADC_NBITS) for item in acq_d]
Vm1 = get_mean_value(ADC_FS, ADC_NBITS, acq_d)
vm1 = []
for i in range(REPEAT):
vm1.append(channels_mean(spec_fmc, fmc, ADC_FS, False))
Vm1 = [mean([row[n] for row in vm1]) for n in range(NB_CHANNELS)]
for channel in range(1,NB_CHANNELS+1):
print('Channel %d: Vm1=%02.9fV')%(channel, Vm1[channel-1])
#plot_all(acq_v, Vm1)
#---------------------------------------------------------------------------
# Measure 2
# Channel input = Vref = 0.04096V, offset DAC = 0V
......@@ -327,23 +334,12 @@ def main (default_directory = '.'):
print('\nMeasurement 2: channel input = Vref = %1.7fV, offset DAC = 0V')%(Vref1)
# Set calibration box to 100mV range Vref
box.select_output('100mV')
time.sleep(BOX_SET_SLEEP)
# All offset DACs to 0V
for channel in range(1,NB_CHANNELS+1):
set_offset_dac(fmc, DAC_FS, DAC_NBITS, channel, 0.0)
set_box_dac_range(box, fmc, '100mV', 0.0, '100mV')
# All channel input opened and grounded
for channel in range(1,NB_CHANNELS+1):
fmc.set_input_range(channel, '100mV')
time.sleep(SSR_SET_SLEEP)
# Measures value on each channel
acq_d = acquisition_all(fmc, spec_fmc)
acq_v = [digital2volt(item,ADC_FS,ADC_NBITS) for item in acq_d]
Vm2 = get_mean_value(ADC_FS, ADC_NBITS, acq_d)
vm2 = []
for i in range(REPEAT):
vm2.append(channels_mean(spec_fmc, fmc, ADC_FS, False))
Vm2 = [mean([row[n] for row in vm2]) for n in range(NB_CHANNELS)]
for channel in range(1,NB_CHANNELS+1):
print('Channel %d: Vm2=%02.9fV')%(channel, Vm2[channel-1])
......@@ -354,23 +350,12 @@ def main (default_directory = '.'):
print('\nMeasurement 3: channel input = 0V, offset DAC = Vref = %1.7fV')%(Vref2)
# Set calibration box to AWG
box.select_output('AWG')
time.sleep(BOX_SET_SLEEP)
# All offset DACs to 0V
for channel in range(1,NB_CHANNELS+1):
set_offset_dac(fmc, DAC_FS, DAC_NBITS, channel, Vref2)
set_box_dac_range(box, fmc, 'AWG', Vref2, 'CAL_100mV')
# All channel input opened and grounded
for channel in range(1,NB_CHANNELS+1):
fmc.set_input_range(channel, 'CAL_100mV')
time.sleep(SSR_SET_SLEEP)
# Measures value on each channel
acq_d = acquisition_all(fmc, spec_fmc)
acq_v = [digital2volt(item,ADC_FS,ADC_NBITS) for item in acq_d]
Vm3 = get_mean_value(ADC_FS, ADC_NBITS, acq_d)
vm3 = []
for i in range(REPEAT):
vm3.append(channels_mean(spec_fmc, fmc, ADC_FS, False))
Vm3 = [mean([row[n] for row in vm3]) for n in range(NB_CHANNELS)]
for channel in range(1,NB_CHANNELS+1):
print('Channel %d: Vm3=%02.9fV')%(channel, Vm3[channel-1])
......@@ -381,23 +366,12 @@ def main (default_directory = '.'):
print('\nMeasurement 4: channel input = Vref = %1.7fV, offset DAC = Vref = %1.7fV')%(Vref1, Vref2)
# Set calibration box to 100mV range Vref
box.select_output('100mV')
time.sleep(BOX_SET_SLEEP)
# All offset DACs to 0V
for channel in range(1,NB_CHANNELS+1):
set_offset_dac(fmc, DAC_FS, DAC_NBITS, channel, Vref2)
set_box_dac_range(box, fmc, '100mV', Vref2, '100mV')
# All channel input opened and grounded
for channel in range(1,NB_CHANNELS+1):
fmc.set_input_range(channel, '100mV')
time.sleep(SSR_SET_SLEEP)
# Measures value on each channel
acq_d = acquisition_all(fmc, spec_fmc)
acq_v = [digital2volt(item,ADC_FS,ADC_NBITS) for item in acq_d]
Vm4 = get_mean_value(ADC_FS, ADC_NBITS, acq_d)
vm4 = []
for i in range(REPEAT):
vm4.append(channels_mean(spec_fmc, fmc, ADC_FS, False))
Vm4 = [mean([row[n] for row in vm4]) for n in range(NB_CHANNELS)]
for channel in range(1,NB_CHANNELS+1):
print('Channel %d: Vm4=%02.9fV')%(channel, Vm4[channel-1])
......@@ -408,7 +382,7 @@ def main (default_directory = '.'):
# gd = DAC gain
# od = DAC offset
#---------------------------------------------------------------------------
print('/n')
print('\n100mV range correction parameters\n----------------------------------')
ga = []
for channel in range(1,NB_CHANNELS+1):
......@@ -430,65 +404,126 @@ def main (default_directory = '.'):
od.append(calc_od(Vm1[channel-1], Vm2[channel-1], Vm3[channel-1], Vm4[channel-1], Vref1))
print('Channel %d DAC offset : %02.9f')%(channel, od[channel-1])
#---------------------------------------------------------------------------
# Write DAC gain and offset corerection value to fmc class
#---------------------------------------------------------------------------
print('\nApply DAC correction\n----------------------------------')
print('DACs are precise enough.\nDo not apply any correction.')
"""
dac_gain_corr = [1/item for item in gd]
dac_offset_corr = [-item for item in od]
fmc.set_dac_corr(dac_gain_corr, dac_offset_corr)
for channel in range(1,NB_CHANNELS+1):
print('CH%d DAC offset correction:%1.9f')%(channel,dac_offset_corr[channel-1])
print('CH%d DAC gain correction :%1.9f')%(channel,dac_gain_corr[channel-1])
#---------------------------------------------------------------------------
# Test
#---------------------------------------------------------------------------
print('\nChannel input = 0V, offset DAC = 0V\n----------------------------------')
#raw_input('...')
set_box_dac_range(box, fmc, 'AWG', 0.0, 'CAL_100mV', True)
mean_v = channels_mean(spec_fmc, fmc, ADC_FS, True)
#plot_all(acq_v, mean_v, ADC_FS/2.0)
"""
#---------------------------------------------------------------------------
# Write ADC + input stage gain and offset correction to hardware
#---------------------------------------------------------------------------
print('\nApply ADC offset correction\n----------------------------------')
#fmc.print_adc_core_config()
adc_gain_corr = [int(round((1/item)*0x8000)) for item in ga]
#adc_gain_corr = [int(round((1/item)*0x8000)) for item in ga]
adc_gain_corr = [0x8000] * 4
adc_offset_corr = [-(volt2digital_without_offset(item,ADC_FS,ADC_NBITS)) for item in oa]
#adc_offset_corr = [0] * 4
for channel in range(1,NB_CHANNELS+1):
fmc.set_adc_gain_offset_corr(channel, adc_gain_corr[channel-1], adc_offset_corr[channel-1])
fmc.print_adc_core_config()
#fmc.print_adc_core_config()
for channel in range(1,NB_CHANNELS+1):
print('CH%d ADC offset correction write:0x%.8X read:0x%.8X')%(channel,adc_offset_corr[channel-1],fmc.get_adc_offset_corr(channel))
print('CH%d ADC gain correction write:0x%.8X read:0x%.8X')%(channel,adc_gain_corr[channel-1],fmc.get_adc_gain_corr(channel))
#---------------------------------------------------------------------------
# Write DAC gain and offset corerection value to fmc class
# Test
#---------------------------------------------------------------------------
dac_gain_corr = [1/item for item in gd]
dac_offset_corr = [-item for item in od]
print('\nChannel input = 0V, offset DAC = 0V\n----------------------------------')
fmc.set_dac_corr(dac_gain_corr, dac_offset_corr)
#raw_input('...')
set_box_dac_range(box, fmc, 'AWG', 0.0, 'CAL_100mV', True)
mean_v = channels_mean(spec_fmc, fmc, ADC_FS, True)
#---------------------------------------------------------------------------
# Test
# Write ADC + input stage gain and offset correction to hardware
#---------------------------------------------------------------------------
print('\nApply ADC gain correction\n----------------------------------')
#fmc.print_adc_core_config()
raw_input('...')
adc_gain_corr = [int(round((1/item)*0x8000)) for item in ga]
#adc_gain_corr = [0x8000] * 4
adc_offset_corr = [-(volt2digital_without_offset(item,ADC_FS,ADC_NBITS)) for item in oa]
#adc_offset_corr = [0] * 4
# Program DAC with corrected 0V offset
for channel in range(1,NB_CHANNELS+1):
dac_v = 0.0
dac_d = volt2digital(dac_v,DAC_FS,DAC_NBITS)
fmc.set_dc_offset_corrected(channel,dac_d)
#fmc.set_dc_offset(channel,dac_d)
fmc.set_adc_gain_offset_corr(channel, adc_gain_corr[channel-1], adc_offset_corr[channel-1])
# Set calibration box to 100mV Vref
#box.select_output('100mV')
box.select_output('AWG')
time.sleep(BOX_SET_SLEEP)
#fmc.print_adc_core_config()
# All channel input opened and grounded
for channel in range(1,NB_CHANNELS+1):
fmc.set_input_range(channel, '100mV')
time.sleep(SSR_SET_SLEEP)
print('CH%d ADC offset correction write:0x%.8X read:0x%.8X')%(channel,adc_offset_corr[channel-1],fmc.get_adc_offset_corr(channel))
print('CH%d ADC gain correction write:0x%.8X read:0x%.8X')%(channel,adc_gain_corr[channel-1],fmc.get_adc_gain_corr(channel))
# Measures value on each channel
acq_d = acquisition_all(fmc, spec_fmc)
acq_v = [digital2volt(item,ADC_FS,ADC_NBITS) for item in acq_d]
mean_v = get_mean_value(ADC_FS, ADC_NBITS, acq_d)
for channel in range(1,NB_CHANNELS+1):
print('Channel %d: mean=%02.9fV')%(channel, mean_v[channel-1])
plot_all(acq_v, mean_v, ADC_FS/2.0)
#---------------------------------------------------------------------------
# Test
#---------------------------------------------------------------------------
print('\nChannel input = 0V, offset DAC = 0V\n----------------------------------')
#raw_input('...')
set_box_dac_range(box, fmc, 'AWG', 0.0, 'CAL_100mV', True)
mean_v = channels_mean(spec_fmc, fmc, ADC_FS, True)
#---------------------------------------------------------------------------
# Test
#---------------------------------------------------------------------------
print('\nChannel input = 0V, offset DAC = Vref = 0.04096V\n----------------------------------')
#raw_input('...')
set_box_dac_range(box, fmc, 'AWG', 0.04096, 'CAL_100mV', True)
mean_v = channels_mean(spec_fmc, fmc, ADC_FS, True)
#---------------------------------------------------------------------------
# Test
#---------------------------------------------------------------------------
print('\nChannel input = Vref = 0.04096V, offset DAC = 0V\n----------------------------------')
#raw_input('...')
set_box_dac_range(box, fmc, '100mV', 0.0, '100mV', True)
mean_v = channels_mean(spec_fmc, fmc, ADC_FS, True)
......
......@@ -18,6 +18,7 @@ from ptsexcept import *
import spec_fmc_adc
import fmc_adc
import calibr_box
import find_usb_tty
from PAGE.Agilent33250A import *
from PAGE.SineWaveform import *
......@@ -29,7 +30,12 @@ Note: Requires test00.py to run first to load the firmware!
"""
USB_DEVICE = "/dev/ttyUSB0"
# Calibration box vendor and device IDs
BOX_USB_VENDOR_ID = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device
# Agilent AWG serial access vendor and device IDs
AWG_USB_VENDOR_ID = 0x0403 # Future Technology Devices International, Ltd
AWG_USB_DEVICE_ID = 0x6001 # FT232 USB-Serial (UART) IC
RS232_BAUD = 57600
NB_CHANNELS = 4
......@@ -100,9 +106,12 @@ def main (default_directory = '.'):
spec = rr.Gennum() # bind to the SPEC board
spec_fmc = spec_fmc_adc.CSpecFmcAdc100Ms(spec)
fmc = fmc_adc.CFmcAdc100Ms(spec)
gen = Agilent33250A(device=USB_DEVICE, bauds=RS232_BAUD)
usb_tty = find_usb_tty.CttyUSB()
awg_tty = usb_tty.find_usb_tty(AWG_USB_VENDOR_ID, AWG_USB_DEVICE_ID)
box_tty = usb_tty.find_usb_tty(BOX_USB_VENDOR_ID, BOX_USB_DEVICE_ID)
gen = Agilent33250A(device=awg_tty[0], bauds=RS232_BAUD)
sine = SineWaveform()
box = calibr_box.CCalibr_box(1)
box = calibr_box.CCalibr_box(box_tty[0])
# Enable "DMA finished" IRQ
spec_fmc.set_irq_en_mask(0x1)
......
......@@ -18,6 +18,7 @@ from ptsexcept import *
import spec_fmc_adc
import fmc_adc
import calibr_box
import find_usb_tty
from PAGE.Agilent33250A import *
from PAGE.SineWaveform import *
......@@ -30,7 +31,12 @@ Note: Requires test00.py to run first to load the firmware!
GN4124_CSR = 0x0
USB_DEVICE = "/dev/ttyUSB0"
# Calibration box vendor and device IDs
BOX_USB_VENDOR_ID = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device
# Agilent AWG serial access vendor and device IDs
AWG_USB_VENDOR_ID = 0x0403 # Future Technology Devices International, Ltd
AWG_USB_DEVICE_ID = 0x6001 # FT232 USB-Serial (UART) IC
RS232_BAUD = 57600
NB_CHANNELS = 4
......@@ -125,6 +131,7 @@ def acquisition_all(fmc, spec_fmc):
return channels_data
def plot_all(data, mean, ylimit):
sample = arange(len(data)/4)
clf()
......@@ -143,10 +150,17 @@ def plot_all(data, mean, ylimit):
show()
return 0
# Converts two's complement hex to signed
def hex2signed(value):
if(value & 0x8000):
return -((~value & 0xFFFF) + 1)
else:
return value
# Converts digital value to volts
def digital2volt(value, full_scale, nb_bit):
return float(value) * float(full_scale)/2**nb_bit - full_scale/2.0
return float(value) * float(full_scale)/2**nb_bit
# Converts volts to digital value
......@@ -184,9 +198,12 @@ def main (default_directory = '.'):
spec = rr.Gennum() # bind to the SPEC board
spec_fmc = spec_fmc_adc.CSpecFmcAdc100Ms(spec)
fmc = fmc_adc.CFmcAdc100Ms(spec)
gen = Agilent33250A(device=USB_DEVICE, bauds=RS232_BAUD)
usb_tty = find_usb_tty.CttyUSB()
awg_tty = usb_tty.find_usb_tty(AWG_USB_VENDOR_ID, AWG_USB_DEVICE_ID)
box_tty = usb_tty.find_usb_tty(BOX_USB_VENDOR_ID, BOX_USB_DEVICE_ID)
gen = Agilent33250A(device=awg_tty[0], bauds=RS232_BAUD)
sine = SineWaveform()
box = calibr_box.CCalibr_box(1)
box = calibr_box.CCalibr_box(box_tty[0])
# Enable "DMA finished" IRQ
spec_fmc.set_irq_en_mask(0x1)
......@@ -245,6 +262,7 @@ def main (default_directory = '.'):
# Measures value on each channel
acq_d = acquisition_all(fmc, spec_fmc)
acq_d = [hex2signed(item) for item in acq_d]
acq_v = [digital2volt(item,ADC_FS,ADC_NBITS) for item in acq_d]
mean_v = get_mean_value(ADC_FS, ADC_NBITS, acq_d)
plot_all(acq_v, mean_v, ADC_FS/2.0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment