use argparse
This commit is contained in:
parent
df08c72d1f
commit
824ecec13d
196
eeprom.py
Normal file → Executable file
196
eeprom.py
Normal file → Executable file
@ -1,8 +1,11 @@
|
|||||||
from sys import argv
|
#!/bin/env python3
|
||||||
|
from sys import exit
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from RPi.GPIO import IN, OUT
|
from RPi.GPIO import IN, OUT
|
||||||
import RPi.GPIO as GPIO
|
import RPi.GPIO as GPIO
|
||||||
from re import fullmatch
|
from re import fullmatch
|
||||||
|
import argparse
|
||||||
|
import atexit
|
||||||
# EEPROM AT28C256 Pin names and RPi GPIO Pin Numbers
|
# EEPROM AT28C256 Pin names and RPi GPIO Pin Numbers
|
||||||
# b means bar = inverted
|
# b means bar = inverted
|
||||||
|
|
||||||
@ -13,12 +16,16 @@ gpio_r = [14, 15, 18, 23, 24, 25, 8, 7, 12, 16, 20, 21]
|
|||||||
# Defining which 6502 pin goes to which GPIO pin
|
# Defining which 6502 pin goes to which GPIO pin
|
||||||
#
|
#
|
||||||
|
|
||||||
A = [27, 22, 10, 9, 11, 5, 6, 13,
|
A = [
|
||||||
17, 4, 3, 2,
|
# 27, 22, 10, 9, 11, 5, 6, 13,
|
||||||
23, 18, 15]
|
13, 6, 5, 11, 9, 10, 22, 27, # A0 - A7
|
||||||
|
2, 3, 4, 17, # A8 - A11
|
||||||
|
23, 18, 15 # A12 - A14
|
||||||
|
]
|
||||||
|
|
||||||
IO = gpio_r[4:12] # 8 io pins
|
# IO = gpio_r[4:12] # 8 io pins
|
||||||
IO.reverse()
|
# IO.reverse()
|
||||||
|
IO = [ 24, 25, 8, 7, 12, 16, 20, 21 ]
|
||||||
|
|
||||||
OEb = 26 # Output Enable
|
OEb = 26 # Output Enable
|
||||||
WEb = 19 # Write Enable
|
WEb = 19 # Write Enable
|
||||||
@ -40,28 +47,33 @@ t_DH = 0 # Data Hold Time
|
|||||||
t_WPH = 50 * 1e-9 # Write Puls High
|
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!!!
|
# 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:
|
def setup_address_control_pins():
|
||||||
|
# setup the pins
|
||||||
|
GPIO.setmode(GPIO.BCM)
|
||||||
|
for pin in controls:
|
||||||
GPIO.setup(pin, OUT, initial=1) # inverted, is 1 means disable
|
GPIO.setup(pin, OUT, initial=1) # inverted, is 1 means disable
|
||||||
for pin in A:
|
for pin in A:
|
||||||
GPIO.setup(pin, OUT, initial=0)
|
GPIO.setup(pin, OUT, initial=0)
|
||||||
|
|
||||||
|
def setup_io_pins(IOdirection=OUT):
|
||||||
def setup_pins(IOdirection=OUT):
|
|
||||||
# OUT when writing and IN when reading
|
# OUT when writing and IN when reading
|
||||||
for pin in IO:
|
for pin in IO:
|
||||||
GPIO.setup(pin, IOdirection)
|
GPIO.setup(pin, IOdirection)
|
||||||
|
|
||||||
|
def cleanup():
|
||||||
|
GPIO.cleanup()
|
||||||
|
|
||||||
|
|
||||||
def print_pins():
|
def print_pins():
|
||||||
for i in range(len(A)):
|
for i in range(len(A)):
|
||||||
print(f"A{i} - {A[i]}")
|
print(f" A{i:02} - {A[i]}")
|
||||||
for i in range(len(IO)):
|
for i in range(len(IO)):
|
||||||
print(f"IO{i} - {IO[i]}")
|
print(f"IO{i:02} - {IO[i]}")
|
||||||
print(f"CEb - {CEb}")
|
print(f" CEb - {CEb}")
|
||||||
print(f"WEb - {WEb}")
|
print(f" WEb - {WEb}")
|
||||||
print(f"OEb - {OEb}")
|
print(f" OEb - {OEb}")
|
||||||
|
|
||||||
|
|
||||||
def set_address(address: int, bits=8):
|
def set_address(address: int, bits=8):
|
||||||
@ -85,20 +97,23 @@ def get_bits(i: int):
|
|||||||
return len(bin(i)) - 2 # -2 for the "0x"
|
return len(bin(i)) - 2 # -2 for the "0x"
|
||||||
|
|
||||||
|
|
||||||
def check_valid_list(l: list, bits=8):
|
def convert_to_int(v):
|
||||||
"""
|
"""
|
||||||
check if the list only has x-bit binary numbers
|
convert 0xABC and 0b0101 to int
|
||||||
"""
|
"""
|
||||||
for line in l:
|
if type(v) == str and fullmatch(f"0x[0-9,a-f,A-F]+", v):
|
||||||
if not fullmatch("[01]{8}", line):
|
return int(v.replace("0x", ""), 16)
|
||||||
return False
|
elif type(v) == str and fullmatch(f"0b[0]+", v):
|
||||||
return True
|
return int(v.replace("0b", ""), 2)
|
||||||
|
return int(v)
|
||||||
|
|
||||||
|
|
||||||
def get_8_bit(l: list):
|
def get_8_bit(l: list):
|
||||||
for i in range(len(l)):
|
for i in range(len(l)):
|
||||||
l[i] = format(l[i], f"08b") # get the 8-bit bin value
|
l[i] = format(l[i], f"08b") # get the 8-bit bin value
|
||||||
return l
|
return l
|
||||||
|
|
||||||
|
|
||||||
def erase(from_ad=0, to_ad=32767, **keys):
|
def erase(from_ad=0, to_ad=32767, **keys):
|
||||||
"""
|
"""
|
||||||
Write all 1 to the EEPROM
|
Write all 1 to the EEPROM
|
||||||
@ -114,7 +129,7 @@ def write_byte(byte, address, verbose=True):
|
|||||||
GPIO.output(OEb, 1)
|
GPIO.output(OEb, 1)
|
||||||
# setup the address
|
# setup the address
|
||||||
ad_bin = set_address(address, bits=15)
|
ad_bin = set_address(address, bits=15)
|
||||||
setup_pins(OUT)
|
setup_io_pins(OUT)
|
||||||
# Setup Data
|
# Setup Data
|
||||||
for j in range(8):
|
for j in range(8):
|
||||||
if byte[7-j] == "1":
|
if byte[7-j] == "1":
|
||||||
@ -143,7 +158,7 @@ def write_byte(byte, address, verbose=True):
|
|||||||
|
|
||||||
GPIO.output(CEb, 0)
|
GPIO.output(CEb, 0)
|
||||||
GPIO.cleanup(IO)
|
GPIO.cleanup(IO)
|
||||||
setup_pins(IN)
|
setup_io_pins(IN)
|
||||||
|
|
||||||
# check the toggle bit IO6, if it stops toggling the write is done
|
# check the toggle bit IO6, if it stops toggling the write is done
|
||||||
timeout = 0
|
timeout = 0
|
||||||
@ -165,9 +180,10 @@ def write_byte(byte, address, verbose=True):
|
|||||||
if verbose:
|
if verbose:
|
||||||
print(f"Writing:\t0b{format(address, '015b')} - 0b{byte} ||| 0x{format(address, '04x')} - {hex(int(byte, 2))}")
|
print(f"Writing:\t0b{format(address, '015b')} - 0b{byte} ||| 0x{format(address, '04x')} - {hex(int(byte, 2))}")
|
||||||
|
|
||||||
|
|
||||||
def read_byte(address):
|
def read_byte(address):
|
||||||
GPIO.output(WEb, 1)
|
GPIO.output(WEb, 1)
|
||||||
setup_pins(IN)
|
setup_io_pins(IN)
|
||||||
# set the address valid
|
# set the address valid
|
||||||
ad_bin = set_address(address, bits=15)
|
ad_bin = set_address(address, bits=15)
|
||||||
|
|
||||||
@ -190,6 +206,7 @@ def read_byte(address):
|
|||||||
GPIO.output(CEb, 1)
|
GPIO.output(CEb, 1)
|
||||||
return int(byte, 2)
|
return int(byte, 2)
|
||||||
|
|
||||||
|
|
||||||
def read(from_ad=0, to_ad=255, delay=1e-3, ignore=[0xff], verbose=True, single_step=False, compare=None):
|
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
|
from_ad: start address from where to read
|
||||||
@ -219,6 +236,7 @@ def read(from_ad=0, to_ad=255, delay=1e-3, ignore=[0xff], verbose=True, single_s
|
|||||||
return unequal
|
return unequal
|
||||||
return content
|
return content
|
||||||
|
|
||||||
|
|
||||||
def write(content: list, from_ad=0, delay=0, single_step=False, verbose=True, check_written=True):
|
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.
|
Write a list if bytes to the eeprom.
|
||||||
@ -254,100 +272,44 @@ def get_bytes(filepath, from_ad=0):
|
|||||||
return bindata[from_ad:]
|
return bindata[from_ad:]
|
||||||
|
|
||||||
|
|
||||||
action = None
|
def main():
|
||||||
file = None
|
parser = argparse.ArgumentParser(
|
||||||
from_ad = 0
|
prog="AT28C256-EEPROM Writer",
|
||||||
to_ad = 32767 #2^15 -1
|
description="Read and write from/to an AT28C256 EEPROM via the Raspberry Pi 4's GPIO pins\n2023 Matthias Quintern",
|
||||||
delay = 0
|
epilog="Numbers can be passed as int, hex prefixed with '0x' and binary prefixed with '0b'",
|
||||||
single_step = False
|
)
|
||||||
verbose = False
|
parser.add_argument("--write", "-w", dest="write", action="store_true", default=False, help="write binary file onto the EEPROM")
|
||||||
ignore = [0xff]
|
parser.add_argument("--compare", "-c", dest="compare", action="store_true", default=False, help="compare EEPROM content to binary file")
|
||||||
content = []
|
parser.add_argument("--read", "-r", dest="read", action="store_true", default=False, help="read the contents of the EEPROM")
|
||||||
|
parser.add_argument("--erase", "-e", dest="erase", action="store_true", default=False, help="erase the contents of the EEPROM")
|
||||||
|
parser.add_argument("--file", "-f", metavar="file", dest="file", action="store", default="", help="file for --write and --compare")
|
||||||
|
parser.add_argument("--from", metavar="start-address", dest="from_ad", action="store", default=0, type=convert_to_int, help="start at address x")
|
||||||
|
parser.add_argument("--to", metavar="end-address", dest="to_ad", action="store", default=32767, type=convert_to_int, help="end at address y (inclusive)")
|
||||||
|
parser.add_argument("--single-step", dest="single_step", action="store_true", default=False, help="single step the program")
|
||||||
|
parser.add_argument("--delay", dest="delay", metavar="delay", action="store", default=0, help="extra delay between cycles")
|
||||||
|
parser.add_argument("--ignore", dest="ignore", metavar="numbers", action="store", nargs="*", type=convert_to_int, default=[0x100], help="ignore the numbers a b ... Default=[0xff]")
|
||||||
|
parser.add_argument("--verbose", dest="verbose", action="store_true", default=False, help="increase verbosity")
|
||||||
|
parser.add_argument("--print-pins", dest="print_pins", action="store_true", default=False, help="print the pin layout and exit")
|
||||||
|
|
||||||
if len(argv) > 1:
|
args = parser.parse_args()
|
||||||
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
|
if (args.write or args.compare) and not args.file:
|
||||||
elif argv[i-1] == "--from":
|
parser.error('--file is required with --write and --compare')
|
||||||
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 args.print_pins:
|
||||||
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()
|
print_pins()
|
||||||
# if performing action from this script, put the code HERE:
|
exit(0)
|
||||||
|
if args.erase:
|
||||||
|
erase(from_ad=args.from_ad, to_ad=args.to_ad, delay=args.delay, single_step=args.single_step, verbose=args.verbose)
|
||||||
GPIO.cleanup()
|
if args.write:
|
||||||
|
write(get_bytes(args.file, from_ad=args.from_ad), from_ad=args.from_ad, delay=args.delay, single_step=args.single_step, verbose=args.verbose)
|
||||||
|
if args.read:
|
||||||
|
read(from_ad=args.from_ad, to_ad=args.to_ad, delay=args.delay, single_step=args.single_step, verbose=args.verbose, ignore=args.ignore)
|
||||||
|
if args.compare:
|
||||||
|
compare(from_ad=args.from_ad, to_ad=args.to_ad, delay=args.delay, single_step=args.single_step, verbose=args.verbose, ignore=args.ignore, compare=get_bytes(args.file))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
atexit.register(cleanup)
|
||||||
|
setup_address_control_pins()
|
||||||
|
main()
|
||||||
|
Loading…
Reference in New Issue
Block a user