From 38dfba80f04c0e4d918ea8f8247561393f96669e Mon Sep 17 00:00:00 2001 From: Ross Wilson Date: Sat, 13 Jun 2015 19:10:11 +0700 Subject: [PATCH] New code to test PTR and PTP devices --- pymlac/DisplayCPU.py | 55 +++++++------ pymlac/Ptp.py | 9 ++- pymlac/test_PTR_PTP.py | 173 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 208 insertions(+), 29 deletions(-) create mode 100644 pymlac/test_PTR_PTP.py diff --git a/pymlac/DisplayCPU.py b/pymlac/DisplayCPU.py index af061ed..f54447d 100644 --- a/pymlac/DisplayCPU.py +++ b/pymlac/DisplayCPU.py @@ -26,15 +26,16 @@ DIB = 0 # display CPU ??? DX = 0 # display CPU draw X register DY = 0 # display CPU draw Y register -# state variables -mode = MODE_NORMAL -running = False - +# global state variables +Mode = MODE_NORMAL +Running = False def init(): - mode = MODE_NORMAL - running = False + global Mode, Running + + Mode = MODE_NORMAL + Running = False def DEIMdecode(byte): """Decode a DEIM byte""" @@ -57,6 +58,7 @@ def DEIMdecode(byte): def doDEIMByte(byte): global DPC, DX, DY, DRSindex + global Mode if byte & 0x80: # increment? prevDX = DX @@ -73,7 +75,7 @@ def doDEIMByte(byte): # display.draw(0, prevDX, prevDY, DX, DY) else: # micro instructions if byte & 0x40: - mode = MODE_NORMAL + Mode = MODE_NORMAL if byte & 0x20: # DRJM if DRSindex <= 0: Trace.comment('\nDRS stack underflow at display address %6.6o' @@ -92,18 +94,19 @@ def doDEIMByte(byte): def execute_one_instruction(): global DPC + global Mode - if not running: + if not Running: Trace.dtrace('') return 0 instruction = Memory.get(DPC, 0) DPC = MASK_MEM(DPC + 1) - if mode == MODE_DEIM: + if Mode == MODE_DEIM: Trace.trace(DEIMdecode(instruction >> 8) + '\t') doDEIMByte(instruction >> 8) - if mode == MODE_DEIM: + if Mode == MODE_DEIM: Trace.trace(DEIMdecode(instruction & 0xff) + '\t') doDEIMByte(instruction & 0xff) else: @@ -114,14 +117,14 @@ def execute_one_instruction(): address = instruction & 007777 if opcode == 000: return page00(instruction) - elif opcode == 001: return i_DLXA(address) - elif opcode == 002: return i_DLYA(address) - elif opcode == 003: return i_DEIM(address) - elif opcode == 004: return i_DLVH(address) - elif opcode == 005: return i_DJMS(address) - elif opcode == 006: return i_DJMP(address) - elif opcode == 007: return illegal(instruction) - else: illegal(instruction) + elif opcode == 001: return i_DLXA(address) + elif opcode == 002: return i_DLYA(address) + elif opcode == 003: return i_DEIM(address) + elif opcode == 004: return i_DLVH(address) + elif opcode == 005: return i_DJMS(address) + elif opcode == 006: return i_DJMP(address) + elif opcode == 007: illegal(instruction) + else: illegal(instruction) def illegal(instruction=None): if instruction: @@ -133,7 +136,7 @@ def illegal(instruction=None): sys.exit(0) def ison(): - return running + return Running def i_DDXM(): global DX @@ -148,13 +151,15 @@ def i_DDYM(): Trace.dtrace('DDYM') def i_DEIM(address): - mode = MODE_DEIM + global Mode + + Mode = MODE_DEIM Trace.deimtrace('DEIM', DEIMdecode(address & 0377)) doDEIMByte(address & 0377) return 1 def i_DHLT(): - running = False + Running = False Trace.dtrace('DHLT') def i_DHVC(): @@ -315,11 +320,11 @@ def page00(instruction): return 1 def start(): - global running + global Running - running = True + Running = True def stop(): - global running + global Running - running = False + Running = False diff --git a/pymlac/Ptp.py b/pymlac/Ptp.py index d2eccab..2d46684 100644 --- a/pymlac/Ptp.py +++ b/pymlac/Ptp.py @@ -21,6 +21,7 @@ motor_state = MOTOR_OFF device_state = DEVICE_NOT_READY filename = None open_file = None +cycle_count = None def init(): @@ -50,27 +51,27 @@ def dismount(): open_file = None def start(): - global motor_state, device_state, filename, open_file + global motor_state, device_state, cycle_count motor_state = MOTOR_ON device_state = DEVICE_NOT_READY cycle_count = DEVICE_NOT_READY_CYCLES def stop(): - global motor_state, device_state, filename, open_file + global motor_state, device_state motor_state = MOTOR_OFF device_state = DEVICE_NOT_READY def write(ch): - global motor_state, device_state, filename, open_file + global device_state, open_file, cycle_count device_state = DEVICE_NOT_READY cycle_count = DEVICE_NOT_READY_CYCLES open_file.write(ch) def tick(cycles): - global motor_state, device_state, filename, open_file + global motor_state, device_state, open_file, cycle_count if motor_state == MOTOR_OFF or not open_file: device_state = DEVICE_NOT_READY diff --git a/pymlac/test_PTR_PTP.py b/pymlac/test_PTR_PTP.py new file mode 100644 index 0000000..3a7e6f8 --- /dev/null +++ b/pymlac/test_PTR_PTP.py @@ -0,0 +1,173 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +Test the pymlac papertape reader code. + +Usage: test_PTR_PTP.py + +where is a papertape file (*.ptp) + and is zero or more of: + -h print this help and stop +""" + +# We exercise the papertape reader module by: +# 1. manipulating the device to test error conditions +# 2. writing test *.ptp files which we mount and read + + +import Ptr +import Ptp + + +# module global constants +PtrFilename = '_#PTR#_.ptp' +PtpFilename = '_#PTP#_.ptp' + + +def read_no_tape(): + """Read from device with no tape mounted.""" + + # read before turning on + byte = Ptr.read() + if byte != 0377: + print('Error') + Ptr.tick(1000000) # wait a long time + byte = Ptr.read() + if byte != 0377: + print('Error') + + # turn device on, still no tape + Ptr.start() + Ptr.tick(1000000) # wait a long time + byte = Ptr.read() + if byte != 0377: + print('Error') + Ptr.tick(1000000) # wait a long time + byte = Ptr.read() + if byte != 0377: + print('Error') + Ptr.stop() + +def create_papertape(filename): + """Create a PTP file.""" + + # create a test papertape + with open(filename, 'wb') as fd: + # leader + for _ in range(128): + fd.write(chr(0)) + + for v in range(1, 256): + fd.write(chr(v)) + + # trailer + for _ in range(128): + fd.write(chr(0)) + +def create_papertape_ptp(filename): + """Create a PTP file using the Ptp device.""" + + Ptp.mount(filename) + Ptp.start() + + # leader + for _ in range(128): + while not Ptp.ready(): + Ptp.tick(1) + Ptp.write(chr(0)) + while Ptp.ready(): + Ptp.tick(1) + + # body + for v in range(1, 256): + while not Ptp.ready(): + Ptp.tick(1) + Ptp.write(chr(v)) + while Ptp.ready(): + Ptp.tick(1) + + # trailer + for _ in range(128): + while not Ptp.ready(): + Ptp.tick(1) + Ptp.write(chr(0)) + while Ptp.ready(): + Ptp.tick(1) + + Ptp.stop() + Ptp.dismount() + +def read_tape(filename): + """Create tape and read it.""" + + # now mount and read tape + Ptr.mount(filename) + Ptr.start() + + # read leader + byte = None + count = 0 + while True: + while not Ptr.ready(): + Ptr.tick(1) + byte = Ptr.read() + while Ptr.ready(): + Ptr.tick(1) + if byte != 0: + break + count += 1 + + print('%d bytes of leader' % count) + + # read body, already read first byte + byte = None + count = 1 + while True: + while not Ptr.ready(): + Ptr.tick(1) + byte = Ptr.read() + while Ptr.ready(): + Ptr.tick(1) + if byte == 0: + break + count += 1 + + print('%d bytes of body' % count) + + # read trailer, already read first byte + byte = None + count = 1 + while True: + while not Ptr.ready(): + Ptr.tick(1) + byte = Ptr.read() + if byte != 0: + break + count += 1 + while Ptr.ready(): + Ptr.tick(1) + + Ptr.stop() + + print('%d bytes of trailer' % count) + +def main(): + """Test the papertape reader.""" + + Ptr.init() + Ptp.init() + + read_no_tape() + create_papertape(PtrFilename) + read_tape(PtrFilename) + create_papertape_ptp(PtpFilename) + read_tape(PtpFilename) + + + +################################################################################ + +if __name__ == '__main__': + main() +