Commit a9ebc227 authored by Ross Millar's avatar Ross Millar

Add FmcAdc200k tests and firmware.

parent 85ec062a
#!/bin/sh
# Copyright CERN, 2011
# Author: Ross Millar <ross.millar@cern.ch>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
LOGDIR=./log_fmcadc200k16b11cha
mkdir -p $LOGDIR
sudo rm -fr $LOGDIR/pts*
serial=$1
if [ x$1 = x"" ]; then
echo -n "Please, input SERIAL number: "
read serial
fi
if [ x$serial = x"" ]; then
serial=0000
fi
extra_serial=$2
if [ x$2 = x"" ]; then
echo -n "Please, input extra SERIAL number: "
read extra_serial
fi
if [ x$extra_serial = x"" ]; then
extra_serial=0000
fi
echo -n "--------------------------------------------------------------\n"
sudo ./pts.py -b FmcAdc200k16b11cha -s $serial -e $extra_serial -t./test/fmcadc200k16b11cha/python -l $LOGDIR 00 01 02 03 04 05 06
echo -n "Press enter to exit... "
read tmp
#!/usr/bin/python
import sys
import rr
import time
import spi
import csr
class CAD5662:
def __init__(self, spi, slave):
self.spi = spi
self.slave = slave
#self.config = config
# offset = value to write to the DAC (2 bytes)
def set_offset(self, offset):
#print "DAC offset chose %X " %offset
#tx = [0xFF, 0xFF, 0xF0]
tx = [(offset & 0xFF), ((offset & 0xFF00)>>8), 0x00] # need to check order
#print tx
self.spi.transaction(self.slave, tx)
import fcntl, struct, termios, os
import time
import array
class cp210x_gpio:
def __init__(self, usb_number):
self.fd = open('/dev/ttyUSB' + str(usb_number), 'wb')
def gpio_set(self, mask):
fcntl.ioctl(self.fd.fileno(), 0x8001, mask)
def gpio_get(self):
f = array.array('I', [0])
ret = fcntl.ioctl(self.fd.fileno(), 0x8000, f, 1)
return f[0]
# Create an object (the 0 is used to generate the name, eg. /dev/ttyUSB0
#gpio = cp210x_gpio(0)
# Infinite test loop
#while 1:
# # Pass the mask of the 4 bits as a hex number
# gpio.gpio_set(0xf)
# # Returns the states of the 4 bits as hex number
# print gpio.gpio_get()
# time.sleep(1)
# gpio.gpio_set(0x0)
# print gpio.gpio_get()
# time.sleep(1)
#!/usr/bin/python
import sys
import rr
import time
class CCSR:
def __init__(self, bus, base_addr):
self.base_addr = base_addr;
self.bus = bus;
def wr_reg(self, addr, val):
#print(" wr:%.8X reg:%.8X")%(val,(self.base_addr+addr))
self.bus.iwrite(0, self.base_addr + addr, 4, val)
def rd_reg(self, addr):
reg = self.bus.iread(0, self.base_addr + addr, 4)
#print(" reg:%.8X value:%.8X")%((self.base_addr+addr), reg)
return reg
def wr_bit(self, addr, bit, value):
reg = self.rd_reg(addr)
if(0==value):
reg &= ~(1<<bit)
else:
reg |= (1<<bit)
self.wr_reg(addr, reg)
def rd_bit(self, addr, bit):
if(self.rd_reg(addr) & (1<<bit)):
return 1
else:
return 0
#!/usr/bin/python
import sys
import rr
import time
import i2c
class CAD5622:
def __init__(self, i2c, i2c_addr):
self.i2c = i2c
self.i2c_addr = i2c_addr
# def wr_data(self, data_msb, data_lsb):
# self.i2c.start(self.i2c_addr, True)
# self.i2c.write((data_msb & 0xFF), False)
# self.i2c.write((data_lsb & 0xFF), True)
# return 0;
def wr_data(self,data):
data_wr_msb = ((0xF00 & data) >> 8)
data_wr_lsb = (0x0FF & data)
self.i2c.start(self.i2c_addr, True)
self.i2c.write((data_wr_msb & 0x0F), False)
self.i2c.write((data_wr_lsb & 0xFF), True)
return 0;
def power_down(self):
data_wr_msb = ((1 & 0xF)<<4) + ((0xF00 & 0) >> 8)
data_wr_lsb = (0x0FF & 0)
self.i2c.start(self.i2c_addr, True)
self.i2c.write((data_wr_msb & 0xFF), False)
self.i2c.write((data_wr_lsb & 0xFF), True)
return "DAC powered down";
def rd_data(self):
self.i2c.start(self.i2c_addr, False)
data = []
#print('24AA64:read: data lenght=%d')%(size)
data.append(self.i2c.read(False))
data.append(self.i2c.read(True))
data_return = (((data[0] <<8) + data[1])>>2)
return data_return;
#!/usr/bin/env python
#coding: utf8
# Copyright CERN, 2011
# Author: Ross Millar <ross.millar@cern.ch>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
import sys
import rr
import random
import time
import spi
import csr
import i2c
import gn4124
import fmc_adc_test_suite
import fmc_adc
import cp210x_gpio
#from pylab import *
#from ptsexcept import *
import fcntl, struct, termios, os
import time
import array
hw_en =0
sw_en =1
chan_for_thresh = 0x1 # check that this is masked in the fmc class
int_thresh = 0x1000 # 16 bit in twos comp
slope = 1 # 1 for positive, 0 for negative
delay = 0 # Trigger delay
edge_detect = 0 # Trig on Rising or falling edges, depends on slope
pre_trig_val =10
post_trig_val = 10
thresh_negative = 0
thresh_positive = 0
error=0
def main (default_directory='.'):
# if (int_thresh & 0x8000) >> 15 ==0x1:
# int_thresh = -0x10000 + int_thresh
# thresh_negative = 1
# else:
# thresh_positive = 1
# Object Declaration
spec = rr.Gennum() # bind to the SPEC board
fmc = fmc_adc.CFmcAdc100ks(spec)
# Set trigger Register
#fmc.set_trig_config(hw_en,sw_en,chan_for_thresh,int_thresh,slope,delay,edge_detect)
# Do acq on the same channel as selected channel for thresh trig
result = fmc.do_acq( chan_for_thresh, "all_chans" ,"y",post_trig_val,pre_trig_val,0)
if __name__ == '__main__':
main()
#!/usr/bin/python
import sys
import rr
import time
import onewire
class CDS18B20:
# ROM commands
ROM_SEARCH = 0xF0
ROM_READ = 0x33
ROM_MATCH = 0x55
ROM_SKIP = 0xCC
ROM_ALARM_SEARCH = 0xEC
# DS18B20 fonctions commands
CONVERT_TEMP = 0x44
WRITE_SCRATCHPAD = 0x4E
READ_SCRATCHPAD = 0xBE
COPY_SCRATCHPAD = 0x48
RECALL_EEPROM = 0xB8
READ_POWER_SUPPLY = 0xB4
# Thermometer resolution configuration
RES = {'9-bit':0x0, '10-bit':0x1, '11-bit':0x2, '12-bit':0x3}
def __init__(self, onewire, port):
self.onewire = onewire
self.port = port
def read_serial_number(self):
#print('[DS18B20] Reading serial number')
if(1 != self.onewire.reset(self.port)):
print('[DS18B20] No presence pulse detected')
return -1
else:
#print('[DS18B20] Write ROM command %.2X') % self.ROM_READ
err = self.onewire.write_byte(self.port, self.ROM_READ)
if(err != 0):
print('[DS18B20] Write error')
return -1
family_code = self.onewire.read_byte(self.port)
serial_number = 0
for i in range(6):
serial_number |= self.onewire.read_byte(self.port) << (i*8)
crc = self.onewire.read_byte(self.port)
#print('[DS18B20] Family code : %.2X') % family_code
#print('[DS18B20] Serial number: %.12X') % serial_number
#print('[DS18B20] CRC : %.2X') % crc
return ((crc<<56) | (serial_number<<8) | family_code)
def access(self, serial_number):
#print('[DS18B20] Accessing device')
if(1 != self.onewire.reset(self.port)):
print('[DS18B20] No presence pulse detected')
return -1
else:
#print('[DS18B20] Write ROM command %.2X') % self.ROM_MATCH
err = self.onewire.write_byte(self.port, self.ROM_MATCH)
#print serial_number
block = []
for i in range(8):
block.append(serial_number & 0xFF)
serial_number >>= 8
#print block
self.onewire.write_block(self.port, block)
return 0
def read_temp(self, serial_number):
#print('[DS18B20] Reading temperature')
err = self.access(serial_number)
#print('[DS18B20] Write function command %.2X') % self.CONVERT_TEMP
err = self.onewire.write_byte(self.port, self.CONVERT_TEMP)
time.sleep(1)
err = self.access(serial_number)
#print('[DS18B20] Write function command %.2X') % self.READ_SCRATCHPAD
err = self.onewire.write_byte(self.port, self.READ_SCRATCHPAD)
data = self.onewire.read_block(self.port, 9)
#for i in range(9):
# print('Scratchpad data[%1d]: %.2X') % (i, data[i])
temp = (data[1] << 8) | (data[0])
if(temp & 0x1000):
temp = -0x10000 + temp
temp = temp/16.0
return temp
# Set temperature thresholds
# Configure thermometer resolution
#!/usr/bin/python
import sys
import rr
import time
import i2c
class C24AA64:
def __init__(self, i2c, i2c_addr):
self.i2c = i2c
self.i2c_addr = i2c_addr
def wr_data(self, mem_addr, data):
i=0
self.i2c.start(self.i2c_addr, True)
self.i2c.write((mem_addr >> 8), False)
self.i2c.write((mem_addr & 0xFF), False)
#print('24AA64:write: data lenght=%d')%(len(data))
for i in range(len(data)-1):
#print('24AA64:write: i=%d')%(i)
print data[i]
self.i2c.write(data[i],False)
i += 1
#print('24AA64:write:last i=%d')%(i)
if len(data)==1:
self.i2c.write(data[0],True)
print data[0]
return 0
self.i2c.write(data[i],True)
print data[i]
return 0;
def rd_data(self, mem_addr, size):
self.i2c.start(self.i2c_addr, True)
self.i2c.write((mem_addr >> 8), False)
self.i2c.write((mem_addr & 0xFF), False)
self.i2c.start(self.i2c_addr, False)
data = []
#print('24AA64:read: data lenght=%d')%(size)
for i in range(size-1):
data.append(self.i2c.read(False))
#print('24AA64:read: i=%d')%(i)
i += 1
#print('24AA64:read:last i=%d')%(i)
data.append(self.i2c.read(True))
return data;
def dump_file_to_eeprom(self,filename):
eeprom_content = []
eeprom_addr = []
print filename
f = open(filename,"r+")
for line in f:
addr,data=line.split()
eeprom_content=(int(data,2)& 0xFF)
eeprom_addr=(int(addr,2))
self.wr_data(eeprom_addr,[eeprom_content])
time.sleep(.01)
return 0
This diff is collapsed.
#!/usr/bin/python
import sys
import rr
import time
import csr
class CGN4124:
# Host registers (BAR12), for DMA items storage
HOST_BAR = 0xC
HOST_DMA_CARRIER_START_ADDR = 0x00
HOST_DMA_HOST_START_ADDR_L = 0x04
HOST_DMA_HOST_START_ADDR_H = 0x08
HOST_DMA_LENGTH = 0x0C
HOST_DMA_NEXT_ITEM_ADDR_L = 0x10
HOST_DMA_NEXT_ITEM_ADDR_H = 0x14
HOST_DMA_ATTRIB = 0x18
# GN4124 chip registers (BAR4)
GN4124_BAR = 0x4
R_CLK_CSR = 0x808
R_INT_CFG0 = 0x820
R_GPIO_DIR_MODE = 0xA04
R_GPIO_INT_MASK_CLR = 0xA18
R_GPIO_INT_MASK_SET = 0xA1C
R_GPIO_INT_STATUS = 0xA20
R_GPIO_INT_VALUE = 0xA28
CLK_CSR_DIVOT_MASK = 0x3F0
INT_CFG0_GPIO = 15
GPIO_INT_SRC = 8
# GN4124 core registers (BAR0)
R_DMA_CTL = 0x00
R_DMA_STA = 0x04
R_DMA_CARRIER_START_ADDR = 0x08
R_DMA_HOST_START_ADDR_L = 0x0C
R_DMA_HOST_START_ADDR_H = 0x10
R_DMA_LENGTH = 0x14
R_DMA_NEXT_ITEM_ADDR_L = 0x18
R_DMA_NEXT_ITEM_ADDR_H = 0x1C
R_DMA_ATTRIB = 0x20
DMA_CTL_START = 0
DMA_CTL_ABORT = 1
DMA_CTL_SWAP = 2
DMA_STA = ['Idle','Done','Busy','Error','Aborted']
DMA_ATTRIB_LAST = 0
DMA_ATTRIB_DIR = 1
def rd_reg(self, bar, addr):
return self.bus.iread(bar, addr, 4)
def wr_reg(self, bar, addr, value):
self.bus.iwrite(bar, addr, 4, value)
def __init__(self, bus, csr_addr):
self.bus = bus
self.dma_csr = csr.CCSR(bus, csr_addr)
self.dma_item_cnt = 0
# Get page list
self.pages = self.bus.getplist()
# Shift by 12 to get the 32-bit physical addresses
self.pages = [addr << 12 for addr in self.pages]
self.set_interrupt_config()
# Enable interrupt from gn4124
self.bus.irqena()
# Set local bus frequency
def set_local_bus_freq(self, freq):
# freq in MHz
# LCLK = (25MHz*(DIVFB+1))/(DIVOT+1)
# DIVFB = 31
# DIVOT = (800/LCLK)-1
divot = int(round((800/freq)-1,0))
#print '%d' % divot
data = 0xe001f00c + (divot << 4)
#print '%.8X' % data
#print 'Set local bus freq to %dMHz' % int(round(800/(divot+1),0))
self.wr_reg(self.GN4124_BAR, self.R_CLK_CSR, data)
# Get local bus frequency
# return: frequency in MHz
def get_local_bus_freq(self):
reg = self.rd_reg(self.GN4124_BAR, self.R_CLK_CSR)
divot = ((reg & self.CLK_CSR_DIVOT_MASK)>>4)
return (800/(divot + 1))
# Get physical addresses of the pages allocated to GN4124
def get_physical_addr(self):
return self.pages
# Wait for interrupt
def wait_irq(self):
# Add here reading of the interrupt source (once the irq core will be present)
return self.bus.irqwait()
# GN4124 interrupt configuration
def set_interrupt_config(self):
# Set interrupt line from FPGA (GPIO8) as input
self.wr_reg(self.GN4124_BAR, self.R_GPIO_DIR_MODE, (1<<self.GPIO_INT_SRC))
# Set interrupt mask for all GPIO except for GPIO8
self.wr_reg(self.GN4124_BAR, self.R_GPIO_INT_MASK_SET, ~(1<<self.GPIO_INT_SRC))
# Make sure the interrupt mask is cleared for GPIO8
self.wr_reg(self.GN4124_BAR, self.R_GPIO_INT_MASK_CLR, (1<<self.GPIO_INT_SRC))
# Interrupt on rising edge of GPIO8
self.wr_reg(self.GN4124_BAR, self.R_GPIO_INT_VALUE, (1<<self.GPIO_INT_SRC))
# GPIO as interrupt 0 source
self.wr_reg(self.GN4124_BAR, self.R_INT_CFG0, (1<<self.INT_CFG0_GPIO))
# Get DMA controller status
def get_dma_status(self):
reg = self.dma_csr.rd_reg(self.R_DMA_STA)
if(reg > len(self.DMA_STA)):
print("DMA status register : %.8X") % reg
raise Exception('Invalid DMA status')
else:
return self.DMA_STA[reg]
# Configure DMA byte swapping
# 0 = A1 B2 C3 D4 (straight)
# 1 = B2 A1 D4 C3 (swap bytes in words)
# 2 = C3 D4 A1 B2 (swap words)
# 3 = D4 C3 B2 A1 (invert bytes)
def set_dma_swap(self, swap):
if(swap > 3):
raise Exception('Invalid swapping configuration : %d') % swap
else:
self.dma_csr.wr_reg(self.R_CTL, (swap << self.DMA_CTL_SWAP))
# Add DMA item (first item is on the board, the following in the host memory)
# carrier_addr, host_addr, length and next_item_addr are in bytes
# dma_dir = 1 -> PCIe to carrier
# dma_dir = 0 -> carrier to PCIe
# dma_last = 0 -> last item in the transfer
# dma_last = 1 -> more item in the transfer
# Only supports 32-bit host address
def add_dma_item(self, carrier_addr, host_addr, length, dma_dir, last_item):
if(0 == self.dma_item_cnt):
# write the first DMA item in the carrier
self.dma_csr.wr_reg(self.R_DMA_CARRIER_START_ADDR, carrier_addr)
self.dma_csr.wr_reg(self.R_DMA_HOST_START_ADDR_L, (host_addr & 0xFFFFFFFF))
self.dma_csr.wr_reg(self.R_DMA_HOST_START_ADDR_H, (host_addr >> 32))
self.dma_csr.wr_reg(self.R_DMA_LENGTH, length)
self.dma_csr.wr_reg(self.R_DMA_NEXT_ITEM_ADDR_L, (self.pages[0] & 0xFFFFFFFF))
self.dma_csr.wr_reg(self.R_DMA_NEXT_ITEM_ADDR_H, 0x0)
attrib = (dma_dir << self.DMA_ATTRIB_DIR) + (last_item << self.DMA_ATTRIB_LAST)
self.dma_csr.wr_reg(self.R_DMA_ATTRIB, attrib)
else:
# write nexy DMA item(s) in host memory
# uses page 0 to store DMA items
# current and next item addresses are automatically set
current_item_addr = (self.dma_item_cnt-1)*0x20
next_item_addr = (self.dma_item_cnt)*0x20
self.wr_reg(self.HOST_BAR, self.HOST_DMA_CARRIER_START_ADDR + current_item_addr, carrier_addr)
self.wr_reg(self.HOST_BAR, self.HOST_DMA_HOST_START_ADDR_L + current_item_addr, host_addr)
self.wr_reg(self.HOST_BAR, self.HOST_DMA_HOST_START_ADDR_H + current_item_addr, 0x0)
self.wr_reg(self.HOST_BAR, self.HOST_DMA_LENGTH + current_item_addr, length)
self.wr_reg(self.HOST_BAR, self.HOST_DMA_NEXT_ITEM_ADDR_L + current_item_addr,
self.pages[0] + next_item_addr)
self.wr_reg(self.HOST_BAR, self.HOST_DMA_NEXT_ITEM_ADDR_H + current_item_addr, 0x0)
attrib = (dma_dir << self.DMA_ATTRIB_DIR) + (last_item << self.DMA_ATTRIB_LAST)
self.wr_reg(self.HOST_BAR, self.HOST_DMA_ATTRIB + current_item_addr, attrib)
self.dma_item_cnt += 1
# Start DMA transfer
def start_dma(self):
self.dma_item_cnt = 0
self.dma_csr.wr_bit(self.R_DMA_CTL, self.DMA_CTL_START, 1)
# The following two lines should be removed
# when the GN4124 vhdl core will implement auto clear of start bit
#while(('Idle' == self.get_dma_status()) or
# ('Busy' == self.get_dma_status())):
# pass
self.dma_csr.wr_bit(self.R_DMA_CTL, self.DMA_CTL_START, 0)
# Abort DMA transfer
def abort_dma(self):
self.dma_item_cnt = 0
self.dma_csr.wr_bit(self.R_DMA_CTL, self.DMA_CTL_ABORT, 1)
# The following two lines should be removed
# when the GN4124 vhdl core will implement auto clear of start bit
while('Aborted' != self.get_dma_status()):
pass
self.dma_csr.wr_bit(self.R_DMA_CTL, self.DMA_CTL_ABORT, 0)
# Get memory page
def get_memory_page(self, page_nb):
data = []
for i in range(2**10):
data.append(self.rd_reg(self.HOST_BAR, (page_nb<<12)+(i<<2)))
return data
# Set memory page
def set_memory_page(self, page_nb, pattern):
for i in range(2**10):
self.wr_reg(self.HOST_BAR, (page_nb<<12)+(i<<2), pattern)
#! /usr/bin/env python
# coding: utf8
import sys
import rr
import time
class COpenCoresI2C:
# OpenCores I2C registers description
R_PREL = 0x0
R_PREH = 0x4
R_CTR = 0x8
R_TXR = 0xC
R_RXR = 0xC
R_CR = 0x10
R_SR = 0x10
CTR_EN = (1<<7)
CR_STA = (1<<7)
CR_STO = (1<<6)
CR_RD = (1<<5)
CR_WR = (1<<4)
CR_ACK = (1<<3)
SR_RXACK = (1<<7)
SR_TIP = (1<<1)
def wr_reg(self, addr, val):
self.bus.iwrite(0, self.base_addr + addr, 4, val)
def rd_reg(self,addr):
return self.bus.iread(0, self.base_addr + addr, 4)
# Function called during object creation
# bus = host bus (PCIe, VME, etc...)
# base_addr = I2C core base address
# prescaler = SCK prescaler, prescaler = (Fsys/(5*Fsck))-1
def __init__(self, bus, base_addr, prescaler):
self.bus = bus
self.base_addr = base_addr
self.wr_reg(self.R_CTR, 0)
#print("prescaler: %.4X") % prescaler
self.wr_reg(self.R_PREL, (prescaler & 0xff))
#print("PREL: %.2X") % self.rd_reg(self.R_PREL)
self.wr_reg(self.R_PREH, (prescaler >> 8))
#print("PREH: %.2X") % self.rd_reg(self.R_PREH)
self.wr_reg(self.R_CTR, self.CTR_EN)
#print("CTR: %.2X") % self.rd_reg(self.R_CTR)
if(not(self.rd_reg(self.R_CTR) & self.CTR_EN)):
print "Warning! I2C core is not enabled!"
def wait_busy(self):
while(self.rd_reg(self.R_SR) & self.SR_TIP):
pass
def start(self, addr, write_mode):
#print('i2c:start: addr=%.2X')%addr
addr = addr << 1
#print('i2c:start: addr=%.2X')%addr
if(write_mode == False):
addr = addr | 1
#print('i2c:start: addr=%.2X')%addr
self.wr_reg(self.R_TXR, addr)
#print("R_TXR: %.2X") % self.rd_reg(self.R_TXR)
self.wr_reg(self.R_CR, self.CR_STA | self.CR_WR)
self.wait_busy()
if(self.rd_reg(self.R_SR) & self.SR_RXACK):
raise Exception('No ACK upon address (device 0x%x not connected?)' % addr)
return "nack"
else:
return "ack"
def write(self, data, last):
self.wr_reg(self.R_TXR, data)
cmd = self.CR_WR
if(last):
cmd = cmd | self.CR_STO
self.wr_reg(self.R_CR, cmd)
self.wait_busy()
if(self.rd_reg(self.R_SR) & self.SR_RXACK):
raise Exception('No ACK upon write')
def read(self, last):
cmd = self.CR_RD
if(last):
cmd = cmd | self.CR_STO | self.CR_ACK
self.wr_reg(self.R_CR, cmd)
self.wait_busy()
return self.rd_reg(self.R_RXR)
def scan(self):
periph_addr = []
for i in range(0,128):
addr = i << 1
addr |= 1
self.wr_reg(self.R_TXR, addr)
self.wr_reg(self.R_CR, self.CR_STA | self.CR_WR)
self.wait_busy()
if(not(self.rd_reg(self.R_SR) & self.SR_RXACK)):
periph_addr.append(i)
print("Device found at address: 0x%.2X") % i
self.wr_reg(self.R_TXR, 0)
self.wr_reg(self.R_CR, self.CR_STO | self.CR_WR)
self.wait_busy()
return periph_addr
##########################################
# Usage example
#gennum = rr.Gennum();
#i2c = COpenCoresI2C(gennum, 0x40000, 500);
#i2c.scan()
#!/usr/bin/python
import sys
import rr
import time
import spi
class CLTC217x:
R_RST = 0x00
R_FMT = 0x01
R_OUTMODE = 0x02
R_TESTPAT_MSB = 0x03
R_TESTPAT_LSB = 0x04
RST = (1<<7)
FMT_DCSOFF = (1<<7)
FMT_RAND = (1<<6)
FMT_TWOSCOMP = (1<<5)
FMT_SLEEP = (1<<4)
FMT_CH4_NAP = (1<<3)
FMT_CH3_NAP = (1<<2)
FMT_CH2_NAP = (1<<1)
FMT_CH1_NAP = (1<<0)
OUTMODE_ILVDS_3M5 = (0<<5)
OUTMODE_ILVDS_4M0 = (1<<5)
OUTMODE_ILVDS_4M5 = (2<<5)
OUTMODE_ILVDS_3M0 = (4<<5)
OUTMODE_ILVDS_2M5 = (5<<5)
OUTMODE_ILVDS_2M1 = (6<<5)
OUTMODE_ILVDS_1M75 = (7<<5)
OUTMODE_TERMON = (1<<4)
OUTMODE_OUTOFF = (1<<3)
OUTMODE_2L_16B = (0<<0)
OUTMODE_2L_14B = (1<<0)
OUTMODE_2L_12B = (2<<0)
OUTMODE_1L_14B = (5<<0)
OUTMODE_1L_12B = (6<<0)
OUTMODE_1L_16B = (7<<0)
TESTPAT_MSB_OUTTEST = (1<<7)
TESTPAT_MSB_MASK = 0x3F
TESTPAT_LSB_MASK = 0xFF
# addr = ltc217x register address (1 byte)
# value = value to write to the register (1 byte)
def wr_reg(self, addr, value):
tx = [value, addr]
self.spi.transaction(self.slave, tx)
def rd_reg(self, addr):
tx = [0xFF, (addr | 0x80)]
rx = self.spi.transaction(self.slave, tx)
return (rx[0] & 0xFF)
def __init__(self, spi, slave):
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_OUTMODE, (self.OUTMODE_ILVDS_4M5 | self.OUTMODE_2L_16B | self.OUTMODE_TERMON))
def get_fmt(self):
return self.rd_reg(self.R_FMT)
def get_outmode(self):
return self.rd_reg(self.R_OUTMODE)
def get_testpat(self):
return (((self.rd_reg(self.R_TESTPAT_MSB) & self.TESTPAT_MSB_MASK)<<8)
+ (self.rd_reg(self.R_TESTPAT_LSB) & self.TESTPAT_LSB_MASK))
def get_testpat_stat(self):
return ((self.rd_reg(self.R_TESTPAT_MSB))>>7)
def set_testpat(self, pattern):
self.wr_reg(self.R_TESTPAT_MSB, ((pattern>>8) & self.TESTPAT_MSB_MASK))
self.wr_reg(self.R_TESTPAT_LSB, (pattern & self.TESTPAT_LSB_MASK))
def en_testpat(self):
reg = self.rd_reg(self.R_TESTPAT_MSB)
reg |= self.TESTPAT_MSB_OUTTEST
self.wr_reg(self.R_TESTPAT_MSB, reg)
def dis_testpat(self):
reg = self.rd_reg(self.R_TESTPAT_MSB)
reg &= ~self.TESTPAT_MSB_OUTTEST
self.wr_reg(self.R_TESTPAT_MSB, reg)
def print_regs(self):
print '\nLTC217x registers:'
for i in range(0,5):
print("reg %d: %.2X") % (i, self.rd_reg(i))
#!/usr/bin/python
import sys
import rr
import time
import spi
import csr
class CMAX5442:
def __init__(self, spi, slave):
self.spi = spi
self.slave = slave
# offset = value to write to the DAC (2 bytes)
def set_offset(self, offset):
tx = [(offset & 0xFF), ((offset & 0xFF00)>>8)]
#print('[max5442] Set offset: %.4X') % offset
#for i in range(len(tx)):
# print('[max5442] tx[%d]: %.2X') %(i, tx[i])
self.spi.transaction(self.slave, tx)
#!/usr/bin/python
import sys
import rr
import time
class COpenCoresOneWire:
# OpenCores 1-wire registers description
R_CSR = 0x0
R_CDR = 0x4
CSR_DAT_MSK = (1<<0)
CSR_RST_MSK = (1<<1)
CSR_OVD_MSK = (1<<2)
CSR_CYC_MSK = (1<<3)
CSR_PWR_MSK = (1<<4)
CSR_IRQ_MSK = (1<<6)
CSR_IEN_MSK = (1<<7)
CSR_SEL_OFS = 8
CSR_SEL_MSK = (0xF<<8)
CSR_POWER_OFS = 16
CSR_POWER_MSK = (0xFFFF<<16)
CDR_NOR_MSK = (0xFFFF<<0)
CDR_OVD_OFS = 16
CDR_OVD_MSK = (0XFFFF<<16)
def wr_reg(self, addr, val):
self.bus.iwrite(0, self.base_addr + addr, 4, val)
def rd_reg(self,addr):
return self.bus.iread(0, self.base_addr + addr, 4)
# Function called during object creation
# bus = host bus (PCIe, VME, etc...)
# base_addr = 1-wire core base address
# clk_div_nor = clock divider normal operation, clk_div_nor = Fclk * 5E-6 - 1
# clk_div_ovd = clock divider overdrive operation, clk_div_ovd = Fclk * 1E-6 - 1
def __init__(self, bus, base_addr, clk_div_nor, clk_div_ovd):
self.bus = bus
self.base_addr = base_addr
#print('\n### Onewire class init ###')
#print("Clock divider (normal operation): %.4X") % clk_div_nor
#print("Clock divider (overdrive operation): %.4X") % clk_div_ovd
data = ((clk_div_nor & self.CDR_NOR_MSK) | ((clk_div_ovd<<self.CDR_OVD_OFS) & self.CDR_OVD_MSK))
#print('CRD register wr: %.8X') % data
self.wr_reg(self.R_CDR, data)
#print('CRD register rd: %.8X') % self.rd_reg(self.R_CDR)
# return: 1 -> presence pulse detected
# 0 -> no presence pulse detected
def reset(self, port):
data = ((port<<self.CSR_SEL_OFS) & self.CSR_SEL_MSK) | self.CSR_CYC_MSK | self.CSR_RST_MSK
#print('[onewire] Sending reset command, CSR: %.8X') % data
self.wr_reg(self.R_CSR, data)
while(self.rd_reg(self.R_CSR) & self.CSR_CYC_MSK):
pass
reg = self.rd_reg(self.R_CSR)
#print('[onewire] Reading CSR: %.8X') % reg
return ~reg & self.CSR_DAT_MSK
def slot(self, port, bit):
data = ((port<<self.CSR_SEL_OFS) & self.CSR_SEL_MSK) | self.CSR_CYC_MSK | (bit & self.CSR_DAT_MSK)
self.wr_reg(self.R_CSR, data)
while(self.rd_reg(self.R_CSR) & self.CSR_CYC_MSK):
pass
reg = self.rd_reg(self.R_CSR)
return reg & self.CSR_DAT_MSK
def read_bit(self, port):
return self.slot(port, 0x1)
def write_bit(self, port, bit):
return self.slot(port, bit)
def read_byte(self, port):
data = 0
for i in range(8):
data |= self.read_bit(port) << i
return data
def write_byte(self, port, byte):
data = 0
byte_old = byte
for i in range(8):
data |= self.write_bit(port, (byte & 0x1)) << i
byte >>= 1
if(byte_old == data):
return 0
else:
return -1
def write_block(self, port, block):
if(160 < len(block)):
return -1
data = []
for i in range(len(block)):
data.append(self.write_byte(port, block[i]))
return data
def read_block(self, port, length):
if(160 < length):
return -1
data = []
for i in range(length):
data.append(self.read_byte(port))
return data
#! /usr/bin/env python
# coding: utf8
class PtsException(Exception):
pass
class PtsCritical(PtsException):
"""critical error, abort the whole test suite"""
pass
class PtsError(PtsException):
"""error, continue remaining tests in test suite"""
pass
class PtsUser(PtsException):
"""error, user intervention required"""
pass
class PtsWarning(PtsException):
"""warning, a cautionary message should be displayed"""
pass
class PtsInvalid(PtsException):
"""reserved: invalid parameters"""
class PtsNoBatch(PtsInvalid):
"""reserved: a suite was created without batch of tests to run"""
pass
class PtsBadTestNo(PtsInvalid):
"""reserved: a bad test number was given"""
pass
if __name__ == '__main__':
pass
#! /usr/bin/env python
# :vi:ts=4 sw=4 et
from ctypes import *
import os, errno, re, sys, struct
# python 2.4 kludge
if not 'SEEK_SET' in dir(os):
os.SEEK_SET = 0
# unsigned formats to unpack words
fmt = { 1: 'B', 2: 'H', 4: 'I', 8: 'L' }
# some defaults from rawrabbit.h
RR_DEVSEL_UNUSED = 0xffff
RR_DEFAULT_VENDOR = 0x1a39
RR_DEFAULT_DEVICE = 0x0004
RR_BAR_0 = 0x00000000
RR_BAR_2 = 0x20000000
RR_BAR_4 = 0x40000000
RR_BAR_BUF = 0xc0000000
bar_map = {
0 : RR_BAR_0,
2: RR_BAR_2,
4: RR_BAR_4,
0xc: RR_BAR_BUF }
# classes to interface with the driver via ctypes
Plist = c_int * 256
class RR_Devsel(Structure):
_fields_ = [
("vendor", c_ushort),
("device", c_ushort),
("subvendor", c_ushort),
("subdevice", c_ushort),
("bus", c_ushort),
("devfn", c_ushort),
]
class RR_U(Union):
_fields_ = [
("data8", c_ubyte),
("data16", c_ushort),
("data32", c_uint),
("data64", c_ulonglong),
]
class RR_Iocmd(Structure):
_anonymous_ = [ "data", ]
_fields_ = [
("address", c_uint),
("datasize", c_uint),
("data", RR_U),
]
class Gennum(object):
device = '/dev/rawrabbit'
rrlib = './rrlib.so'
def __init__(self):
"""get a file descriptor for the Gennum device"""
self.lib = CDLL(Gennum.rrlib)
self.fd = os.open(Gennum.device, os.O_RDWR)
self.errno = 0
if self.fd < 0:
self.errno = self.fd
def iread(self, bar, offset, width):
"""do a read by means of the ioctl interface
bar = 0, 2, 4 (or c for DMA buffer access
offset = address within bar
width = data size (1, 2, 4 or 8 bytes)
"""
address = bar_map[bar] + offset
ds = RR_Iocmd(address=address, datasize=width)
self.errno = self.lib.rr_iread(self.fd, byref(ds))
return ds.data32
def read(self, bar, offset, width):
"""do a read by means of lseek+read
bar = 0, 2, 4 (or c for DMA buffer access
offset = address within bar
width = data size (1, 2, 4 or 8 bytes)
"""
address = bar_map[bar] + offset
self.errno = os.lseek(self.fd, address, os.SEEK_SET)
buf = os.read(self.fd, width)
return struct.unpack(fmt[width], buf)[0]
def iwrite(self, bar, offset, width, datum):
"""do a write by means of the ioctl interface
bar = 0, 2, 4 (or c for DMA buffer access
offset = address within bar
width = data size (1, 2, 4 or 8 bytes)
datum = value to be written
"""
address = bar_map[bar] + offset
ds = RR_Iocmd(address=address, datasize=width, data32=datum)
self.errno = self.lib.rr_iwrite(self.fd, byref(ds))
return ds.data32
def write(self, bar, offset, width, datum):
"""do a write by means of lseek+write
bar = 0, 2, 4 (or c for DMA buffer access
offset = address within bar
width = data size (1, 2, 4 or 8 bytes)
datum = value to be written
"""
address = bar_map[bar] + offset
self.errno = os.lseek(self.fd, address, os.SEEK_SET)
return os.write(self.fd, struct.pack(fmt[width], datum))
def irqwait(self):
"""wait for an interrupt"""
return self.lib.rr_irqwait(self.fd);
def irqena(self):
"""enable the interrupt line"""
return self.lib.rr_irqena(self.fd);
def getdmasize(self):
"""return the size of the allocated DMA buffer (in bytes)"""
return self.lib.rr_getdmasize(self.fd);
def getplist(self):
"""get a list of pages for DMA access
The addresses returned, shifted by 12 bits, give the physical
addresses of the allocated pages
"""
plist = Plist()
self.lib.rr_getplist(self.fd, plist);
return plist
def info(self):
"""get a string describing the interface the driver is bound to
The syntax of the string is
vendor:device/dubvendor:subdevice@bus:devfn
"""
ds = RR_Devsel()
self.errno = self.lib.rr_devget(self.fd, byref(ds))
for key in RR_Devsel._fields_:
setattr(self, key[0], getattr(ds, key[0], RR_DEVSEL_UNUSED))
return '%04x:%04x/%04x:%04x@%04x:%04x' % (
ds.vendor, ds.device,
ds.subvendor, ds.subdevice,
ds.bus, ds.devfn)
def parse_addr(self, addr):
"""take a string of the form
vendor:device[/subvendor:subdevice][@bus:devfn]
and return a dictionary object with the corresponding values,
initialized to RR_DEVSEL_UNUSED when absent
"""
# address format
reg = ( r'(?i)^'
r'(?P<vendor>[a-f0-9]{1,4}):(?P<device>[a-f0-9]{1,4})'
r'(/(?P<subvendor>[a-f0-9]{1,4}):(?P<subdevice>[a-f0-9]{1,4}))?'
r'(@(?P<bus>[a-f0-9]{1,4}):(?P<devfn>[a-f0-9]{1,4}))?$' )
match = re.match(reg, addr).groupdict()
if not 'sub' in match:
match['subvendor'] = match['subdevice'] = RR_DEVSEL_UNUSED
if not 'geo' in match:
match['bus'] = match['devfn'] = RR_DEVSEL_UNUSED
for k, v in match.items():
if type(v) is str:
match[k] = int(v, 16)
return match
def bind(self, device):
"""bind the rawrabbit driver to a device
The device is specified with a syntax described in parse_addr
"""
d = self.parse_addr(device)
ds = RR_Devsel(**d)
self.errno = self.lib.rr_devsel(self.fd, byref(ds))
return self.errno
if __name__ == '__main__':
g = Gennum()
print g.parse_addr('1a39:0004/1a39:0004@0020:0000')
print g.bind('1a39:0004/1a39:0004@0020:0000')
print '%x' % g.write(bar=RR_BAR_4, offset=0xa08, width=4, datum=0xdeadface)
print '%x' % g.read(bar=RR_BAR_4, offset=0xa08, width=4)
print g.getdmasize()
for page in g.getplist():
print '%08x ' % (page<<12),
#!/usr/bin/python
import sys
import rr
import time
import i2c
class CSi57x:
R_HS = 0x07
R_RFREQ4 = 0x08
R_RFREQ3 = 0x09
R_RFREQ2 = 0x0A
R_RFREQ1 = 0x0B
R_RFREQ0 = 0x0C
R_RFMC = 0x87
R_FDCO = 0x89
HS_DIV_MASK = 0xE0
N1_H_MASK = 0x1F
N1_L_MASK = 0xC0
RFREQ4_MASK = 0x3F
RFMC_RST = (1<<7)
RFMC_NEW_FREQ = (1<<6)
RFMC_FREEZE_M = (1<<5)
RFMC_FREEZE_VCADC = (1<<4)
RFMC_RECALL = (1<<0)
FDCO_FREEZE_DCO = (1<<4)
def __init__(self, i2c, addr):
self.i2c = i2c
self.addr = addr
def rd_reg(self, addr):
self.i2c.start(self.addr, True)
self.i2c.write(addr, False)
self.i2c.start(self.addr, False)
reg = self.i2c.read(True)
#print("raw data from Si570: %.2X")%reg
return reg
def wr_reg(self, addr, data):
self.i2c.start(self.addr, True)
self.i2c.write(addr, False)
self.i2c.write(data, True)
def get_rfreq(self):
rfreq = self.rd_reg(self.R_RFREQ0)
rfreq += (self.rd_reg(self.R_RFREQ1)<<8)
rfreq += (self.rd_reg(self.R_RFREQ2)<<16)
rfreq += (self.rd_reg(self.R_RFREQ3)<<24)
rfreq += ((self.rd_reg(self.R_RFREQ4) & self.RFREQ4_MASK)<<32)
return (rfreq>>28)+((rfreq & 0x0FFFFFFF)/2.0**28)
def get_n1_div(self):
n1 = ((self.rd_reg(self.R_RFREQ4) & self.N1_L_MASK)>>6)
n1 += ((self.rd_reg(self.R_HS) & self.N1_H_MASK)<<2)
return n1
def get_hs_div(self):
return ((self.rd_reg(self.R_HS))>>5)
def set_rfreq(self, freq):
self.wr_reg(self.R_RFERQ0, (freq & 0xFF))
self.wr_reg(self.R_RFERQ1, ((freq>>8) & 0xFF))
self.wr_reg(self.R_RFERQ2, ((freq>>16) & 0xFF))
self.wr_reg(self.R_RFERQ3, ((freq>>24) & 0xFF))
reg = self.rd_reg(self.R_RFERQ4)
self.wr_reg(self.R_RFERQ4, (((freq>>32) & self.RFREQ4_MASK) | (reg & self.N1_L_MASK)))
def set_hs_div(self, div):
reg = self.rd_reg(self.R_HS)
self.wr_reg(self.R_HS, ((div<<5) | (reg & self.N1_H_MASK)))
def set_n1_div(self, div):
reg = self.rd_reg(self.R_HS)
self.wr_reg(self.R_HS, ((div>>2) | (reg & self.HS_DIV_MASK)))
reg = self.rd_reg(self.R_RFREQ4)
self.wr_reg(self.R_RFREQ4, (((div & self.N1_L_MASK)<<6) | (reg & self.RFREQ4_MASK)))
def freeze_m(self):
reg = self.rd_reg(self.R_RFMC) | self.RFMC_FREEZE_M
self.wr_reg(self.R_RFMC, reg)
def unfreeze_m(self):
reg = self.rd_reg(self.R_RFMC) & ~(self.RFMC_FREEZE_M)
self.wr_reg(self.R_RFMC, reg)
def freeze_dco(self):
self.wr_reg(self.R_RDCO, self.FDCO_FREEZE_DCO)
def unfreeze_dco(self):
self.wr_reg(self.R_RDCO, 0)
def reset_reg(self):
reg = self.rd_reg(self.R_RFMC) | self.RFMC_RST
self.wr_reg(self.R_RFMC, reg)
def recall_nvm(self):
reg = self.rd_reg(self.R_RFMC) | self.RFMC_RECALL
self.wr_reg(self.R_RFMC, reg)
# For Si571 only !
def freeze_vcadc(self):
reg = self.rd_reg(self.R_RFMC) | self.RFMC_FREEZE_VCADC
self.wr_reg(self.R_RFMC, reg)
def unfreeze_vcadc(self):
reg = self.rd_reg(self.R_RFMC) & ~(self.RFMC_FREEZE_VCADC)
self.wr_reg(self.R_RFMC, reg)
#!/usr/bin/python
import sys
import rr
import time
class COpenCoresSPI:
R_RX = [0x00, 0x04, 0x08, 0x0C]
R_TX = [0x00, 0x04, 0x08, 0x0C]
R_CTRL = 0x10
R_DIV = 0x14
R_SS = 0x18
LGH_MASK = (0x7F)
CTRL_GO = (1<<8)
CTRL_BSY = (1<<8)
CTRL_RXNEG = (1<<9)
CTRL_TXNEG = (1<<10)
CTRL_LSB = (1<<11)
CTRL_IE = (1<<12)
CTRL_ASS = (1<<13)
DIV_MASK = (0xFFFF)
SS_SEL = [0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40]
conf = 0x0
def wr_reg(self, addr, val):
self.bus.iwrite(0, self.base_addr + addr, 4, val)
def rd_reg(self, addr):
return self.bus.iread(0, self.base_addr + addr, 4)
def __init__(self, bus, base_addr, divider):
self.bus = bus;
self.base_addr = base_addr;
self.wr_reg(self.R_DIV, (divider & self.DIV_MASK));
# default configuration
self.conf = self.CTRL_ASS | self.CTRL_TXNEG
def wait_busy(self):
while(self.rd_reg(self.R_CTRL) & self.CTRL_BSY):
pass
def config(self, ass, rx_neg, tx_neg, lsb, ie):
self.conf = 0
if(ass):
self.conf |= self.CTRL_ASS
if(tx_neg):
self.conf |= self.CTRL_TXNEG
if(rx_neg):
self.conf |= self.CTRL_RXNEG
if(lsb):
self.conf |= self.CTRL_LSB
if(ie):
self.conf |= self.CTRL_IE
# slave = slave number (0 to 7)
# data = byte data array to send, in case if read fill with dummy data of the right size
def transaction(self, slave, data):
txrx = [0x00000000, 0x00000000, 0x00000000, 0x00000000]
for i in range(0,len(data)):
txrx[i/4] += (data[i]<<((i%4)*8))
#print("tx[%d]=%.8X data[%d]=%.2X") %(i/4,txrx[i/4],i,data[i])
for i in range(0, len(txrx)):
self.wr_reg(self.R_TX[i], txrx[i])
#print('data length: 0x%X')%len(data)
self.wr_reg(self.R_SS, self.SS_SEL[slave])
self.wr_reg(self.R_CTRL, (self.LGH_MASK & (len(data)<<3)) | self.CTRL_GO | self.conf)
self.wait_busy()
for i in range(0, len(txrx)):
txrx[i] = self.rd_reg(self.R_RX[i])
#print("rx[%d]=%.8X") %(i,txrx[i])
return txrx
#gennum = rr.Gennum();
#spi = COpenCoresSPI(gennum, 0x80000, 500);
#! /usr/bin/env python
# coding: utf8
# Copyright CERN, 2011
# Author: Matthieu Cattin <matthieu.cattin@cern.ch>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
import sys
import rr
import time
import os
import fmc_adc_test_suite
from ptsexcept import *
import csr
"""
test00: Load firmware and test mezzanine presence line.
"""
def main (default_directory='.'):
path_fpga_loader = '../firmwares/fpga_loader';
path_firmware = '../firmwares/TestSuite.bin';
firmware_loader = os.path.join(default_directory, path_fpga_loader)
bitstream = os.path.join(default_directory, path_firmware)
os.system( firmware_loader + ' ' + bitstream)
time.sleep(2);
# Objects declaration
spec = rr.Gennum()
fmc = fmc_adc_test_suite.CFmcAdc100ks(spec)
# Check bitsteam type
bitstream_type = fmc.bitstream_type()
print('bitstream type:%.8X') % bitstream_type
if(bitstream_type == 0xFFFFFFFF):
raise PtsCritical ("Firmware not properly loaded.")
print "Pts Critical - firmware not loaded properly"
if(bitstream_type != 0x1):
raise PtsCritical ("Wrong bitstream type.")
print "Pts Critical - wrong bitstream"
# Dump carrier CSR to log
print("PCB version : %d") % ( fmc.pcb_version() ) # used to be a mask here
print("Carrier type : %d") % ( fmc.carrier_type()) # and here
print("Bitstream type : 0x%.8X") % (fmc.bitstream_type())
print("Bitstream date : 0x%.8X") % (fmc.bitstream_date())
print("Status : 0x%.8X") % (fmc.carrier_csr_sta())
print("Control : 0x%.8X") % (fmc.carrier_csr_ctl())
# Check mezzanine presence flag
status = fmc.check_mez_present()
print('carrier csr :%.8X') % status
if(status & 0x1):
print "Pts Critical - mez not pres"
raise PtsCritical ("Mezzanine not present or PRSNT_M2C_L faulty.")
if __name__ == '__main__' :
main()
#! /usr/bin/env python
# coding: utf8
# Copyright CERN, 2011
# Author: Matthieu Cattin <matthieu.cattin@cern.ch>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
import sys
import rr
import time
import os
import fmc_adc_test_suite
from ptsexcept import *
import csr
import fcntl, struct, termios, os
import time
import array
"""
test01: Validates TestBox is working
"""
class cp210x_gpio:
def __init__(self, usb_number):
self.fd = open('/dev/ttyUSB' + str(usb_number), 'wb')
def gpio_set(self, mask):
fcntl.ioctl(self.fd.fileno(), 0x8001, mask)
def gpio_get(self):
f = array.array('I', [0])
ret = fcntl.ioctl(self.fd.fileno(), 0x8000, f, 1)
return f[0]
def main (default_directory='.'):
gpio_wr = 0xF
gpio = cp210x_gpio(0)
gpio.gpio_set(gpio_wr)
gpio_rd = gpio.gpio_get()
print "Value written to test box : %X"%gpio_wr
print "Value read back from testbox : %X"%gpio_rd
if gpio_rd != gpio_wr:
print " Problem with test box"
print " Please check test box is attached properly"
print " Check power LED on test box"
raise PtsCritical("Problem with test box : Not all tests can be fully completed")
if __name__ == '__main__' :
main()
#! /usr/bin/env python
# coding: utf8
# Copyright CERN, 2011
# Author: Ross Millar <ross.millar@cern.ch>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
## TEST FOR VCXO
import sys
import os
import os.path
import rr
import random
import time
import spi
import csr
import i2c
import gn4124
import fmc_adc_test_suite
from pylab import *
from ptsexcept import *
"""
Test Suite test 1:
Counts 2^31 clock ticks on the mez clock, in terms of the system clock.
Writes a new value to the DAC, which in turn alters the mez clock
Counts 2^31 clock ticks on the mez clock again
Compares the 2 resuls to see if the mez clock has changed appropriately
"""
def mean(numberList):
if len(numberList)==0:
return int('nan')
intnums = [int(x) for x in numberList]
return sum(intnums)/len(numberList)
def main(default_directory='.') :
# Objects declaration
spec = rr.Gennum()
fmc = fmc_adc_test_suite.CFmcAdc100ks(spec)
# Reset DAC register - Set VCXO to lowest frequency
fmc.spi_dac_write(0x0000)
# Number of sys clock ticks for counter on mezzanine clock to complete count
result = fmc.clock_comparison()
time.sleep(.1)
fmc.spi_dac_write(0xFFFF)
time.sleep(.1)
# Number of sys clock ticks for counter on mezzanine clock to complete count
result_1 = fmc.clock_comparison()
print "VCXO @ lowest frequency - Number of sys clock ticks for mez clock count : %d" %result
print "VCXO @ highest frequency - Number of sys clock ticks for mez clock count : %d" %result_1
if (result - result_1) >10:
print "DAC and VCXO fully working"
else:
fmc.spi_dac_write(0x0000)
dac_low_val = fmc.do_small_acq(15) # decide on channel order in test suite firmware
time.sleep(0.1)
fmc.spi_dac_write(0xFFFF)
time.sleep(0.1)
dac_high_val = fmc.do_small_acq(15)
print "Value with DAC low ",dac_low_val
print "Value with DAC high ",dac_high_val
if mean(dac_low_val)+1000 < mean(dac_high_val):
print "DAC appears operational however VCXO frequency didnt change as expected"
print "Potential connection problem between DAC Vout and VCXO Vctrl Pin"
raise PtsError("VCXO not working, DAC operational, test connection between DAC output and VCXO input")
else:
print "DAC not working"
print "VCXO pullability untested"
raise PtsError("DAC not working - Check solder connection")
if __name__ == '__main__':
main()
#! /usr/bin/env python
# coding: utf8
# Copyright CERN, 2011
# Author: Ross Millar <ross.millar@cern.ch>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
import sys
import rr
import random
import time
import spi
import csr
import i2c
import gn4124
import fmc_adc_test_suite
#from pylab import *
from ptsexcept import *
import os
"""
EEPROM test, tests if you can write and then read a result from the EEPROM on the mezzanine
"""
def main (default_directory='.'):
path_fpga_loader = '../firmwares/fpga_loader';
path_firmware = '../firmwares/TestSuite.bin';
firmware_loader = os.path.join(default_directory, path_fpga_loader)
bitstream = os.path.join(default_directory, path_firmware)
os.system( firmware_loader + ' ' + bitstream)
time.sleep(2);
# Objects declaration
spec = rr.Gennum()
fmc = fmc_adc_test_suite.CFmcAdc100ks(spec)
EEPROM_ADDR = 0x50
EEPROM_ADDR_FOUND = fmc.sys_i2c_scan()
if(len(EEPROM_ADDR_FOUND) == 0):
raise PtsError('No peripheral detected on system management I2C bus')
else:
if(len(EEPROM_ADDR_FOUND) != 1):
raise PtsError('Signal integrity problem detected on system management I2C bus, %d devices detected instead of 1'%(len(EEPROM_ADDR_FOUND)))
else:
if(EEPROM_ADDR != EEPROM_ADDR_FOUND[0]):
raise PtsError('Wrong device mounted on system management I2C bus, address is:0x%.2X expected:0x%.2X'%(EEPROM_ADDR_FOUND[0],EEPROM_ADDR))
addr = 0x10
wr_data = [0x11,0x22,0x33,0x44]
rd_data = []
print('Write data at EEPROM address:0x%.2X')%addr
print wr_data
fmc.sys_i2c_eeprom_write(addr, wr_data)
time.sleep(.1)
print('Read back data from EEPROM address:0x%.2X')%addr
rd_data = fmc.sys_i2c_eeprom_read(addr,len(wr_data))
print rd_data
if(rd_data != wr_data):
raise PtsError('Cannot access EEPROM at address:0x%.2X'%(EEPROM_ADDR))
else:
print('Data comparison OK.')
print"EEPROM Device fully functional"
if __name__ == '__main__' :
main()
#! /usr/bin/env python
# coding: utf8
# Copyright CERN, 2011
# Author: Ross Millar <ross.millar@cern.ch>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
import sys
import rr
import random
import time
import spi
import csr
import i2c
import gn4124
import fmc_adc_test_suite
#from pylab import *
from ptsexcept import *
"""
Test03
ADC digital signal test : Tests all flags and conrol lines to both ADC chips on the FMC
"""
def main (default_directory='.'):
# Objects declaration
spec = rr.Gennum() # bind to the SPEC board
fmc = fmc_adc_test_suite.CFmcAdc100ks(spec)
# Run Acqusition Test
print "Running test acquisition - Checking if state machine becomes stuck waiting for ADC flags"
Error_state = fmc.do_test_acq()
error_cnt = 0
if Error_state!=0:
error_cnt=error_cnt +1
if Error_state == 0:
print "No errors found : CONVST, BUSY1, BUSY2, FIRSTDATA1, FIRSTDATA2 - All fully functional "
elif Error_state ==3:
print "Error: One of the Busy lines not responding - "
elif Error_state ==4:
print "Error: Busy Line on ADC chip 1 tied high"
elif Error_state ==5:
print "Error: First Data high on ADC chip 1 not responding, possible bad solder connection"
elif Error_state ==7:
print "Error: Busy Line on ADC chip 2 tied high"
elif Error_state ==8:
print "Error: First Data line on ADC chip 2 not responding, possible bad solder connection"
else:
print "Error: stuck in an unexpected state"
if Error_state == 3:
busy_lines = fmc.check_busy_lines()
if busy_lines == 1:
print "Busy line not raised on ADC 2 (bottom as facing board)"
print "Possible bad solder connection for this chip"
elif busy_lines == 2:
print "Busy line not raised on ADC 1 (top as facing board)"
print "Possible bad solder connection for this chip"
elif busy_lines ==3:
print "Both busy appear to have been raised"
elif busy_lines==0:
print "Neither Busy line 1 or 2 were raised as expected"
print "Potential problems :"
print "1. Flip-flop solder connection problem - meaning CONVST line was never raised"
print "2. Both ADC chips are faulty or have not been soldered correctly to the board"
else:
print "Values not writen to CSR correctly"
elif Error_state == 4:
busy_lines = fmc.check_busy_lines()
if busy_lines == 1:
print "Busy line 1 tied high - Possible short to a power supply"
print "Busy line 2 did not respond - Possible bad solder connection on CNVST line to ADC chip 2,"
print "or on busy line to LPC connector"
elif busy_lines == 2:
print "Busy line 2 tied high - Possible short to a power supply"
print "Busy line 1 did not respond - Possible bad solder connection on CNVST line to ADC chip 1,"
print "or on busy line to LPC connector"
# Check range pin on ADC 1
range_working = fmc.check_range_pin(1)
if range_working ==1:
print "Range pin fully working on ADC chip 1"
elif range_working ==0:
print "Error: Range pin not working on ADC chip 1"
print "Possible Cause: Possible bad solder connection on ADC chip 1 - (Top chip as facing Board)"
error_cnt=error_cnt+1
# Check range pin on ADC 2
range_working = fmc.check_range_pin(2)
if range_working ==1:
print "Range pin fully working on ADC chip 2"
elif range_working ==0:
print"Error: Range pin not working on ADC chip 2"
print"Possible Cause: Possible bad solder connection on ADC chip 1 - (Bottom chip as facing Board)"
print"Please ensure test box is properly connected"
error_cnt=error_cnt+1
if error_cnt!=0:
raise PtsError("ADC Digital I/Os Failed - See log for details of fail")
if __name__ == '__main__':
main()
#!/usr/bin/env python
#coding: utf8
# Copyright CERN, 2011
# Author: Ross Millar <ross.millar@cern.ch>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
import sys
import rr
import random
import time
import spi
import csr
import i2c
import gn4124
import fmc_adc_test_suite
#from pylab import *
from ptsexcept import *
"""
Test03
Tests Front Panel LEDs
"""
def main (default_directory='.'):
spec = rr.Gennum() # bind to the SPEC board
fmc = fmc_adc_test_suite.CFmcAdc100ks(spec)
print "Starting blinking leds test."
# Start the leds blinking
fmc.start_leds_blinking()
ask = "";
tmp_stdout = sys.stdout;
sys.stdout = sys.__stdout__;
tmp_stdin = sys.stdin;
sys.stdin = sys.__stdin__;
while ((ask != "Y") and (ask != "N")) :
print "-------------------------------------------------------------"
print "\t Look at the ADC BOARD "
ask = raw_input("Are the LEDs blinking? [Y/N]")
ask = ask.upper()
print "-------------------------------------------------------------"
sys.stdout = tmp_stdout;
sys.stdin = tmp_stdin;
if (ask == "N") :
raise PtsError("Error: There is a problem with the LEDs");
print "The LEDs are working as expected"
fmc.stop_leds_blinking()
if __name__ == '__main__':
main()
#!/usr/bin/env python
#coding: utf8
# Copyright CERN, 2011
# Author: Ross Millar <ross.millar@cern.ch>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
import sys
import rr
import random
import time
import spi
import csr
import i2c
import gn4124
import fmc_adc_test_suite
import cp210x_gpio
#from pylab import *
#from ptsexcept import *
import fcntl, struct, termios, os
import time
import array
class cp210x_gpio:
def __init__(self, usb_number):
self.fd = open('/dev/ttyUSB' + str(usb_number), 'wb')
def gpio_set(self, mask):
fcntl.ioctl(self.fd.fileno(), 0x8001, mask)
def gpio_get(self):
f = array.array('I', [0])
ret = fcntl.ioctl(self.fd.fileno(), 0x8000, f, 1)
return f[0]
"""
Test the analog inputs to the ADC
"""
def main (default_directory='.'):
# Object Declaration
spec = rr.Gennum() # bind to the SPEC board
fmc = fmc_adc_test_suite.CFmcAdc100ks(spec)
gpio = cp210x_gpio(0)
# All inputs high
#force_inputs = sim_function(12)
gpio.gpio_set(0xF)
split_channels = []
average = []
error_cnt =0
average = fmc.do_acq(1, "camera_link" ,"Y",10,10,0)
for element in range(len(average)):
if average[element] <100: # Change from 5 to something more reasonable
print "\nError: Pin voltage lower than expected on pin %d "%element
print "Details: Expected value was ~5 "
print "Details: Received value was %d \n"%average[element]
error_cnt = error_cnt+1
else:
print "Voltage on pin %d was as expected"%(element+1)
for i in range(11):
print "Setting Channel %d low ..."%(i+1)
# Set Addr on GPIOs in the test box
gpio.gpio_set((i) & 0xF)
# Do an acquisiton, return the average voltage on each channel
average = fmc.do_acq(1, "camera_link" ,"Y",10,10,0)
for k in range(11):
# if channel doesnt equal the input with ~ 0V on input
if k!=i:
if average[k] <= 1000:
print "Error: channel value not as expected on channel %d\n"%(k+1)
print "Error: Expected V high of _____, found value of %d" %average[k]
print "Error: Possiblity of Channel %d shorted to ground"%(k+1)
error_cnt =error_cnt+1
elif i == k:
if average[k] >=50:
print "Error: Expected V low of ~0 V on input, found value of %d"%average[i]
print "Error: Possibility of Pin %d shorted to an adjacent pin"%(k+1)
error_cnt =error_cnt +1
if error_cnt==0:
print "No Errors, All input pins fully functional"
else:
raise PtsError("ADC Analogue input Test Failed - See Log for reason of failure")
print "test failed - see log for details"
if __name__ == '__main__':
main()
#! /usr/bin/env python
# coding: utf8
# Copyright CERN, 2011
# Author: Ross Millar <ross.millar@cern.ch>
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
import sys
import rr
import random
import time
import spi
import csr
import i2c
import gn4124
import fmc_adc_test_suite
from ptsexcept import *
import os
"""
EEPROM test - Runs python tool to generate binary input file from calibration data and input XML file
"""
def main (default_directory='.'):
path_fpga_loader = '../firmwares/fpga_loader';
path_firmware = '../firmwares/TestSuite.bin';
firmware_loader = os.path.join(default_directory, path_fpga_loader)
bitstream = os.path.join(default_directory, path_firmware)
os.system( firmware_loader + ' ' + bitstream)
time.sleep(2);
# Objects declaration
spec = rr.Gennum()
fmc = fmc_adc_test_suite.CFmcAdc100ks(spec)
# Runs fmc_eeprom_gen.py - giving file containg calibration data as an argument
os.system("python fmc_eeprom_gen.py -r calibration_data.txt")
# Uses eeprom class to dump the output file from fmc_eeprom_gen, into eeprom
fmc.fmc_eeprom_gen_wr("eeprom_formatted_data.txt")
time.sleep(.1)
if __name__ == '__main__' :
main()
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