Skip to content

Commit

Permalink
docs, udp logger, scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
mortenjc committed Nov 15, 2024
1 parent ca56178 commit aa6b439
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 48 deletions.
7 changes: 7 additions & 0 deletions docs/source/log.rst
Original file line number Diff line number Diff line change
Expand Up @@ -630,3 +630,10 @@ The emulated system now comes preloaded with two floppy images: datamuseum and
debugdisk. The first has good integrity the second has a lot of bad tracks so
most programs will fail to load and execute. Some good files are: SCR, ALTER,
DISPTEST, PTEST, COPY

2024 11 13
----------

Added support for UDP based logging via the class **utils/UdpTx**. Added scripts
to start logging in **utils**. Now the emulator console can be used for debugging
and the other windows for device-specific inspection.
19 changes: 11 additions & 8 deletions src/devices/disk.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import sys
import utils.misc as misc
import utils.udptx as udp

# System can have multple Disks (Floppy, Harddisks)
# Disks can have multiple Drives (0, 1, ...)

udptx = udp.UdpTx(port=5006, timestamp=True, nl=True)

class Disk:
def __init__(self, type, drives):
print(f'disk {type} has {len(drives)} drives')
udptx.send(f'disk {type} has {len(drives)} drives')
self.type = type
self.selected_drive = -1
self.numdrives = len(drives)
Expand Down Expand Up @@ -37,10 +40,10 @@ def select_drive(self, i):

self.selected_drive = drive # allow selection of unavailable drives
if drive <= len(self.drives):
print(f'select_drive: {self.type}/{drive} - available')
udptx.send(f'select_drive: {self.type}/{drive} - available')
self.drive = self.drives[drive - 1]
else:
print(f'select_drive: {self.type}/{drive} - unavailable')
udptx.send(f'select_drive: {self.type}/{drive} - unavailable')
self.drive = 'unavailable'
assert self.selected_drive in [1, 2, 3, 4, 5, 6, 7]

Expand Down Expand Up @@ -76,16 +79,17 @@ def isbusy(self):

def status(self) -> int:
if self.type != 'floppy':
print(f'disk.status: {self.type} drive not available')
udptx.send(f'disk.status: {self.type} drive not available')
return 0
if not self.isdriveavailable():
print(f'status: drive {self.selected_drive} not valid')
udptx.send(f'status: drive {self.selected_drive} not valid')
return 0
return self.drive.status()


class Drive:
def __init__(self, driveno, fs): #
self.udp = udp.UdpTx(port=5006)
self.driveno = driveno
self.tracks = fs.tracks
self.bytes_per_track = fs.bpt
Expand All @@ -112,12 +116,12 @@ def step(self, direction):
if direction: # UP
msg = f'disk {self.driveno}, step up 0x{direction:02x}'
msg += f', track {self.current_track} -> {self.current_track + 1}'
print(msg)
udptx.send(msg)
self.current_track = (self.current_track + 1) % self.tracks
else: # DOWN
msg = f'disk {self.driveno}, step down {direction:02x}'
msg += f', track {self.current_track} -> {self.current_track - 1}'
print(msg)
udptx.send(msg)
if self.current_track == 0:
return
self.current_track -= 1
Expand Down Expand Up @@ -150,7 +154,6 @@ def gettrackno(self):
def isbusy(self):
while self.current_byte not in self.marks[self.current_track]:
self.current_byte = (self.current_byte + 1) % self.bytes_per_track
#print(f'mark {self.current_byte}')
return True


Expand Down
14 changes: 4 additions & 10 deletions src/devices/display.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
import socket
import utils.udptx as udp

'''
Display emulator for Q1
'''


def txudp(message):
UDP_IP = "127.0.0.1"
UDP_PORT = 5005

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(message.encode(), (UDP_IP, UDP_PORT))


class Display:

def __init__(self, height=12, width=40):
Expand All @@ -21,6 +13,8 @@ def __init__(self, height=12, width=40):
self.pos = (0,0)
self.buffer = [[chr(0x20) for x in range(width)] for y in range(height)]

self.udp = udp.UdpTx(port=5005)


def _incx(self):
x, y = self.pos
Expand Down Expand Up @@ -57,7 +51,7 @@ def update(self):
msg = chr(self.pos[0]) + chr(self.pos[1])
for l in self.buffer:
msg += ''.join(l)
txudp(msg)
self.udp.send(msg)

if __name__ == '__main__':
import time
Expand Down
7 changes: 5 additions & 2 deletions src/devices/printer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@

import utils.udptx as udp


udptx = udp.UdpTx(port=5008, timestamp=True, nl=True)

