Commit 40a16639 authored by Mariusz Mroz's avatar Mariusz Mroz

Documentation on new template. Software and gateware corrections.

parent 410ac7fe
......@@ -21,11 +21,16 @@ transcript
doc/*.pdf
*.o
*.so
*.a
*.pyc
*.elf
output
software/rf-test
*.png
*.odt.saved
python/sdbfs/IPMI-FRU
\ No newline at end of file
python/sdbfs/IPMI-FRU
python/gensdbfs
ptsfiles/cp210x/*
!ptsfiles/cp210x/Makefile
!ptsfiles/cp210x/cp210x.c
\ No newline at end of file
......@@ -14,3 +14,6 @@
path = gateware/ip_cores/etherbone-core
url = git://ohwr.org/hdl-core-lib/etherbone-core.git
[submodule "software/fpga-config-space"]
path = software/fpga-config-space
url = git://ohwr.org/hdl-core-lib/fpga-config-space.git
No preview for this file type
#!/bin/bash
rmmod fmc_adc_100m14b 2> /dev/null
rmmod zio 2> /dev/null
rmmod rawrabbit 2> /dev/null
rmmod spec 2> /dev/null
rmmod fmc 2> /dev/null
rmmod cp210x 2>/dev/null
rmmod usbtmc 2>/dev/null
prg=$0
if [ ! -e "$prg" ]; then
case $prg in
(*/*) exit 1;;
(*) prg=$(command -v -- "$prg") || exit;;
esac
fi
dir=$(
cd -P -- "$(dirname -- "$prg")" && pwd -P
) || exit
prg=$dir/$(basename -- "$prg") || exit
top=`echo "$prg" | sed 's/fmcdac600m12b1chadds.*/fmcdac600m12b1chadds\//'`
insmod "$top/software/fmc-bus/kernel/fmc.ko"
insmod "$top/software/spec-sw/kernel/spec.ko" "fw_name=../../$top/gateware/spec-init.bin-2012-12-14"
insmod "$top/software/fmc-adc-100m14b4cha-sw/zio/zio.ko"
insmod "$top/software/fmc-adc-100m14b4cha-sw/kernel/fmc-adc-100m14b.ko" "gateware=../../$top/gateware/spec-fmc-adc-v4.0.bin"
adc=`python -c 'import sys; sys.path.append('\'python\''); import spec_identification; spec_identification.adc_bus()'`
dut=`python -c 'import sys; sys.path.append('\'python\''); import spec_identification; spec_identification.dut_bus()'`
echo "Please verify if both SPEC cards were correctly identified"
echo ""
echo "Files belowe are named with following pattern:"
echo "[arbitrary lenght]-[2 numbers][2 numbers]"
echo "<name>-<bus><slot>"
echo ""
echo "ls /sys/bus/fmc/devices/"
ls /sys/bus/fmc/devices/
echo ""
if [ $adc -ge 0 ]
then
echo "FmcAdc100m14b was found on bus $adc"
else
echo "FmcAdc100m14b was not found"
echo "Make sure that single FmcAdc100m14b board is mounted in PCIe slot and that it contain valid eeprom content"
fi
if [ $dut -ge 0 ]
then
echo "Board under test was found on bus $dut"
else
echo "Board under test was not found"
echo "Make sure that card is mounted in PCIe slot"
fi
#!/bin/bash
echo "WARRNING!!!"
echo "errors indicating that modules are not loaded should be ignored"
echo "i.e: rmmod: \"ERROR: Module fmc_adc_100m14b is not currently loaded\" should be ignored"
rmmod fmc_adc_100m14b > /dev/null
rmmod zio > /dev/null
rmmod rawrabbit > /dev/null
rmmod spec > /dev/null
rmmod fmc > /dev/null
rmmod fmc_adc_100m14b 2> /dev/null
rmmod zio 2> /dev/null
rmmod rawrabbit 2> /dev/null
rmmod spec 2> /dev/null
rmmod fmc 2> /dev/null
modprobe usbserial
rmmod cp210x
rmmod usbtmc
rmmod cp210x 2>/dev/null
rmmod usbtmc 2>/dev/null
prg=$0
......@@ -32,21 +28,19 @@ top=`echo "$prg" | sed 's/pts.*/pts\//'`
insmod "$top/test/fmcdac600m12b1chadds/software/fmc-bus/kernel/fmc.ko"
insmod "$top/test/fmcdac600m12b1chadds/software/spec-sw/kernel/spec.ko"
insmod "$top/test/fmcdac600m12b1chadds/software/fmc-bus/kernel/fmc.ko"
insmod "$top/test/fmcdac600m12b1chadds/software/spec-sw/kernel/spec.ko" "fw_name=../../$top/test/fmcdac600m12b1chadds/gateware/spec-init.bin-2012-12-14"
insmod "$top/test/fmcdac600m12b1chadds/software/fmc-adc-100m14b4cha-sw/zio/zio.ko"
insmod "$top/test/fmcdac600m12b1chadds/software/fmc-adc-100m14b4cha-sw/kernel/fmc-adc-100m14b.ko"
insmod "$top/test/fmcdac600m12b1chadds/software/fmc-adc-100m14b4cha-sw/kernel/fmc-adc-100m14b.ko" "gateware=../../$top/test/fmcdac600m12b1chadds/gateware/spec-fmc-adc-v4.0.bin"
insmod "$top/cp210x/cp210x.ko"
# "$top/usbdriver/usbtmc_load"
LOGDIR="$top/log_fmcdac600m12b1chadds"
mkdir -p "$LOGDIR"
mkdir -p "$LOGDIR/eeprom"
# sudo rm -fr $LOGDIR/pts*
serial=$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 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(0.8)
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):
if len(data) > 32:
print "Maximum sequence write size is 32 byte!"
return -1;
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)
self.i2c.write(data[i],False)
if len(data) > 1:
i += 1
else:
i = 0
#print('24AA64:write:last i=%d')%(i)
self.i2c.write(data[i],True)
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)
#print('24AA64:read:last i=%d')%(i)
data.append(self.i2c.read(True))
return data;
#!/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_PCI_SYS_CFG = 0x800
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 RSTOUT33 assert/de-assert cycle
def rstout33_cycle(self):
# assert RSTOUT33 pin
self.wr_reg(self.GN4124_BAR, self.R_PCI_SYS_CFG, 0x00021040)
# de-assert RSTOUT33 pin
self.wr_reg(self.GN4124_BAR, self.R_PCI_SYS_CFG, 0x00025000)
# 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/python
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, 0x80000, 500);
#!/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_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))
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/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)
HS_DIV = [4, 5, 6, 7, 0, 9, 0, 11]
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+1
def get_hs_div(self):
return self.HS_DIV[((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)
def get_raw_config(self):
config = []
config.append(self.rd_reg(self.R_HS))
config.append(self.rd_reg(self.R_RFREQ4))
config.append(self.rd_reg(self.R_RFREQ3))
config.append(self.rd_reg(self.R_RFREQ2))
config.append(self.rd_reg(self.R_RFREQ1))
config.append(self.rd_reg(self.R_RFREQ0))
return config
# 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);
obj-m = cp210x.o
KVERSION = $(shell uname -r)
all:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
install:
cp cp210x.ko /lib/modules/$(KVERSION)/kernel/drivers/usb/serial/
/*
* Silicon Laboratories CP210x USB to RS232 serial adaptor driver
*
* Copyright (C) 2005 Craig Shelley (craig@microtron.org.uk)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*
* Support to set flow control line levels using TIOCMGET and TIOCMSET
* thanks to Karl Hiramoto karl@hiramoto.org. RTSCTS hardware flow
* control thanks to Munir Nassar nassarmu@real-time.com
*
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/usb.h>
#include <linux/uaccess.h>
#include <linux/usb/serial.h>
/*
* Version Information
*/
#define DRIVER_VERSION "v0.09"
#define DRIVER_DESC "Silicon Labs CP210x RS232 serial adaptor driver"
/*
* Function Prototypes
*/
static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *);
static void cp210x_close(struct usb_serial_port *);
static int cp210x_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg);
static void cp210x_get_termios(struct tty_struct *,
struct usb_serial_port *port);
static void cp210x_get_termios_port(struct usb_serial_port *port,
unsigned int *cflagp, unsigned int *baudp);
static void cp210x_change_speed(struct tty_struct *, struct usb_serial_port *,
struct ktermios *);
static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *,
struct ktermios*);
static int cp210x_tiocmget(struct tty_struct *);
static int cp210x_tiocmset(struct tty_struct *, unsigned int, unsigned int);
static int cp210x_tiocmset_port(struct usb_serial_port *port,
unsigned int, unsigned int);
static void cp210x_break_ctl(struct tty_struct *, int);
static int cp210x_startup(struct usb_serial *);
static void cp210x_release(struct usb_serial *);
static void cp210x_dtr_rts(struct usb_serial_port *p, int on);
static bool debug;
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x045B, 0x0053) }, /* Renesas RX610 RX-Stick */
{ USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */
{ USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
{ USB_DEVICE(0x0489, 0xE003) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */
{ USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */
{ USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */
{ USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */
{ USB_DEVICE(0x0BED, 0x1100) }, /* MEI (TM) Cashflow-SC Bill/Voucher Acceptor */
{ USB_DEVICE(0x0BED, 0x1101) }, /* MEI series 2000 Combo Acceptor */
{ USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */
{ USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */
{ USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */
{ USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */
{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
{ USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */
{ USB_DEVICE(0x10C4, 0x0F91) }, /* Vstabi */
{ USB_DEVICE(0x10C4, 0x1101) }, /* Arkham Technology DS101 Bus Monitor */
{ USB_DEVICE(0x10C4, 0x1601) }, /* Arkham Technology DS101 Adapter */
{ USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */
{ USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */
{ USB_DEVICE(0x10C4, 0x8044) }, /* Cygnal Debug Adapter */
{ USB_DEVICE(0x10C4, 0x804E) }, /* Software Bisque Paramount ME build-in converter */
{ USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */
{ USB_DEVICE(0x10C4, 0x8054) }, /* Enfora GSM2228 */
{ USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */
{ USB_DEVICE(0x10C4, 0x806F) }, /* IMS USB to RS422 Converter Cable */
{ USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */
{ USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
{ USB_DEVICE(0x10C4, 0x80DD) }, /* Tracient RFID */
{ USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */
{ USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */
{ USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */
{ USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */
{ USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
{ USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
{ USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */
{ USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
{ USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */
{ USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */
{ USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */
{ USB_DEVICE(0x10C4, 0x81A9) }, /* Multiplex RC Interface */
{ USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */
{ USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */
{ USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
{ USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
{ USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */
{ USB_DEVICE(0x10C4, 0x81E8) }, /* Zephyr Bioharness */
{ USB_DEVICE(0x10C4, 0x81F2) }, /* C1007 HF band RFID controller */
{ USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */
{ USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */
{ USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demonstration module */
{ USB_DEVICE(0x10C4, 0x8293) }, /* Telegesis ETRX2USB */
{ USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */
{ USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */
{ USB_DEVICE(0x10C4, 0x8382) }, /* Cygnal Integrated Products, Inc. */
{ USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */
{ USB_DEVICE(0x10C4, 0x83D8) }, /* DekTec DTA Plus VHF/UHF Booster/Attenuator */
{ USB_DEVICE(0x10C4, 0x8411) }, /* Kyocera GPS Module */
{ USB_DEVICE(0x10C4, 0x8418) }, /* IRZ Automation Teleport SG-10 GSM/GPRS Modem */
{ USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */
{ USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */
{ USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */
{ USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */
{ USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */
{ USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA80) }, /* Silicon Labs factory default */
{ USB_DEVICE(0x10C4, 0xEA71) }, /* Infinity GPS-MIC-1 Radio Monophone */
{ USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */
{ USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */
{ USB_DEVICE(0x10C4, 0xF003) }, /* Elan Digital Systems USBpulse100 */
{ USB_DEVICE(0x10C4, 0xF004) }, /* Elan Digital Systems USBcount50 */
{ USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */
{ USB_DEVICE(0x10CE, 0xEA6A) }, /* Silicon Labs MobiData GPRS USB Modem 100EU */
{ USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */
{ USB_DEVICE(0x1555, 0x0004) }, /* Owen AC4 USB-RS485 Converter */
{ USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */
{ USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */
{ USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */
{ USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */
{ USB_DEVICE(0x16DC, 0x0012) }, /* W-IE-NE-R Plein & Baus GmbH MPOD Multi Channel Power Supply */
{ USB_DEVICE(0x16DC, 0x0015) }, /* W-IE-NE-R Plein & Baus GmbH CML Control, Monitoring and Data Logger */
{ USB_DEVICE(0x17A8, 0x0001) }, /* Kamstrup Optical Eye/3-wire */
{ USB_DEVICE(0x17A8, 0x0005) }, /* Kamstrup M-Bus Master MultiPort 250D */
{ USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */
{ USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */
{ USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */
{ USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
{ USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */
{ USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(usb, id_table);
struct cp210x_port_private {
__u8 bInterfaceNumber;
__u8 bPartNumber;
};
/*static struct usb_driver cp210x_driver = {
.name = "cp210x",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
.no_dynamic_id = 1,
};*/
static struct usb_serial_driver cp210x_device = {
.driver = {
.owner = THIS_MODULE,
.name = "cp210x",
},
// .usb_driver = &cp210x_driver,
.id_table = id_table,
.num_ports = 1,
.bulk_in_size = 256,
.bulk_out_size = 256,
.open = cp210x_open,
.close = cp210x_close,
.ioctl = cp210x_ioctl,
.break_ctl = cp210x_break_ctl,
.set_termios = cp210x_set_termios,
.tiocmget = cp210x_tiocmget,
.tiocmset = cp210x_tiocmset,
.attach = cp210x_startup,
.release = cp210x_release,
.dtr_rts = cp210x_dtr_rts
};
static struct usb_serial_driver * const serial_drivers[] = {
&cp210x_device, NULL
};
/* Part number definitions */
#define CP2101_PARTNUM 0x01
#define CP2102_PARTNUM 0x02
#define CP2103_PARTNUM 0x03
#define CP2104_PARTNUM 0x04
#define CP2105_PARTNUM 0x05
#define CP2108_PARTNUM 0x08
/* IOCTLs */
#define IOCTL_GPIOGET 0x8000
#define IOCTL_GPIOSET 0x8001
/* Config request types */
#define REQTYPE_HOST_TO_INTERFACE 0x41
#define REQTYPE_INTERFACE_TO_HOST 0xc1
#define REQTYPE_HOST_TO_DEVICE 0x40
#define REQTYPE_DEVICE_TO_HOST 0xc0
/* Config request codes */
#define CP210X_IFC_ENABLE 0x00
#define CP210X_SET_BAUDDIV 0x01
#define CP210X_GET_BAUDDIV 0x02
#define CP210X_SET_LINE_CTL 0x03
#define CP210X_GET_LINE_CTL 0x04
#define CP210X_SET_BREAK 0x05
#define CP210X_IMM_CHAR 0x06
#define CP210X_SET_MHS 0x07
#define CP210X_GET_MDMSTS 0x08
#define CP210X_SET_XON 0x09
#define CP210X_SET_XOFF 0x0A
#define CP210X_SET_EVENTMASK 0x0B
#define CP210X_GET_EVENTMASK 0x0C
#define CP210X_SET_CHAR 0x0D
#define CP210X_GET_CHARS 0x0E
#define CP210X_GET_PROPS 0x0F
#define CP210X_GET_COMM_STATUS 0x10
#define CP210X_RESET 0x11
#define CP210X_PURGE 0x12
#define CP210X_SET_FLOW 0x13
#define CP210X_GET_FLOW 0x14
#define CP210X_EMBED_EVENTS 0x15
#define CP210X_GET_EVENTSTATE 0x16
#define CP210X_SET_CHARS 0x19
#define CP210X_GET_BAUDRATE 0x1D
#define CP210X_SET_BAUDRATE 0x1E
#define CP210X_VENDOR_SPECIFIC 0xFF
/* CP210X_IFC_ENABLE */
#define UART_ENABLE 0x0001
#define UART_DISABLE 0x0000
/* CP210X_VENDOR_SPECIFIC */
#define CP210X_WRITE_LATCH 0x37E1
#define CP210X_READ_LATCH 0x00C2
#define CP210X_GET_PARTNUM 0x370B
/* CP210X_(SET|GET)_BAUDDIV */
#define BAUD_RATE_GEN_FREQ 0x384000
/* CP210X_(SET|GET)_LINE_CTL */
#define BITS_DATA_MASK 0X0f00
#define BITS_DATA_5 0X0500
#define BITS_DATA_6 0X0600
#define BITS_DATA_7 0X0700
#define BITS_DATA_8 0X0800
#define BITS_DATA_9 0X0900
#define BITS_PARITY_MASK 0x00f0
#define BITS_PARITY_NONE 0x0000
#define BITS_PARITY_ODD 0x0010
#define BITS_PARITY_EVEN 0x0020
#define BITS_PARITY_MARK 0x0030
#define BITS_PARITY_SPACE 0x0040
#define BITS_STOP_MASK 0x000f
#define BITS_STOP_1 0x0000
#define BITS_STOP_1_5 0x0001
#define BITS_STOP_2 0x0002
/* CP210X_SET_BREAK */
#define BREAK_ON 0x0001
#define BREAK_OFF 0x0000
/* CP210X_(SET_MHS|GET_MDMSTS) */
#define CONTROL_DTR 0x0001
#define CONTROL_RTS 0x0002
#define CONTROL_CTS 0x0010
#define CONTROL_DSR 0x0020
#define CONTROL_RING 0x0040
#define CONTROL_DCD 0x0080
#define CONTROL_WRITE_DTR 0x0100
#define CONTROL_WRITE_RTS 0x0200
/*
* cp210x_get_config
* Reads from the CP210x configuration registers
* 'size' is specified in bytes.
* 'data' is a pointer to a pre-allocated array of integers large
* enough to hold 'size' bytes (with 4 bytes to each integer)
*/
static int cp210x_get_config(struct usb_serial_port *port, u8 requestType,
u8 request, int value, unsigned int *data, int size)
{
struct usb_serial *serial = port->serial;
struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
__le32 *buf;
int result, i, length;
/* Number of integers required to contain the array */
length = (((size - 1) | 3) + 1)/4;
buf = kcalloc(length, sizeof(__le32), GFP_KERNEL);
if (!buf) {
dev_err(&port->dev, "%s - out of memory.\n", __func__);
return -ENOMEM;
}
/* Issue the request, attempting to read 'size' bytes */
result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
request, requestType, value,
port_priv->bInterfaceNumber, buf, size, 300);
/* Convert data into an array of integers */
for (i = 0; i < length; i++)
data[i] = le32_to_cpu(buf[i]);
kfree(buf);
if (result != size) {
dev_dbg(&port->dev, "%s - Unable to send config request, "
"request=0x%x size=%d result=%d\n",
__func__, request, size, result);
if (result > 0)
result = -EPROTO;
return result;
}
return 0;
}
/*
* cp210x_set_config
* Writes to the CP210x configuration registers
* Values less than 16 bits wide are sent directly
* 'size' is specified in bytes.
*/
static int cp210x_set_config(struct usb_serial_port *port, u8 requestType,
u8 request, int value, unsigned int *data, int size)
{
struct usb_serial *serial = port->serial;
struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
__le32 *buf = NULL;
int result, i, length = 0;
if (size)
{
/* Number of integers required to contain the array */
length = (((size - 1) | 3) + 1)/4;
buf = kmalloc(length * sizeof(__le32), GFP_KERNEL);
if (!buf) {
dev_err(&port->dev, "%s - out of memory.\n",
__func__);
return -ENOMEM;
}
/* Array of integers into bytes */
for (i = 0; i < length; i++)
buf[i] = cpu_to_le32(data[i]);
}
result = usb_control_msg(serial->dev,
usb_sndctrlpipe(serial->dev, 0),
request, requestType, value,
port_priv->bInterfaceNumber, buf, size, 300);
if (buf)
kfree(buf);
if (result != size) {
dev_dbg(&port->dev, "%s - Unable to send request, "
"request=0x%x size=%d result=%d\n",
__func__, request, size, result);
if (result > 0)
result = -EPROTO;
return result;
}
return 0;
}
/*
* cp210x_quantise_baudrate
* Quantises the baud rate as per AN205 Table 1
*/
static unsigned int cp210x_quantise_baudrate(unsigned int baud) {
if (baud <= 300)
baud = 300;
else if (baud <= 600) baud = 600;
else if (baud <= 1200) baud = 1200;
else if (baud <= 1800) baud = 1800;
else if (baud <= 2400) baud = 2400;
else if (baud <= 4000) baud = 4000;
else if (baud <= 4803) baud = 4800;
else if (baud <= 7207) baud = 7200;
else if (baud <= 9612) baud = 9600;
else if (baud <= 14428) baud = 14400;
else if (baud <= 16062) baud = 16000;
else if (baud <= 19250) baud = 19200;
else if (baud <= 28912) baud = 28800;
else if (baud <= 38601) baud = 38400;
else if (baud <= 51558) baud = 51200;
else if (baud <= 56280) baud = 56000;
else if (baud <= 58053) baud = 57600;
else if (baud <= 64111) baud = 64000;
else if (baud <= 77608) baud = 76800;
else if (baud <= 117028) baud = 115200;
else if (baud <= 129347) baud = 128000;
else if (baud <= 156868) baud = 153600;
else if (baud <= 237832) baud = 230400;
else if (baud <= 254234) baud = 250000;
else if (baud <= 273066) baud = 256000;
else if (baud <= 491520) baud = 460800;
else if (baud <= 567138) baud = 500000;
else if (baud <= 670254) baud = 576000;
else if (baud < 1000000)
baud = 921600;
else if (baud > 2000000)
baud = 2000000;
return baud;
}
static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port)
{
int result;
dev_dbg(&port->dev, "%s - port %d", __func__, port->port_number);
result = cp210x_set_config(port, REQTYPE_HOST_TO_INTERFACE,
CP210X_IFC_ENABLE, UART_ENABLE, NULL, 0);
if (result) {
dev_err(&port->dev, "%s - Unable to enable UART\n", __func__);
return result;
}
/* Configure the termios structure */
cp210x_get_termios(tty, port);
/* The baud rate must be initialised on cp2104 */
if (tty)
cp210x_change_speed(tty, port, NULL);
return usb_serial_generic_open(tty, port);
}
static void cp210x_close(struct usb_serial_port *port)
{
dev_dbg(&port->dev, "%s - port %d", __func__, port->port_number);
usb_serial_generic_close(port);
mutex_lock(&port->serial->disc_mutex);
if (!port->serial->disconnected)
cp210x_set_config(port, REQTYPE_HOST_TO_INTERFACE,
CP210X_IFC_ENABLE, UART_DISABLE, NULL, 0);
mutex_unlock(&port->serial->disc_mutex);
}
static int cp210x_ioctl(struct tty_struct *tty,
unsigned int cmd, unsigned long arg)
{
struct usb_serial_port *port = tty->driver_data;
struct cp210x_port_private *port_priv = usb_get_serial_port_data(port);
if(arg == 0)
return -EINVAL;
switch (cmd) {
case IOCTL_GPIOGET:
if ((port_priv->bPartNumber == CP2103_PARTNUM) ||
(port_priv->bPartNumber == CP2104_PARTNUM)) {
cp210x_get_config(port, REQTYPE_DEVICE_TO_HOST,
CP210X_VENDOR_SPECIFIC,
CP210X_READ_LATCH,
(unsigned int*)arg, 1);
}
else if (port_priv->bPartNumber == CP2105_PARTNUM) {
cp210x_get_config(port, REQTYPE_INTERFACE_TO_HOST,
CP210X_VENDOR_SPECIFIC,
CP210X_READ_LATCH,
(unsigned int*)arg, 1);
}
else {
return -ENOTSUPP;
}
break;
case IOCTL_GPIOSET:
if ((port_priv->bPartNumber == CP2103_PARTNUM) ||
(port_priv->bPartNumber == CP2104_PARTNUM)) {
/*cp210x_set_config(port, REQTYPE_HOST_TO_DEVICE,
CP210x_VENDOR_SPECIFIC,
CP210x_GPIO_WRITE_LATCH, &val, 2);*/
// printk("dev %x arg %x\n", port->serial->dev, arg);
usb_control_msg(port->serial->dev,
usb_sndctrlpipe(port->serial->dev, 0),
CP210X_VENDOR_SPECIFIC,
REQTYPE_HOST_TO_DEVICE,
CP210X_WRITE_LATCH,
*(unsigned long*)arg,
NULL, 0, 300);
}
else if (port_priv->bPartNumber == CP2105_PARTNUM) {
cp210x_set_config(port, REQTYPE_HOST_TO_INTERFACE,
CP210X_VENDOR_SPECIFIC,
CP210X_WRITE_LATCH,
(unsigned int*)arg, 2);
}
else {
return -ENOTSUPP;
}
break;
default:
return -ENOIOCTLCMD;
break;
}
return 0;
}
/*
* cp210x_get_termios
* Reads the baud rate, data bits, parity, stop bits and flow control mode
* from the device, corrects any unsupported values, and configures the
* termios structure to reflect the state of the device
*/
static void cp210x_get_termios(struct tty_struct *tty,
struct usb_serial_port *port)
{
unsigned int baud;
if (tty) {
cp210x_get_termios_port(tty->driver_data,
&tty->termios.c_cflag, &baud);
tty_encode_baud_rate(tty, baud, baud);
}
else {
unsigned int cflag;
cflag = 0;
cp210x_get_termios_port(port, &cflag, &baud);
}
}
/*
* cp210x_get_termios_port
* This is the heart of cp210x_get_termios which always uses a &usb_serial_port.
*/
static void cp210x_get_termios_port(struct usb_serial_port *port,
unsigned int *cflagp, unsigned int *baudp)
{
unsigned int cflag, modem_ctl[4];
unsigned int baud;
unsigned int bits;
dev_dbg(&port->dev, "%s - port %d", __func__, port->port_number);
cp210x_get_config(port, REQTYPE_INTERFACE_TO_HOST,
CP210X_GET_BAUDRATE, 0, &baud, 4);
dev_dbg(&port->dev, "%s - baud rate = %d", __func__, baud);
*baudp = baud;
cflag = *cflagp;
cp210x_get_config(port, REQTYPE_INTERFACE_TO_HOST,
CP210X_GET_LINE_CTL, 0, &bits, 2);
cflag &= ~CSIZE;
switch (bits & BITS_DATA_MASK) {
case BITS_DATA_5:
dev_dbg(&port->dev, "%s - data bits = 5", __func__);
cflag |= CS5;
break;
case BITS_DATA_6:
dev_dbg(&port->dev, "%s - data bits = 6", __func__);
cflag |= CS6;
break;
case BITS_DATA_7:
dev_dbg(&port->dev, "%s - data bits = 7", __func__);
cflag |= CS7;
break;
case BITS_DATA_8:
dev_dbg(&port->dev, "%s - data bits = 8", __func__);
cflag |= CS8;
break;
case BITS_DATA_9:
dev_dbg(&port->dev, "%s - data bits = 9 (not supported, using 8 data bits)",
__func__);
cflag |= CS8;
bits &= ~BITS_DATA_MASK;
bits |= BITS_DATA_8;
cp210x_set_config(port, REQTYPE_HOST_TO_INTERFACE,
CP210X_SET_LINE_CTL, 0, &bits, 2);
break;
default:
dev_dbg(&port->dev, "%s - Unknown number of data bits, using 8", __func__);
cflag |= CS8;
bits &= ~BITS_DATA_MASK;
bits |= BITS_DATA_8;
cp210x_set_config(port, REQTYPE_HOST_TO_INTERFACE,
CP210X_SET_LINE_CTL, 0, &bits, 2);
break;
}
switch (bits & BITS_PARITY_MASK) {
case BITS_PARITY_NONE:
dev_dbg(&port->dev, "%s - parity = NONE", __func__);
cflag &= ~PARENB;
break;
case BITS_PARITY_ODD:
dev_dbg(&port->dev, "%s - parity = ODD", __func__);
cflag |= (PARENB|PARODD);
break;
case BITS_PARITY_EVEN:
dev_dbg(&port->dev, "%s - parity = EVEN", __func__);
cflag &= ~PARODD;
cflag |= PARENB;
break;
case BITS_PARITY_MARK:
dev_dbg(&port->dev, "%s - parity = MARK", __func__);
cflag |= (PARENB|PARODD|CMSPAR);
break;
case BITS_PARITY_SPACE:
dev_dbg(&port->dev, "%s - parity = SPACE", __func__);
cflag &= ~PARODD;
cflag |= (PARENB|CMSPAR);
break;
default:
dev_dbg(&port->dev, "%s - Unknown parity mode, disabling parity", __func__);
cflag &= ~PARENB;
bits &= ~BITS_PARITY_MASK;
cp210x_set_config(port, REQTYPE_HOST_TO_INTERFACE,
CP210X_SET_LINE_CTL, 0, &bits, 2);
break;
}
cflag &= ~CSTOPB;
switch (bits & BITS_STOP_MASK) {
case BITS_STOP_1:
dev_dbg(&port->dev, "%s - stop bits = 1", __func__);
break;
case BITS_STOP_1_5:
dev_dbg(&port->dev, "%s - stop bits = 1.5 (not supported, using 1 stop bit)",
__func__);
bits &= ~BITS_STOP_MASK;
cp210x_set_config(port, REQTYPE_HOST_TO_INTERFACE,
CP210X_SET_LINE_CTL, 0, &bits, 2);
break;
case BITS_STOP_2:
dev_dbg(&port->dev, "%s - stop bits = 2", __func__);
cflag |= CSTOPB;
break;
default:
dev_dbg(&port->dev, "%s - Unknown number of stop bits, using 1 stop bit",
__func__);
bits &= ~BITS_STOP_MASK;
cp210x_set_config(port, REQTYPE_HOST_TO_INTERFACE,
CP210X_SET_LINE_CTL, 0, &bits, 2);
break;
}
cp210x_get_config(port, REQTYPE_INTERFACE_TO_HOST,
CP210X_GET_FLOW, 0, modem_ctl, 16);
if (modem_ctl[0] & 0x0008) {
dev_dbg(&port->dev, "%s - flow control = CRTSCTS", __func__);
cflag |= CRTSCTS;
} else {
dev_dbg(&port->dev, "%s - flow control = NONE", __func__);
cflag &= ~CRTSCTS;
}
*cflagp = cflag;
}
/*
* CP2101 supports the following baud rates:
*
* 300, 600, 1200, 1800, 2400, 4800, 7200, 9600, 14400, 19200, 28800,
* 38400, 56000, 57600, 115200, 128000, 230400, 460800, 921600
*
* CP2102 and CP2103 support the following additional rates:
*
* 4000, 16000, 51200, 64000, 76800, 153600, 250000, 256000, 500000,
* 576000
*
* The device will map a requested rate to a supported one, but the result
* of requests for rates greater than 1053257 is undefined (see AN205).
*
* CP2104, CP2105 and CP2110 support most rates up to 2M, 921k and 1M baud,
* respectively, with an error less than 1%. The actual rates are determined
* by
*
* div = round(freq / (2 x prescale x request))
* actual = freq / (2 x prescale x div)
*
* For CP2104 and CP2105 freq is 48Mhz and prescale is 4 for request <= 365bps
* or 1 otherwise.
* For CP2110 freq is 24Mhz and prescale is 4 for request <= 300bps or 1
* otherwise.
*/
static void cp210x_change_speed(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
u32 baud;
baud = tty->termios.c_ospeed;
/* This maps the requested rate to a rate valid on cp2102 or cp2103,
* or to an arbitrary rate in [1M,2M].
*
* NOTE: B0 is not implemented.
*/
baud = cp210x_quantise_baudrate(baud);
dev_dbg(&port->dev, "%s - setting baud rate to %u", __func__, baud);
if (cp210x_set_config(port, REQTYPE_HOST_TO_INTERFACE,
CP210X_SET_BAUDRATE, 0, &baud, sizeof(baud))) {
dev_warn(&port->dev, "failed to set baud rate to %u\n", baud);
if (old_termios)
baud = old_termios->c_ospeed;
else
baud = 9600;
}
tty_encode_baud_rate(tty, baud, baud);
}
static void cp210x_set_termios(struct tty_struct *tty,
struct usb_serial_port *port, struct ktermios *old_termios)
{
unsigned int cflag, old_cflag;
unsigned int bits;
unsigned int modem_ctl[4];
dev_dbg(&port->dev, "%s - port %d", __func__, port->port_number);
if (!tty)
return;
cflag = tty->termios.c_cflag;
old_cflag = old_termios->c_cflag;
cp210x_change_speed(tty, port, old_termios);
/* If the number of data bits is to be updated */
if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
cp210x_get_config(port, REQTYPE_INTERFACE_TO_HOST,
CP210X_GET_LINE_CTL, 0, &bits, 2);
bits &= ~BITS_DATA_MASK;
switch (cflag & CSIZE) {
case CS5:
bits |= BITS_DATA_5;
dev_dbg(&port->dev, "%s - data bits = 5", __func__);
break;
case CS6:
bits |= BITS_DATA_6;
dev_dbg(&port->dev, "%s - data bits = 6", __func__);
break;
case CS7:
bits |= BITS_DATA_7;
dev_dbg(&port->dev, "%s - data bits = 7", __func__);
break;
case CS8:
bits |= BITS_DATA_8;
dev_dbg(&port->dev, "%s - data bits = 8", __func__);
break;
/*case CS9:
bits |= BITS_DATA_9;
dev_dbg(&port->dev, "%s - data bits = 9", __func__);
break;*/
default:
dev_dbg(&port->dev, "cp210x driver does not "
"support the number of bits requested,"
" using 8 bit mode\n");
bits |= BITS_DATA_8;
break;
}
if (cp210x_set_config(port, REQTYPE_HOST_TO_INTERFACE,
CP210X_SET_LINE_CTL, 0, &bits, 2))
dev_dbg(&port->dev, "Number of data bits requested "
"not supported by device\n");
}
if ((cflag & (PARENB|PARODD|CMSPAR)) !=
(old_cflag & (PARENB|PARODD|CMSPAR))) {
cp210x_get_config(port, REQTYPE_INTERFACE_TO_HOST,
CP210X_GET_LINE_CTL, 0, &bits, 2);
bits &= ~BITS_PARITY_MASK;
if (cflag & PARENB) {
if (cflag & CMSPAR) {
if (cflag & PARODD) {
bits |= BITS_PARITY_MARK;
dev_dbg(&port->dev, "%s - parity = MARK", __func__);
} else {
bits |= BITS_PARITY_SPACE;
dev_dbg(&port->dev, "%s - parity = SPACE", __func__);
}
} else {
if (cflag & PARODD) {
bits |= BITS_PARITY_ODD;
dev_dbg(&port->dev, "%s - parity = ODD", __func__);
} else {
bits |= BITS_PARITY_EVEN;
dev_dbg(&port->dev, "%s - parity = EVEN", __func__);
}
}
}
if (cp210x_set_config(port, REQTYPE_HOST_TO_INTERFACE,
CP210X_SET_LINE_CTL, 0, &bits, 2))
dev_dbg(&port->dev, "Parity mode not supported "
"by device\n");
}
if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) {
cp210x_get_config(port, REQTYPE_INTERFACE_TO_HOST,
CP210X_GET_LINE_CTL, 0, &bits, 2);
bits &= ~BITS_STOP_MASK;
if (cflag & CSTOPB) {
bits |= BITS_STOP_2;
dev_dbg(&port->dev, "%s - stop bits = 2", __func__);
} else {
bits |= BITS_STOP_1;
dev_dbg(&port->dev, "%s - stop bits = 1", __func__);
}
if (cp210x_set_config(port, REQTYPE_HOST_TO_INTERFACE,
CP210X_SET_LINE_CTL, 0, &bits, 2))
dev_dbg(&port->dev, "Number of stop bits requested "
"not supported by device\n");
}
if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
cp210x_get_config(port, REQTYPE_INTERFACE_TO_HOST,
CP210X_GET_FLOW, 0, modem_ctl, 16);
dev_dbg(&port->dev, "%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x",
__func__, modem_ctl[0], modem_ctl[1],
modem_ctl[2], modem_ctl[3]);
if (cflag & CRTSCTS) {
modem_ctl[0] &= ~0x7B;
modem_ctl[0] |= 0x09;
modem_ctl[1] = 0x80;
dev_dbg(&port->dev, "%s - flow control = CRTSCTS", __func__);
} else {
modem_ctl[0] &= ~0x7B;
modem_ctl[0] |= 0x01;
modem_ctl[1] |= 0x40;
dev_dbg(&port->dev, "%s - flow control = NONE", __func__);
}
dev_dbg(&port->dev, "%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x",
__func__, modem_ctl[0], modem_ctl[1],
modem_ctl[2], modem_ctl[3]);
cp210x_set_config(port, REQTYPE_HOST_TO_INTERFACE,
CP210X_SET_FLOW, 0, modem_ctl, 16);
}
}
static int cp210x_tiocmset (struct tty_struct *tty,
unsigned int set, unsigned int clear)
{
struct usb_serial_port *port = tty->driver_data;
return cp210x_tiocmset_port(port, set, clear);
}
static int cp210x_tiocmset_port(struct usb_serial_port *port,
unsigned int set, unsigned int clear)
{
unsigned int control = 0;
dev_dbg(&port->dev, "%s - port %d", __func__, port->port_number);
if (set & TIOCM_RTS) {
control |= CONTROL_RTS;
control |= CONTROL_WRITE_RTS;
}
if (set & TIOCM_DTR) {
control |= CONTROL_DTR;
control |= CONTROL_WRITE_DTR;
}
if (clear & TIOCM_RTS) {
control &= ~CONTROL_RTS;
control |= CONTROL_WRITE_RTS;
}
if (clear & TIOCM_DTR) {
control &= ~CONTROL_DTR;
control |= CONTROL_WRITE_DTR;
}
dev_dbg(&port->dev, "%s - control = 0x%.4x", __func__, control);
return cp210x_set_config(port, REQTYPE_HOST_TO_INTERFACE,
CP210X_SET_MHS, 0, &control, 2);
}
static void cp210x_dtr_rts(struct usb_serial_port *p, int on)
{
if (on)
cp210x_tiocmset_port(p, TIOCM_DTR|TIOCM_RTS, 0);
else
cp210x_tiocmset_port(p, 0, TIOCM_DTR|TIOCM_RTS);
}
static int cp210x_tiocmget (struct tty_struct *tty)
{
struct usb_serial_port *port = tty->driver_data;
unsigned int control;
int result;
dev_dbg(&port->dev, "%s - port %d", __func__, port->port_number);
cp210x_get_config(port, REQTYPE_INTERFACE_TO_HOST,
CP210X_GET_MDMSTS, 0, &control, 1);
result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0)
|((control & CONTROL_RTS) ? TIOCM_RTS : 0)
|((control & CONTROL_CTS) ? TIOCM_CTS : 0)
|((control & CONTROL_DSR) ? TIOCM_DSR : 0)
|((control & CONTROL_RING)? TIOCM_RI : 0)
|((control & CONTROL_DCD) ? TIOCM_CD : 0);
dev_dbg(&port->dev, "%s - control = 0x%.2x", __func__, control);
return result;
}
static void cp210x_break_ctl (struct tty_struct *tty, int break_state)
{
struct usb_serial_port *port = tty->driver_data;
unsigned int state;
dev_dbg(&port->dev, "%s - port %d", __func__, port->port_number);
if (break_state == 0)
state = BREAK_OFF;
else
state = BREAK_ON;
dev_dbg(&port->dev, "%s - turning break %s", __func__,
state == BREAK_OFF ? "off" : "on");
cp210x_set_config(port, REQTYPE_HOST_TO_INTERFACE,
CP210X_SET_BREAK, 0, &state, 2);
}
static int cp210x_startup(struct usb_serial *serial)
{
struct cp210x_port_private *port_priv;
int i;
unsigned int partNum;
/* cp210x buffers behave strangely unless device is reset */
usb_reset_device(serial->dev);
for (i = 0; i < serial->num_ports; i++) {
port_priv = kzalloc(sizeof(*port_priv), GFP_KERNEL);
if (!port_priv)
return -ENOMEM;
memset(port_priv, 0x00, sizeof(*port_priv));
port_priv->bInterfaceNumber =
serial->interface->cur_altsetting->desc.bInterfaceNumber;
usb_set_serial_port_data(serial->port[i], port_priv);
/* Get the 1-byte part number of the cp210x device */
cp210x_get_config(serial->port[i],
REQTYPE_DEVICE_TO_HOST, CP210X_VENDOR_SPECIFIC,
CP210X_GET_PARTNUM, &partNum, 1);
port_priv->bPartNumber = partNum & 0xFF;
}
return 0;
}
static void cp210x_release(struct usb_serial *serial)
{
struct cp210x_port_private *port_priv;
int i;
for (i = 0; i < serial->num_ports; i++) {
port_priv = usb_get_serial_port_data(serial->port[i]);
kfree(port_priv);
usb_set_serial_port_data(serial->port[i], NULL);
}
}
/*
static int __init cp210x_init(void)
{
int retval;
retval = usb_serial_register(&cp210x_device);
if (retval)
return retval;
retval = usb_register(&cp210x_driver);
if (retval) {
usb_serial_deregister(&cp210x_device);
return retval;
}
printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":"
DRIVER_DESC "\n");
return 0;
}
static void __exit cp210x_exit(void)
{
usb_deregister(&cp210x_driver);
usb_serial_deregister(&cp210x_device);
}
module_init(cp210x_init);
module_exit(cp210x_exit);
*/
module_usb_serial_driver(serial_drivers, id_table);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Enable verbose debugging messages");
#! /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
......@@ -24,15 +24,19 @@ $PATH"
rm /tmp/data.bin
# echo "1"
echo 1 > /sys/bus/zio/devices/adc-100m14b-0200/cset0/trigger/sw-trg-enable
tmp=`printf "%02x00" $3`
adcpath="/sys/bus/zio/devices/adc-100m14b-$tmp/"
echo 1 > "${adcpath}/cset0/trigger/sw-trg-enable"
# echo 1 > /sys/bus/zio/devices/adc-100m14b-0200/cset0/trigger/sw-trg-enable
# echo "2"
sleep 1
# echo "3"
fald-acq -b 0 -a $1 -r $2 -B /tmp/data.bin 0x0200 &
fald-acq -b 0 -a $1 -r $2 -B /tmp/data.bin "0x${tmp}" &
# echo "4"
sleep 2
# echo "5"
echo 1 > /sys/bus/zio/devices/adc-100m14b-0200/cset0/trigger/sw-trg-fire
echo 1 > "${adcpath}/cset0/trigger/sw-trg-fire"
# echo 1 > /sys/bus/zio/devices/adc-100m14b-0200/cset0/trigger/sw-trg-fire
# echo "6"
wait
# echo "7"
......
import commands
def spec_identification():
dutnr = commands.getoutput("ls /sys/bus/fmc/devices/ | grep -iv adc | grep -v 100. | grep -e '.*-[0-9][0-9][0-9][0-9]$' | wc -w ")
if int( dutnr ) == 1:
dutbus_string=commands.getoutput("ls /sys/bus/fmc/devices/ | grep -iv adc | grep -v 100. | grep -e '.*-[0-9][0-9][0-9][0-9]$' | sed 's/.*-//'")
dutbus = int(dutbus_string[1:2],16)
else:
dutbus = -1;
adcnr=commands.getoutput("ls /sys/bus/fmc/devices/ | grep -i adc | grep 100. | grep -e '.*-[0-9][0-9][0-9][0-9]$' | wc -w")
if int( adcnr ) == 1:
adcbus_string=commands.getoutput("ls /sys/bus/fmc/devices/ | grep -i adc | grep 100. | grep -e '.*-[0-9][0-9][0-9][0-9]$' | sed 's/.*-//'")
adcbus = int(adcbus_string[1:2],16)
else:
adcbus = -1;
return [ dutbus, adcbus ]
def dut_bus():
print spec_identification()[0]
def adc_bus():
print spec_identification()[1]
\ No newline at end of file
......@@ -17,6 +17,15 @@ from ptsexcept import *
from utilFunctions import *
import calibr_box
import find_usb_tty
import calibration_box_connections
from spec_identification import *
# Quick test designed to ensure that communication with carrier is possible
"""
......@@ -31,7 +40,7 @@ test00:
UIDEL = 1;
FIRMWARE_PATH = '/../gateware/syn/spec_top.bin'
INPUT_TIMEOUT = 20;
AUTOMATION = True
def test_sdbid(dut):
......@@ -89,8 +98,31 @@ def verify_fmc_present(dut):
def main (card=None, default_directory='.',suite=None):
specid = spec_identification()[0];
if specid < 0 :
raise PtsCritical("Bus number of FmcDac600m12b1chadds was not found")
if AUTOMATION:
BOX_USB_VENDOR_ID = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device
print("Looking for calibration box")
box_tty = find_usb_tty.CttyUSB().find_usb_tty(BOX_USB_VENDOR_ID, BOX_USB_DEVICE_ID)
if len( box_tty ) < 1:
raise PtsCritical( "Can't find calibration box. Make sure that it is connected, and that CP210x driver was correctly mounted");
# print("Calibration Box device: %s" % box_tty[0])
box = calibr_box.CCalibr_box(box_tty[0])
box.select_trigger_loopback(0)
box.select_output(calibration_box_connections.connections['ref_clk'])
else:
box = 0;
carrier=spec( FIRMWARE_PATH, 1, True );
carrier=spec( FIRMWARE_PATH, specid, True );
# Verification whether communication with SPEC is possible and if firmware is correct
# SDB magic number verification
......
......@@ -15,10 +15,15 @@ import time
from fmcdds import *
from spec import *
from ad9516 import *
from ptsexcept import PtsCritical
from ptsexcept import *
from utilFunctions import *
import calibr_box
import find_usb_tty
import calibration_box_connections
from spec_identification import *
"""
test01:
......@@ -36,6 +41,8 @@ test01:
LATER: check DAC CLK
"""
AUTOMATION = True
OSC_TUNNING_THD = 1e-6
FIRMWARE_PATH = '/../gateware/syn/spec_top.bin'
INPUT_TIMEOUT = 5;
......@@ -120,15 +127,15 @@ def ad9516_test_ld(carrier ):
device.write_reg( 0x232, 1);
time.sleep(0.5)
if( device.gpio_get(device.LD) == 0 ):
raise PtsCritical("FPGA did not didn\'t read correct value of AD9516 LD pin. This might be caused by interrupted trace.")
raise PtsError("FPGA did not didn\'t read correct value of AD9516 LD pin. This might be caused by interrupted trace.")
# redirector.InOut()
print >> sys.__stdout__, "Please check if PLL LED on FmcDac600m12b1chaDDS is ON."
print >> sys.__stdout__, "Please check if PLL LED on FmcDac600m12b1chaDDS is ON and type [y/n]."
# redirector.InOut()
tmp = yesnoquestion( "Please check if PLL LED on FmcDac600m12b1chaDDS is ON.", INPUT_TIMEOUT )
tmp = yesnoquestion( "Please check if PLL LED on FmcDac600m12b1chaDDS is ON and type [y/n].", INPUT_TIMEOUT )
if ( tmp == 0 ):
raise PtsError("User verification of PLL LED on FmcDac600m12b1chaDDS failed. LED didn\'t turn on.")
......@@ -142,12 +149,12 @@ def ad9516_test_ld(carrier ):
device.write_reg( 0x232, 1);
time.sleep(0.5)
if( device.gpio_get(device.LD) != 0 ):
raise PtsCritical("FPGA did not correct value of AD9516 LD pin. This might be caused by interrupted trace.")
raise PtsError("FPGA did not correct value of AD9516 LD pin. This might be caused by interrupted trace.")
# redirector.InOut()
print >> sys.__stdout__, "Please check if PLL LED on FmcDac600m12b1chaDDS is OFF."
print >> sys.__stdout__, "Please check if PLL LED on FmcDac600m12b1chaDDS is OFF and type [y/n]."
# redirector.InOut()
tmp = yesnoquestion( "Please check if PLL LED on FmcDac600m12b1chaDDS is OFF.", INPUT_TIMEOUT )
tmp = yesnoquestion( "Please check if PLL LED on FmcDac600m12b1chaDDS is OFF and type [y/n].", INPUT_TIMEOUT )
if ( tmp == 0 ):
raise PtsError("User verification of PLL LED on FmcDac600m12b1chaDDS failed. LED didn\'t turn off.")
......@@ -167,14 +174,38 @@ def ad9516_test_reset(carrier):
dev.gpio_set( dev.RESET_N, 0 )
if( (carrier.readl( DDS_REG_FPGACTRL ) & DDS_FPGACTRL_MAINPLL() ) != 0 ):
raise PtsCritical("AD9516 didn\'t reset after receive reset signal. This line might be corrupted.")
raise PtsError("AD9516 didn\'t reset after receive reset signal. This line might be corrupted.")
print "AD9516 reset line tests succeeded"
def main (card=None, default_directory='.',suite=None):
carrier=spec( FIRMWARE_PATH, 1, True );
if AUTOMATION:
BOX_USB_VENDOR_ID = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device
print("Looking for calibration box")
box_tty = find_usb_tty.CttyUSB().find_usb_tty(BOX_USB_VENDOR_ID, BOX_USB_DEVICE_ID)
if len( box_tty ) < 1:
raise PtsCritical( "Can't find calibration box. Make sure that it is connected, and that CP210x driver was correctly mounted");
# print("Calibration Box device: %s" % box_tty[0])
box = calibr_box.CCalibr_box(box_tty[0])
box.select_trigger_loopback(0)
box.select_output(calibration_box_connections.connections['ref_clk'])
else:
box = 0;
specid = spec_identification()[0];
if specid < 0 :
raise PtsCritical("Bus number of FmcDac600m12b1chadds was not found")
carrier=spec( FIRMWARE_PATH, specid, True );
# verifies
# SPI communication with the device
......
......@@ -33,27 +33,71 @@ from pylab import *
from spec import *
from ad9516 import *
from dac import *
from ptsexcept import PtsCritical
from ptsexcept import *
import calibr_box
import find_usb_tty
import calibration_box_connections
from spec_identification import *
"""
test01:
DAC tests
"""
AUTOMATION = True
FIRMWARE_PATH = '/../gateware/syn/spec_top.bin'
WORK_PATH='/test/fmcdac600m12b1chadds/python/'
# WORK_PATH='/./'
LOG_PATH = 'log_fmcdac600m12b1chadds/tmp'
DEBUG = False
card=None
default_directory='.'
suite=None
delay = 0;
carrier=spec( FIRMWARE_PATH, 1, True );
if AUTOMATION:
BOX_USB_VENDOR_ID = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device
print("Looking for calibration box")
box_tty = find_usb_tty.CttyUSB().find_usb_tty(BOX_USB_VENDOR_ID, BOX_USB_DEVICE_ID)
if len( box_tty ) < 1:
raise PtsCritical( "Can't find calibration box. Make sure that it is connected, and that CP210x driver was correctly mounted");
# print("Calibration Box device: %s" % box_tty[0])
box = calibr_box.CCalibr_box(box_tty[0])
box.select_trigger_loopback(0)
box.select_output(calibration_box_connections.connections['ref_clk'])
else:
box = 0;
specid = spec_identification()[0];
if specid < 0 :
raise PtsCritical("Bus number of FmcDac600m12b1chadds was not found")
adcid = spec_identification()[1];
if adcid < 0 :
raise PtsCritical("Bus number of FmcAdc100m14b was not found")
carrier=spec( FIRMWARE_PATH, specid, True );
sys_pll = ad9516(carrier);
......@@ -74,8 +118,10 @@ def measure_spectrum(bit_amp,urange,f, logname):
time.sleep(2.0)
curr = os.getcwd()
os.system(curr+WORK_PATH+"acq.sh "+str(n_samples*n_repeat)+" "+urange + " 2>>" + logname + " 1>/dev/null")
# os.system(curr+WORK_PATH+"acq.sh "+str(n_samples*n_repeat)+" "+urange + "")
if DEBUG:
os.system(curr+WORK_PATH+"acq.sh "+str(n_samples*n_repeat)+" "+urange + " " + str( adcid ) +"")
else:
os.system(curr+WORK_PATH+"acq.sh "+str(n_samples*n_repeat)+" "+urange + " " + str( adcid ) +" 2>>" + logname + " 1>/dev/null")
#
......@@ -119,6 +165,12 @@ def test_proc(fm, logname ):
w_sig_bk=measure_spectrum(i, urange,fm, logname)
w_sig=w_sig_bk-w_bkgr
if gen_figs:
plot(w_bkgr)
title("background: bit value=%d frequency=%g" % (i, fm))
grid()
savefig("spectrum_bg_u%i_f_%g.png" % (i, fm))
show()
clf()
plot(w_sig_bk)
title("s+b: bit value=%d frequency=%g" % (i, fm))
grid()
......@@ -139,16 +191,15 @@ def test_proc(fm, logname ):
s_pow=sum(w_sig[(n_pos-2):(n_pos+3)])/5
#Check if the signal is visible
if s_pow/m_pow < 5:
raise PtsCritical("DAC: bit nr %d does not generate output signal, P/Pt=%g", (b, s_pow/m_pow))
# print "DAC: bit nr %d does not generate output signal, P/Pt=%g" % (b, s_pow/m_pow)
raise PtsError("DAC: bit nr %d does not generate output signal, P/Pt=%g", (b, s_pow/m_pow))
# print "DAC: bit nr %d does not generate output signal, P/Pt=%g" % (b, s_pow/m_pow)
#If this is not bit number 0, check if power increased ba ca.4 (in fact between 2 and 8)
#comparing to the signal generated by the previous bit
if b > 0:
r_pow = s_pow / old_s_pow
if (r_pow < 2) or (r_pow > 8):
raise PtsCritical("DAC: incorrect increase of power when switching from bit nr %d to bit nr %d : %g (expected between 2 and 8)" %
(b-1, b, r_pow))
# print "DAC: incorrect increase of power when switching from bit nr %d to bit nr %d : %g (expected between 2 and 8)" % (b-1, b, r_pow)
raise PtsError("DAC: incorrect increase of power when switching from bit nr %d to bit nr %d : %g (expected between 2 and 8)" % (b-1, b, r_pow))
# print "DAC: incorrect increase of power when switching from bit nr %d to bit nr %d : %g (expected between 2 and 8)" % (b-1, b, r_pow)
old_s_pow = s_pow
results.append([i,s_pow, m_pow])
......@@ -168,6 +219,8 @@ def main (card=None, logname=None, default_directory='.',suite=None):
# print >> __stdout__, "Connect direct DAC output to ADC input 0 and confirm with enter key"
# raw_input("")
if logname == None :
# os.system( default_directory + "log_fmcdac600m")
logname = '../../../log_fmcdac600m12b1chadds/tmp'
......
......@@ -12,19 +12,21 @@ import os
import csr
import time
import calibr_box
import find_usb_tty
from spec import *
from ad9516 import *
from ad9510 import *
from dac import *
from ptsexcept import PtsCritical
from ptsexcept import *
from sys import __stdout__
import calibr_box
import find_usb_tty
import calibration_box_connections
from spec_identification import *
"""
test03:
AD9510 tests
......@@ -36,15 +38,8 @@ test03:
REF OUT (connector output of DAC)
STATUS
REF_IN
TODO:
CLK_PD - output same clk to PD and FPGA
- in FPGA output received clk do dac
- this should give the same clk freq
- it should be able to phase shift one of clocks in ext pll
- phase shift should be readable in adc
CLK
CLK_PD
"""
......@@ -53,7 +48,7 @@ test03:
FIRMWARE_PATH = '/../gateware/syn/spec_top.bin'
AUTOMATION = True
TEST_RAW_DAC = False
TEST_RAW_DAC = True
def spi_test(dut):
......@@ -66,7 +61,7 @@ def spi_test(dut):
read = dut.read_reg(0x49);
if written != read:
raise PtsCritical("AD9510: SPI communication FAILED on 0xFF")
raise PtsError("AD9510: SPI communication FAILED on 0xFF")
time.sleep(0.001)
......@@ -75,7 +70,7 @@ def spi_test(dut):
read = dut.read_reg(0x49);
if written != read:
raise PtsCritical("AD9510: SPI communication FAILED on 0x00")
raise PtsError("AD9510: SPI communication FAILED on 0x00")
time.sleep(0.001)
......@@ -84,7 +79,7 @@ def spi_test(dut):
read = dut.read_reg(0x49);
if written != read:
raise PtsCritical("AD9510: SPI communication FAILED on 0xAA")
raise PtsError("AD9510: SPI communication FAILED on 0xAA")
time.sleep(0.001)
......@@ -93,7 +88,7 @@ def spi_test(dut):
read = dut.read_reg(0x49);
if written != read:
raise PtsCritical("AD9510: SPI communication FAILED on 0x55")
raise PtsError("AD9510: SPI communication FAILED on 0x55")
print "AD9510: SPI test succeeded"
......@@ -108,7 +103,7 @@ def test_function_line( dut ):
# SPI should fail if Function line (reset_n) is connected
try:
spi_test(dut);
except PtsCritical:
except PtsError:
print "AD9510: Function line was verified"
# disable reset
......@@ -165,7 +160,7 @@ def test_ld_line(dut):
# It only matters if reference doesn't show up or fade in meantime
# DAC output is REF input for PLL and it didn't change
if low == high:
raise PtsCritical("AD9510: STATUS line test failed. This line might be corrupted")
raise PtsError("AD9510: STATUS line test failed. This line might be corrupted")
else:
print "AD9510: STATUS line verification succeeded"
......@@ -193,7 +188,7 @@ def test_refclk_presense(dut):
if result == 0:
raise PtsCritical("AD9510: REFIN not detected. Connection between DAC and VXCO_PLL might be corrupted.")
raise PtsError("AD9510: REFIN not detected. Connection between DAC and VXCO_PLL might be corrupted.")
else:
print "AD9510: REFIN line verification succeeded"
......@@ -273,7 +268,7 @@ def test_rf_in(carrier, pll,dacinst, box):
# measure frequency in fpga
if test_clk2(carrier, 10e6, 1e6) > 0:
raise PtsCritical("RF IN input might be corrupted")
raise PtsError("RF IN input might be corrupted")
def test_ref_out(carrier, pll,dacinst, box):
......@@ -328,7 +323,7 @@ def test_ref_out(carrier, pll,dacinst, box):
# measure frequency in FPGA
if test_clk2(carrier, 10e6, 1e6) > 0:
raise PtsCritical("RF IN input might be corrupted")
raise PtsError("RF IN input might be corrupted")
def test_beam_out(carrier, pll,dacinst, box):
......@@ -376,14 +371,37 @@ def test_beam_out(carrier, pll,dacinst, box):
# measure frequency in FPGA
# BEAM should be 500MHz
if test_clk2(carrier, 50e6, 10e6) > 0:
raise PtsCritical("RF IN input might be corrupted")
raise PtsError("RF IN input might be corrupted")
def main (card=None, default_directory='.',suite=None):
if AUTOMATION:
BOX_USB_VENDOR_ID = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device
print("Looking for calibration box")
box_tty = find_usb_tty.CttyUSB().find_usb_tty(BOX_USB_VENDOR_ID, BOX_USB_DEVICE_ID)
if len( box_tty ) < 1:
raise PtsCritical( "Can't find calibration box. Make sure that it is connected, and that CP210x driver was correctly mounted");
# print("Calibration Box device: %s" % box_tty[0])
box = calibr_box.CCalibr_box(box_tty[0])
carrier=spec( FIRMWARE_PATH, 1, True );
box.select_trigger_loopback(0)
box.select_output(calibration_box_connections.connections['ref_clk'])
else:
box = 0;
specid = spec_identification()[0];
if specid < 0 :
raise PtsCritical("Bus number of FmcDac600m12b1chadds was not found")
carrier=spec( FIRMWARE_PATH, specid, True );
sys_pll = ad9516(carrier);
# default configuration
......@@ -401,17 +419,6 @@ def main (card=None, default_directory='.',suite=None):
vcxo_pll = ad9510(carrier, 1);
if AUTOMATION:
BOX_USB_VENDOR_ID = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device
box_tty = find_usb_tty.CttyUSB().find_usb_tty(BOX_USB_VENDOR_ID, BOX_USB_DEVICE_ID)
# print("Calibration Box device: %s" % box_tty[0])
box = calibr_box.CCalibr_box(box_tty[0])
box.select_trigger_loopback(0)
else:
box = 0;
# check status line
test_ld_line(vcxo_pll);
......@@ -425,7 +432,7 @@ def main (card=None, default_directory='.',suite=None):
print "Testing CLK2 line with 50 MHz frequency clock"
# validate CLK2 lines to FPGA
if test_clk2(carrier, 50e6, 5e6) > 0:
raise PtsCritical("ad9510: CLK2 clock lines might be corrupted")
raise PtsError("ad9510: CLK2 clock lines might be corrupted")
if TEST_RAW_DAC:
# validate RF IN input connector
......
......@@ -17,11 +17,20 @@ from ad9516 import *
from ad9510 import *
from adf4002 import *
from dac import *
from ptsexcept import PtsCritical
from ptsexcept import *
import matplotlib.pyplot as plt
import pylab
import numpy
import calibr_box
import find_usb_tty
import calibration_box_connections
from spec_identification import *
"""
test04:
communication + LockDetect lines
......@@ -30,7 +39,7 @@ test04:
"""
AUTOMATION = True
FIRMWARE_PATH = '/../gateware/syn/spec_top.bin'
......@@ -47,7 +56,7 @@ def test_muxout_spi(dev, carrier):
# verify
if tmp == 0:
raise PtsCritical("ADF4002: Lock Detect line didn't go high. Communication lines or LD line might be corrupted.")
raise PtsError("ADF4002: Lock Detect line didn't go high. Communication lines or LD line might be corrupted.")
# force GND on muxout
......@@ -59,7 +68,7 @@ def test_muxout_spi(dev, carrier):
# verify
if tmp > 0:
raise PtsCritical("ADF4002: Lock Detect line didn't go low. Communication lines or LD line might be corrupted.")
raise PtsError("ADF4002: Lock Detect line didn't go low. Communication lines or LD line might be corrupted.")
def test_pd_inputs(dev,carrier, vcxo_pll, input):
......@@ -89,7 +98,7 @@ def test_pd_inputs(dev,carrier, vcxo_pll, input):
if( vcxo_pll.gpio_get(vcxo_pll.PIN_STATUS) ):
print "VCXO PLL locked on ref (DAC) clock"
else:
print "VCXO PLL is not locked on ref clock. Can't continue test PD input tests"
raise PtsError("VCXO PLL is not locked on ref clock. Can't continue test PD input tests")
return 1
mean = 0
......@@ -99,9 +108,9 @@ def test_pd_inputs(dev,carrier, vcxo_pll, input):
mean /= 10
# print "mean: %d" % mean
print "Measured signal frequency: %d" % mean
if abs( mean - CENTER ) > MAXDIFF :
raise PtsCritical("ADF4002: %s signal not detected. This line might be corrupted." % input_str )
raise PtsError("ADF4002: %s signal not detected. This line might be corrupted." % input_str )
else:
print "ADF4002: %s signal detected." % input_str
......@@ -115,7 +124,7 @@ def resync(vcxo_pll):
def test_cp(dev,carrier, vcxo_pll ):
VAR_OF_MEAN_THD = 1e3;
MEAN_OF_VAR_THD = 300;
MEAN_OF_VAR_THD = 400;
nsamples = 1e4;
nr = 10;
......@@ -128,7 +137,7 @@ def test_cp(dev,carrier, vcxo_pll ):
if( vcxo_pll.gpio_get(vcxo_pll.PIN_STATUS) ):
print "VCXO PLL locked on ref (DAC) clock"
else:
print "VCXO PLL is not locked on ref clock. Can't continue Charge Pump and ADC test"
raise PtsError("VCXO PLL is not locked on ref clock. Can't continue Charge Pump and ADC test")
return
......@@ -146,7 +155,7 @@ def test_cp(dev,carrier, vcxo_pll ):
if ( numpy.mean(std_arr) > MEAN_OF_VAR_THD ):
print "Big variance on Phase Detector output was measured. This might be caused by corrupted PD or ADC"
raise PtsError("Measured variance ( %s ) on Phase Detector output was bigger then threshold ( %s ). This might be caused by corrupted PD or ADC" % ( str( numpy.mean(std_arr) ), str( MEAN_OF_VAR_THD ) ))
# to ensure that ADC doesn't measure noise i will change phase shift
......@@ -156,7 +165,7 @@ def test_cp(dev,carrier, vcxo_pll ):
if( vcxo_pll.gpio_get(vcxo_pll.PIN_STATUS) ):
print "VCXO PLL locked on ref (DAC) clock"
else:
print "VCXO PLL is not locked on ref clock. Can't continue Charge Pump and ADC test"
raise PtsError("VCXO PLL is not locked on ref clock. Can't continue Charge Pump and ADC test")
mean_arr=[];
std_arr=[];
......@@ -170,15 +179,15 @@ def test_cp(dev,carrier, vcxo_pll ):
# change phase shift
resync(vcxo_pll)
# print "variancja srednich " + str( numpy.std(mean_arr) )
# print "srednia variancji " + str( numpy.mean(std_arr) )
print "Variance of mean values " + str( numpy.std(mean_arr) ) + " threshold is set to: " + str( VAR_OF_MEAN_THD )
print "Mean variance: " + str( numpy.mean(std_arr) ) + " threshold is set to: " + str( MEAN_OF_VAR_THD )
if ( numpy.std(mean_arr) < VAR_OF_MEAN_THD ):
print "Resynchronization of VCXO PLL didn't cause significant Phase Detector output change. This might be caused by corrupted PD or ADC"
raise PtsError("Resynchronization of VCXO PLL didn't cause significant Phase Detector output change. This might be caused by corrupted PD or ADC")
if ( numpy.mean(std_arr) > MEAN_OF_VAR_THD ):
print "Big variance on Phase Detector output was measured during resynchronizations. This might be caused by corrupted PD or ADC"
raise PtsError("Measured variance ( %s ) on Phase Detector output was bigger then threshold ( %s ). This might be caused by corrupted PD or ADC" % [ str( numpy.mean(std_arr) ), str( MEAN_OF_VAR_THD ) ])
def get_adc(carrier, nr = 1e4):
......@@ -209,8 +218,32 @@ def get_adc(carrier, nr = 1e4):
def main (card=None, default_directory='.',suite=None):
if AUTOMATION:
BOX_USB_VENDOR_ID = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device
print("Looking for calibration box")
box_tty = find_usb_tty.CttyUSB().find_usb_tty(BOX_USB_VENDOR_ID, BOX_USB_DEVICE_ID)
if len( box_tty ) < 1:
raise PtsCritical( "Can't find calibration box. Make sure that it is connected, and that CP210x driver was correctly mounted");
# print("Calibration Box device: %s" % box_tty[0])
box = calibr_box.CCalibr_box(box_tty[0])
box.select_trigger_loopback(0)
box.select_output(calibration_box_connections.connections['ref_clk'])
else:
box = 0;
specid = spec_identification()[0];
if specid < 0 :
raise PtsCritical("Bus number of FmcDac600m12b1chadds was not found")
# init spec
carrier=spec( FIRMWARE_PATH, 1, True );
carrier=spec( FIRMWARE_PATH, specid, True );
#configure main clock source
sys_pll = ad9516(carrier);
......
......@@ -20,32 +20,35 @@ from spec import *
from ad9516 import *
from ad9510 import *
from dac import *
from ptsexcept import PtsCritical
from ptsexcept import *
from sys import __stdout__
import calibration_box_connections
from Canvas import Line
import calibr_box
import find_usb_tty
import calibration_box_connections
from spec_identification import *
"""
test03:
AD9510 tests
SPI check
Function (SYNCB) line
CLK2OUT
CLK_VCXO (Beam out)
RF_IN
REF OUT (connector output of DAC)
STATUS
REF_IN
TODO:
CLK_PD - output same clk to PD and FPGA
- in FPGA output received clk do dac
- this should give the same clk freq
- it should be able to phase shift one of clocks in ext pll
- phase shift should be readable in adc
CLK
test05:
Delay line test
125 Mhz (8ns) clock (CLK1) is outputed from FPGA through Delay line
Delay line is connected with Pulse Output (set to input mode) with lemo-lemo cable
Delayed clock (CLK2) is probed with CLK1
Since both clocks have the same frequency, probed signal should be constant '0' or '1'
For some delay values both clocks edges will be nearly aligned resulting in variable output
Dedicated logic was developed in order to detect such cases
During the test delay value is modified from min to max with constant step
Probed signal value are assigned to each delay value (with indication if signal was stable)
Delay is possible in 10 ns range (bigger then clock period)
Test is supposed to find probed signal edges, and evaluate tunning range
Evaluated value will be significantly smaller then real value, since jitter will be added to measured period
"""
......@@ -103,7 +106,7 @@ def test_delay_line( carrier, dacinst ):
print "Trigger input frequency: %d Hz" % tmp
if ( abs( tmp - default_freq ) > freq_thd ):
PtsCritical( "Input frequency measured on Trigger input differ from correct value. This input might be corrupted" )
PtsError( "Input frequency measured on Trigger input differ from correct value. This input might be corrupted" )
else:
print "Trigger input and pulse output verified successfully"
......@@ -191,8 +194,31 @@ def write_delay(carrier, value ):
def main (card=None, default_directory='.',suite=None):
if AUTOMATION:
BOX_USB_VENDOR_ID = 0x10c4 # Cygnal Integrated Products, Inc.
BOX_USB_DEVICE_ID = 0xea60 # CP210x Composite Device
print("Looking for calibration box")
box_tty = find_usb_tty.CttyUSB().find_usb_tty(BOX_USB_VENDOR_ID, BOX_USB_DEVICE_ID)
if len( box_tty ) < 1:
raise PtsError( "Can't find calibration box. Make sure that it is connected, and that CP210x driver was correctly mounted");
# print("Calibration Box device: %s" % box_tty[0])
box = calibr_box.CCalibr_box(box_tty[0])
box.select_trigger_loopback(0)
box.select_output(calibration_box_connections.connections['ref_clk'])
else:
box = 0;
specid = spec_identification()[0];
if specid < 0 :
raise PtsError("Bus number of FmcDac600m12b1chadds was not found")
carrier=spec( FIRMWARE_PATH, 1, True );
carrier=spec( FIRMWARE_PATH, specid, True );
sys_pll = ad9516(carrier);
# default configuration
......@@ -248,7 +274,7 @@ def main (card=None, default_directory='.',suite=None):
# clock period in ns
REF_PERIOD = 8.0
# measurement tolerance in ns
TOLERANCE = 1
TOLERANCE = 2
# configure number of same value consecutive samples
# that are considered as stable signal
......@@ -308,13 +334,13 @@ def main (card=None, default_directory='.',suite=None):
# calculate clock period based on sampled edges
# 2 edges are required to measure half of period
if len(edges) < 2:
print "Not enough edges to calculate half period"
PtsError( "Not enough edges to calculate half period")
return
elif len( edges ) == 2:
period = 2 * ( edges[1] - edges[0] )
if abs( period - (REF_PERIOD*100.0) ) > 2*TOLERANCE*100 :
print "Delay line test failed"
PtsError("Delay line test failed")
else:
print "Delay line test succeeded"
......@@ -322,7 +348,7 @@ def main (card=None, default_directory='.',suite=None):
period = edges[2] - edges[0]
if abs( period - (REF_PERIOD*100.0) ) > TOLERANCE*100 :
print "Delay line test failed"
PtsError("Delay line test failed")
else:
print "Delay line test succeeded"
......
......@@ -21,6 +21,10 @@ from adf4002 import *
from dac import *
from sys import __stdout__
from spec_identification import *
"""
test06: Writes and validates the card's EEPROM.
"""
......@@ -29,8 +33,13 @@ FIRMWARE_PATH = '/../gateware/syn/spec_top.bin'
def main (card=None, default_directory='.',suite=None):
specid = spec_identification()[0];
if specid < 0 :
raise PtsCritical("Bus number of FmcDac600m12b1chadds was not found")
# init spec
carrier=spec( FIRMWARE_PATH, 1, True );
carrier=spec( FIRMWARE_PATH, specid, True );
#configure main clock source
# sys_pll = ad9516(carrier);
......@@ -54,9 +63,9 @@ def main (card=None, default_directory='.',suite=None):
print("eeprom file written to eeprom")
eeprom = "/home/gumas/pts/log_fmcdac600m12b1chadds/eeprom/fd-eeprom_%s.bin" % datetime.datetime.now()
eeprom = "log_fmcdac600m12b1chadds/eeprom/fd-eeprom_%s.bin" % datetime.datetime.now()
print "%s/fd-eeprom.bin" % default_directory, "%s" % eeprom
os.rename("%s/fd-eeprom.bin" % default_directory, "%s" % eeprom)
os.rename("%s/fd-eeprom.bin" % default_directory, "%s" % eeprom )
print("eeprom file moved to %s" % eeprom)
#os.remove("%s/fd-eeprom.bin" % (default_directory))
......
......@@ -3,12 +3,23 @@
# Whole software was tested under Ubuntu 14.04 LTS with kernel 3.13.
# clone repository to ~/pts/test/fmcdac600m12b1chadds
# in order to run fmcdac600m12b1chadds tests you need
# cp210x and common directories from pts repository
# you may either copy whole pts repository or use a coppy attached in fmcdac600m12b1chadds repository
# if you do not want to clone pts repository:
# mv ptsfiles/* ../../
######################################
######################################
##### Getting all submodules ##########
######################################
######################################
git submodule init
git submodule update
......@@ -34,7 +45,7 @@ mv pts_fmcdac600m12b1chadds ~/pts/test/fmcdac600m12b1chadds
# setting up main scripts in pts directory
cp ~/pts/test/fmcdac600m12b1chadds/fmcdac600m12b1chadds.sh ~/pts/fmcdac600m12b1chadds.sh
cp ~/pts/test/fmcdds.sh ~/pts/fmcdds.sh
cp ~/pts/test/fmcdac600m12b1chadds/fmcdac600m12b1chadds.sh ~/pts/fmcdds.sh
cp ~/pts/test/fmcdac600m12b1chadds/ptsDacDDS.py ~/pts/ptsDacDDS.py
......
......@@ -9,7 +9,9 @@ OBJ2 = spec-sw/tools/speclib.o spec-sw/kernel/loader-ll.o
CFLAGS = -I../include -g -Imini_bone -Ispec-sw/tools/ -I. -Ispec-sw/kernel/ -fPIC
DIRS = fmc-bus spec-sw fmc-adc-100m14b4cha-sw
DIRS = fmc-bus spec-sw fmc-adc-100m14b4cha-sw ../python/libipmi fpga-config-space/sdbfs/lib fpga-config-space/sdbfs/userspace
# rf-test: $(OBJS)
......@@ -21,11 +23,13 @@ DIRS = fmc-bus spec-sw fmc-adc-100m14b4cha-sw
# ar rc libfinedelay.a $(OBJS)
all modules install modules_install: $(OBJS)
for d in $(DIRS); do $(MAKE) -C $$d $@ || exit 1; done
for d in $(DIRS); do $(MAKE) -C $$d $@ ; done
gcc -o rf-test $(OBJS) $(SPECLIB) -lm
gcc -shared -o rf-lib.so -Wl,--whole-archive spec-sw/tools/libspec.a -Wl,--no-whole-archive $(OBJS)
gcc -o rf-test $(OBJS) $(SPECLIB) -lm
ln -fs ../software/fpga-config-space/sdbfs/userspace/gensdbfs ../python/gensdbfs
clean:
for d in $(DIRS); do $(MAKE) -C $$d $@ || exit 1; done
for d in $(DIRS); do $(MAKE) -C $$d $@; done
rm -f $(OBJS) rf-test
rm -f ../python/gensdbfs
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