""" # TOP2049 Open Source programming suite # # M24C16 I2C based serial EEPROM # # Copyright (c) 2011-2017 Michael Buesch # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. """ from libtoprammer.chip import * class Chip_m24cXXdip8_common(Chip): I2C_BASE_ADDR = 0x50 << 1 I2C_READ = 0x01 I2C_WRITE = 0x00 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 self.currentWriteMode = None def erase(self): self.writeEEPROM("\xFF" * self.eepromSize) def readEEPROM(self): self.__chipTurnOn() image = "" 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.__setAddressExtension(addr, writeMode=False) # Begin sequential random read self.__runI2C(data=self.I2C_BASE_ADDR | self.currentAddrExt | self.I2C_WRITE, read=False, do_start=True, do_stop=False) self.__expectACK() self.__runI2C(data=addr & 0xFF, read=False, do_start=False, do_stop=False) self.__expectACK() self.__runI2C(data=self.I2C_BASE_ADDR | self.currentAddrExt | self.I2C_READ, read=False, do_start=True, do_stop=False) self.__expectACK() prevAddr = addr # Sequential random read if addr >= self.eepromSize - 1: # Last byte self.__runI2C(read=True, do_start=False, do_stop=True) self.__expectNACK() else: self.__runI2C(read=True, do_start=False, do_stop=False, drive_ack=True) self.__expectACK() self.__readData() image += self.top.cmdReadBufferReg(1) 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) if prevAddr is None or (prevAddr & 0xFFF0) != (addr & 0xFFF0): self.__setAddressExtension(addr, writeMode=True) self.__runI2C(data=self.I2C_BASE_ADDR | self.currentAddrExt | self.I2C_WRITE, read=False, do_start=True, do_stop=False) self.__expectACK() self.__runI2C(data=addr & 0xFF, read=False, do_start=False, do_stop=False) self.__expectACK() prevAddr = addr if (addr & 0xF) == 0xF: self.__runI2C(data=byte2int(image[addr]), read=False, do_start=False, do_stop=True) self.__expectACK() self.top.cmdDelay(0.005) # Max write time else: self.__runI2C(data=byte2int(image[addr]), read=False, do_start=False, do_stop=False) self.__expectACK() self.progressMeterFinish() def __readData(self): self.top.cmdFPGARead(0) def __setData(self, dataByte): self.top.cmdFPGAWrite(1, dataByte & 0xFF) def __setAddressExtension(self, address, writeMode): sizeMask = self.eepromSize - 1 assert(sizeMask & ~0x7FF == 0) addrExt = ((address & 0x700 & sizeMask) >> 8) << 1 if self.currentWriteMode != writeMode: E0 = E1 = E2 = 0 E0_en = not (sizeMask & 0x0100) E1_en = not (sizeMask & 0x0200) E2_en = not (sizeMask & 0x0400) WC = not writeMode self.__setControlPins(E0=E0, E0_en=E0_en, E1=E1, E1_en=E1_en, E2=E2, E2_en=E2_en, WC=WC) self.currentAddrExt = addrExt self.currentWriteMode = writeMode def __runI2C(self, data=None, read=False, do_start=False, do_stop=False, drive_ack=False): if data is not None: self.__setData(data) else: self.__setData(0) command = (0x01 if read else 0) |\ (0x02 if do_start else 0) |\ (0x04 if do_stop else 0) |\ (0x08 if drive_ack else 0) self.top.cmdFPGAWrite(0, command) self.__busyWait() def __isBusy(self): (busy, ack) = self.__getStatusFlags() return busy 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(1) stat = self.top.cmdReadBufferReg8() busy = bool(stat & 0x01) ack = not bool(stat & 0x02) self.lastAck = ack return (busy, ack) def __expectACK(self): if not self.lastAck: self.throwError("Expected I2C ACK, but received NACK") def __expectNACK(self): if self.lastAck: self.throwError("Expected I2C NACK, but received ACK") 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(2, 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", )