summaryrefslogtreecommitdiffstats
path: root/libtoprammer/chips
diff options
context:
space:
mode:
authorMichael Buesch <m@bues.ch>2012-04-06 23:23:11 +0200
committerMichael Buesch <m@bues.ch>2012-04-06 23:23:11 +0200
commitc9b74898f30ba1218e2e683151fb082d3bc35fd5 (patch)
tree308f0bca2ddfa98a86d6b3741dbb63cfd7ce26a4 /libtoprammer/chips
parent06de5a43527c12b41eebf2f96f85febaf64668b0 (diff)
downloadtoprammer-c9b74898f30ba1218e2e683151fb082d3bc35fd5.tar.xz
toprammer-c9b74898f30ba1218e2e683151fb082d3bc35fd5.zip
Move chip algorithms to submodule
Signed-off-by: Michael Buesch <m@bues.ch>
Diffstat (limited to 'libtoprammer/chips')
-rw-r--r--libtoprammer/chips/_74hc4094.py150
-rw-r--r--libtoprammer/chips/__init__.py15
-rw-r--r--libtoprammer/chips/at27c256r.py82
-rw-r--r--libtoprammer/chips/at89c2051dip20.py230
-rw-r--r--libtoprammer/chips/atmega32dip40.py47
-rw-r--r--libtoprammer/chips/atmega88dip28.py47
-rw-r--r--libtoprammer/chips/atmega8dip28.py79
-rw-r--r--libtoprammer/chips/atmega_common.py465
-rw-r--r--libtoprammer/chips/attiny13dip8.py358
-rw-r--r--libtoprammer/chips/attiny26dip20.py48
-rw-r--r--libtoprammer/chips/generic_sram.py122
-rw-r--r--libtoprammer/chips/hm62256dip28.py45
-rw-r--r--libtoprammer/chips/m24cxxdip8.py260
-rw-r--r--libtoprammer/chips/m2764a.py173
-rw-r--r--libtoprammer/chips/m8cissp.py457
-rw-r--r--libtoprammer/chips/unitest.py171
-rw-r--r--libtoprammer/chips/w29ee011dip32.py254
17 files changed, 3003 insertions, 0 deletions
diff --git a/libtoprammer/chips/_74hc4094.py b/libtoprammer/chips/_74hc4094.py
new file mode 100644
index 0000000..e04d63e
--- /dev/null
+++ b/libtoprammer/chips/_74hc4094.py
@@ -0,0 +1,150 @@
+"""
+# TOP2049 Open Source programming suite
+#
+# 74HC4094 unit-tester
+#
+# Copyright (c) 2011 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 unitest import *
+
+class Chip_74hc4094(Chip_Unitest):
+ def __init__(self):
+ Chip_Unitest.__init__(self, chipPackage="DIP16",
+ chipPinVCC=16,
+ chipPinGND=8,
+ VCCVoltage=5)
+
+ def __initChip(self):
+ self.zifPin_STR = self.generator.getZifPinForPackagePin(1)
+ self.zifPin_D = self.generator.getZifPinForPackagePin(2)
+ self.zifPin_CP = self.generator.getZifPinForPackagePin(3)
+ self.zifPin_OE = self.generator.getZifPinForPackagePin(15)
+ self.zifPin_QS1 = self.generator.getZifPinForPackagePin(9)
+ self.zifPin_QS2 = self.generator.getZifPinForPackagePin(10)
+ self.zifPins_QP = []
+ for packagePin in (4, 5, 6, 7, 14, 13, 12, 11):
+ self.zifPins_QP.append(
+ self.generator.getZifPinForPackagePin(packagePin))
+
+ self.reset()
+
+ outen = 0
+ for zifPin in (self.zifPin_STR, self.zifPin_D,
+ self.zifPin_CP, self.zifPin_OE):
+ outen |= (1 << (zifPin - 1))
+ self.setOutputEnableMask(outen)
+
+ self.applyGND(True)
+ self.applyVCC(True)
+
+ def test(self):
+ testPatterns = (0xFF, 0x00, 0xAA, 0x55, 0xF0, 0x0F,
+ 0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
+ 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00)
+
+ self.progressMeterInit("Logic test", len(testPatterns))
+ self.__initChip()
+
+ # Initialize the register to all-zero
+ self.setOutputs(self.__makeOutMask(STR=0, D=0, CP=0, OE=0))
+ for i in range(0, 9):
+ self.setOutputs(self.__makeOutMask(STR=0, D=0, CP=1, OE=0))
+ self.setOutputs(self.__makeOutMask(STR=0, D=0, CP=0, OE=0))
+ self.setOutputs(self.__makeOutMask(STR=1, D=0, CP=0, OE=0))
+ self.setOutputs(self.__makeOutMask(STR=0, D=0, CP=0, OE=1))
+
+ QP = self.__readQP()
+ if QP != 0x00:
+ self.throwError("Failed to clear the shiftregister. Got 0x%02X" % QP)
+
+ prevContents = 0x00
+ prev_QS1 = False
+ count = 0
+ for testPattern in testPatterns:
+ self.progressMeter(count)
+ self.setOutputs(self.__makeOutMask(STR=0, D=0, CP=0, OE=0))
+ for bitNr in range(7, -1, -1): # MSB first
+ self.setOutputs(self.__makeOutMask(STR=0,
+ D=(testPattern & (1 << bitNr)),
+ CP=0, OE=0))
+ self.setOutputs(self.__makeOutMask(STR=0, D=0, CP=1, OE=0))
+ (QS1, QS2) = self.__readQS()
+ word = (prevContents << 8) | testPattern
+ expect_QS1 = bool(word & (1 << (bitNr + 7)))
+ expect_QS2 = prev_QS1
+ prev_QS1 = expect_QS1
+ if QS1 != expect_QS1 or QS2 != expect_QS2:
+ self.throwError("Got invalid QS serial output for "
+ "test pattern 0x%02X bit %d. Got %d/%d, but "
+ "expected %d/%d" %\
+ (testPattern, bitNr, QS1, QS2,
+ expect_QS1, expect_QS2))
+ self.setOutputs(self.__makeOutMask(STR=0, D=0, CP=0, OE=0))
+ self.setOutputs(self.__makeOutMask(STR=1, D=0, CP=0, OE=0))
+ self.setOutputs(self.__makeOutMask(STR=0, D=0, CP=0, OE=1))
+
+ QP = self.__readQP()
+ if QP != testPattern:
+ self.throwError("Failed on test pattern 0x%02X. Got 0x%02X" %\
+ (testPattern, QP))
+
+ prevContents = testPattern
+ count += 1
+ self.progressMeterFinish()
+
+ def __makeOutMask(self, STR, D, CP, OE):
+ mask = 0
+ if STR:
+ mask |= (1 << (self.zifPin_STR - 1))
+ if D:
+ mask |= (1 << (self.zifPin_D - 1))
+ if CP:
+ mask |= (1 << (self.zifPin_CP - 1))
+ if OE:
+ mask |= (1 << (self.zifPin_OE - 1))
+ return mask
+
+ def __readQP(self):
+ QPValue = 0
+ count = 0
+ inputs = self.getInputs()
+ for zifPin in self.zifPins_QP:
+ if inputs & (1 << (zifPin - 1)):
+ QPValue |= (1 << count)
+ count += 1
+ return QPValue
+
+ def __readQS(self):
+ QS1 = False
+ QS2 = False
+ inputs = self.getInputs()
+ if inputs & (1 << (self.zifPin_QS1 - 1)):
+ QS1 = True
+ if inputs & (1 << (self.zifPin_QS2 - 1)):
+ QS2 = True
+ return (QS1, QS2)
+
+ChipDescription(
+ Chip_74hc4094,
+ chipID = "74hc4094dip16",
+ bitfile = "unitest",
+ runtimeID = (0x0008, 0x01),
+ chipType = ChipDescription.TYPE_LOGIC,
+ description = "74HC(T)4094 shift-register",
+ chipVendors = ("Philips", "Other"),
+)
diff --git a/libtoprammer/chips/__init__.py b/libtoprammer/chips/__init__.py
new file mode 100644
index 0000000..32ee95d
--- /dev/null
+++ b/libtoprammer/chips/__init__.py
@@ -0,0 +1,15 @@
+# Import all chip modules in alphabetical order
+from _74hc4094 import *
+from at27c256r import *
+from at89c2051dip20 import *
+from atmega32dip40 import *
+from atmega8dip28 import *
+from atmega88dip28 import *
+from attiny13dip8 import *
+from attiny26dip20 import *
+from hm62256dip28 import *
+from m24cxxdip8 import *
+from m2764a import *
+from m8cissp import *
+from unitest import *
+from w29ee011dip32 import *
diff --git a/libtoprammer/chips/at27c256r.py b/libtoprammer/chips/at27c256r.py
new file mode 100644
index 0000000..9dff427
--- /dev/null
+++ b/libtoprammer/chips/at27c256r.py
@@ -0,0 +1,82 @@
+"""
+# TOP2049 Open Source programming suite
+#
+# Atmel AT27C256R EPROM
+#
+# 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.chip import *
+
+
+class Chip_at27c256r(Chip):
+ def __init__(self):
+ Chip.__init__(self,
+ chipPackage = "DIP28",
+ chipPinVCC = 28,
+ chipPinsVPP = 1,
+ chipPinGND = 14)
+ self.sizeBytes = 32 * 1024
+ self.generic = GenericAlgorithms(self)
+ self.addrSetter = AddrSetter(self, 0x10, 0x11)
+
+ def readEEPROM(self):
+ self.__turnOn()
+ return self.generic.simpleReadEPROM(
+ sizeBytes = self.sizeBytes,
+ readData8Func = self.__dataRead,
+ addrSetter = self.addrSetter,
+ initFunc = lambda: self.__setFlags(oe=0, ce=0),
+ exitFunc = lambda: self.__setFlags(oe=1, ce=1)
+ )
+
+# def writeEEPROM(self):
+# pass#TODO
+
+ def __turnOn(self):
+ self.__setFlags()
+ self.generic.simpleVoltageSetup()
+
+ def __setDataPins(self, value):
+ self.top.cmdFPGAWrite(0x12, value)
+
+ def __setFlags(self, data_en=0, prog_en=0, ce=1, oe=1):
+ value = 0
+ if data_en:
+ value |= (1 << 0)
+ if prog_en:
+ value |= (1 << 1)
+ if ce:
+ value |= (1 << 2)
+ if oe:
+ value |= (1 << 3)
+ self.top.cmdFPGAWrite(0x13, value)
+
+ def __progPulse(self):
+ self.top.cmdFPGAWrite(0x14, 0)
+
+ def __dataRead(self):
+ self.top.cmdFPGARead(0x10)
+
+ChipDescription(Chip_at27c256r,
+ bitfile = "at27c256r",
+ runtimeID = (0x000C, 0x01),
+ chipType = ChipDescription.TYPE_EPROM,
+ chipVendors = "Atmel",
+ description = "AT27C256R",
+ packages = ( ("DIP28", ""), )
+)
diff --git a/libtoprammer/chips/at89c2051dip20.py b/libtoprammer/chips/at89c2051dip20.py
new file mode 100644
index 0000000..c23a89d
--- /dev/null
+++ b/libtoprammer/chips/at89c2051dip20.py
@@ -0,0 +1,230 @@
+"""
+# TOP2049 Open Source programming suite
+#
+# Atmel AT89C2051 DIP20 Support
+#
+# Copyright (c) 2010 Guido
+# Copyright (c) 2010 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.chip import *
+
+
+class Chip_AT89C2051dip20(Chip):
+ STAT_BUSY = 0x01 # Programmer is running a command
+ STAT_ERR = 0x02 # Error during write
+
+ def __init__(self):
+ Chip.__init__(self,
+ chipPackage = "DIP20",
+ chipPinVCC = 20,
+ chipPinsVPP = 1,
+ chipPinGND = 10)
+
+ def __initChip(self):
+ self.applyVCC(False)
+ self.applyVPP(False)
+ self.applyGND(True)
+ self.top.cmdSetVCCVoltage(5)
+ self.top.cmdSetVPPVoltage(5)
+
+ def readSignature(self):
+ self.__initChip()
+ self.applyGND(True)
+ self.applyVCC(True)
+ self.top.cmdSetVPPVoltage(5)
+ self.__loadCommand(5) # VPP on
+ self.__loadCommand(1) # set P3.2
+ self.__setP3x(P33=0, P34=0, P35=0, IA=0)
+ data = ""
+ self.top.cmdFPGARead(0x10)
+ self.__setP3x(P33=0, P34=0, P35=0, IA=1)
+ self.__setP3x(P33=0, P34=0, P35=0, IA=0)
+ self.top.cmdFPGARead(0x10)
+ self.__setP3x(P33=0, P34=0, P35=0, IA=1)
+ self.__setP3x(P33=0, P34=0, P35=0, IA=0)
+ self.top.cmdFPGARead(0x10)
+ data += self.top.cmdReadBufferReg()
+ self.__setP3x(P33=0, P34=1, P35=0, IA=0)
+ self.__loadCommand(6) # VPP off
+ signature = ""
+ signature += data[0]
+ signature += data[1]
+ self.top.printInfo("Signature: %X, %X" % (byte2int(signature[0]), byte2int(signature[1])))
+ return signature
+
+ def erase(self):
+ self.__initChip()
+ self.applyGND(True)
+ self.applyVCC(True)
+ self.__loadCommand(1) # set P3.2
+ self.top.cmdSetVPPVoltage(5)
+ self.applyVPP(True)
+ self.__loadCommand(5) # VPP on
+ self.__setP3x(P33=1, P34=0, P35=0, IA=0)
+ self.top.cmdSetVPPVoltage(12)
+ self.__runCommandSync(4)
+ self.applyVPP(False)
+ self.top.cmdSetVPPVoltage(5)
+ self.__setP3x(P33=0, P34=1, P35=0, IA=0)
+ self.__loadCommand(5) # VPP off
+ self.top.flushCommands()
+ self.top.printInfo("at89c2051dip20: Erasing flash, verifying ...")
+ ok = self.__verifyErase()
+ if ok == 0:
+ self.top.printInfo("at89c2051dip20: Erase done.")
+ else:
+ self.top.printInfo("at89c2051dip20: Erase failed!")
+
+ def readProgmem(self):
+ self.__initChip()
+ self.applyGND(True)
+ self.applyVCC(True)
+ self.__loadCommand(1) # set P3.2
+ self.top.cmdSetVPPVoltage(5)
+ self.applyVPP(True)
+ self.__loadCommand(5) # VPP on
+ self.__setP3x(P33=0, P34=0, P35=1, IA=0)
+ image = ""
+ byteCount = 0
+ self.progressMeterInit("Reading Flash", 0x800)
+ for addr in range(0, 0x800):
+ self.progressMeter(addr)
+ self.top.cmdFPGARead(0x10)
+ self.__setP3x(P33=0, P34=0, P35=1, IA=1)
+ self.__setP3x(P33=0, P34=0, P35=1, IA=0)
+ byteCount += 1
+ if byteCount == self.top.getBufferRegSize():
+ image += self.top.cmdReadBufferReg(byteCount)
+ byteCount = 0
+ image += self.top.cmdReadBufferReg(byteCount)
+ self.applyVPP(False)
+ self.__setP3x(P33=0, P34=1, P35=0, IA=0)
+ self.__loadCommand(5) # VPP off
+ self.top.flushCommands()
+ self.progressMeterFinish()
+
+ return image
+
+ def writeProgmem(self, image):
+ if len(image) > 0x800:
+ self.throwError("Invalid EPROM image size %d (expected <=%d)" %\
+ (len(image), 0x800))
+ self.__initChip()
+ self.applyGND(True)
+ self.applyVCC(True)
+ self.__loadCommand(1) # set P3.2
+ self.top.cmdSetVPPVoltage(5)
+ self.applyVPP(True)
+ self.__loadCommand(5) # VPP on
+ self.__setP3x(P33=0, P34=1, P35=1, IA=0)
+ self.top.cmdSetVPPVoltage(12)
+ self.progressMeterInit("Writing Flash", len(image))
+ for addr in range(0, len(image)):
+ self.progressMeter(addr)
+ data = byte2int(image[addr])
+ if data != 0xFF:
+ self.__loadData(data)
+ self.__loadCommand(3)
+ ok = self.__progWait()
+ if (ok & self.STAT_ERR) != 0:
+ self.throwError("Write byte failed.")
+ self.__setP3x(P33=0, P34=1, P35=1, IA=1)
+ self.__setP3x(P33=0, P34=1, P35=1, IA=0)
+ self.applyVPP(False)
+ self.top.cmdSetVPPVoltage(5)
+ self.__setP3x(P33=0, P34=1, P35=0, IA=0)
+ self.__loadCommand(5) # VPP off
+ self.top.flushCommands()
+ self.progressMeterFinish()
+ ok = self.__verifyProgmem(image)
+ if ok == 0:
+ self.top.printInfo("at89c2051dip20: Write flash done.")
+ else:
+ self.top.printInfo("at89c2051dip20: Write flash failed!")
+
+ def __verifyErase(self):
+ ok = 0
+ image = self.readProgmem()
+ for addr in range(0, 0x800):
+ if byte2int(image[addr]) != 0xFF:
+ ok = 1
+ return ok
+
+ def __verifyProgmem(self,image):
+ data = self.readProgmem()
+ ok = 0
+ for addr in range(0, 0x800):
+ if byte2int(image[addr]) != byte2int(data[addr]):
+ ok = 1
+ return ok
+
+ def __loadData(self, data):
+ self.top.cmdFPGAWrite(0x10, data)
+
+ def __loadCommand(self, command):
+ self.top.cmdFPGAWrite(0x12, command & 0xFF)
+
+ def __runCommandSync(self, command):
+ self.__loadCommand(command)
+ self.__busyWait()
+
+ def __setP3x(self, P33, P34, P35, IA):
+ data = 0
+ if P33:
+ data |= 1
+ if P34:
+ data |= 2
+ if P35:
+ data |= 4
+ if IA:
+ data |= 8
+ self.top.cmdFPGAWrite(0x16, data)
+
+ def __getStatusFlags(self):
+ self.top.cmdFPGARead(0x12)
+ stat = self.top.cmdReadBufferReg()
+ return byte2int(stat[0])
+
+ def __busy(self):
+ return bool(self.__getStatusFlags() & self.STAT_BUSY)
+
+ def __busyWait(self):
+ for i in range(0, 26):
+ if not self.__busy():
+ return
+ self.top.hostDelay(0.001)
+ self.throwError("Timeout in busywait.")
+
+ def __progWait(self):
+ for i in range(0,4):
+ self.top.cmdFPGARead(0x12)
+ stat = self.top.cmdReadBufferReg()
+ if (byte2int(stat[0]) & self.STAT_BUSY) == 0:
+ return byte2int(stat[0])
+ self.top.hostDelay(0.001)
+ self.throwError("Timeout in busywait.")
+
+ChipDescription(
+ Chip_AT89C2051dip20,
+ bitfile = "at89c2051dip20",
+ runtimeID = (0x0005, 0x01),
+ chipVendors = "Atmel",
+ description = "AT89C2051",
+ maintainer = None,
+ packages = ( ("DIP20", ""), )
+)
diff --git a/libtoprammer/chips/atmega32dip40.py b/libtoprammer/chips/atmega32dip40.py
new file mode 100644
index 0000000..486cec3
--- /dev/null
+++ b/libtoprammer/chips/atmega32dip40.py
@@ -0,0 +1,47 @@
+"""
+# TOP2049 Open Source programming suite
+#
+# Atmel Mega32 DIP40 support
+#
+# Copyright (c) 2009-2010 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 atmega_common import *
+
+
+class Chip_ATMega32DIP40(Chip_ATMega_common):
+ def __init__(self):
+ Chip_ATMega_common.__init__(self,
+ chipPackage = "DIP40",
+ chipPinVCC = 10,
+ chipPinsVPP = 9,
+ chipPinGND = 11,
+ signature = "\x1E\x95\x02",
+ flashPageSize = 64,
+ flashPages = 256,
+ eepromPageSize = 4,
+ eepromPages = 256)
+
+ChipDescription(
+ Chip_ATMega32DIP40,
+ bitfile = "atmega32dip40",
+ runtimeID = (0x0004, 0x01),
+ chipVendors = "Atmel",
+ description = "AtMega32",
+ packages = ( ("DIP40", ""), ),
+ comment = "Insert upside down into ZIF socket"
+)
diff --git a/libtoprammer/chips/atmega88dip28.py b/libtoprammer/chips/atmega88dip28.py
new file mode 100644
index 0000000..de1fc2b
--- /dev/null
+++ b/libtoprammer/chips/atmega88dip28.py
@@ -0,0 +1,47 @@
+"""
+# TOP2049 Open Source programming suite
+#
+# Atmel Mega88 DIP28 support
+#
+# Copyright (c) 2009-2010 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 atmega_common import *
+
+
+class Chip_ATMega88DIP28(Chip_ATMega_common):
+ def __init__(self):
+ Chip_ATMega_common.__init__(self,
+ chipPackage = "DIP28",
+ chipPinVCC = 7,
+ chipPinsVPP = 1,
+ chipPinGND = 8,
+ signature = "\x1E\x93\x0A",
+ flashPageSize = 32,
+ flashPages = 128,
+ eepromPageSize = 4,
+ eepromPages = 128)
+
+ChipDescription(
+ Chip_ATMega88DIP28,
+ bitfile = "atmega8dip28",
+ chipID = "atmega88dip28",
+ runtimeID = (0x0003, 0x01),
+ chipVendors = "Atmel",
+ description = "AtMega88",
+ packages = ( ("DIP28", ""), ),
+)
diff --git a/libtoprammer/chips/atmega8dip28.py b/libtoprammer/chips/atmega8dip28.py
new file mode 100644
index 0000000..6b680bb
--- /dev/null
+++ b/libtoprammer/chips/atmega8dip28.py
@@ -0,0 +1,79 @@
+"""
+# TOP2049 Open Source programming suite
+#
+# Atmel Mega8 DIP28 support
+#
+# Copyright (c) 2009-2010 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 atmega_common import *
+
+
+class Chip_ATMega8DIP28(Chip_ATMega_common):
+ def __init__(self):
+ Chip_ATMega_common.__init__(self,
+ chipPackage = "DIP28",
+ chipPinVCC = 7,
+ chipPinsVPP = 1,
+ chipPinGND = 8,
+ signature = "\x1E\x93\x07",
+ flashPageSize = 32,
+ flashPages = 128,
+ eepromPageSize = 4,
+ eepromPages = 128)
+
+fuseDesc = (
+ BitDescription(0, "CKSEL0"),
+ BitDescription(1, "CKSEL1"),
+ BitDescription(2, "CKSEL2"),
+ BitDescription(3, "CKSEL3"),
+ BitDescription(4, "SUT0"),
+ BitDescription(5, "SUT1"),
+ BitDescription(6, "BODEN"),
+ BitDescription(7, "BODLEVEL"),
+ BitDescription(8, "BOOTRST"),
+ BitDescription(9, "BOOTSZ0"),
+ BitDescription(10, "BOOTSZ1"),
+ BitDescription(11, "EESAVE"),
+ BitDescription(12, "CKOPT"),
+ BitDescription(13, "SPIEN"),
+ BitDescription(14, "WDTON"),
+ BitDescription(15, "RSTDISBL"),
+)
+
+lockbitDesc = (
+ BitDescription(0, "LB1"),
+ BitDescription(1, "LB2"),
+ BitDescription(2, "BLB01"),
+ BitDescription(3, "BLB02"),
+ BitDescription(4, "BLB11"),
+ BitDescription(5, "BLB12"),
+ BitDescription(6, "Unused"),
+ BitDescription(7, "Unused"),
+ BitDescription(8, "Unused"),
+)
+
+ChipDescription(
+ Chip_ATMega8DIP28,
+ bitfile = "atmega8dip28",
+ runtimeID = (0x0003, 0x01),
+ chipVendors = "Atmel",
+ description = "AtMega8",
+ fuseDesc = fuseDesc,
+ lockbitDesc = lockbitDesc,
+ packages = ( ("DIP28", ""), )
+)
diff --git a/libtoprammer/chips/atmega_common.py b/libtoprammer/chips/atmega_common.py
new file mode 100644
index 0000000..1609528
--- /dev/null
+++ b/libtoprammer/chips/atmega_common.py
@@ -0,0 +1,465 @@
+"""
+# TOP2049 Open Source programming suite
+#
+# Implements the Atmel Mega MCU parallel HV programming algorithm
+#
+# Copyright (c) 2009-2010 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.chip import *
+
+
+class Chip_ATMega_common(Chip):
+ # The Atmel Mega programming commands
+ CMD_CHIPERASE = 0x80 # Chip Erase
+ CMD_WRITEFUSE = 0x40 # Write Fuse Bits
+ CMD_WRITELOCK = 0x20 # Write Lock Bits
+ CMD_WRITEFLASH = 0x10 # Write Flash
+ CMD_WRITEEEPROM = 0x11 # Write EEPROM
+ CMD_READSIG = 0x08 # Read Signature bytes and Calibration byte
+ CMD_READFUSELOCK = 0x04 # Read Fuse and Lock bits
+ CMD_READFLASH = 0x02 # Read Flash
+ CMD_READEEPROM = 0x03 # Read EEPROM
+
+ def __init__(self,
+ chipPackage, chipPinVCC, chipPinsVPP, chipPinGND,
+ signature,
+ flashPageSize, flashPages,
+ eepromPageSize, eepromPages
+ ):
+ Chip.__init__(self,
+ chipPackage = chipPackage,
+ chipPinVCC = chipPinVCC,
+ chipPinsVPP = chipPinsVPP,
+ chipPinGND = chipPinGND)
+ self.signature = signature
+ self.flashPageSize = flashPageSize # Flash page size, in words
+ self.flashPages = flashPages # Nr of flash pages
+ self.eepromPageSize = eepromPageSize # EEPROM page size, in bytes
+ self.eepromPages = eepromPages # Nr of EEPROM pages
+
+ def readSignature(self):
+ self.__enterPM()
+
+ (signature, calibration) = self.__readSigAndCalib()
+
+ return signature
+
+ def erase(self):
+ self.__enterPM()
+
+ self.progressMeterInit("Erasing chip", 0)
+ self.__loadCommand(self.CMD_CHIPERASE)
+ self.__pulseWR()
+ self.__waitForRDY()
+ self.progressMeterFinish()
+
+ def readProgmem(self):
+ self.__enterPM()
+
+ self.progressMeterInit("Reading Flash", self.flashPages)
+ image = ""
+ for page in range(0, self.flashPages):
+ self.progressMeter(page)
+ readWords = 0
+ for word in range(0, self.flashPageSize):
+ self.__loadCommand(self.CMD_READFLASH)
+ self.__loadAddr((page * self.flashPageSize) + word)
+ self.__readWordToStatusReg()
+ readWords += 1
+ if readWords >= 32:
+ image += self.top.cmdReadBufferReg()
+ readWords = 0
+ if readWords:
+ data = self.top.cmdReadBufferReg()
+ image += data[0:readWords*2]
+ self.progressMeterFinish()
+ return image
+
+ def writeProgmem(self, image):
+ flashBytes = self.flashPageSize * 2 * self.flashPages
+ if len(image) != flashBytes:
+ self.throwError("Invalid program memory image size %d (expected %d)" %\
+ (len(image), flashBytes))
+ self.__enterPM()
+
+ self.progressMeterInit("Writing Flash", self.flashPages)
+ for page in range(0, self.flashPages):
+ self.progressMeter(page)
+ for word in range(0, self.flashPageSize):
+ self.__loadCommand(self.CMD_WRITEFLASH)
+ addr = (page * self.flashPageSize) + word
+ self.__loadAddr(addr)
+ addr *= 2
+ data = image[addr : addr + 2]
+ self.__loadData(byte2int(data[0]) | (byte2int(data[1]) << 8))
+ self.__setBS1(1)
+ self.__pulsePAGEL()
+ self.__setBS1(0)
+ self.__pulseWR()
+ self.__waitForRDY()
+ self.progressMeterFinish()
+
+ def readEEPROM(self):
+ self.__enterPM()
+
+ assert(self.eepromPageSize <= self.top.getBufferRegSize())
+ self.progressMeterInit("Reading EEPROM", self.eepromPages)
+ image = ""
+ for page in range(0, self.eepromPages):
+ self.progressMeter(page)
+ for byte in range(0, self.eepromPageSize):
+ self.__loadCommand(self.CMD_READEEPROM)
+ self.__loadAddr((page * self.eepromPageSize) + byte)
+ self.__readLowByteToStatusReg()
+ data = self.top.cmdReadBufferReg()
+ image += data[0:self.eepromPageSize]
+ self.progressMeterFinish()
+ return image
+
+ def writeEEPROM(self, image):
+ eepromBytes = self.eepromPageSize * self.eepromPages
+ if len(image) != eepromBytes:
+ self.throwError("Invalid EEPROM image size %d (expected %d)" %\
+ (len(image), eepromBytes))
+ self.__enterPM()
+
+ self.progressMeterInit("Writing EEPROM", self.eepromPages)
+ for page in range(0, self.eepromPages):
+ self.progressMeter(page)
+ for byte in range(0, self.eepromPageSize):
+ self.__loadCommand(self.CMD_WRITEEEPROM)
+ addr = (page * self.eepromPageSize) + byte
+ self.__loadAddr(addr)
+ data = image[addr]
+ self.__loadDataLow(byte2int(data[0]))
+ self.__pulsePAGEL()
+ self.__setBS1(0)
+ self.__pulseWR()
+ self.__waitForRDY()
+ self.progressMeterFinish()
+
+ def readFuse(self):
+ self.__enterPM()
+
+ self.progressMeterInit("Reading Fuse bits", 0)
+ (fuse, lock) = self.__readFuseAndLockBits()
+ self.progressMeterFinish()
+ return fuse
+
+ def writeFuse(self, image):
+ if len(image) != 2:
+ self.throwError("Invalid Fuses image size %d (expected %d)" %\
+ (len(image), 2))
+ self.__enterPM()
+
+ self.progressMeterInit("Writing Fuse bits", 0)
+ self.__loadCommand(self.CMD_WRITEFUSE)
+ self.__setBS2(0)
+ self.__loadDataLow(byte2int(image[0]))
+ self.__pulseWR()
+ self.__waitForRDY()
+ self.__loadCommand(self.CMD_WRITEFUSE)
+ self.__loadDataLow(byte2int(image[1]))
+ self.__setBS1(1)
+ self.__pulseWR()
+ self.__waitForRDY()
+ self.progressMeterFinish()
+
+ def readLockbits(self):
+ self.__enterPM()
+
+ self.progressMeterInit("Reading lock bits", 0)
+ (fuses, lockbits) = self.__readFuseAndLockBits()
+ self.progressMeterFinish()
+
+ return lockbits
+
+ def writeLockbits(self, image):
+ if len(image) != 1:
+ self.throwError("Invalid lock-bits image size %d (expected %d)" %\
+ (len(image), 1))
+ self.__enterPM()
+
+ self.progressMeterInit("Writing lock bits", 0)
+ self.__loadCommand(self.CMD_WRITELOCK)
+ self.__loadDataLow(byte2int(image[0]))
+ self.__pulseWR()
+ self.__waitForRDY()
+ self.progressMeterFinish()
+
+ def __readSigAndCalib(self):
+ """Reads the signature and calibration bytes and returns them.
+ This function expects a DUT present and pins initialized."""
+ signature = ""
+ calibration = ""
+ for addr in range(0, 3):
+ self.__loadCommand(self.CMD_READSIG)
+ self.__loadAddr(addr)
+ self.__readWordToStatusReg()
+ data = self.top.cmdReadBufferReg()
+ if addr == 0:
+ calibration += data[1]
+ signature += data[0]
+ return (signature, calibration)
+
+ def __readFuseAndLockBits(self):
+ """Reads the Fuse and Lock bits and returns them.
+ This function expects a DUT present and pins initialized."""
+ self.__loadCommand(self.CMD_READFUSELOCK)
+ self.__setBS2(0)
+ self.__readWordToStatusReg()
+ self.__setBS2(1)
+ self.__readWordToStatusReg()
+ self.__setBS2(0)
+ data = self.top.cmdReadBufferReg()
+ fuses = data[0] + data[3]
+ lock = data[1]
+ return (fuses, lock)
+
+ def __enterPM(self):
+ "Enter HV programming mode."
+ self.applyVPP(False)
+ self.applyVCC(False)
+ self.applyGND(True)
+ self.top.cmdSetVPPVoltage(0)
+ self.top.cmdSetVPPVoltage(12)
+ self.top.cmdSetVCCVoltage(5)
+
+ self.__setVoltageControl(VPP_en=1, VPP=0, VCC_en=1, VCC=0)
+ self.__setXA0(0)
+ self.__setXA1(0)
+ self.__setBS1(0)
+ self.__setPAGEL(0)
+ self.__setWR(0)
+ self.top.hostDelay(0.1)
+
+ self.applyVCC(True)
+ self.__setVoltageControl(VPP_en=1, VPP=0, VCC_en=1, VCC=1)
+ self.top.hostDelay(0.1)
+
+ self.__setOE(0)
+ self.__setWR(1)
+ self.__setXTAL1(0)
+ self.__setXA0(0)
+ self.__setXA1(0)
+ self.__setBS1(0)
+ self.__setBS2(0)
+ self.__setPAGEL(0)
+ self.__pulseXTAL1(10)
+ self.top.flushCommands()
+
+ self.__setVoltageControl(VPP_en=0, VPP=0, VCC_en=1, VCC=1)
+ self.applyVPP(True)
+
+ self.__setOE(1)
+
+ (signature, calibration) = self.__readSigAndCalib()
+ if signature != self.signature:
+ msg = "Unexpected device signature. " +\
+ "Want %02X%02X%02X, but got %02X%02X%02X" % \
+ (byte2int(self.signature[0]), byte2int(self.signature[1]),
+ byte2int(self.signature[2]),
+ byte2int(signature[0]), byte2int(signature[1]),
+ byte2int(signature[2]))
+ if self.top.getForceLevel() >= 1:
+ self.printWarning(msg)
+ else:
+ self.throwError(msg)
+
+ def __readWordToStatusReg(self):
+ """Read a data word from the DUT into the status register."""
+ self.__setBS1(0)
+ self.__setOE(0)
+ self.top.cmdFPGARead(0x10)
+ self.__setBS1(1)
+ self.top.cmdFPGARead(0x10)
+ self.__setOE(1)
+
+ def __readLowByteToStatusReg(self):
+ """Read the low data byte from the DUT into the status register."""
+ self.__setBS1(0)
+ self.__setOE(0)
+ self.top.cmdFPGARead(0x10)
+ self.__setOE(1)
+
+ def __readHighByteToStatusReg(self):
+ """Read the high data byte from the DUT into the status register."""
+ self.__setBS1(1)
+ self.__setOE(0)
+ self.top.cmdFPGARead(0x10)
+ self.__setOE(1)
+
+ def __loadData(self, data):
+ """Load a data word."""
+ self.__loadDataLow(data)
+ self.__loadDataHigh(data >> 8)
+
+ def __loadDataLow(self, dataLow):
+ """Load the low data byte."""
+ self.__setBS1(0)
+ self.__setXA0(1)
+ self.__setXA1(0)
+ self.top.cmdFPGAWrite(0x10, dataLow & 0xFF)
+ self.__pulseXTAL1()
+
+ def __loadDataHigh(self, dataHigh):
+ """Load the high data byte."""
+ self.__setBS1(1)
+ self.__setXA0(1)
+ self.__setXA1(0)
+ self.top.cmdFPGAWrite(0x10, dataHigh & 0xFF)
+ self.__pulseXTAL1()
+
+ def __loadAddr(self, addr):
+ """Load an address word."""
+ self.__loadAddrLow(addr)
+ self.__loadAddrHigh(addr >> 8)
+
+ def __loadAddrLow(self, addrLow):
+ """Load the low address byte."""
+ self.__setBS1(0)
+ self.__setXA0(0)
+ self.__setXA1(0)
+ self.top.cmdFPGAWrite(0x10, addrLow & 0xFF)
+ self.__pulseXTAL1()
+
+ def __loadAddrHigh(self, addrHigh):
+ """Load the high address byte."""
+ self.__setBS1(1)
+ self.__setXA0(0)
+ self.__setXA1(0)
+ self.top.cmdFPGAWrite(0x10, addrHigh & 0xFF)
+ self.__pulseXTAL1()
+
+ def __loadCommand(self, command):
+ """Load a command into the device."""
+# self.top.queueCommand("\x34")
+ self.__setBS1(0)
+# self.top.queueCommand("\x34")
+ self.__setXA0(0)
+ self.__setXA1(1)
+ self.top.cmdFPGAWrite(0x10, command)
+ self.__pulseXTAL1()
+
+ def __waitForRDY(self):
+ """Wait for the RDY pin to go high."""
+ self.top.hostDelay(0.01)
+ for i in range(0, 50):
+ if self.__getRDY():
+ return
+ self.top.hostDelay(0.01)
+ self.throwError("Timeout waiting for READY signal from chip.")
+
+ def __getRDY(self):
+ """Read the state of the RDY/BSY pin."""
+ return bool(self.__getStatus() & 0x01)
+
+ def __getStatus(self):
+ """Read the programmer status register"""
+ self.top.cmdFPGARead(0x12)
+ stat = self.top.cmdReadBufferReg()
+ return byte2int(stat[0])
+
+ def __setOE(self, high):
+ """Set the OE pin of the DUT"""
+ value = 0x02
+ if high:
+ value |= 0x80
+ self.top.cmdFPGAWrite(0x12, value)
+
+ def __setWR(self, high):
+ """Set the WR pin of the DUT"""
+ value = 0x03
+ if high:
+ value |= 0x80
+ self.top.cmdFPGAWrite(0x12, value)
+
+ def __pulseWR(self, count=1):
+ """Do a negative pulse on the WR pin of the DUT"""
+ while count > 0:
+ self.__setWR(0)
+ self.__setWR(1)
+ count -= 1
+
+ def __setBS1(self, high):
+ """Set the BS1 pin of the DUT"""
+ value = 0x04
+ if high:
+ value |= 0x80
+ self.top.cmdFPGAWrite(0x12, value)
+
+ def __setXA0(self, high):
+ """Set the XA0 pin of the DUT"""
+ value = 0x05
+ if high:
+ value |= 0x80
+ self.top.cmdFPGAWrite(0x12, value)
+
+ def __setXA1(self, high):
+ """Set the XA1 pin of the DUT"""
+ value = 0x06
+ if high:
+ value |= 0x80
+ self.top.cmdFPGAWrite(0x12, value)
+
+ def __setXTAL1(self, high):
+ """Set the XTAL1 pin of the DUT"""
+ value = 0x07
+ if high:
+ value |= 0x80
+ self.top.cmdFPGAWrite(0x12, value)
+
+ def __pulseXTAL1(self, count=1):
+ """Do a positive pulse on the XTAL1 pin of the DUT"""
+ while count > 0:
+ self.__setXTAL1(1)
+ self.__setXTAL1(0)
+ count -= 1
+
+ def __setPAGEL(self, high):
+ """Set the PAGEL pin of the DUT"""
+ value = 0x09
+ if high:
+ value |= 0x80
+ self.top.cmdFPGAWrite(0x12, value)
+
+ def __pulsePAGEL(self, count=1):
+ """Do a positive pulse on the PAGEL pin of the DUT"""
+ while count > 0:
+ self.__setPAGEL(1)
+ self.__setPAGEL(0)
+ count -= 1
+
+ def __setBS2(self, high):
+ """Set the BS2 pin of the DUT"""
+ value = 0x0A
+ if high:
+ value |= 0x80
+ self.top.cmdFPGAWrite(0x12, value)
+
+ def __setVoltageControl(self, VPP_en, VPP, VCC_en, VCC):
+ value = 0
+ if VPP_en:
+ value |= 0x01
+ if VPP:
+ value |= 0x02
+ if VCC_en:
+ value |= 0x04
+ if VCC:
+ value |= 0x08
+ self.top.cmdFPGAWrite(0x11, value)
diff --git a/libtoprammer/chips/attiny13dip8.py b/libtoprammer/chips/attiny13dip8.py
new file mode 100644
index 0000000..bacd3b7
--- /dev/null
+++ b/libtoprammer/chips/attiny13dip8.py
@@ -0,0 +1,358 @@
+"""
+# TOP2049 Open Source programming suite
+#
+# Atmel Tiny13 DIP8
+#
+# Copyright (c) 2010 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.chip import *
+
+
+class Chip_AtTiny13dip8(Chip):
+ PROGCMD_SENDINSTR = 1 # Send an instruction to the chip
+
+ STAT_BUSY = 0x01 # Programmer is running a command
+ STAT_SDO = 0x02 # Raw SDO pin state
+
+ def __init__(self):
+ Chip.__init__(self,
+ chipPackage = "DIP8",
+ chipPinVCC = 8,
+ chipPinsVPP = 1,
+ chipPinGND = 4)
+ self.signature = "\x1E\x90\x07"
+ self.flashPageSize = 16
+ self.flashPages = 32
+ self.eepromPageSize = 4
+ self.eepromPages = 16
+
+ def readSignature(self):
+ self.__enterPM()
+ self.progressMeterInit("Reading signature", 0)
+ signature = self.__readSignature()
+ self.progressMeterFinish()
+ return signature
+
+ def erase(self):
+ self.__enterPM()
+ self.progressMeterInit("Erasing chip", 0)
+ self.__sendInstr(SDI=0x80, SII=0x4C)
+ self.__sendInstr(SDI=0x00, SII=0x64)
+ self.__sendInstr(SDI=0x00, SII=0x6C)
+ self.__waitHighSDO()
+ self.__sendNOP()
+ self.progressMeterFinish()
+
+ def readProgmem(self):
+ nrWords = self.flashPages * self.flashPageSize
+ image = ""
+ self.__enterPM()
+ self.progressMeterInit("Reading flash", nrWords)
+ self.__sendReadFlashInstr()
+ currentHigh = -1
+ bufferedBytes = 0
+ for word in range(0, nrWords):
+ self.progressMeter(word)
+ low = word & 0xFF
+ high = (word >> 8) & 0xFF
+ self.__sendInstr(SDI=low, SII=0x0C)
+ if high != currentHigh:
+ self.__sendInstr(SDI=high, SII=0x1C)
+ currentHigh = high
+ self.__sendInstr(SDI=0x00, SII=0x68)
+ self.__sendInstr(SDI=0x00, SII=0x6C)
+ self.__readSDOBufferHigh()
+ bufferedBytes += 1
+ self.__sendInstr(SDI=0x00, SII=0x78)
+ self.__sendInstr(SDI=0x00, SII=0x7C)
+ self.__readSDOBufferHigh()
+ bufferedBytes += 1
+ if bufferedBytes == self.top.getBufferRegSize():
+ image += self.top.cmdReadBufferReg(bufferedBytes)
+ bufferedBytes = 0
+ image += self.top.cmdReadBufferReg(bufferedBytes)
+ self.progressMeterFinish()
+ return image
+
+ def writeProgmem(self, image):
+ nrWords = self.flashPages * self.flashPageSize
+ if len(image) > nrWords * 2 or len(image) % 2 != 0:
+ self.throwError("Invalid flash image size %d (expected <=%d and word aligned)" %\
+ (len(image), nrWords * 2))
+ self.__enterPM()
+ self.progressMeterInit("Writing flash", len(image) // 2)
+ self.__sendWriteFlashInstr()
+ currentHigh = -1
+ for word in range(0, len(image) // 2):
+ self.progressMeter(word)
+ low = word & 0xFF
+ high = (word >> 8) & 0xFF
+ self.__sendInstr(SDI=low, SII=0x0C)
+ self.__sendInstr(SDI=byte2int(image[word * 2 + 0]), SII=0x2C)
+ self.__sendInstr(SDI=byte2int(image[word * 2 + 1]), SII=0x3C)
+ self.__sendInstr(SDI=0x00, SII=0x7D)
+ self.__sendInstr(SDI=0x00, SII=0x7C)
+ if ((word + 1) % self.flashPageSize == 0) or word == len(image) // 2 - 1:
+ if currentHigh != high:
+ self.__sendInstr(SDI=high, SII=0x1C)
+ currentHigh = high
+ self.__sendInstr(SDI=0x00, SII=0x64)
+ self.__sendInstr(SDI=0x00, SII=0x6C)
+ self.__waitHighSDO()
+ self.__sendNOP()
+ self.progressMeterFinish()
+
+ def readEEPROM(self):
+ nrBytes = self.eepromPages * self.eepromPageSize
+ image = ""
+ self.__enterPM()
+ self.progressMeterInit("Reading EEPROM", nrBytes)
+ self.__sendReadEEPROMInstr()
+ currentPage = -1
+ bufferedBytes = 0
+ for i in range(0, nrBytes):
+ self.progressMeter(i)
+ low = i & 0xFF
+ high = (i >> 8) & 0xFF
+ self.__sendInstr(SDI=low, SII=0x0C)
+ if currentPage != high:
+ self.__sendInstr(SDI=high, SII=0x1C)
+ currentPage = high
+ self.__sendInstr(SDI=0x00, SII=0x68)
+ self.__sendInstr(SDI=0x00, SII=0x6C)
+ self.__readSDOBufferHigh()
+ bufferedBytes += 1
+ if bufferedBytes == self.top.getBufferRegSize():
+ image += self.top.cmdReadBufferReg(bufferedBytes)
+ bufferedBytes = 0
+ image += self.top.cmdReadBufferReg(bufferedBytes)
+ self.progressMeterFinish()
+ return image
+
+ def writeEEPROM(self, image):
+ nrBytes = self.eepromPages * self.eepromPageSize
+ if len(image) > nrBytes:
+ self.throwError("Invalid EEPROM image size %d (expected <=%d)" %\
+ (len(image), nrBytes))
+ self.__enterPM()
+ self.progressMeterInit("Writing EEPROM", len(image))
+ self.__sendWriteEEPROMInstr()
+ for i in range(0, len(image)):
+ self.progressMeter(i)
+ self.__sendInstr(SDI=i, SII=0x0C)
+ self.__sendInstr(SDI=byte2int(image[i]), SII=0x2C)
+ self.__sendInstr(SDI=0x00, SII=0x6D)
+ self.__sendInstr(SDI=0x00, SII=0x6C)
+ if ((i + 1) % self.eepromPageSize == 0) or i == len(image) - 1:
+ self.__sendInstr(SDI=0x00, SII=0x64)
+ self.__sendInstr(SDI=0x00, SII=0x6C)
+ self.__waitHighSDO()
+ self.__sendNOP()
+ self.progressMeterFinish()
+
+ def readFuse(self):
+ fuses = []
+ self.__enterPM()
+ self.progressMeterInit("Reading fuses", 0)
+ self.__sendInstr(SDI=0x04, SII=0x4C)
+ self.__sendInstr(SDI=0x00, SII=0x68)
+ self.__sendInstr(SDI=0x00, SII=0x6C)
+ self.__readSDOBufferHigh()
+ fuses.append(self.top.cmdReadBufferReg(1))
+ self.__sendInstr(SDI=0x04, SII=0x4C)
+ self.__sendInstr(SDI=0x00, SII=0x7A)
+ self.__sendInstr(SDI=0x00, SII=0x7E)
+ self.__readSDOBufferHigh()
+ fuses.append(int2byte(self.top.cmdReadBufferReg8() | 0xE0))
+ self.progressMeterFinish()
+ return b"".join(fuses)
+
+ def writeFuse(self, image):
+ if len(image) != 2:
+ self.throwError("Invalid Fuses image size %d (expected %d)" %\
+ (len(image), 2))
+ self.__enterPM()
+ self.progressMeterInit("Writing fuses", 0)
+ self.__sendInstr(SDI=0x40, SII=0x4C)
+ self.__sendInstr(SDI=byte2int(image[0]), SII=0x2C)
+ self.__sendInstr(SDI=0x00, SII=0x64)
+ self.__sendInstr(SDI=0x00, SII=0x6C)
+ self.__waitHighSDO()
+ self.__sendInstr(SDI=0x40, SII=0x4C)
+ self.__sendInstr(SDI=(byte2int(image[1]) & 0x1F), SII=0x2C)
+ self.__sendInstr(SDI=0x00, SII=0x74)
+ self.__sendInstr(SDI=0x00, SII=0x7C)
+ self.__waitHighSDO()
+ self.progressMeterFinish()
+
+ def readLockbits(self):
+ self.__enterPM()
+ self.progressMeterInit("Reading lockbits", 0)
+ self.__sendInstr(SDI=0x04, SII=0x4C)
+ self.__sendInstr(SDI=0x00, SII=0x78)
+ self.__sendInstr(SDI=0x00, SII=0x7C)
+ self.__readSDOBufferHigh()
+ lockbits = int2byte(self.top.cmdReadBufferReg8() | 0xFC)
+ self.progressMeterFinish()
+ return lockbits
+
+ def writeLockbits(self, image):
+ if len(image) != 1:
+ self.throwError("Invalid Lockbits image size %d (expected %d)" %\
+ (len(image), 1))
+ self.__enterPM()
+ self.progressMeterInit("Writing lockbits", 0)
+ self.__sendInstr(SDI=0x20, SII=0x4C)
+ self.__sendInstr(SDI=(byte2int(image[0]) & 3), SII=0x2C)
+ self.__sendInstr(SDI=0x00, SII=0x64)
+ self.__sendInstr(SDI=0x00, SII=0x6C)
+ self.__waitHighSDO()
+ self.progressMeterFinish()
+
+ def __readSignature(self):
+ self.__sendInstr(SDI=0x08, SII=0x4C)
+ for i in range(0, 3):
+ self.__sendInstr(SDI=i, SII=0x0C)
+ self.__sendInstr(SDI=0x00, SII=0x68)
+ self.__sendInstr(SDI=0x00, SII=0x6C)
+ self.__readSDOBufferHigh()
+ return self.top.cmdReadBufferReg()[0:3]
+
+ def __enterPM(self):
+ "Enter HV programming mode."
+ self.applyVCC(False)
+ self.applyVPP(False)
+ self.applyGND(False)
+ self.top.cmdSetVCCVoltage(5)
+ self.top.cmdSetVPPVoltage(0)
+ self.top.cmdSetVPPVoltage(12)
+ self.applyGND(True)
+ self.applyVCC(True)
+
+ self.__setPins(SCI=0, SDO_en=0, RST_en=1, RST=0)
+ for i in range(0, 6):
+ self.__setPins(SCI=0, SDO_en=0, RST_en=1, RST=0)
+ self.__setPins(SCI=1, SDO_en=0, RST_en=1, RST=0)
+ self.__setPins(SCI=0, SDO_en=1, SDO=0, RST_en=1, RST=0)
+ self.top.hostDelay(0.001)
+ self.__setPins(SDO_en=1, SDO=0, RST_en=0)
+ self.applyVPP(True)
+ self.top.hostDelay(0.001)
+ self.__setPins(SDO_en=0)
+ self.top.hostDelay(0.01)
+
+ signature = self.__readSignature()
+ if signature != self.signature:
+ msg = "Unexpected device signature. " +\
+ "Want %02X%02X%02X, but got %02X%02X%02X" % \
+ (byte2int(self.signature[0]), byte2int(self.signature[1]),
+ byte2int(self.signature[2]),
+ byte2int(signature[0]), byte2int(signature[1]),
+ byte2int(signature[2]))
+ if self.top.getForceLevel() >= 1:
+ self.printWarning(msg)
+ else:
+ self.throwError(msg)
+
+ def __sendReadEEPROMInstr(self):
+ self.__sendInstr(SDI=0x03, SII=0x4C)
+
+ def __sendWriteEEPROMInstr(self):
+ self.__sendInstr(SDI=0x11, SII=0x4C)
+
+ def __sendReadFlashInstr(self):
+ self.__sendInstr(SDI=0x02, SII=0x4C)
+
+ def __sendWriteFlashInstr(self):
+ self.__sendInstr(SDI=0x10, SII=0x4C)
+
+ def __sendNOP(self):
+ self.__sendInstr(SDI=0x00, SII=0x4C)
+
+ def __sendInstr(self, SDI, SII):
+ self.__setSDI(SDI)
+ self.__setSII(SII)
+ self.__loadCommand(self.PROGCMD_SENDINSTR)
+ # We do not poll the busy flag, because that would result
+ # in a significant slowdown. We delay long enough for the
+ # command to finish execution, instead.
+ self.top.hostDelay(0.001)
+
+ def __setSDI(self, sdi):
+ self.top.cmdFPGAWrite(0x13, sdi & 0xFF)
+
+ def __setSII(self, sii):
+ self.top.cmdFPGAWrite(0x14, sii & 0xFF)
+
+ def __loadCommand(self, command):
+ self.top.cmdFPGAWrite(0x12, command & 0xFF)
+
+ def __runCommandSync(self, command):
+ self.__loadCommand(command)
+ self.__busyWait()
+
+ def __setPins(self, SCI=0, SDO_en=0, SDO=0, RST_en=0, RST=0):
+ data = 0
+ if SCI:
+ data |= 1
+ if SDO_en:
+ data |= 2
+ if SDO:
+ data |= 4
+ if RST_en:
+ data |= 8
+ if RST:
+ data |= 16
+ self.top.cmdFPGAWrite(0x15, data)
+
+ def __getStatusFlags(self):
+ self.top.cmdFPGARead(0x12)
+ stat = self.top.cmdReadBufferReg()
+ return byte2int(stat[0])
+
+ def __readSDOBufferHigh(self):
+ self.top.cmdFPGARead(0x10)
+
+ def __rawSDOState(self):
+ return bool(self.__getStatusFlags() & self.STAT_SDO)
+
+ def __busy(self):
+ return bool(self.__getStatusFlags() & self.STAT_BUSY)
+
+ def __busyWait(self):
+ for i in range(0, 100):
+ if not self.__busy():
+ return
+ self.top.hostDelay(0.01)
+ self.throwError("Timeout in busywait.")
+
+ def __waitHighSDO(self):
+ for i in range(0, 100):
+ if self.__rawSDOState():
+ return
+ self.top.hostDelay(0.01)
+ self.throwError("Timeout waiting for SDO.")
+
+ChipDescription(
+ Chip_AtTiny13dip8,
+ bitfile = "attiny13dip8",
+ runtimeID = (0x0001, 0x01),
+ chipVendors = "Atmel",
+ description = "AtTiny13",
+ packages = ( ("DIP8", ""), ),
+)
diff --git a/libtoprammer/chips/attiny26dip20.py b/libtoprammer/chips/attiny26dip20.py
new file mode 100644
index 0000000..0faaa63
--- /dev/null
+++ b/libtoprammer/chips/attiny26dip20.py
@@ -0,0 +1,48 @@
+"""
+# TOP2049 Open Source programming suite
+#
+# Atmel Tiny26 DIP20 support
+#
+# Copyright (c) 2009-2010 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 atmega_common import *
+
+
+class Chip_ATTiny26DIP20(Chip_ATMega_common):
+ def __init__(self):
+ Chip_ATMega_common.__init__(self,
+ chipPackage = "DIP20",
+ chipPinVCC = 5,
+ chipPinsVPP = 10,
+ chipPinGND = 6,
+ signature = "\x1E\x91\x09",
+ flashPageSize = 16,
+ flashPages = 64,
+ eepromPageSize = 4,
+ eepromPages = 32)
+
+ChipDescription(
+ Chip_ATTiny26DIP20,
+ bitfile = "attiny26dip20",
+ runtimeID = (0x0002, 0x01),
+ chipVendors = "Atmel",
+ description = "AtTiny26",
+ packages = ( ("DIP20", ""), ),
+ comment = "Special ZIF position",
+ broken = True
+)
diff --git a/libtoprammer/chips/generic_sram.py b/libtoprammer/chips/generic_sram.py
new file mode 100644
index 0000000..29ba860
--- /dev/null
+++ b/libtoprammer/chips/generic_sram.py
@@ -0,0 +1,122 @@
+"""
+# TOP2049 Open Source programming suite
+#
+# Generic SRAM chip
+#
+# Copyright (c) 2011 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.chip import *
+
+
+class Chip_genericSRAM(Chip):
+ def __init__(self, chipPackage, chipPinVCC, chipPinGND,
+ VCCVoltage,
+ nrAddressBits, nrDataBits):
+ Chip.__init__(self,
+ chipPackage = chipPackage,
+ chipPinVCC = chipPinVCC,
+ chipPinGND = chipPinGND)
+ self.VCCVoltage = VCCVoltage
+ self.nrAddressBits = nrAddressBits
+ self.nrAddressBytes = int(math.ceil((float(self.nrAddressBits) - 0.1) / 8))
+ self.nrDataBits = nrDataBits
+ assert(nrDataBits == 8)
+
+ def erase(self):
+ self.writeRAM(int2byte(0) * self.__sizeBytes())
+
+ def test(self):
+ generic = GenericAlgorithms(self)
+ generic.simpleTest(self.readRAM, self.writeRAM,
+ self.__sizeBytes())
+
+ def readRAM(self):
+ image = []
+
+ self.progressMeterInit("Reading SRAM", self.__sizeBytes())
+ self.__turnOnChip()
+ self.__setControlPins(CE=0, OE=0, WE=1)
+ nrBytes = 0
+ for addr in range(0, self.__sizeBytes()):
+ self.progressMeter(addr)
+ self.__setAddress(addr)
+ self.__readData()
+ nrBytes += 1
+ if nrBytes == self.top.getBufferRegSize():
+ image.append(self.top.cmdReadBufferReg(nrBytes))
+ nrBytes = 0
+ image.append(self.top.cmdReadBufferReg(nrBytes))
+ self.__setControlPins(CE=1, OE=1, WE=1)
+ self.progressMeterFinish()
+
+ return b"".join(image)
+
+ def writeRAM(self, image):
+ if len(image) > self.__sizeBytes():
+ self.throwError("Invalid memory image size %d (expected max %d)" %\
+ (len(image), self.__sizeBytes()))
+
+ self.progressMeterInit("Writing SRAM", self.__sizeBytes())
+ self.__turnOnChip()
+ self.__setControlPins(CE=0, OE=1, WE=1)
+ for addr in range(0, len(image)):
+ self.progressMeter(addr)
+ self.__setAddress(addr)
+ self.__writeData(image[addr])
+ self.__setControlPins(CE=0, OE=1, WE=0)
+ self.top.cmdDelay(0.00000007) # Delay at least 70 nsec
+ self.__setControlPins(CE=0, OE=1, WE=1)
+ self.__setControlPins(CE=1, OE=1, WE=1)
+ self.progressMeterFinish()
+
+ def __sizeBytes(self):
+ return (1 << self.nrAddressBits)
+
+ def __turnOnChip(self):
+ self.__setControlPins(CE=1, OE=1, WE=1)
+ self.top.cmdSetVCCVoltage(self.VCCVoltage)
+ self.applyGND(True)
+ self.applyVCC(True)
+ self.lastAddress = None
+
+ def __setControlPins(self, CE=1, OE=1, WE=1):
+ value = 0
+ if CE:
+ value |= 1
+ if OE:
+ value |= 2
+ if WE:
+ value |= 4
+ self.top.cmdFPGAWrite(0x11, value)
+
+ def __writeData(self, data):
+ data = byte2int(data)
+ self.top.cmdFPGAWrite(0x10, data)
+
+ def __readData(self):
+ self.top.cmdFPGARead(0x10)
+
+ def __setAddress(self, addr):
+ for i in range(0, self.nrAddressBytes):
+ shift = 8 * i
+ mask = 0xFF << shift
+ if self.lastAddress is None or\
+ (self.lastAddress & mask) != (addr & mask):
+ self.top.cmdFPGAWrite(0x12 + i,
+ (addr & mask) >> shift)
+ self.lastAddress = addr
diff --git a/libtoprammer/chips/hm62256dip28.py b/libtoprammer/chips/hm62256dip28.py
new file mode 100644
index 0000000..708c5a9
--- /dev/null
+++ b/libtoprammer/chips/hm62256dip28.py
@@ -0,0 +1,45 @@
+"""
+# TOP2049 Open Source programming suite
+#
+# HM62256 DIP28 SRAM support
+#
+# Copyright (c) 2011 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 generic_sram import *
+
+
+class Chip_HM62256DIP28(Chip_genericSRAM):
+ def __init__(self):
+ Chip_genericSRAM.__init__(self,
+ chipPackage = "DIP28",
+ chipPinVCC = 28,
+ chipPinGND = 14,
+ VCCVoltage = 5,
+ nrAddressBits = 15,
+ nrDataBits = 8,
+ )
+
+ChipDescription(
+ Chip_HM62256DIP28,
+ bitfile = "hm62256dip28",
+ runtimeID = (0x000A, 0x01),
+ chipType = ChipDescription.TYPE_SRAM,
+ chipVendors = "S@Tech",
+ description = "HM62256 SRAM",
+ packages = ( ("DIP28", ""), )
+)
diff --git a/libtoprammer/chips/m24cxxdip8.py b/libtoprammer/chips/m24cxxdip8.py
new file mode 100644
index 0000000..8d3f156
--- /dev/null
+++ b/libtoprammer/chips/m24cxxdip8.py
@@ -0,0 +1,260 @@
+"""
+# TOP2049 Open Source programming suite
+#
+# M24C16 I2C based serial EEPROM
+#
+# Copyright (c) 2011 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.chip import *
+
+
+class Chip_m24cXXdip8_common(Chip):
+ CMD_DEVSEL_READ = 0
+ CMD_DEVSEL_WRITE = 1
+ CMD_SETADDR = 2
+ CMD_DATA_READ = 3
+ CMD_DATA_READ_STOP = 4
+ CMD_DATA_WRITE = 5
+ CMD_DATA_WRITE_STOP = 6
+
+ def __init__(self, eepromSize):
+ Chip.__init__(self,
+ chipPackage = "DIP8",
+ chipPinVCC = 8,
+ chipPinGND = 4)
+ self.eepromSize = eepromSize # in bytes
+
+ def __chipTurnOn(self):
+ self.top.cmdSetVCCVoltage(5)
+ self.top.cmdSetVPPVoltage(5)
+ self.applyVCC(True)
+ self.applyVPP(False)
+ self.applyGND(True)
+ self.top.cmdEnableZifPullups(True)
+
+ self.currentAddrExt = None
+
+ def erase(self):
+ self.writeEEPROM("\xFF" * self.eepromSize)
+
+ def readEEPROM(self):
+ self.__chipTurnOn()
+
+ image = ""
+ count = 0
+ prevAddr = None
+ self.progressMeterInit("Reading EEPROM", self.eepromSize)
+ for addr in range(0, self.eepromSize):
+ self.progressMeter(addr)
+ if prevAddr is None or (prevAddr & 0xFF00) != (addr & 0xFF00):
+ self.__setAddress(addr, writeMode=False)
+ self.__runCommand(self.CMD_DEVSEL_WRITE)
+ self.__runCommand(self.CMD_SETADDR)
+ self.__runCommand(self.CMD_DEVSEL_READ)
+ self.__runCommand(self.CMD_DATA_READ_STOP)
+ prevAddr = addr
+ else:
+ self.__runCommand(self.CMD_DEVSEL_READ)
+ self.__runCommand(self.CMD_DATA_READ_STOP)
+ self.__readData()
+ count += 1
+ if count == self.top.getBufferRegSize():
+ image += self.top.cmdReadBufferReg(count)
+ count = 0
+ image += self.top.cmdReadBufferReg(count)
+ self.progressMeterFinish()
+
+ return image
+
+ def writeEEPROM(self, image):
+ if len(image) > self.eepromSize:
+ self.throwError("Invalid EEPROM image size %d (expected <=%d)" %\
+ (len(image), self.eepromSize))
+ self.__chipTurnOn()
+
+ self.progressMeterInit("Writing EEPROM", len(image))
+ prevAddr = None
+ for addr in range(0, len(image)):
+ self.progressMeter(addr)
+ self.__setData(byte2int(image[addr]))
+ if prevAddr is None or (prevAddr & 0xFFF0) != (addr & 0xFFF0):
+ self.__setAddress(addr, writeMode=True)
+ self.__runCommand(self.CMD_DEVSEL_WRITE, busyWait=True)
+ self.__runCommand(self.CMD_SETADDR, busyWait=True)
+ self.__runCommand(self.CMD_DATA_WRITE, busyWait=True)
+ prevAddr = addr
+ else:
+ if (addr & 0xF) == 0xF:
+ self.__runCommand(self.CMD_DATA_WRITE_STOP, busyWait=True)
+ else:
+ self.__runCommand(self.CMD_DATA_WRITE, busyWait=True)
+ self.progressMeterFinish()
+
+ def __readData(self):
+ self.top.cmdFPGARead(0x10)
+
+ def __setData(self, dataByte):
+ self.top.cmdFPGAWrite(0x12, dataByte & 0xFF)
+
+ def __setAddress(self, address, writeMode):
+ # Address base
+ self.top.cmdFPGAWrite(0x11, address & 0xFF)
+ # Address extension
+ sizeMask = self.eepromSize - 1
+ assert(sizeMask & ~0x7FF == 0)
+ addrExt = address & 0x700 & sizeMask
+ if self.currentAddrExt != addrExt:
+ self.currentAddrExt = addrExt
+ if sizeMask & 0x0100:
+ E0 = addrExt & 0x0100
+ E0_en = 0
+ else:
+ E0 = 0
+ E0_en = 1
+ if sizeMask & 0x0200:
+ E1 = addrExt & 0x0200
+ E1_en = 0
+ else:
+ E1 = 0
+ E1_en = 1
+ if sizeMask & 0x0400:
+ E2 = addrExt & 0x0400
+ E2_en = 0
+ else:
+ E2 = 0
+ E2_en = 1
+ if writeMode:
+ WC = 0
+ else:
+ WC = 1
+ self.__setControlPins(E0=E0, E0_en=E0_en,
+ E1=E1, E1_en=E1_en,
+ E2=E2, E2_en=E2_en,
+ WC=WC)
+
+ def __runCommand(self, command, busyWait=False):
+ self.top.cmdFPGAWrite(0x10, command & 0xFF)
+ if busyWait:
+ self.__busyWait()
+ else:
+ # We do not read busy flags, but wait long enough for
+ # the operation to finish. This is safe for eeprom read.
+ self.top.cmdDelay(0.00009)
+
+ def __isBusy(self):
+ (busy0, busy1) = self.__getStatusFlags()
+ return busy0 != busy1
+
+ def __busyWait(self):
+ for i in range(0, 100):
+ if not self.__isBusy():
+ return
+ self.top.hostDelay(0.001)
+ self.throwError("Timeout in busywait.")
+
+ def __getStatusFlags(self):
+ self.top.cmdFPGARead(0x11)
+ stat = self.top.cmdReadBufferReg8()
+ busy0 = bool(stat & 0x01)
+ busy1 = bool(stat & 0x02)
+ return (busy0, busy1)
+
+ def __setControlPins(self, E0, E0_en, E1, E1_en, E2, E2_en, WC):
+ value = 0
+ if E0:
+ value |= (1 << 0)
+ if E0_en:
+ value |= (1 << 1)
+ if E1:
+ value |= (1 << 2)
+ if E1_en:
+ value |= (1 << 3)
+ if E2:
+ value |= (1 << 4)
+ if E2_en:
+ value |= (1 << 5)
+ if WC:
+ value |= (1 << 6)
+ self.top.cmdFPGAWrite(0x13, value)
+
+class Chip_m24c01dip8(Chip_m24cXXdip8_common):
+ def __init__(self):
+ Chip_m24cXXdip8_common.__init__(self, eepromSize = 1024 * 1 // 8)
+
+class Chip_m24c02dip8(Chip_m24cXXdip8_common):
+ def __init__(self):
+ Chip_m24cXXdip8_common.__init__(self, eepromSize = 1024 * 2 // 8)
+
+class Chip_m24c04dip8(Chip_m24cXXdip8_common):
+ def __init__(self):
+ Chip_m24cXXdip8_common.__init__(self, eepromSize = 1024 * 4 // 8)
+
+class Chip_m24c08dip8(Chip_m24cXXdip8_common):
+ def __init__(self):
+ Chip_m24cXXdip8_common.__init__(self, eepromSize = 1024 * 8 // 8)
+
+class Chip_m24c16dip8(Chip_m24cXXdip8_common):
+ def __init__(self):
+ Chip_m24cXXdip8_common.__init__(self, eepromSize = 1024 * 16 // 8)
+
+class ChipDescription_m24cXX(ChipDescription):
+ def __init__(self, chipImplClass, chipID, description):
+ ChipDescription.__init__(self,
+ chipImplClass = chipImplClass,
+ bitfile = "m24c16dip8",
+ chipID = chipID,
+ runtimeID = (0x000B, 0x01),
+ chipType = ChipDescription.TYPE_EEPROM,
+ chipVendors = "ST",
+ description = description,
+ packages = (
+ ("DIP8", ""),
+ ("SO8", "With 1:1 adapter"),
+ ("TSSOP8", "With 1:1 adapter"),
+ ),
+ )
+
+ChipDescription_m24cXX(
+ Chip_m24c01dip8,
+ chipID = "m24c01dip8",
+ description = "M24C01 I2C EEPROM",
+)
+
+ChipDescription_m24cXX(
+ Chip_m24c02dip8,
+ chipID = "m24c02dip8",
+ description = "M24C02 I2C EEPROM",
+)
+
+ChipDescription_m24cXX(
+ Chip_m24c04dip8,
+ chipID = "m24c04dip8",
+ description = "M24C04 I2C EEPROM",
+)
+
+ChipDescription_m24cXX(
+ Chip_m24c08dip8,
+ chipID = "m24c08dip8",
+ description = "M24C08 I2C EEPROM",
+)
+
+ChipDescription_m24cXX(
+ Chip_m24c16dip8,
+ chipID = "m24c16dip8",
+ description = "M24C16 I2C EEPROM",
+)
diff --git a/libtoprammer/chips/m2764a.py b/libtoprammer/chips/m2764a.py
new file mode 100644
index 0000000..7eecbb9
--- /dev/null
+++ b/libtoprammer/chips/m2764a.py
@@ -0,0 +1,173 @@
+"""
+# TOP2049 Open Source programming suite
+#
+# M2764A EPROM programmer
+#
+# Copyright (c) 2010 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.chip import *
+
+
+class Chip_M2764A(Chip):
+ PROGCMD_PPULSE = 1 # Perform a P-pulse
+
+ STAT_BUSY = 0x01 # Programmer is running a command
+
+ def __init__(self):
+ Chip.__init__(self,
+ chipPackage = "DIP28",
+ chipPinVCC = 28,
+ chipPinsVPP = 1,
+ chipPinGND = 14)
+
+ def __initChip(self):
+ self.applyVCC(False)
+ self.applyVPP(False)
+ self.applyGND(False)
+ self.top.cmdSetVCCVoltage(5)
+ self.top.cmdSetVPPVoltage(0)
+ self.top.cmdSetVPPVoltage(5)
+
+ def readEEPROM(self):
+ self.__initChip()
+ self.top.cmdSetVCCVoltage(5)
+ self.top.cmdSetVPPVoltage(5)
+ self.applyVCC(True)
+ self.applyVPP(True)
+ self.applyGND(True)
+
+ image = ""
+ self.progressMeterInit("Reading EPROM", 0x2000)
+ self.__setEG(E=1, G=1)
+ byteCount = 0
+ for addr in range(0, 0x2000):
+ self.progressMeter(addr)
+ self.__readDataToStatusReg(addr)
+ byteCount += 1
+ if byteCount == self.top.getBufferRegSize():
+ image += self.top.cmdReadBufferReg(byteCount)
+ byteCount = 0
+ image += self.top.cmdReadBufferReg(byteCount)
+ self.__setEG(E=1, G=1)
+ self.progressMeterFinish()
+
+ return image
+
+ def writeEEPROM(self, image):
+ if len(image) > 0x2000:
+ self.throwError("Invalid EPROM image size %d (expected <=%d)" %\
+ (len(image), 0x2000))
+
+ self.__initChip()
+ self.top.cmdSetVCCVoltage(5)
+ self.top.cmdSetVPPVoltage(12)
+ self.applyVCC(True)
+ self.applyVPP(True)
+ self.applyGND(True)
+
+ self.progressMeterInit("Writing EPROM", len(image))
+ self.__setEG(E=1, G=1)
+ for addr in range(0, len(image)):
+ self.progressMeter(addr)
+ data = byte2int(image[addr])
+ if data != 0xFF:
+ self.__writeData(addr, data)
+ self.__setEG(E=1, G=1)
+ self.progressMeterFinish()
+
+ def __readDataToStatusReg(self, addr):
+ self.__loadAddr(addr)
+ self.__setEG(E=0, G=0)
+ self.top.cmdFPGARead(0x10)
+
+ def __writeData(self, addr, data):
+ self.__setEG(E=0, G=1)
+ self.__loadAddr(addr)
+ self.__loadData(data)
+ self.__loadPPulseLen(1)
+ self.__runCommandSync(self.PROGCMD_PPULSE)
+ for i in range(0, 25):
+ self.__readDataToStatusReg(addr)
+ stat = self.top.cmdReadBufferReg()
+ r = byte2int(stat[0])
+ if r == data:
+ break
+ self.__setEG(E=0, G=1)
+ self.__runCommandSync(self.PROGCMD_PPULSE)
+ else:
+ self.throwError("Failed to program 0x%04X (got 0x%02X, expected 0x%02X)" %\
+ (addr, r, data))
+ self.__setEG(E=0, G=1)
+ self.__loadPPulseLen(3 * (i + 1))
+ self.__runCommandSync(self.PROGCMD_PPULSE)
+
+ def __loadData(self, data):
+ self.top.cmdFPGAWrite(0x10, data)
+
+ def __loadCommand(self, command):
+ self.top.cmdFPGAWrite(0x12, command & 0xFF)
+
+ def __runCommandSync(self, command):
+ self.__loadCommand(command)
+ self.__busyWait()
+
+ def __loadAddrLow(self, addrLow):
+ self.top.cmdFPGAWrite(0x13, addrLow & 0xFF)
+
+ def __loadAddrHigh(self, addrHigh):
+ self.top.cmdFPGAWrite(0x14, addrHigh & 0xFF)
+
+ def __loadAddr(self, addr):
+ self.__loadAddrLow(addr)
+ self.__loadAddrHigh(addr >> 8)
+
+ def __loadPPulseLen(self, msec):
+ self.top.cmdFPGAWrite(0x15, msec)
+
+ def __setEG(self, E, G):
+ data = 0
+ if E:
+ data |= 1
+ if G:
+ data |= 2
+ self.top.cmdFPGAWrite(0x16, data)
+
+ def __getStatusFlags(self):
+ self.top.cmdFPGARead(0x12)
+ stat = self.top.cmdReadBufferReg()
+ return byte2int(stat[0])
+
+ def __busy(self):
+ return bool(self.__getStatusFlags() & self.STAT_BUSY)
+
+ def __busyWait(self):
+ for i in range(0, 100):
+ if not self.__busy():
+ return
+ self.top.hostDelay(0.01)
+ self.throwError("Timeout in busywait.")
+
+ChipDescription(
+ Chip_M2764A,
+ bitfile = "m2764a",
+ runtimeID = (0x0006, 0x01),
+ chipType = ChipDescription.TYPE_EPROM,
+ description = "M2764A EPROM",
+ maintainer = None,
+ packages = ( ("DIP28", ""), ),
+)
diff --git a/libtoprammer/chips/m8cissp.py b/libtoprammer/chips/m8cissp.py
new file mode 100644
index 0000000..975a5ea
--- /dev/null
+++ b/libtoprammer/chips/m8cissp.py
@@ -0,0 +1,457 @@
+"""
+# TOP2049 Open Source programming suite
+#
+# Cypress M8C In System Serial Programmer
+#
+# Copyright (c) 2010-2011 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.chip import *
+import time
+
+
+class Chip_M8C_ISSP(Chip):
+ ISSPCMD_POR = 1 # Perform a power-on-reset
+ ISSPCMD_PWROFF = 2 # Turn power off
+ ISSPCMD_EXEC = 3 # Do an "execute" transfer
+
+ STAT_BUSY0 = 0x01
+ STAT_BUSY1 = 0x02
+ STAT_ISSPSTATE = 0x1C
+ STAT_ISSPSTATE_SHIFT = 2
+ STAT_SDATA = 0x20
+
+ STRVEC_INIT1 = (
+ "1100101010000000000111",
+ "0000000000000000000000",
+ "0000000000000000000000",
+ "0000000000000000000000",
+ "0000000000000000000000",
+ "0000000000000000000000",
+ "1101111011100010000111",
+ "1101111101000000000111",
+ "1101111011100000000111",
+ "1101111011100010000111",
+ "1101111111000000100111",
+ "1101110001000000100111",
+ "1101110000000000011111",
+ "1101111011100000000111",
+ "1001111100000111010111",
+ "1001111100100000011111",
+ "1001111101101000000111",
+ "1001111110000000000111",
+ "1001111111001010110111",
+ "1001111110100000001111",
+ "1001111111100000001111",
+ "1001111111110000000111",
+ "1101111011100010000111",
+ "1101110001000000000111",
+ "1101111111000000000111",
+ "1101110000000000000111",
+ "1101111011100000000111",
+ "1101111010000000011111",
+ "1101111010100000000111",
+ "1101111011000000000111",
+ "1101111100000000000111",
+ "1101111100100110000111",
+ )
+
+ STRVEC_INIT2 = (
+ "1001111101000000000111",
+ "1101111000000000110111",
+ "1101111100000000000111",
+ "1101111111100010010111",
+ )
+
+ STRVEC_IDSETUP = (
+ "1101111011100010000111",
+ "1101110000000000010111",
+ "1101111011100010000111",
+ "1101111101000000000111",
+ "1101111011100000000111",
+ "1101111011100010000111",
+ "1101111111000000100111",
+ "1101110001000000100111",
+ "1101110000000000011111",
+ "1101111011100000000111",
+ "1001111100000111010111",
+ "1001111100100000011111",
+ "1001111101101000000111",
+ "1001111110000000000111",
+ "1001111111001010110111",
+ "1001111110100000001111",
+ "1001111111100000001111",
+ "1001111111110000000111",
+ "1101111011100010000111",
+ "1101110001000000000111",
+ "1101111111000000000111",
+ "1101110000000000000111",
+ "1101111011100000000111",
+ "1101111010000000011111",
+ "1101111010100000000111",
+ "1101111011000000000111",
+ "1101111100000000000111",
+ "1101111100100110000111",
+ "1001111101000000000111",
+ "1101111000000000110111",
+ "1101111100000000000111",
+ "1101111111100010010111",
+ )
+
+ STRVEC_READBYTE = (
+ "101aaaaaaaaZDDDDDDDDZ1",
+ )
+
+ STRVEC_WRITEBYTE = (
+ "100aaaaaaaadddddddd111",
+ )
+
+ STRVEC_ERASEALL = (
+ "1001111110000010101111",
+ "1001111111001010110111",
+ "1101111011100010000111",
+ "1101111101000000000111",
+ "1101111011100000000111",
+ "1101111011100010000111",
+ "1101111111000000100111",
+ "1101110001000000100111",
+ "1101110000000000011111",
+ "1101111011100000000111",
+ "1001111100000111010111",
+ "1001111100100000011111",
+ "1001111101101000000111",
+ "1001111110000000000111",
+ "1001111111001010110111",
+ "1001111110100000001111",
+ "1001111111100000001111",
+ "1001111111110000000111",
+ "1101111011100010000111",
+ "1101110001000000000111",
+ "1101111111000000000111",
+ "1101110000000000000111",
+ "1101111011100000000111",
+ "1101111010000000011111",
+ "1101111010100000000111",
+ "1101111011000000000111",
+ "1101111100000000000111",
+ "1101111100100110000111",
+ "1101111000000000101111",
+ "1101111100000000000111",
+ "1101111111100010010111",
+ )
+
+ STRVEC_SETBLKNUM = (
+ "10011111010dddddddd111",
+ )
+
+ STRVEC_READBLK = (
+ "1101111011100010000111",
+ "1101111101000000000111",
+ "1101111011100000000111",
+ "1101111011100010000111",
+ "1101111111000000100111",
+ "1101110001000000100111",
+ "1101110000000000011111",
+ "1101111011100000000111",
+ "1001111100000111010111",
+ "1001111100100000011111",
+ "1001111101101000000111",
+ "1001111110000000000111",
+ "1001111111001010110111",
+ "1001111110100000001111",
+ "1001111111100000001111",
+ "1001111111110000000111",
+ "1101111011100010000111",
+ "1101110001000000000111",
+ "1101111111000000000111",
+ "1101110000000000000111",
+ "1101111011100000000111",
+ "1101111010000000011111",
+ "1101111010100000000111",
+ "1101111011000000000111",
+ "1101111100000000000111",
+ "1101111100100110000111",
+ "1101111000000000001111",
+ "1101111100000000000111",
+ "1101111111100010010111",
+ )
+
+ STRVEC_WRITEBLK = (
+ "1001111110001010100111",
+ "1001111111001010110111",
+ "1101111011100010000111",
+ "1101111101000000000111",
+ "1101111011100000000111",
+ "1101111011100010000111",
+ "1101111111000000100111",
+ "1101110001000000100111",
+ "1101110000000000011111",
+ "1101111011100000000111",
+ "1001111100000111010111",
+ "1001111100100000011111",
+ "1001111101101000000111",
+ "1001111110000000000111",
+ "1001111111001010110111",
+ "1001111110100000001111",
+ "1001111111100000001111",
+ "1001111111110000000111",
+ "1101111011100010000111",
+ "1101110001000000000111",
+ "1101111111000000000111",
+ "1101110000000000000111",
+ "1101111011100000000111",
+ "1101111010000000011111",
+ "1101111010100000000111",
+ "1101111011000000000111",
+ "1101111100000000000111",
+ "1101111100100110000111",
+ "1101111000000000010111",
+ "1101111100000000000111",
+ "1101111111100010010111",
+ )
+
+ STRVEC_READCHKSUM = (
+ "10111111001ZDDDDDDDDZ1",
+ "10111111000ZDDDDDDDDZ1",
+ )
+
+ STRVEC_READID = (
+ "10111111000ZDDDDDDDDZ1",
+ "10111111001ZDDDDDDDDZ1",
+ )
+
+ def __init__(self):
+ Chip.__init__(self)
+# self.progmemSize = 1024 * 16
+ self.progmemSize = 256#XXX
+
+ def readSignature(self):
+ self.progressMeterInit("Reading chip ID", 0)
+ self.__powerOnReset()
+ gotID = self.__readID()
+ self.progressMeterFinish()
+
+ return int2byte(gotID & 0xFF) + int2byte((gotID >> 8) & 0xFF)
+
+ def erase(self):
+ self.progressMeterInit("Erasing chip", 0)
+ self.__powerOnReset()
+ self.__bitbangStringVectors(self.STRVEC_ERASEALL)
+ self.__runCommandSync(self.ISSPCMD_EXEC)
+ self.progressMeterFinish()
+
+ def writeProgmem(self, image):
+ if len(image) > self.progmemSize or len(image) % 64 != 0:
+ self.throwError("Invalid program memory image size %d "
+ "(expected <=%d and multiple of 64)" %\
+ (len(image), self.progmemSize))
+
+ self.progressMeterInit("Writing program memory", len(image))
+ self.__powerOnReset()
+ for blknum in range(0, len(image) // 64):
+ for i in range(0, 64):
+ self.progressMeter(blknum * 64 + i)
+ self.__writeByte(i, byte2int(image[blknum * 64 + i]))
+ vec = self.__stringVectorReplace(self.STRVEC_SETBLKNUM[0], "d", blknum)
+ self.__bitbangStringVector(vec)
+ self.__bitbangStringVectors(self.STRVEC_WRITEBLK)
+ self.__runCommandSync(self.ISSPCMD_EXEC)
+ self.progressMeterFinish()
+
+ def readProgmem(self):
+ self.progressMeterInit("Reading program memory", self.progmemSize)
+ self.__powerOnReset()
+ assert(self.progmemSize % 64 == 0)
+ image = []
+ for blknum in range(0, self.progmemSize // 64):
+ vec = self.__stringVectorReplace(self.STRVEC_SETBLKNUM[0], "d", blknum)
+ self.__bitbangStringVector(vec)
+ self.__bitbangStringVectors(self.STRVEC_READBLK)
+ self.__runCommandSync(self.ISSPCMD_EXEC)
+ for i in range(0, 64):
+ self.progressMeter(blknum * 64 + i)
+ image.append(int2byte(self.__readByte(i)))
+ #FIXME return_code
+ self.progressMeterFinish()
+ return b"".join(image)
+
+ def __powerDown(self):
+ "Turn the power to the device off"
+ self.printDebug("Powering device down...")
+ self.__runCommandSync(self.ISSPCMD_PWROFF)
+ self.top.hostDelay(5)
+
+ def __powerOnReset(self):
+ "Perform a complete power-on-reset and initialization"
+ self.top.vcc.setLayoutMask(0)
+ self.top.vpp.setLayoutMask(0)
+ self.top.gnd.setLayoutMask(0)
+ self.top.cmdSetVCCVoltage(5)
+ self.top.cmdSetVPPVoltage(5)
+
+ self.printDebug("Initializing supply power...")
+ self.top.gnd.setLayoutPins( (20,) )
+ self.top.vcc.setLayoutPins( (21,) )
+
+#FIXME when to do exec?
+ self.__powerDown()
+ self.printDebug("Performing a power-on-reset...")
+ self.__uploadStringVector(self.STRVEC_INIT1[0])
+ self.__runCommandSync(self.ISSPCMD_POR)
+ self.printDebug("Sending vector 1...")
+ self.__bitbangStringVectors(self.STRVEC_INIT1[1:])
+#XXX self.__runCommandSync(self.ISSPCMD_EXEC)
+ self.printDebug("Sending vector 2...")
+ self.__bitbangStringVectors(self.STRVEC_INIT2)
+ self.__runCommandSync(self.ISSPCMD_EXEC)
+
+ def __readID(self):
+ "Read the silicon ID"
+ self.__bitbangStringVectors(self.STRVEC_IDSETUP)
+ self.__runCommandSync(self.ISSPCMD_EXEC)
+
+ low = (self.__bitbangStringVector(self.STRVEC_READID[0]) >> 2) & 0xFF
+ high = (self.__bitbangStringVector(self.STRVEC_READID[1]) >> 2) & 0xFF
+
+ return low | (high << 8)
+
+ def __readByte(self, address):
+ vec = self.__stringVectorReplace(self.STRVEC_READBYTE[0], "a", address)
+ inputData = self.__bitbangStringVector(vec)
+ return (inputData >> 2) & 0xFF
+
+ def __writeByte(self, address, byte):
+ vec = self.__stringVectorReplace(self.STRVEC_WRITEBYTE[0], "a", address)
+ vec = self.__stringVectorReplace(vec, "d", byte)
+ self.__bitbangStringVector(vec)
+
+ def __loadCommand(self, command):
+ self.top.cmdFPGAWrite(0x11, command & 0xFF)
+
+ def __runCommandSync(self, command):
+ self.printDebug("Running synchronous command %d" % command)
+ self.__loadCommand(command)
+ self.__busyWait()
+
+ def __setBitbang(self, SDATA, SDATA_in, SCLK, SCLK_z):
+ value = 0
+ if SDATA:
+ value |= 0x01
+ if SDATA_in:
+ value |= 0x02
+ if SCLK:
+ value |= 0x04
+ if SCLK_z:
+ value |= 0x08
+ self.top.cmdFPGAWrite(0x10, value)
+
+ def __getStatusFlags(self):
+ self.top.cmdFPGARead(0x10)
+ stat = self.top.cmdReadBufferReg8()
+ isspState = (stat & self.STAT_ISSPSTATE) >> self.STAT_ISSPSTATE_SHIFT
+ sdata = bool(stat & self.STAT_SDATA)
+ isBusy = bool(stat & self.STAT_BUSY0) != bool(stat & self.STAT_BUSY1)
+ self.printDebug("isspState = 0x%02X, isBusy = %d, busyFlags = 0x%01X, sdata = %d" %\
+ (isspState, isBusy, (stat & (self.STAT_BUSY0 | self.STAT_BUSY1)), sdata))
+ return (isBusy, sdata, isspState)
+
+ def __busy(self):
+ (isBusy, sdata, isspState) = self.__getStatusFlags()
+ return isBusy
+
+ def __getSDATA(self):
+ (isBusy, sdata, isspState) = self.__getStatusFlags()
+ return int(sdata)
+
+ def __busyWait(self):
+ for i in range(0, 200):
+ if not self.__busy():
+ return
+ self.top.hostDelay(0.01)
+ self.throwError("Timeout in busywait. Chip not responding?")
+
+ def __stringVectorToBinary(self, vector):
+ binary = 0
+ inputMask = 0
+ assert(len(vector) == 22)
+ bit = len(vector) - 1
+ for b in vector:
+ if b == "1":
+ binary |= (1 << bit)
+ elif b == "0":
+ pass
+ elif b == "H" or b == "L" or b == "Z" or b == "D":
+ inputMask |= (1 << bit)
+ else:
+ assert(0)
+ bit -= 1
+ return (binary, inputMask)
+
+ def __stringVectorReplace(self, strVec, replace, data):
+ ret = ""
+ for i in range(len(strVec) - 1, -1, -1):
+ b = strVec[i]
+ if b == replace:
+ if (data & 1):
+ ret = "1" + ret
+ else:
+ ret = "0" + ret
+ data >>= 1
+ else:
+ ret = b + ret
+ return ret
+
+ def __bitbangStringVector(self, strVec):
+ vectorSize = len(strVec)
+ (vector, inputMask) = self.__stringVectorToBinary(strVec)
+ inputData = 0
+ self.__setBitbang(SDATA=0, SDATA_in=1, SCLK=0, SCLK_z=0)
+ for i in range(vectorSize - 1, -1, -1):
+ if inputMask & (1 << i):
+ self.__setBitbang(SDATA=0, SDATA_in=1, SCLK=1, SCLK_z=0)
+ self.__setBitbang(SDATA=0, SDATA_in=1, SCLK=0, SCLK_z=0)
+ self.top.cmdDelay(0.000001)
+ sdata = self.__getSDATA()
+ inputData |= (sdata << i)
+ else:
+ self.__setBitbang(SDATA=(vector & (1 << i)), SDATA_in=0,
+ SCLK=1, SCLK_z=0)
+ self.__setBitbang(SDATA=0, SDATA_in=0, SCLK=0, SCLK_z=0)
+ self.top.cmdDelay(0.000001)
+ return inputData
+
+ def __bitbangStringVectors(self, strVecList):
+ for strVec in strVecList:
+ self.__bitbangStringVector(strVec)
+
+ def __uploadStringVector(self, strVec):
+ (vector, inputMask) = self.__stringVectorToBinary(strVec)
+ assert(inputMask == 0)
+ self.top.cmdFPGAWrite(0x12, vector & 0xFF)
+ self.top.cmdFPGAWrite(0x13, (vector >> 8) & 0xFF)
+ self.top.cmdFPGAWrite(0x14, (vector >> 8) & 0xFF)
+
+ChipDescription(
+ Chip_M8C_ISSP,
+ bitfile = "m8c-issp",
+ runtimeID = (0x0007, 0x01),
+ chipVendors = "Cypress",
+ description = "M8C In System Serial Programmer",
+ packages = ( ("M8C ISSP header", "Special adapter"), ),
+ comment = "Special adapter required",
+ broken = True
+)
diff --git a/libtoprammer/chips/unitest.py b/libtoprammer/chips/unitest.py
new file mode 100644
index 0000000..9f4cf87
--- /dev/null
+++ b/libtoprammer/chips/unitest.py
@@ -0,0 +1,171 @@
+"""
+# TOP2049 Open Source programming suite
+#
+# Universal device tester
+#
+# Copyright (c) 2010 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.chip import *
+
+
+class Chip_Unitest(Chip):
+ def __init__(self, chipPackage=None, chipPinVCC=None, chipPinsVPP=None, chipPinGND=None,
+ VCCVoltage=None, VPPVoltage=None):
+ Chip.__init__(self, chipPackage=chipPackage, chipPinVCC=chipPinVCC,
+ chipPinsVPP=chipPinsVPP, chipPinGND=chipPinGND)
+ self.autogenVCCVoltage = VCCVoltage
+ self.autogenVPPVoltage = VPPVoltage
+
+ def shutdownChip(self):
+ self.printDebug("Shutdown chip")
+ self.reset()
+
+ def reset(self):
+ self.top.vcc.setLayoutPins( [] )
+ self.vccMask = 0
+ self.top.vpp.setLayoutPins( [] )
+ self.vppMask = 0
+ self.top.gnd.setLayoutPins( [] )
+ self.gndMask = 0
+ self.top.cmdSetVCCVoltage(self.top.vcc.minVoltage())
+ self.top.cmdSetVPPVoltage(self.top.vpp.minVoltage())
+ self.oscMask = 0
+ self.setOutputEnableMask(0)
+ self.setOutputs(0)
+ self.setOscMask(0)
+ self.top.flushCommands()
+
+ def setVCC(self, voltage, layout):
+ self.vccMask = self.top.vcc.ID2mask(layout)
+ self.__updateOutEn()
+ self.top.cmdSetVCCVoltage(voltage)
+ self.top.vcc.setLayoutID(layout)
+ self.top.flushCommands()
+
+ def setVPP(self, voltage, layouts):
+ self.vppMask = 0
+ for layout in layouts:
+ self.vppMask |= self.top.vpp.ID2mask(layout)
+ self.__updateOutEn()
+ self.top.cmdSetVPPVoltage(voltage)
+ self.top.vpp.setLayoutMask(0) # Reset
+ for layout in layouts:
+ self.top.vpp.setLayoutID(layout)
+ self.top.flushCommands()
+
+ def setGND(self, layout):
+ self.gndMask = self.top.gnd.ID2mask(layout)
+ self.__updateOutEn()
+ self.top.gnd.setLayoutID(layout)
+ self.top.flushCommands()
+
+ # Overloaded layout generator interface.
+ def applyVCC(self, turnOn):
+ layoutID = 0
+ if turnOn:
+ (layoutID, layoutMask) = self.generator.getVCCLayout()
+ self.setVCC(self.autogenVCCVoltage, layoutID)
+
+ # Overloaded layout generator interface.
+ def applyVPP(self, turnOn, packagePinsToTurnOn=[]):
+ assert(not packagePinsToTurnOn) # Not supported, yet.
+ layouts = []
+ if turnOn:
+ layouts = map(lambda (layoutID, layoutMask): layoutID,
+ self.generator.getVPPLayouts())
+ self.setVPP(self.autogenVPPVoltage, layouts)
+
+ # Overloaded layout generator interface.
+ def applyGND(self, turnOn):
+ layoutID = 0
+ if turnOn:
+ (layoutID, layoutMask) = self.generator.getGNDLayout()
+ self.setGND(layoutID)
+
+ def __updateOutEn(self):
+ mask = self.desiredOutEnMask
+ mask &= ~self.gndMask
+ mask &= ~self.vccMask
+ mask &= ~self.vppMask
+ mask |= self.oscMask
+ self.top.cmdFPGAWrite(0x50, mask & 0xFF)
+ self.top.cmdFPGAWrite(0x51, (mask >> 8) & 0xFF)
+ self.top.cmdFPGAWrite(0x52, (mask >> 16) & 0xFF)
+ self.top.cmdFPGAWrite(0x53, (mask >> 24) & 0xFF)
+ self.top.cmdFPGAWrite(0x54, (mask >> 32) & 0xFF)
+ self.top.cmdFPGAWrite(0x55, (mask >> 40) & 0xFF)
+ self.top.flushCommands()
+
+ def setOutputEnableMask(self, mask):
+ self.desiredOutEnMask = mask
+ self.__updateOutEn()
+
+ def __updateOut(self):
+ mask = self.desiredOutMask
+ mask &= ~self.oscMask
+ self.top.cmdFPGAWrite(0x70, mask & 0xFF)
+ self.top.cmdFPGAWrite(0x71, (mask >> 8) & 0xFF)
+ self.top.cmdFPGAWrite(0x72, (mask >> 16) & 0xFF)
+ self.top.cmdFPGAWrite(0x73, (mask >> 24) & 0xFF)
+ self.top.cmdFPGAWrite(0x74, (mask >> 32) & 0xFF)
+ self.top.cmdFPGAWrite(0x75, (mask >> 40) & 0xFF)
+ self.top.flushCommands()
+
+ def setOutputs(self, mask):
+ self.desiredOutMask = mask
+ self.__updateOut()
+
+ def getInputs(self):
+ self.top.cmdFPGARead(0x30)
+ self.top.cmdFPGARead(0x31)
+ self.top.cmdFPGARead(0x32)
+ self.top.cmdFPGARead(0x33)
+ self.top.cmdFPGARead(0x34)
+ self.top.cmdFPGARead(0x35)
+ inputs = self.top.cmdReadBufferReg48()
+ return inputs
+
+ def getOscFreq(self):
+ return self.top.getOscillatorHz()
+
+ def setOscDivider(self, div):
+ self.top.cmdFPGAWrite(0x12, div & 0xFF)
+ self.top.cmdFPGAWrite(0x13, (div >> 8) & 0xFF)
+ self.top.cmdFPGAWrite(0x14, (div >> 16) & 0xFF)
+ self.top.cmdFPGAWrite(0x15, (div >> 24) & 0xFF)
+ self.top.flushCommands()
+
+ def setOscMask(self, mask):
+ self.oscMask = mask
+ self.top.cmdFPGAWrite(0x30, mask & 0xFF)
+ self.top.cmdFPGAWrite(0x31, (mask >> 8) & 0xFF)
+ self.top.cmdFPGAWrite(0x32, (mask >> 16) & 0xFF)
+ self.top.cmdFPGAWrite(0x33, (mask >> 24) & 0xFF)
+ self.top.cmdFPGAWrite(0x34, (mask >> 32) & 0xFF)
+ self.top.cmdFPGAWrite(0x35, (mask >> 40) & 0xFF)
+ self.__updateOutEn()
+ self.__updateOut()
+ self.top.flushCommands()
+
+ChipDescription(
+ Chip_Unitest,
+ bitfile = "unitest",
+ runtimeID = (0x0008, 0x01),
+ chipType = ChipDescription.TYPE_INTERNAL,
+ description = "Universal device tester",
+)
diff --git a/libtoprammer/chips/w29ee011dip32.py b/libtoprammer/chips/w29ee011dip32.py
new file mode 100644
index 0000000..0948c0f
--- /dev/null
+++ b/libtoprammer/chips/w29ee011dip32.py
@@ -0,0 +1,254 @@
+"""
+# TOP2049 Open Source programming suite
+#
+# Winbond W29EE011 DIP32
+# Winbond W29EE011 PLCC32 (inside 1:1 PLCC32->DIP32 adapter)
+#
+# Copyright (c) 2010 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.chip import *
+
+
+class Chip_w29ee011dip32(Chip):
+ PROGCMD_WRITEBUF = 1 # Write buffer to chip
+
+ STAT_BUSY = 0x01 # Programmer is running a command
+
+ def __init__(self):
+ Chip.__init__(self,
+ chipPackage = "DIP32",
+ chipPinVCC = 32,
+ chipPinsVPP = None,
+ chipPinGND = 16)
+
+ def erase(self):
+ self.applyVCC(True)
+ self.applyVPP(True)
+ self.applyGND(True)
+
+ commands = (
+ (0x5555, 0xAA),
+ (0x2AAA, 0x55),
+ (0x5555, 0x80),
+ (0x5555, 0xAA),
+ (0x2AAA, 0x55),
+ (0x5555, 0x10),
+ )
+
+ self.progressMeterInit("Erasing chip", 0)
+ self.__setCEOE(CE=0, OE=1)
+
+ self.__resetBufferPointers()
+ self.__swDataProtect(False)
+ self.__runCommandSync(self.PROGCMD_WRITEBUF)
+ self.top.hostDelay(0.05)
+ self.__resetBufferPointers()
+ for command in commands:
+ self.__appendJEDEC(command[0], command[1])
+ self.__runCommandSync(self.PROGCMD_WRITEBUF)
+ self.top.hostDelay(0.05)
+
+ self.__setCEOE(CE=1, OE=1)
+ self.progressMeterFinish()
+
+ def readEEPROM(self):
+ self.applyVCC(True)
+ self.applyVPP(True)
+ self.applyGND(True)
+
+ self.progressMeterInit("Reading EEPROM", 0x20000)
+ self.__setCEOE(CE=0, OE=0)
+ image = self.__readRange(0, 0x20000, progress=True)
+ self.__setCEOE(CE=1, OE=1)
+ self.progressMeterFinish()
+
+ return image
+
+ def __readRange(self, baseAddress, size, progress=False):
+ image = ""
+ byteCount = 0
+ prevAddr = baseAddress
+ self.__loadReadAddrLo(baseAddress)
+ self.__loadReadAddrMed(baseAddress >> 8)
+ self.__loadReadAddrHi(baseAddress >> 16)
+ for offset in range(0, size):
+ addr = baseAddress + offset
+ if progress:
+ self.progressMeter(addr)
+ if (addr & 0xFF) != (prevAddr & 0xFF):
+ self.__loadReadAddrLo(addr)
+ if (addr & 0xFF00) != (prevAddr & 0xFF00):
+ self.__loadReadAddrMed(addr >> 8)
+ if (addr & 0xFF0000) != (prevAddr & 0xFF0000):
+ self.__loadReadAddrHi(addr >> 16)
+ prevAddr = addr
+ self.top.cmdFPGARead(0x10)
+ byteCount += 1
+ if byteCount == self.top.getBufferRegSize():
+ image += self.top.cmdReadBufferReg(byteCount)
+ byteCount = 0
+ image += self.top.cmdReadBufferReg(byteCount)
+ return image
+
+ def writeEEPROM(self, image):
+ if len(image) > 0x20000:
+ self.throwError("Invalid EPROM image size %d (expected <=%d)" %\
+ (len(image), 0x20000))
+
+ self.applyVCC(True)
+ self.applyVPP(True)
+ self.applyGND(True)
+
+ self.progressMeterInit("Writing EEPROM", len(image))
+ self.__setCEOE(CE=0, OE=1)
+ for addr in range(0, len(image), 128):
+ self.progressMeter(addr)
+ pagelen = min(128, len(image) - addr)
+ page = image[addr:addr+pagelen]
+ self.__writePage(addr, page)
+ self.__setCEOE(CE=1, OE=1)
+ self.progressMeterFinish()
+
+ def __swDataProtect(self, enable):
+ if enable:
+ jedecCommands = (
+ (0x5555, 0xAA),
+ (0x2AAA, 0x55),
+ (0x5555, 0xA0),
+ )
+ else:
+ jedecCommands = (
+ (0x5555, 0xAA),
+ (0x2AAA, 0x55),
+ (0x5555, 0x80),
+ (0x5555, 0xAA),
+ (0x2AAA, 0x55),
+ (0x5555, 0x20),
+ )
+ for command in jedecCommands:
+ self.__appendJEDEC(command[0], command[1])
+
+ def __writePage(self, pageAddress, pageData):
+ for t in range(0, 15):
+ self.__resetBufferPointers()
+ self.__swDataProtect(True)
+ assert(len(pageData) <= 128)
+ for byte in pageData:
+ self.__writeBufAppend(byte2int(byte))
+ self.__loadWriteAddr(pageAddress)
+ self.__runCommandSync(self.PROGCMD_WRITEBUF)
+ self.top.hostDelay(0.01)
+ # Verify
+ self.__setCEOE(CE=0, OE=0)
+ verifyImage = self.__readRange(pageAddress, len(pageData))
+ self.__setCEOE(CE=0, OE=1)
+ if verifyImage == pageData:
+ break
+ self.top.hostDelay(0.1)
+ else:
+ self.throwError("Verify error on page write at address 0x%05X" % pageAddress)
+
+ def __writeBufAppend(self, byte):
+ # This also auto-increments the write buffer pointer
+ self.top.cmdFPGAWrite(0x10, byte & 0xFF)
+
+ def __resetBufferPointers(self):
+ self.top.cmdFPGAWrite(0x13, 0)
+
+ def __loadCommand(self, command):
+ self.top.cmdFPGAWrite(0x12, command & 0xFF)
+
+ def __runCommandSync(self, command):
+ self.__loadCommand(command)
+ self.__busyWait()
+
+ def __loadWriteAddr(self, addr):
+ self.__loadWriteAddrLo(addr)
+ self.__loadWriteAddrMed(addr >> 8)
+ self.__loadWriteAddrHi(addr >> 16)
+
+ def __loadWriteAddrLo(self, addrLo):
+ self.top.cmdFPGAWrite(0x14, addrLo & 0xFF)
+
+ def __loadWriteAddrMed(self, addrMed):
+ self.top.cmdFPGAWrite(0x15, addrMed & 0xFF)
+
+ def __loadWriteAddrHi(self, addrHi):
+ self.top.cmdFPGAWrite(0x16, addrHi & 0xFF)
+
+ def __loadReadAddrLo(self, addrLo):
+ self.top.cmdFPGAWrite(0x17, addrLo & 0xFF)
+
+ def __loadReadAddrMed(self, addrMed):
+ self.top.cmdFPGAWrite(0x18, addrMed & 0xFF)
+
+ def __loadReadAddrHi(self, addrHi):
+ self.top.cmdFPGAWrite(0x19, addrHi & 0xFF)
+
+ def __setCEOE(self, CE, OE):
+ data = 0
+ if CE:
+ data |= 0x01
+ if OE:
+ data |= 0x02
+ self.top.cmdFPGAWrite(0x1A, data)
+
+ def __appendJEDEC(self, addr, data):
+ self.__loadJEDECAddrLo(addr)
+ self.__loadJEDECAddrMed(addr >> 8)
+ self.__loadJEDECAddrHi(addr >> 16)
+ self.__loadJEDECData(data)
+
+ def __loadJEDECAddrLo(self, addrLo):
+ self.top.cmdFPGAWrite(0x1B, addrLo & 0xFF)
+
+ def __loadJEDECAddrMed(self, addrMed):
+ self.top.cmdFPGAWrite(0x1C, addrMed & 0xFF)
+
+ def __loadJEDECAddrHi(self, addrHi):
+ self.top.cmdFPGAWrite(0x1D, addrHi & 0xFF)
+
+ def __loadJEDECData(self, data):
+ # This also auto-increments the JEDEC buffer pointer
+ self.top.cmdFPGAWrite(0x1E, data & 0xFF)
+
+ def __getStatusFlags(self):
+ self.top.cmdFPGARead(0x12)
+ stat = self.top.cmdReadBufferReg()
+ return byte2int(stat[0])
+
+ def __busy(self):
+ return bool(self.__getStatusFlags() & self.STAT_BUSY)
+
+ def __busyWait(self):
+ for i in range(0, 100):
+ if not self.__busy():
+ return
+ self.top.hostDelay(0.01)
+ self.throwError("Timeout in busywait.")
+
+ChipDescription(
+ Chip_w29ee011dip32,
+ bitfile = "w29ee011dip32",
+ runtimeID = (0x0009, 0x01),
+ chipType = ChipDescription.TYPE_EEPROM,
+ chipVendors = "Winbond",
+ description = "W29EE011 EEPROM",
+ packages = ( ("DIP32", ""), ("PLCC32", "Use 1:1 PLCC32->DIP32 adapter"), ),
+ broken = True,
+)
bues.ch cgit interface