# "Q1 ASM IO addresses usage Q1 Lite" p. 75 - 77
class SerialImpactPrinter:

Expand Down Expand Up @@ -40,7 +43,7 @@ def ctrl_06(self, value: int):
v = cm * dy
y = y + v
self.pos = [x, y]
#print(f'SI printer ctrl: move {dir} {v:6.2f} cm. pos ({x:6.2f}, {y:6.2f})')
udptx.send(f'SI printer ctrl 06: move {dir} {v:6.2f} cm. pos ({x:6.2f}, {y:6.2f})')



Expand Down Expand Up @@ -71,4 +74,4 @@ def ctrl_07(self, value: int):
desc += 'forward '
desc += 'motion'

#print(f'SI printer ctrl: - 0x{value:02x} [{desc}]')
udptx.send(f'SI printer ctrl 07: {value:02x}: [{desc}]')
56 changes: 28 additions & 28 deletions src/devices/z80io.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@
import devices.disk as disk
import devices.display as display
import devices.printer as printer
import utils.udptx as udp

#

udptx = udp.UdpTx(port=5007, timestamp=True, nl=True)

def isprintable(c):
"""True if character is printable ASCII"""
return 0x20 <= c <= 0x7D
Expand All @@ -29,7 +32,6 @@ def __init__(self, m, floppys, hds):
self.go = 0
self.stop = 0
self.timeout = False
self.verbose = False
self.register_in_cb( 0x00, self.handle_rtc_in)
self.register_out_cb(0x00, self.handle_rtc_out)

Expand Down Expand Up @@ -69,10 +71,6 @@ def __init__(self, m, floppys, hds):
self.register_out_cb(0x1b, self.handle_disk_out_1b)


def print(self, s):
if self.verbose:
print(s)

### Functions for registering and handling IO

def register_out_cb(self, outaddr: int, outfunc):
Expand All @@ -87,7 +85,8 @@ def handle_io_in(self, value) -> int:
if inaddr in self.incb:
return self.incb[inaddr]()

print(f'IO - unregistered input address 0x{inaddr:02x} at pc {self.m.pc:04x}, exiting')
udptx.send(f'0x{inaddr:02x} - unregistered input address at pc {self.m.pc:04x}, exiting')
print(msg)
print()
sys.exit()
return 0
Expand All @@ -98,7 +97,9 @@ def handle_io_out(self, outaddr, outval):
if outaddr in self.outcb:
self.outcb[outaddr](outval)
else:
print(f'IO - unregistered output address 0x{outaddr:02x} (0x{outval:02x})')
msg = f'0x{outaddr:02x} - unregistered output address, value (0x{outval:02x})'
udptx.send(msg)
print(msg)
sys.exit()


Expand All @@ -112,13 +113,13 @@ def handle_rtc_in(self) -> int:
return 0

def handle_rtc_out(self, val):
print(f"setting timeout value {val} not supported")
udptx.send(f"0x00 out - rtc: setting timeout value {val} not supported")


### Display

def handle_display_in(self) -> int:
self.print('IO - display status: 32 + 16 (Lite, 40 char)')
udptx.send('0x04 in - display status: 32 + 16 (Lite, 40 char)')
return 32 + 16


Expand All @@ -135,7 +136,7 @@ def handle_display_out_ctrl(self, val) -> str:
desc = 'advance right (or new line)'
else:
desc = f'0x{val:02}'
self.print(f"IO out - display control - {desc}")
#udptx.send(f"IO out - display control - {desc}")


### Keyboard
Expand All @@ -148,7 +149,7 @@ def handle_key_in(self) -> int:
if self.stop:
retval = 0x0f
self.stop = 0
self.print(f'IO in - key : 0x{retval:02x}')
udptx.send(f'0x01 in - key: 0x{retval:02x}')
return retval


Expand All @@ -170,7 +171,7 @@ def handle_key_out(self, val):
desc += 'K3 '
if val & 0x80:
desc += 'INS '
print(f'IO out - key [{desc}]')
udptx.send(f'0x01 out - key: [{desc}]')


### Printer 5,6,7 - Serial Impact Printer
Expand All @@ -181,19 +182,23 @@ def handle_key_out(self, val):
# "Q1 ASM IO addresses usage Q1 Lite" p. 77
def handle_printer_in_5(self) -> int:
status = self.printer.status()
self.print(f'IO in - printer 0x5 status - {status} (1 == selected)')
udptx.send(f'0x05 in - printer status - {status} (1 == selected)')
return status


# Print character at current position
def handle_printer_out_5(self, val : int):
udptx.send(f'0x05 out - printer output - {val}')
self.printer.output(val)


