from sys import argv from time import sleep from RPi.GPIO import IN, OUT import RPi.GPIO as GPIO from re import fullmatch # EEPROM AT28C256 Pin names and RPi GPIO Pin Numbers # b means bar = inverted gpio_l = [2, 3, 4, 17, 27, 22, 10, 9, 11, 5, 6, 13, 19, 26] gpio_r = [14, 15, 18, 23, 24, 25, 8, 7, 12, 16, 20, 21] # # Defining which 6502 pin goes to which GPIO pin # A = [27, 22, 10, 9, 11, 5, 6, 13, 17, 4, 3, 2, 23, 18, 15] IO = gpio_r[4:12] # 8 io pins IO.reverse() OEb = 26 # Output Enable WEb = 19 # Write Enable CEb = 14 # Chip Enable is hooked up to A15 on the processor controls = [CEb, WEb, OEb] # TIMES # Read: t_ACC = 150 * 1e-9 # Address to Output Delay # Write: t_AS = 0 # Address Setup time t_AH = 50 * 1e-9 # Address Hold Time t_CS = 0 # Chip Select Hold Time t_WP = 100 * 1e-9 # Write Pulse Width t_DS = 50 * 1e-9 # Data Setup Time_CS = 0 t_DH = 0 # Data Hold Time t_WPH = 50 * 1e-9 # Write Puls High # t_WPH = 50 * 1e-4 # Write Pulse High !!!2*e5 longer than in Datasheet, since shorter high caused Problems with my Chip!!! # setup the pins GPIO.setmode(GPIO.BCM) for pin in controls: GPIO.setup(pin, OUT, initial=1) # inverted, is 1 means disable for pin in A: GPIO.setup(pin, OUT, initial=0) def setup_pins(IOdirection=OUT): # OUT when writing and IN when reading for pin in IO: GPIO.setup(pin, IOdirection) def print_pins(): for i in range(len(A)): print(f"A{i} - {A[i]}") for i in range(len(IO)): print(f"IO{i} - {IO[i]}") print(f"CEb - {CEb}") print(f"WEb - {WEb}") print(f"OEb - {OEb}") def set_address(address: int, bits=8): """ set the address pins to the given value """ ad_bin = format(address, f"0{bits}b") # get the x-bit verion if the address, eg 12 -> 00001100 for j in range(bits): # print("Address:", address, ad_bin, j) if ad_bin[bits-1-j] == "0": GPIO.output(A[j], 0) elif ad_bin[bits-1-j] == "1": GPIO.output(A[j], 1) return ad_bin def get_bits(i: int): """ return how many bits are needed to express the number in binary """ return len(bin(i)) - 2 # -2 for the "0x" def check_valid_list(l: list, bits=8): """ check if the list only has x-bit binary numbers """ for line in l: if not fullmatch("[01]{8}", line): return False return True def get_8_bit(l: list): for i in range(len(l)): l[i] = format(l[i], f"08b") # get the 8-bit bin value return l def erase(from_ad=0, to_ad=32767, **keys): """ Write all 1 to the EEPROM WEb controlled """ data = [0xff for i in range(from_ad, to_ad)] write(data, from_ad=from_ad, **keys) print("Erased EEPROM - Done!") return def write_byte(byte, address, verbose=True): GPIO.output(OEb, 1) # setup the address ad_bin = set_address(address, bits=15) setup_pins(OUT) # Setup Data for j in range(8): if byte[7-j] == "1": bit = 1 else: bit = 0 GPIO.output(IO[j], bit) # wait "Address" Setup Time sleep(t_AS) # wait "Data Setup Time" sleep(t_DS) GPIO.output(CEb, 0) # Start the write pulse -> enable WEb GPIO.output(WEb, 0) # wait until minimum write pulse width is reached. in theory, should be t_WP-t_DS but this caused problems sleep(t_WP) # End Write Pulse -> disable WEb GPIO.output(WEb, 1) GPIO.output(CEb, 1) # wait "Data Hold" sleep(t_DH) GPIO.output(CEb, 0) GPIO.cleanup(IO) setup_pins(IN) # check the toggle bit IO6, if it stops toggling the write is done timeout = 0 while timeout < 1e3: GPIO.output(OEb, 0) sleep(1e-9) bit1 = GPIO.input(IO[6]) GPIO.output(OEb, 1) sleep(1e-9) GPIO.output(OEb, 0) sleep(1e-9) bit2 = GPIO.input(IO[6]) GPIO.output(OEb, 1) sleep(1e-9) if bit1 == bit2: timeout = 1e3 timeout += 1 GPIO.output(CEb, 1) if verbose: print(f"Writing:\t0b{format(address, '015b')} - 0b{byte} ||| 0x{format(address, '04x')} - {hex(int(byte, 2))}") def read_byte(address): GPIO.output(WEb, 1) setup_pins(IN) # set the address valid ad_bin = set_address(address, bits=15) # low in chip/output enable -> enable GPIO.output(CEb, 0) GPIO.output(OEb, 0) # wait the "Address to Output Delay" until the output is valid sleep(t_ACC) byte = "" for j in range(8): if GPIO.input(IO[7-j]) == 1: byte += "1" else: byte += "0" # high in OEb and CEb -> disable GPIO.output(OEb, 1) GPIO.output(CEb, 1) return int(byte, 2) def read(from_ad=0, to_ad=255, delay=1e-3, ignore=[0xff], verbose=True, single_step=False, compare=None): """ from_ad: start address from where to read to_ad: end address to read to delay: delay between readings in s verbose wether to print the reading ignore list of values which are not printed """ content = [] unequal = [] for i in range(from_ad, to_ad + 1): byte = read_byte(i) content.append(byte) if not compare and verbose and not byte in ignore: print(f"Reading:\t0b{format(i, '015b')} - 0b{format(byte, '08b')} ||| 0x{format(i, '04x')} - 0x{format(byte, '02x')}") elif compare: if not compare[i] == byte: unequal.append(i) print(f"Unequal at Address 0x{format(i, '04x')} ||| File: 0x{format(compare[i], '02x')} vs EEPROM: 0x{format(byte, '02x')}") # wait artifical delay sleep(delay) if single_step: input("Press Return to read the next byte") if compare: return unequal return content def write(content: list, from_ad=0, delay=0, single_step=False, verbose=True, check_written=True): """ Write a list if bytes to the eeprom. WEb controlled """ or_content = content.copy() content = get_8_bit(content) failed = [] print(f"Writing to EEPROM: {len(content)} bytes from address {hex(from_ad)}.") for i in range(len(content)): write_byte(content[i], from_ad + i, verbose=verbose) # wait artifical delay sleep(delay) if single_step: input("Press Return to write the next byte") print("Write to EEPROM - Done!") if check_written: print("Comparing EEPROM to file...") failed = read(from_ad=from_ad, delay=delay, single_step=single_step, verbose=False, compare=or_content) while len(failed) > 0: for ad in failed: write_byte(content[ad], ad, verbose=verbose) failed = read(from_ad=from_ad, delay=delay, single_step=single_step, verbose=False, compare=or_content) print("Comparing complete") return def get_bytes(filepath, from_ad=0): with open(filepath, "rb") as file: bindata = [] for byte in file.read(): bindata.append(byte) return bindata[from_ad:] action = None file = None from_ad = 0 to_ad = 32767 #2^15 -1 delay = 0 single_step = False verbose = False ignore = [0xff] content = [] if len(argv) > 1: for i in range(1, len(argv)): arg = argv[i] if argv[i-1] == "-w": action = "write_file" file = arg elif argv[i-1] == "-wh": action = "write_hex" content = arg.split(",") for i in range(len(content)): content[i] = int(content[i].replace("0x", ""), 16) elif arg == "-r": action = "read" verbose = True elif argv[i-1] == "-c": action = "compare" file = arg verbose = True elif arg == "-e": action = "erase" elif arg == "-h": action = "help" # Addresses elif argv[i-1] == "--from": if "0x" in arg: from_ad = int(arg.replace("0x", ""), 16) else: from_ad = int(arg) elif argv[i-1] == "--to": if "0x" in arg: to_ad = int(arg.replace("0x", ""), 16) else: to_ad = int(arg) # options elif argv[i-1] == "--delay": delay = float(arg) elif arg == "--single_step": single_step = True elif arg == "--verbose": verbose = True elif argv[i-1] == "--ignore": ignore = arg.split(",") for i in range(len(ignore)): ignore[i] = int(ignore[i].replace("0x", ""), 16) # print(action, file, from_ad, to_ad) if action == "write_file": write(get_bytes(file, from_ad=from_ad), from_ad=from_ad, delay=delay, single_step=single_step, verbose=verbose) elif action == "write_hex": write(content, from_ad=from_ad, delay=delay, single_step=single_step, verbose=verbose) elif action == "read": read(from_ad=from_ad, to_ad=to_ad, delay=delay, single_step=single_step, verbose=verbose, ignore=ignore) elif action == "compare": read(from_ad=from_ad, to_ad=to_ad, delay=delay, single_step=single_step, verbose=verbose, ignore=ignore, compare=get_bytes(file)) elif action == "erase": erase(from_ad=from_ad, to_ad=to_ad, delay=delay, single_step=single_step, verbose=verbose) elif action == "help": print(""" program options: -w file write file -e erase EEPROM -c compare EEPROM content to binary file -r read EEPROM -h print this --from x start at address x (can be int or hex with '0x' prefix)) --to y end at address y --single_step single step the program --delay t extra delay t between cycles --verbose print extra information --ignore a,b,.. ignore the numbers a,b,... (in hex) when printing. Default is 0xff if no option is given the GPIO-Pin-settings are printed """) else: print("No valid action given. Printing Pin-Settings") print_pins() # if performing action from this script, put the code HERE: GPIO.cleanup()