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)
......
This diff is collapsed.
......@@ -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