def handle_printer_out_6(self, val):
udptx.send(f'0x06 out - printer ctrl 1 - {val}')
self.printer.ctrl_06(val)


def handle_printer_out_7(self, val):
udptx.send(f'0x07 out - printer ctrl 2 - {val}')
self.printer.ctrl_07(val)


Expand All @@ -202,26 +207,26 @@ def handle_printer_out_7(self, val):
# From "Q1 ASM IO addresses usage Q1 Lite" p. 77
def handle_printer_in_8(self) -> int:
status = 0x01
self.print(f'IO in - printer 0x8 status - {status} (1 == selected)')
udptx.send(f'0x08 in - printer status - {status} (1 == selected)')
return status


### Disk 1? Data and Control
### From "Q1 ASM IO addresses usage Q1 Lite" p. 77 - 80
def handle_disk_out_0a(self, val):
if val:
self.print(f'IO out - floppy (control 1 ) - (0x{val:02x})')
udptx.send(f'0x0a out - floppy (control 1 ) - (0x{val:02x})')
self.floppy.control1(val)


def handle_disk_out_0b(self, val):
if val:
self.print(f'IO out - floppy (control 2 ) - (0x{val:02x})')
udptx.send(f'0x0b out - floppy (control 2 ) - (0x{val:02x})')
self.floppy.control2(val)


def handle_disk_out_09(self, val):
self.print(f'IO out - floppy (data) - (0x{val:02x})')
udptx.send(f'0x09 out - floppy (data) - (0x{val:02x})')
self.floppy.data_out(val)


Expand All @@ -239,44 +244,39 @@ def handle_unkn_in_0c(self):
# status 0x80 - program stuck in start up
# status 0x40 - DINDEX stuck in F5
status = 0x00
self.print(f'IO in - unknown in for 0xc - (return {status})')
udptx.send(f'0x0c in - unknown in for 0xc - (return {status})')
return status


def handle_unkn_out_0c(self, val):
udptx.send(f'0x0c out - unknown device - (0x{val:02x})')
if val == 0xa:
print(self.prtbuf)
self.prtbuf=""
else:
self.prtbuf += chr(val)

#print(f'{chr(val)}')


def handle_disk_out_0c(self, val):
print(f'IO out - unknown device - (0x{val:02x})')


### Disk 2 Data and Control
### From "Q1 Assembler" p. 52 - 54
def handle_disk_in_19(self):
retval = self.hdd.data_in()
self.print(f'IO in - hdd (data): {retval}')
udptx.send(f'0x19 in - hdd (data): {retval}')
return retval

def handle_disk_in_1a(self):
retval = self.hdd.status()
self.print(f'IO in - hdd (status): {retval}')
udptx.send(f'0x1a in - hdd (status): {retval}')
return retval


def handle_disk_out_1a(self, val):
if val:
self.print(f'IO out - hdd (control 1 ) - (0x{val:02x})')
udptx.send(f'0x1a out - hdd (control 1 ) - (0x{val:02x})')
self.hdd.control1(val)


def handle_disk_out_1b(self, val):
if val != 0:
self.print(f'IO out - hdd (control 2 ) - (0x{val:02x})')
udptx.send(f'0x1b out - hdd (control 2 ) - (0x{val:02x})')
self.hdd.control2(val)
4 changes: 4 additions & 0 deletions src/utils/logdisk
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
printf "\e]1337;SetBadgeFormat=%s\a" \
$(echo "Q1 Disk" | base64)

nc -kluvw 0 127.0.0.1 5006
4 changes: 4 additions & 0 deletions src/utils/logio
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
printf "\e]1337;SetBadgeFormat=%s\a" \
$(echo "Q1 IO" | base64)

nc -kluvw 0 127.0.0.1 5007
4 changes: 4 additions & 0 deletions src/utils/logprt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
printf "\e]1337;SetBadgeFormat=%s\a" \
$(echo "Q1 PRINTER" | base64)

nc -kluvw 0 127.0.0.1 5008
24 changes: 24 additions & 0 deletions src/utils/udptx.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import socket
import time


class UdpTx:

def __init__(self, ip='127.0.0.1', port=9901, timestamp=False, nl=False, term=False):
self.addr = (ip, port)
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.ts = timestamp
self.toffset = time.time()
self.nl = nl
self.term = term


def send(self, message: str):
msg = message
if self.term:
print(msg)
if self.ts:
msg = f'{time.time()-self.toffset:7.3f}: ' + msg
if self.nl:
msg += '\n'
self.sock.sendto(msg.encode(), self.addr)

0 comments on commit aa6b439

Please sign in to comment.