1
0
mirror of https://github.com/rzzzwilson/pymlac.git synced 2025-06-10 09:32:41 +00:00
2015-10-30 21:20:08 +07:00

125 lines
3.2 KiB
Python

#!/usr/bin/python
"""
Emulate the imlac Paper Tape Reader (PTR).
We take some pains to closely emulate the *real* PTR device, even
including misuse, such as no tape mounted. This means we must tell
the PTR object how many CPU cycles have passed (tick()).
"""
from Globals import *
class Ptr(object):
# number of chars per second we want
CharsPerSecond = 300
# duty cycle for PTR is 30% ready and 70% not ready
ReadyCycles = int((CYCLES_PER_SECOND / CharsPerSecond) / 0.7) / 25
NotReadyCycles = int((CYCLES_PER_SECOND / CharsPerSecond) / 0.3) / 25
# no tape in reader, return 0377 (all holes see light)
PtrEOF = 0377
# module-level state variables
motor_on = False
device_ready = False
open_file = None
filename = None
at_eof = True
value = PtrEOF
cycle_count = 0
def __init__(self):
"""Initialize the paertape reader device."""
self.motor_on = False
self.device_ready = False
self.open_file = None
self.filename = None
self.at_eof = True
self.value = self.PtrEOF
self.cycle_count = 0
def mount(self, fname):
"""Mount papertape file on the reader device."""
self.motor_on = False
self.device_ready = False
self.cycle_count = self.NotReadyCycles
self.filename = fname
self.open_file = open(self.filename, 'rb')
self.at_eof = False
self.value = None
def dismount(self):
"""Dismount a papertape file."""
self.motor_on = False
self.device_ready = False
if self.filename:
self.open_file.close()
self.open_file = None
self.filename = None
self.at_eof = True
self.value = self.PtrEOF
def start(self):
"""Turn papertape reader motor on."""
self.motor_on = True
self.device_ready = False
self.cycle_count = self.ReadyCycles
def stop(self):
"""Stop reader motor."""
self.motor_on = False
self.device_ready = False
self.cycle_count = self.ReadyCycles
def read(self):
"""Read papertape value."""
return self.value
def eof(self):
"""Return reader EOF status."""
return self.at_eof
def tick(self, cycles):
"""Called to push PTR state along.
cycles number of cycles passed since last tick
"""
# if end of tape or motor off, do nothing, state remains unchanged
if self.at_eof or not self.motor_on:
return
self.cycle_count -= cycles
if self.cycle_count <= 0:
if self.device_ready:
self.device_ready = False
self.cycle_count += self.NotReadyCycles
else:
self.device_ready = True
self.cycle_count += self.ReadyCycles
self.value = self.open_file.read(1)
if len(self.value) < 1:
# EOF on input file, pretend end of tape
self.at_eof = True
self.value = self.PtrEOF
else:
self.value = ord(self.value)
def ready(self):
"""Test if reader is ready."""
return self.device_ready