summaryrefslogtreecommitdiffstats
path: root/libtoprammer/top2049
diff options
context:
space:
mode:
authorMichael Buesch <m@bues.ch>2012-04-26 19:06:16 +0200
committerMichael Buesch <m@bues.ch>2012-04-26 19:06:16 +0200
commit7bfffdbbfe7b6ca42575c176083a2c9466692e6e (patch)
tree873b2f1af0dba68bd23007460a54e96af39e45c6 /libtoprammer/top2049
parentb20b4a6fd7826c7a377a2268675ba915aabba904 (diff)
downloadtoprammer-7bfffdbbfe7b6ca42575c176083a2c9466692e6e.tar.xz
toprammer-7bfffdbbfe7b6ca42575c176083a2c9466692e6e.zip
Move hardware access routines to programmer implementation
Signed-off-by: Michael Buesch <m@bues.ch>
Diffstat (limited to 'libtoprammer/top2049')
-rw-r--r--libtoprammer/top2049/hardware_access.py183
1 files changed, 183 insertions, 0 deletions
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 <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):
+ 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()
bues.ch cgit interface