4k-rom-tester.py
4k-rom-tester.py (3705 bytes)
import os
import time
import board
import digitalio
import struct
# 4k ram tester
def make_dios(*args):
return [digitalio.DigitalInOut(a) for a in args]
address_pins = make_dios(*(getattr(board, f"GP{i}") for i in range(11, 11+12)))
for a in address_pins:
a.switch_to_output()
data_pins = make_dios(*(getattr(board, f"GP{i}") for i in range(8)))
not_write_enable = digitalio.DigitalInOut(board.GP10)
not_write_enable.switch_to_output(True)
not_output_enable = digitalio.DigitalInOut(board.GP8)
not_output_enable.switch_to_output(True)
not_chip_enable = digitalio.DigitalInOut(board.GP9)
not_chip_enable.switch_to_output(True)
random_data = os.urandom(16)
def set_pins(value, pins):
for p in pins:
p.switch_to_output(value & 1)
value >>= 1
def get_pins(pins):
value = 0
for i, p in enumerate(pins):
value |= p.value << i
return value
def read_out(*args):
for p in data_pins:
p.switch_to_input(digitalio.Pull.UP)
not_chip_enable.value = False
if not args: args = (0x800,)
for addr in range(*args):
set_pins(addr, address_pins) # There's no way the 150ns setup is violated at CP speeds!
not_output_enable.value = False
yield get_pins(data_pins)
not_output_enable.value = True
not_chip_enable.value = True
def _write(data, start_addr=0):
for p in data_pins:
p.switch_to_output(False)
not_output_enable.value = True
print(end=f"{start_addr:04x}")
for offset, byte in enumerate(data):
addr = start_addr + offset
set_pins(addr, address_pins)
set_pins(byte, data_pins)
not_chip_enable.value = False
assert get_pins(data_pins) == byte
not_write_enable.value = False
not_write_enable.value = True
not_chip_enable.value = True
print(end='.')
not_chip_enable.value = True
def write(data, start_addr=0):
_write(data, start_addr)
print()
def verify(data, start_addr = 0):
for p in data_pins:
p.switch_to_input(digitalio.Pull.UP)
not_output_enable.value = False
not_chip_enable.value = False
result = True
for offset, byte in enumerate(data):
addr = start_addr + offset
set_pins(addr, address_pins)
readback = get_pins(data_pins)
if readback != byte:
print(f"0x{addr:04x} {byte:02x} {readback:02x}")
result = False
if not result:
raise ValueError("Verify failed")
print("Verified")
def write_verify(data, start_addr = 0):
_write(data, start_addr)
verify(data, start_addr)
## Uncomment if you want to pre-erase the eeprom (not needed)
#write_verify(b"\xff" * 2048)
def readn(start, count=1):
return bytes(read_out(start, start+count))
def print_ihex(address, rectype, data):
data = list(data)
data_str = "".join(f"{b:02x}" for b in data)
data_len = len(data)
assert data_len < 256
assert 0 <= rectype < 256
assert 0 <= address < 65536
checksum = (-(data_len + sum(data) + rectype + address + address // 256)) & 0xff
print(f":{data_len:02x}{address:04x}{rectype:02x}{data_str}{checksum:02x}")
if __name__ == '__main__':
command = input("[P]rogram, [V]erify or [R]eadout? ").lower()
if command == "p":
write(random_data, 0)
if command in ("p", "v"):
verify(random_data, 0)
else:
stride = 32
end = 4096
if end % stride != 0:
raise ValueError("{stride=} incompatible with {end=}")
for start_address in range(0, 2048, stride):
print_ihex(start_address, 0, read_out(start_address, start_address + stride))
print_ihex(0, 1, [])
cp-2k-ram-flasher.py
cp-2k-ram-flasher.py (4793 bytes)
import time
import board
import digitalio
import struct
def make_dios(*args):
return [digitalio.DigitalInOut(a) for a in args]
address_pins = make_dios(
board.GP19,
board.GP20,
board.GP21,
board.GP22,
board.GP26,
board.GP27,
board.GP28,
board.GP4,
board.GP5,
board.GP6,
board.GP9,
)
for a in address_pins:
a.switch_to_output()
data_pins = make_dios(
board.GP18,
board.GP17,
board.GP16,
board.GP15,
board.GP14,
board.GP13,
board.GP12,
board.GP11,
)
not_write_enable = digitalio.DigitalInOut(board.GP7)
not_write_enable.switch_to_output(True)
not_output_enable = digitalio.DigitalInOut(board.GP8)
not_output_enable.switch_to_output(True)
not_chip_enable = digitalio.DigitalInOut(board.GP10)
not_chip_enable.switch_to_output(True)
def a2b_hex(data):
if len(data) % 2 != 0:
raise ValueError("Odd-length string")
return bytes(int(data[i:i+2], 16) for i in range(0, len(data), 2))
def print_ihex(address, rectype, data):
data = list(data)
data_str = "".join(f"{b:02x}" for b in data)
data_len = len(data)
assert data_len < 256
assert 0 <= rectype < 256
assert 0 <= address < 65536
checksum = (-(data_len + sum(data) + rectype + address + address // 256)) & 0xff
print(f":{data_len:02x}{address:04x}{rectype:02x}{data_str}{checksum:02x}")
def ihex(f):
lineno = 0
while True:
lineno += 1
line = f.readline()
if not line:
break
line = line.strip()
if not line.startswith(':'): continue
line_bin = a2b_hex(line[1:])
if sum(line_bin) % 256 != 0:
raise ValueError(f"Bad checksum on line {lineno}")
data_len = struct.unpack('>BHB', line_bin[:4])[0]
data_len, address, rectype, data, checksum = struct.unpack(f'>BHB{data_len}sB', line_bin)
yield (address, rectype, data)
def set_pins(value, pins):
for p in pins:
p.switch_to_output(value & 1)
value >>= 1
def get_pins(pins):
value = 0
for i, p in enumerate(pins):
value |= p.value << i
return value
def strobe(pin):
pin.value = False
pin.value = True
def read_out(*args):
for p in data_pins:
p.switch_to_input(digitalio.Pull.UP)
not_output_enable.value = False
not_chip_enable.value = False
if not args: args = (0x800,)
for addr in range(*args):
set_pins(addr, address_pins) # There's no way the 150ns setup is violated at CP speeds!
yield get_pins(data_pins)
def _write(data, start_addr=0):
for p in data_pins:
p.switch_to_output(False)
not_output_enable.value = True
not_chip_enable.value = False
print(end=f"{start_addr:04x}")
for offset, byte in enumerate(data):
addr = start_addr + offset
set_pins(addr, address_pins)
set_pins(byte, data_pins)
assert get_pins(data_pins) == byte
not_write_enable.value = False
not_write_enable.value = True
print(end='.')
def write(data, start_addr=0):
_write(data, start_addr)
print()
def verify(data, start_addr = 0):
for p in data_pins:
p.switch_to_input(digitalio.Pull.UP)
not_output_enable.value = False
not_chip_enable.value = False
result = True
for offset, byte in enumerate(data):
addr = start_addr + offset
set_pins(addr, address_pins)
readback = get_pins(data_pins)
if readback != byte:
print(f"0x{addr:04x} {byte:02x} {readback:02x}")
result = False
if not result:
raise ValueError("Verify failed")
print("Verified")
def write_verify(data, start_addr = 0):
_write(data, start_addr)
verify(data, start_addr)
## Uncomment if you want to pre-erase the eeprom (not needed)
#write_verify(b"\xff" * 2048)
command = input("[P]rogram, [V]erify or [R]eadout? ").lower()
if command == "p":
with open("xrxpl.hex") as f:
for address, rectype, data in ihex(f):
if rectype == 0:
write_verify(data, address)
elif rectype == 1:
break
else:
print(address, rectype, data)
if command in ("p", "v"):
with open("xrxpl.hex") as f:
for address, rectype, data in ihex(f):
if rectype == 0:
verify(data, address)
elif rectype == 1:
break
else:
print(address, rectype, data)
else:
stride = 32
end = 2048
if end % stride != 0:
raise ValueError("{stride=} incompatible with {end=}")
for start_address in range(0, 2048, stride):
print_ihex(start_address, 0, read_out(start_address, start_address + stride))
print_ihex(0, 1, [])