123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- """
- # TOP2049 Open Source programming suite
- #
- # TOP2049 Lowlevel hardware access
- #
- # Copyright (c) 2012 Michael Buesch <m@bues.ch>
- #
- # 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
- # (at your option) 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, write to the Free Software Foundation, Inc.,
- # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- """
- from libtoprammer.util import *
- from libtoprammer.hardware_access_usb import *
- class HardwareAccess(HardwareAccessUSB):
- "TOP2049 hardware access"
- ADDR_OK_BIT = 4
- def __init__(self, foundUSBDev,
- noQueue=False, doRawDump=False):
- HardwareAccessUSB.__init__(self,
- usbdev = foundUSBDev.usbdev,
- maxPacketBytes = 64,
- noQueue = noQueue,
- doRawDump = doRawDump)
- def getOscillatorHz(self):
- "Get the 'OSC' frequency."
- return 24000000
- def getBufferRegSize(self):
- "Get the buffer register size, in bytes."
- return 64
- def readBufferReg(self, nrBytes):
- "Reads and returns the buffer register from hardware."
- self.queueCommand(int2byte(0x07))
- return self.receive(self.getBufferRegSize())[:nrBytes]
- def hardwareInit(self):
- "Initialize the hardware."
- self.queueCommand(b"\x0D")
- if self.readBufferReg(4) != b"\x69\x0C\x02\x00":
- print("Init: Unexpected status (a)")
- self.setVPPVoltage(0)
- self.setVPPVoltage(0)
- self.queueCommand(b"\x0E\x20\x00\x00")
- self.delay(0.01)
- self.setVCCVoltage(0)
- self.loadGNDLayout(0)
- self.loadVPPLayout(0)
- self.loadVCCLayout(0)
- self.queueCommand(b"\x0E\x20\x00\x00")
- self.delay(0.01)
- self.queueCommand(b"\x0E\x25\x00\x00")
- if self.readBufferReg(4) != b"\x6C\x68\x00\x00":
- print("Init: Unexpected status (b)")
- self.enableZifPullups(False)
- self.flushCommands()
- def readVersionString(self):
- "Returns the device ID and versioning string."
- self.queueCommand(b"\x0E\x11\x00\x00")
- data = self.readBufferReg(16)
- return data.decode("ASCII", "ignore").strip()
- def getFPGAType(self):
- "Get the FPGA architecture."
- return "xc2s15"
- def getFPGAMaxConfigChunkSize(self):
- "Maximum config chunk size."
- return 60
- def FPGAInitiateConfig(self):
- "Initiate a configuration sequence on the FPGA."
- self.queueCommand(b"\x0E\x21\x00\x00")
- stat = byte2int(self.readBufferReg(1))
- expected = 0x01
- if stat != expected:
- raise TOPException("bit-upload: Failed to initiate " +\
- "config sequence (got 0x%02X, expected 0x%02X)" %\
- (stat, expected))
- def FPGAUploadConfig(self, offset, data):
- "Upload configuration data into the FPGA."
- assert(len(data) <= self.getFPGAMaxConfigChunkSize())
- cmd = b"\x0E\x22\x00\x00" + data
- cmd += b"\x00" * (64 - len(cmd)) # padding
- self.queueCommand(cmd)
- def makeFPGAAddr(self, address):
- # Set the "address OK" bit
- return address | (1 << self.ADDR_OK_BIT)
- def FPGARead(self, address):
- "Do an FPGA read at 'address'. Data is put into buffer reg."
- address = self.makeFPGAAddr(address)
- if address == self.makeFPGAAddr(0): # Fast tracked
- self.queueCommand(int2byte(0x01))
- return
- self.queueCommand(int2byte(0x0B) + int2byte(address))
- def FPGAWrite(self, address, byte):
- "Write 'byte' to FPGA at 'address'."
- address = self.makeFPGAAddr(address)
- if address == self.makeFPGAAddr(0): # Fast tracked
- self.queueCommand(int2byte(0x10) + int2byte(byte))
- return
- self.queueCommand(int2byte(0x0A) + int2byte(address) +\
- int2byte(byte))
- def loadGNDLayout(self, layout):
- "Load the GND configuration into the H/L shiftregisters."
- cmd = int2byte(0x0E) + int2byte(0x16) +\
- int2byte(layout) + int2byte(0)
- self.queueCommand(cmd)
- self.delay(0.01)
- self.flushCommands(0.15)
- def setVPPVoltage(self, voltage):
- "Set the VPP voltage. voltage is a floating point voltage number."
- centivolt = int(voltage * 10)
- cmd = int2byte(0x0E) + int2byte(0x12) +\
- int2byte(centivolt) + int2byte(0)
- self.queueCommand(cmd)
- self.delay(0.01)
- def loadVPPLayout(self, layout):
- "Load the VPP configuration into the shift registers."
- cmd = int2byte(0x0E) + int2byte(0x14) +\
- int2byte(layout) + int2byte(0)
- self.queueCommand(cmd)
- self.delay(0.01)
- self.flushCommands(0.15)
- def setVCCVoltage(self, voltage):
- "Set the VCC voltage."
- centivolt = int(voltage * 10)
- cmd = int2byte(0x0E) + int2byte(0x13) +\
- int2byte(centivolt) + int2byte(0)
- self.queueCommand(cmd)
- self.delay(0.01)
- def loadVCCLayout(self, layout):
- "Load the VCC configuration into the shift registers."
- cmd = int2byte(0x0E) + int2byte(0x15) +\
- int2byte(layout) + int2byte(0)
- self.queueCommand(cmd)
- self.delay(0.01)
- self.flushCommands(0.15)
- def enableZifPullups(self, enable):
- "Enable the ZIF socket signal pullups."
- param = 1 if enable else 0
- cmd = int2byte(0x0E) + int2byte(0x28) +\
- int2byte(param) + int2byte(0)
- self.queueCommand(cmd)
- def __delay_4usec(self):
- self.queueCommand(int2byte(0x00))
- def __delay_10msec(self):
- self.queueCommand(int2byte(0x1B))
- def delay(self, seconds):
- "Perform an on-device or host delay."
- if seconds >= 0.5:
- # Perform long delays on the host
- self.flushCommands(seconds)
- return
- if seconds > 0.000255:
- # Need to round up to ten milliseconds
- millisecs = int(math.ceil(seconds * 1000))
- millisecs = roundup(millisecs, 10)
- for i in range(0, millisecs // 10):
- self.__delay_10msec()
- else:
- # Round up to 4 usec boundary
- microsecs = int(math.ceil(seconds * 1000000))
- microsecs = roundup(microsecs, 4)
- for i in range(0, microsecs // 4):
- self.__delay_4usec()
|