pax_global_header 0000666 0000000 0000000 00000000064 12334362607 0014520 g ustar 00root root 0000000 0000000 52 comment=1d2cc24dd96ce9c179d3c923773776f97a02a301
pts-base-1d2cc24dd96ce9c179d3c923773776f97a02a301/ 0000775 0000000 0000000 00000000000 12334362607 0020111 5 ustar 00root root 0000000 0000000 pts-base-1d2cc24dd96ce9c179d3c923773776f97a02a301/LICENSE 0000664 0000000 0000000 00000001327 12334362607 0021121 0 ustar 00root root 0000000 0000000 Production Test Suite, automatized tests for OHWR boards.
Copyright (C) 2011 CERN
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
pts-base-1d2cc24dd96ce9c179d3c923773776f97a02a301/README 0000664 0000000 0000000 00000000215 12334362607 0020767 0 ustar 00root root 0000000 0000000 This is Production Test Suite project.
Supporting automated hardware testing at BE/CO/HT
since 2011 or even less
License: GPL v2 or later
pts-base-1d2cc24dd96ce9c179d3c923773776f97a02a301/common/ 0000775 0000000 0000000 00000000000 12334362607 0021401 5 ustar 00root root 0000000 0000000 pts-base-1d2cc24dd96ce9c179d3c923773776f97a02a301/common/csr.py 0000664 0000000 0000000 00000012035 12334362607 0022543 0 ustar 00root root 0000000 0000000 #!/usr/bin/python
# Copyright CERN, 2011
# Author: Matthieu Cattin (CERN)
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
# Last modifications: 27/4/2012
# Import standard modules
import sys
import time
# Import specific modules
import rr
# Class to access 32-bit wishbone registers on BAR0
class CSRDeviceOperationError(Exception):
def __init__(self, addr, reg_map, msg):
self.msg = msg
self.addr = addr
self.reg_map = reg_map
def __str__(self):
return ("CSR [Wishbone core base address:0x%08X (%s)]: %s" %(self.addr, self.reg_map[0], self.msg))
class CCSR:
def __init__(self, bus, base_addr, reg_map=None):
self.base_addr = base_addr
self.bus = bus
self.reg_map = reg_map
###########################################################################
# The following functions accesses registers with the address offset only,
# the register map is not used.
def wr_reg(self, addr, val):
#print '[CSR] 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 '[CSR] 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<> field_offset))
return reg_val
else:
raise CSRDeviceOperationError(self.base_addr, self.reg_map, 'Requested field (%s) doesn\'t exist.'%field)
else:
raise CSRDeviceOperationError(self.base_addr, self.reg_map, 'Requested register (%s) doesn\'t exist.'%reg)
# Set register's field value
def set_field(self, reg, field, value):
if(reg in self.reg_map[1]): # test if register exist in register map
if(field in self.reg_map[1][reg][2]): # test if field exist in register
reg_addr = self.reg_map[1][reg][0]
field_mask = self.reg_map[1][reg][2][field][2]
field_offset = self.reg_map[1][reg][2][field][0]
reg_val = self.rd_reg(reg_addr)
reg_val &= ~(field_mask << field_offset)
reg_val |= ((field_maks & value) << field_offset)
self.wr_reg(reg_addr, reg_val)
return reg_val
else:
raise CSRDeviceOperationError(self.base_addr, self.reg_map, 'Requested field (%s) doesn\'t exist.'%field)
else:
raise CSRDeviceOperationError(self.base_addr, self.reg_map, 'Requested register (%s) doesn\'t exist.'%reg)
# Get register value
def get_reg(self, reg):
if(reg in self.reg_map[1]): # test if register exist in register map
return self.rd_reg(self.reg_map[1][reg][0])
else:
raise CSRDeviceOperationError(self.base_addr, self.reg_map, 'Requested register (%s) doesn\'t exist.'%reg)
# Set register value
def set_reg(self, reg, value):
if(reg in self.reg_map[1]): # test if register exist in register map
self.wr_reg(self.reg_map[1][reg][0], value)
else:
raise CSRDeviceOperationError(self.base_addr, self.reg_map, 'Requested register (%s) doesn\'t exist.'%reg)
# Print all register map
def print_reg_map(self):
print "\n%s:" % (self.reg_map[0])
print "--------------------------------------------------"
# loop over registers and sort them by address offset
for reg in sorted(self.reg_map[1].iteritems(), key=lambda (k,v): v[0]):
value = self.get_reg(reg[0])
print " * %-50s:0x%08X (%d)" % (reg[1][1],value, value)
# loop over fields and sort them by position
for field in sorted(reg[1][2].iteritems(), key=lambda (k,v): v[0]):
value = self.get_field(reg[0], field[0])
print " - %-48s:0x%X (%d)" % (field[1][1],value, value)
if(len(reg[1][2]) != 0):
print ''
pts-base-1d2cc24dd96ce9c179d3c923773776f97a02a301/common/ds18b20.py 0000664 0000000 0000000 00000010242 12334362607 0023035 0 ustar 00root root 0000000 0000000 #!/usr/bin/python
# Copyright CERN, 2011
# Author: Matthieu Cattin (CERN)
# Author (modifications): Richard Carrillo
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
# Website: http://www.sevensols.com
# Last modifications: 1/4/2012
# Import standard modules
import sys
import time
# Import specific modules
import rr
from onewire import *
# Class to access the DS18B20 (temperature sensor & unique ID) chip.
# It uses the onewire class and supports only one device on the onewire bus.
class DS18B20OperationError(Exception):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return ("DS18B20: %s" %(self.msg))
class CDS18B20:
# ROM commands
ROM_SEARCH = 0xF0
ROM_READ = 0x33
ROM_MATCH = 0x55
ROM_SKIP = 0xCC
ROM_ALARM_SEARCH = 0xEC
# DS18B20 functions commands
CONVERT_TEMP = 0x44
WRITE_SCRATCHPAD = 0x4E
READ_SCRATCHPAD = 0xBE
COPY_SCRATCHPAD = 0x48
RECALL_EEPROM = 0xB8
READ_POWER_SUPPLY = 0xB4
FAMILY_CODE = 0x28
MIN_TEMPER = -55
MAX_TEMPER = 125
# 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):
try:
#print '[DS18B20] Reading serial number'
self.onewire.reset(self.port)
#print '[DS18B20] Write ROM command %.2X' % self.ROM_READ
self.onewire.write_byte(self.port, self.ROM_READ)
family_code = self.onewire.read_byte(self.port)
if family_code != self.FAMILY_CODE:
raise DS18B20OperationError("Invalid family code reported:0x02X (expected:0x02X). Wrong chip mounted?" % (family_code, self.FAMILY_CODE))
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)
except OneWireDeviceOperationError as e:
raise DS18B20OperationError(e)
def access(self, serial_number):
try:
#print '[DS18B20] Accessing device'
self.onewire.reset(self.port)
#print '[DS18B20] Write ROM command %.2X' % self.ROM_MATCH
self.onewire.write_byte(self.port, self.ROM_MATCH)
#print '[DS18B20] Serial number: 0x%16X' % serial_number
block = []
for i in range(8):
block.append(serial_number & 0xFF)
serial_number >>= 8
#print '[DS18B20] block[%d]:0x%02X' % (i, block[-1])
self.onewire.write_block(self.port, block)
except OneWireDeviceOperationError as e:
raise DS18B20OperationError(e)
def read_temp(self, serial_number):
try:
#print '[DS18B20] Reading temperature'
self.access(serial_number)
#print '[DS18B20] Write function command %.2X' % self.CONVERT_TEMP
self.onewire.write_byte(self.port, self.CONVERT_TEMP)
time.sleep(0.9)
self.access(serial_number)
#print '[DS18B20] Write function command %.2X' % self.READ_SCRATCHPAD
self.onewire.write_byte(self.port, self.READ_SCRATCHPAD)
data = self.onewire.read_block(self.port, 9)
#for i in range(9):
# print '[DS18B20] Scratchpad data[%1d]: %.2X' % (i, data[i])
temp = (data[1] << 8) | (data[0])
if temp & 0x1000:
temp = -0x10000 + temp
temp = temp/16.0
if temp < self.MIN_TEMPER or temp > self.MAX_TEMPER:
raise DS18B20OperationError("Sensor reported an invalid temperature.")
return temp
except OneWireDeviceOperationError as e:
raise DS18B20OperationError(e)
# Set temperature thresholds
# TODO
# Configure thermometer resolution
# TODO
pts-base-1d2cc24dd96ce9c179d3c923773776f97a02a301/common/eeprom_24aa64.py 0000664 0000000 0000000 00000010463 12334362607 0024227 0 ustar 00root root 0000000 0000000 #!/usr/bin/python
# Copyright CERN, 2011
# Author: Matthieu Cattin (CERN)
# Author (modifications): Richard Carrillo
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
# Website: http://www.sevensols.com
# Last modifications: 26/4/2012
# Import standard modules
import sys
import time
# Import specific modules
import rr
from i2c import *
# Class to access the 24AA64 (64K EEPROM) chip.
# It uses the I2C class.
class Eeprom24AA64OperationError(Exception):
def __init__(self, addr, msg):
self.msg = msg
self.addr = addr
def __str__(self):
return ("EEPROM 24AA64 [I2C address:0x%02X]: %s" %(self.addr, self.msg))
class C24AA64:
PAGE_SIZE = 32 # in bytes
PAGE_BOUNDARY_MASK = 0xFFFF - (PAGE_SIZE - 1)
def __init__(self, i2c, i2c_addr):
self.i2c = i2c
self.i2c_addr = i2c_addr
def wr_byte(self, mem_addr, byte):
try:
self.i2c.start(self.i2c_addr, True)
self.i2c.write((mem_addr >> 8), False)
self.i2c.write((mem_addr & 0xFF), False)
self.i2c.write(byte,True)
except I2CDeviceOperationError as e:
raise Eeprom24AA64OperationError(self.i2c_addr, e)
def rd_byte(self, mem_addr):
try:
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)
return self.i2c.read(True)
except I2CDeviceOperationError as e:
raise Eeprom24AA64OperationError(self.i2c_addr, e)
def wr_page(self, mem_addr, data):
try:
#print '[24AA64] write data lenght=%d' % (len(data))
#print '[24AA64] write addr=%04X' % (mem_addr)
if(len(data) == 0):
raise Eeprom24AA64OperationError(self.i2c_addr, "Nothing to transmit, data size is 0!")
if(len(data) > self.PAGE_SIZE):
raise Eeprom24AA64OperationError(self.i2c_addr, "Maximum write size is %d byte!" % self.PAGE_SIZE)
if((mem_addr | self.PAGE_BOUNDARY_MASK) ^ self.PAGE_BOUNDARY_MASK):
raise Eeprom24AA64OperationError(self.i2c_addr, "Start write address is not aligned to a page boundary!")
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))
i = 0
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
#print '[24AA64] write last i=%d' % (i)
self.i2c.write(data[i],True)
except I2CDeviceOperationError as e:
raise Eeprom24AA64OperationError(self.i2c_addr, e)
def rd_seq(self, mem_addr, size):
try:
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)
i=0
for i in range(size-1):
data.append(self.i2c.read(False))
#print '[24AA64] read i=%d' % (i)
if len(data) > 1:
i += 1
#print '[24AA64] read last i=%d' % (i)
data.append(self.i2c.read(True))
return data
except I2CDeviceOperationError as e:
raise Eeprom24AA64OperationError(self.i2c_addr, e)
pts-base-1d2cc24dd96ce9c179d3c923773776f97a02a301/common/gn4124.py 0000664 0000000 0000000 00000022044 12334362607 0022674 0 ustar 00root root 0000000 0000000 #! /usr/bin/env python
# coding: utf8
# Copyright CERN, 2011
# Author: Matthieu Cattin (CERN)
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
# Last modifications: 27/4/2012
# Import standard modules
import sys
import time
# Import specific modules
import rr
import csr
# Class to access the GN4124 (PCIe bridge) chip.
# It uses the CSR class.
class GN4124OperationError(Exception):
def __init__(self, msg):
self.msg = msg
def __str__(self):
return ("GN4124: %s" %(self.msg))
class CGN4124:
# Host registers (BAR C), for DMA items storage on the host side
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 (BAR 4)
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 (BAR 0)
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
PAGE_SIZE = 4096 # bytes
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):
self.bus = bus
self.dma_csr = csr
self.dma_item_cnt = 0
# Get pointer list to host memory pages (allocated by the driver)
self.pages = self.bus.getplist()
# Shift by 12 to get the 32-bit physical addresses
self.pages = [addr << 12 for addr in self.pages]
# Configure GN4124 to generate interrupt (MSI) on rising edge of GPIO 8
self.set_interrupt_config()
# Enable interrupt from gn4124 in the driver
self.bus.irqena()
# Set GN4124 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 '[GN4124] DIVOT=%d' % divot
data = 0xe001f00c + (divot << 4)
#print '[GN4124] CLK_CSR reg=0x%.8X' % data
#print '[GN4124] Set local bus freq to %dMHz' % int(round(800/(divot+1),0))
self.wr_reg(self.GN4124_BAR, self.R_CLK_CSR, data)
# Get GN4142 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 host memory pages allocated to GN4124
def get_physical_addr(self):
return self.pages
# Enable interrupt handling in the rawrabbit driver
def irq_en(self):
self.bus.irqena()
# Wait for interrupt
def wait_irq(self):
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< len(self.DMA_STA)):
#print("[GN4142] DMA status register : 0x%.8X") % reg
raise GN4124OperationError("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) | (swap < 0):
raise GN4124OperationError('Invalid swapping configuration : requested %d (should be between 0 and 3)' % swap)
else:
self.dma_csr.wr_reg(self.R_DMA_CTL, (swap << self.DMA_CTL_SWAP))
# Get DMA byte swapping configuration
def get_dma_swap(self):
return (0x3 & (self.dma_csr.rd_reg(self.R_DMA_CTL) >> 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
# Limitations:
# - Only supports 32-bit host address
# - Supports up to 128 items
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
if (self.dma_item_cnt*0x20) > self.PAGE_SIZE:
raise GN4124OperationError('Maximum number of DMA items exceeded!')
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 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 lines should be removed
# when the GN4124 vhdl core will implement auto clear of abort 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 content
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 content
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)
pts-base-1d2cc24dd96ce9c179d3c923773776f97a02a301/common/i2c.py 0000664 0000000 0000000 00000010610 12334362607 0022426 0 ustar 00root root 0000000 0000000 #!/usr/bin/python
# Copyright CERN, 2011
# Author: Matthieu Cattin (CERN)
# Author (modifications): Richard Carrillo
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
# Website: http://www.sevensols.com
# Last modifications: 4/5/2012
# Import standard modules
import sys
import time
# Import specific modules
import rr
# Class to access the wishbone to I2C master module from OpenCores
# http://opencores.org/project,i2c
class I2CDeviceOperationError(Exception):
def __init__(self, addr, msg):
self.msg = msg
self.addr = addr
def __str__(self):
return ("I2C [Wishbone core base address:0x%08X]: %s" %(self.addr, self.msg))
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)
# Constant declaration
WAIT_TIME_OUT = 2
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)
# Initialise the I2C master module
# 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 "[I2C] Prescaler: %.4X" % prescaler
self.wr_reg(self.R_PREL, (prescaler & 0xff))
#print "[I2C] PREL: %.2X" % self.rd_reg(self.R_PREL)
self.wr_reg(self.R_PREH, (prescaler >> 8))
#print "[I2C] PREH: %.2X" % self.rd_reg(self.R_PREH)
self.wr_reg(self.R_CTR, self.CTR_EN)
#print "[I2C] CTR: %.2X" % self.rd_reg(self.R_CTR)
if not(self.rd_reg(self.R_CTR) & self.CTR_EN):
raise I2CDeviceOperationError(self.base_addr, "Core at base address 0x%08X is not enabled" % self.base_addr)
def wait_busy(self):
init_time=time.time()
while(self.rd_reg(self.R_SR) & self.SR_TIP):
if (time.time()-init_time) > self.WAIT_TIME_OUT:
raise I2CDeviceOperationError(self.base_addr, "Wait timeout")
def start(self, addr, write_mode):
#print '[I2C] START addr=%.2X'%addr
addr = addr << 1
#print '[I2C] addr=%.2X'%addr
if(write_mode == False):
addr = addr | 1
#print '[I2C] addr=%.2X'%addr
self.wr_reg(self.R_TXR, addr)
#print '[I2C] 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 I2CDeviceOperationError(self.base_addr, "ACK not received after start from device at address 0x%02X" % (addr >> 1))
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 I2CDeviceOperationError(self.base_addr, "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 = []
print "Addresses of I2C devices found:",
for i in range(0, 128):
addr = i << 1
addr |= 1 # Address's LSB is the R/W flag, set to 1 for read operation
#print '[I2C] addr:%02X' % addr
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("0x{:X}".format(i)),
sys.stdout.flush()
self.wr_reg(self.R_TXR, 0)
self.wr_reg(self.R_CR, self.CR_STO | self.CR_WR)
self.wait_busy()
print ""
return periph_addr
##########################################
# Usage example
#gennum = rr.Gennum();
#i2c = COpenCoresI2C(gennum, 0x80000, 500);
pts-base-1d2cc24dd96ce9c179d3c923773776f97a02a301/common/ltc217x.py 0000664 0000000 0000000 00000016430 12334362607 0023163 0 ustar 00root root 0000000 0000000 #! /usr/bin/env python
# coding: utf8
# Copyright CERN, 2011
# Author: Matthieu Cattin (CERN)
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
# Last modifications: 27/4/2012
# Import standard modules
import sys
import time
# Import specific modules
import rr
from spi import *
# Class to access the LTC217x (ADC) chip.
# It uses the SPI class.
class LTC217xOperationError(Exception):
def __init__(self, addr, msg):
self.msg = msg
self.addr = addr # addr corresponds to the SPI slave number
def __str__(self):
return ("LTC217x [SPI slave number:%d]: %s" %(self.addr, self.msg))
class CLTC217x:
# LTC217x registers
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_MASK = 0xE0
OUTMODE_ILVDS_SHIFT = 5
OUTMODE_TERMON = (1<<4)
OUTMODE_OUTOFF = (1<<3)
OUTMODE_MASK = 0x07
TESTPAT_MSB_OUTTEST = (1<<7)
TESTPAT_MSB_MASK = 0x3F
TESTPAT_LSB_MASK = 0xFF
# Constant definitions
ILVDS = {'3.5mA':0x0, '4.0mA':0x1, '4.5mA':0x2, '3.0mA':0x4, '2.5mA':0x5, '2.1mA':0x6, '1.75mA':0x7}
OUTMODE = {'2lanes16bit':0x0, '2lanes14bit':0x1, '2lanes12bit':0x2, '1lane14bit':0x5, '1lane12bit':0x6, '1lane16bit':0x7}
# addr = ltc217x register address (1 byte)
# value = value to write to the register (1 byte)
def wr_reg(self, addr, value):
try:
tx = [value, addr]
self.spi.transaction(self.slave, tx)
except SPIDeviceOperationError as e:
raise LTC217xOperationError(self.slave, e)
# addr = ltc217x register address (1 byte)
# return = value of the register (1 byte)
def rd_reg(self, addr):
try:
tx = [0xFF, (addr | 0x80)]
rx = self.spi.transaction(self.slave, tx)
return (rx[0] & 0xFF)
except SPIDeviceOperationError as e:
raise LTC217xOperationError(self.slave, e)
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, self.FMT_TWOSCOMP)
self.wr_reg(self.R_OUTMODE, ((self.ILVDS['4.5mA'] << self.OUTMODE_ILVDS_SHIFT) | (self.OUTMODE['2lanes16bit'])))
#self.wr_reg(self.R_FMT, 0)
#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))
def reset(self):
self.wr_reg(self.R_RST, self.RST)
def get_fmt(self):
return self.rd_reg(self.R_FMT)
def set_fmt(self, value):
self.wr_reg(self.R_FMT, value)
return self.rd_reg(self.R_FMT)
def channel_nap(self, ch, en):
reg = self.rd_reg(self.R_FMT)
if(en):
reg |= (1 << (ch-1))
else:
reg &= ~(1 << (ch-1))
self.wr_reg(self.R_FMT, reg)
def sleep(self, en):
reg = self.rd_reg(self.R_FMT)
if(en):
reg |= self.FMT_SLEEP
else:
reg &= ~(self.FMT_SLEEP)
self.wr_reg(self.R_FMT, reg)
def twos_complement(self, en):
reg = self.rd_reg(self.R_FMT)
if(en):
# enable tow's complement data output format
reg |= self.FMT_TWOSCOMP
else:
# binary offset data output format
reg &= ~(self.FMT_TWOSCOMP)
self.wr_reg(self.R_FMT, reg)
def random_out(self, en):
reg = self.rd_reg(self.R_FMT)
if(en):
# Enable random data output
reg |= self.FMT_RAND
else:
# Disable random data output
reg &= ~(self.FMT_RAND)
self.wr_reg(self.R_FMT, reg)
def duty_cycle_stabiliser_dis(self, dis):
reg = self.rd_reg(self.R_FMT)
if(dis):
reg |= self.FMT_DCSOFF
else:
reg &= ~(self.FMT_DCSOFF)
self.wr_reg(self.R_FMT, reg)
def get_outmode(self):
return self.rd_reg(self.R_OUTMODE)
def set_outmode(self, value):
self.wr_reg(self.R_OUTMODE, value)
return self.rd_reg(self.R_OUTMODE)
def set_i_lvds(self, current):
if current in self.ILVDS:
#print "[LTC217x] LVDS settting: %s -> 0x%02X" %(current, self.ILVDS[current])
reg = self.rd_reg(self.R_OUTMODE) # Read register
#print "[LTC217x] Output mode reg: 0x%02X" %(reg)
reg &= ~(self.OUTMODE_ILVDS_MASK) # Reset ILVDS bits
#print "[LTC217x] Output mode reg: 0x%02X" %(reg)
reg |= (self.OUTMODE_ILVDS_MASK & (self.ILVDS[current] << self.OUTMODE_ILVDS_SHIFT))
#print "[LTC217x] Output mode reg: 0x%02X" %(reg)
self.wr_reg(self.R_OUTMODE, reg) # Write new value to register
else:
raise LTC217xOperationError(self.slave, "Requiered LVDS current setting (%s) doesn't exist for LPC217x!" % current)
def set_outmode(self, mode):
if mode in self.OUTMODE:
#print "[LTC217x] Output mode settting: %s" %(mode)
reg = self.rd_reg(self.R_OUTMODE) # Read register
#print "[LTC217x] Ouput mode reg: 0x%02X" %(reg)
reg &= ~(self.OUTMODE_MASK) # Reset ILVDS bits
#print "[LTC217x] Ouput mode reg: 0x%02X" %(reg)
reg |= self.OUTMODE_MASK & (self.OUTMODE[mode])
#print "[LTC217x] Output mode reg: 0x%02X" %(reg)
self.wr_reg(self.R_OUTMODE, reg) # Write new value to register
else:
raise LTC217xOperationError(self.slave, "Requiered output mode setting (%s) doesn't exist for LPC217x!" % mode)
def set_lvds_termination(self, en):
reg = self.rd_reg(self.R_OUTMODE)
if(en):
# Enable LVDS serial terminations
reg |= self.OUTMODE_TERMON
else:
# Disable LVDS serial terminations
reg &= ~(self.OUTMODE_TERMON)
self.wr_reg(self.R_OUTMODE, reg)
def output_dis(self, dis):
reg = self.rd_reg(self.R_OUTMODE)
if(dis):
# Disable LVDS outputs
reg |= self.OUTMODE_OUTOFF
else:
# Enable LVDS outputs
reg &= ~(self.OUTMODE_OUTOFF)
self.wr_reg(self.R_OUTMODE, reg)
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))
pts-base-1d2cc24dd96ce9c179d3c923773776f97a02a301/common/max5442.py 0000664 0000000 0000000 00000002244 12334362607 0023061 0 ustar 00root root 0000000 0000000 #! /usr/bin/env python
# coding: utf8
# Copyright CERN, 2011
# Author: Matthieu Cattin (CERN)
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
# Last modifications: 03/05/2012
# Import standard modules
import sys
import time
# Import specific modules
import rr
from spi import *
# Class to access the MAX5442 (DAC) chip.
# It uses the SPI class.
class MAX5442OperationError(Exception):
def __init__(self, addr, msg):
self.msg = msg
self.addr = addr # addr corresponds to the SPI slave number
def __str__(self):
return ("MAX5442 [SPI slave number:%d]: %s" %(self.addr, self.msg))
class CMAX5442:
def __init__(self, spi, slave):
self.spi = spi
self.slave = slave
# value = DAC digital value (2 bytes)
def set_value(self, value):
try:
tx = [(value & 0xFF), ((value & 0xFF00)>>8)]
#print '[max5442] Value to set: %.4X' % value
#for i in range(len(tx)):
# print '[max5442] tx[%d]: %.2X' %(i, tx[i])
self.spi.transaction(self.slave, tx)
except SPIDeviceOperationError as e:
raise MAX5442OperationError(self.slave, e)
pts-base-1d2cc24dd96ce9c179d3c923773776f97a02a301/common/onewire.py 0000664 0000000 0000000 00000010216 12334362607 0023423 0 ustar 00root root 0000000 0000000 #!/usr/bin/python
# Copyright CERN, 2011
# Author: Matthieu Cattin (CERN)
# Author (modifications): Richard Carrillo
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
# Website: http://www.sevensols.com
# Last modifications: 26/4/2012
# Import standard modules
import sys
import time
# Import specific modules
import rr
# Class to access the wishbone to onewire master module from OpenCores
# http://opencores.org/project,sockit_owm
class OneWireDeviceOperationError(Exception):
def __init__(self, addr, msg):
self.msg = msg
self.addr = addr
def __str__(self):
return ("OneWire [Wishbone core base address:0x%08X]: %s" %(self.addr, self.msg))
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)
# Constants declaration
WAIT_TIME_OUT = 2
MAX_BLOCK_LEN = 160
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)
# Initialise the onewire master module
# 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
data = ((clk_div_nor & self.CDR_NOR_MSK) | ((clk_div_ovd< self.WAIT_TIME_OUT:
raise OneWireDeviceOperationError(self.base_addr, "Wait timeout")
reg = self.rd_reg(self.R_CSR)
if not (~reg & self.CSR_DAT_MSK):
raise OneWireDeviceOperationError(self.base_addr, "No presence pulse detected")
def slot(self, port, bit):
data = ((port< self.WAIT_TIME_OUT:
raise OneWireDeviceOperationError(self.base_addr, "Wait timeout")
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):
raise OneWireDeviceOperationError(self.base_addr, "Error while checking written byte")
def write_block(self, port, block):
if(self.MAX_BLOCK_LEN < len(block)):
raise OneWireDeviceOperationError(self.base_addr, "Block too long")
data = []
for i in range(len(block)):
data.append(self.write_byte(port, block[i]))
return data
def read_block(self, port, length):
if(self.MAX_BLOCK_LEN < length):
raise OneWireDeviceOperationError(self.base_addr, "Block too long")
data = []
for i in range(length):
data.append(self.read_byte(port))
return data
pts-base-1d2cc24dd96ce9c179d3c923773776f97a02a301/common/si57x.py 0000664 0000000 0000000 00000010572 12334362607 0022737 0 ustar 00root root 0000000 0000000 #! /usr/bin/env python
# coding: utf8
# Copyright CERN, 2011
# Author: Matthieu Cattin (CERN)
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
# Last modifications: 27/4/2012
# Import standard modules
import sys
import time
# Import specific modules
import rr
from i2c import *
# Class to access the Si57x (VCXO) chip.
# It uses the I2C class.
class Si57xOperationError(Exception):
def __init__(self, addr, msg):
self.msg = msg
self.addr = addr
def __str__(self):
return ("Si57x [I2C address:0x%02X]: %s" %(self.addr, self.msg))
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):
try:
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
except I2CDeviceOperationError as e:
raise Si57xOperationError(self.addr, e)
def wr_reg(self, addr, data):
try:
self.i2c.start(self.addr, True)
self.i2c.write(addr, False)
self.i2c.write(data, True)
except I2CDeviceOperationError as e:
raise Si57xOperationError(self.addr, e)
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)
pts-base-1d2cc24dd96ce9c179d3c923773776f97a02a301/common/spi.py 0000664 0000000 0000000 00000006264 12334362607 0022556 0 ustar 00root root 0000000 0000000 #! /usr/bin/env python
# coding: utf8
# Copyright CERN, 2011
# Author: Matthieu Cattin (CERN)
# Licence: GPL v2 or later.
# Website: http://www.ohwr.org
# Last modifications: 27/4/2012
# Import standard modules
import sys
import time
# Import specific modules
import rr
# Class to access the wishbone to SPI master module from OpenCores
# http://opencores.org/project,spi
class SPIDeviceOperationError(Exception):
def __init__(self, addr, msg):
self.msg = msg
self.addr = addr
def __str__(self):
return ("SPI [Wishbone core base address:0x%08X]: %s" %(self.addr, self.msg))
class COpenCoresSPI:
# OpenCores SPI registers description
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)
# Static variable
conf = 0x0
# Constant declaration
SS_SEL = [0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40]
WAIT_TIME_OUT = 2
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:
# ASS = Automatic Slave Select
# TXNEG = MOSI changes on SCLK falling edge
self.conf = self.CTRL_ASS | self.CTRL_TXNEG
def wait_busy(self):
init_time=time.time()
while(self.rd_reg(self.R_CTRL) & self.CTRL_BSY):
if (time.time()-init_time) > self.WAIT_TIME_OUT:
raise I2CDeviceOperationError(self.base_addr, "Wait timeout")
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 of read, filled 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 '[SPI] 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 '[SPI] data length: 0x%X' % len(data)
if slave > len(self.SS_SEL):
raise I2CDeviceOperationError(self.base_addr, "Maximum number of slaves is %d" % len(self.SS_SEL))
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 '[SPI] rx[%d]=%.8X' % (i,txrx[i])
return txrx
# Usage example
#gennum = rr.Gennum();
#spi = COpenCoresSPI(gennum, 0x80000, 500);
pts-base-1d2cc24dd96ce9c179d3c923773776f97a02a301/docs/ 0000775 0000000 0000000 00000000000 12334362607 0021041 5 ustar 00root root 0000000 0000000 pts-base-1d2cc24dd96ce9c179d3c923773776f97a02a301/docs/UsersManualProductionTestSuite.doc 0000664 0000000 0000000 00000274000 12334362607 0027713 0 ustar 00root root 0000000 0000000 аЯрЁБс > ўџ Е И ўџџџ Г Д џџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџџьЅС yР јП - bjbjНН Dd п{ п{ " H % џџ џџ џџ З Д Д $ 8 8 8 џџџџ L L L 8 d ш | L о8 Ќ d l а " ђ t t O
Y l Х! И ]8 _8 _8 _8 _8 _8 _8 $ : В <= 6 8 8 }" O O }" }" 8 8 8 t t л 8 _) _) _) }" t 8 t 8 t ]8 _) }" ]8 _) _) r §6 T Е7 t џџџџ @E
Ни\Ь џџџџ ё$ ќ Q7 I8 Ў8 0 о8 _7 V r= э&