From 7bfffdbbfe7b6ca42575c176083a2c9466692e6e Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Thu, 26 Apr 2012 19:06:16 +0200 Subject: Move hardware access routines to programmer implementation Signed-off-by: Michael Buesch --- libtoprammer/top2049/hardware_access.py | 183 ++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 libtoprammer/top2049/hardware_access.py (limited to 'libtoprammer/top2049/hardware_access.py') diff --git a/libtoprammer/top2049/hardware_access.py b/libtoprammer/top2049/hardware_access.py new file mode 100644 index 0000000..b43ee7c --- /dev/null +++ b/libtoprammer/top2049/hardware_access.py @@ -0,0 +1,183 @@ +""" +# TOP2049 Open Source programming suite +# +# TOP2049 Lowlevel hardware access +# +# Copyright (c) 2012 Michael Buesch +# +# 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): + return 24000000 + + def getBufferRegSize(self): + return 64 + + def readBufferReg(self, nrBytes): + self.queueCommand(int2byte(0x07)) + return self.receive(self.getBufferRegSize())[:nrBytes] + + def hardwareInit(self): + self.queueCommand(b"\x0D") + if self.readBufferReg(4) != b"\x69\x0C\x02\x00": + self.printWarning("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": + self.printWarning("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.strip() + + def FPGAMaxConfigChunkSize(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, data): + """Upload configuration data into the FPGA.""" + assert(len(data) <= self.FPGAMaxConfigChunkSize()) + 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): + 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): + 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 = 0 + if enable: + param = 1 + 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): + 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() -- cgit v1.2.3