aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Tuomi <jan@jantuomi.fi>2024-04-13 16:23:36 +0300
committerJan Tuomi <jan@jantuomi.fi>2024-04-13 16:23:36 +0300
commit374feaf304df4fababf82af72776e8e98df00be8 (patch)
treee9eb78b26d521b88826abccc01c3e2e7e7aa0b1f
parent3f9f7eefb9d0836ec53a08e311219f7f497517c7 (diff)
WIP peripherals
-rw-r--r--atk16_asm/builtin_asm/std_mem.atk1619
-rw-r--r--atk16_emu/emu.py26
-rw-r--r--atk16_emu/peripherals.py50
3 files changed, 78 insertions, 17 deletions
diff --git a/atk16_asm/builtin_asm/std_mem.atk16 b/atk16_asm/builtin_asm/std_mem.atk16
new file mode 100644
index 0000000..4c6a455
--- /dev/null
+++ b/atk16_asm/builtin_asm/std_mem.atk16
@@ -0,0 +1,19 @@
+@label memset
+ ; sets a specified number of words in memory to a specified value
+ ; parameters: RA = offset (offset in memory to start at)
+ ; RB = n (number of words to set)
+ ; RC = val (value to set the words to)
+ ; returns: void
+ stack_stash RD RE
+ ldi 0 RD ; RD := i (counter), initially 0
+@label memset_loop
+ subi RB RD RE ; RE := n – i (unused value)
+ bri zero memset_done ; exit the loop
+
+ add RA RD RE ; RE := RA + i (address of the word to set)
+ str RC RE ; set the word at address RE to value in RC
+
+ inc RD ; i := i + 1
+@label memset_done
+ stack_restore RD RE
+ return
diff --git a/atk16_emu/emu.py b/atk16_emu/emu.py
index 90b588d..d17b537 100644
--- a/atk16_emu/emu.py
+++ b/atk16_emu/emu.py
@@ -7,7 +7,7 @@ from dataclasses import dataclass
from .opcodes import *
from .memory import *
from .colors import C
-from .peripherals import Graphics, DummyGraphics
+from .peripherals import *
@dataclass
class ALUFlags:
@@ -131,15 +131,15 @@ class Machine:
self.peripherals_enabled = peripherals_enabled
if peripherals_enabled:
- self.graphics = Graphics()
+ self.peripherals = Peripherals()
else:
- self.graphics = DummyGraphics()
+ self.peripherals = DummyPeripherals()
def make_copy(self):
new_machine = Machine()
new_machine.peripherals_enabled = self.peripherals_enabled
- new_machine.graphics = self.graphics
+ new_machine.peripherals = self.peripherals
new_machine.rom = ROM(self.rom.addr_bits, self.rom.data_bits)
new_machine.rom.memory = self.rom.memory.copy()
@@ -191,8 +191,10 @@ class Machine:
if addr < 2 ** 15:
return self.rom.read(addr & 0x7FFF)
else:
- # TODO: Implement memory-mapped I/O
- return self.ram.read(addr & 0x7FFF)
+ if addr == 0xE001:
+ return self.peripherals.keyboard.read()
+ else:
+ return self.ram.read(addr & 0x7FFF)
def mem_write(self, addr: int, value: int):
if addr < 2 ** 15:
@@ -200,13 +202,15 @@ class Machine:
else:
# TODO: Implement memory-mapped I/O
if addr == 0xE002 and value == 0b00:
- self.graphics.deactivate()
+ self.peripherals.graphics.deactivate()
elif addr == 0xE002 and value == 0b01:
- self.graphics.activate_tpu()
+ self.peripherals.graphics.activate_tpu()
elif addr == 0xE002 and value == 0b10:
- self.graphics.activate_ppu()
+ self.peripherals.graphics.activate_ppu()
elif 0xF800 < addr <= 0xFFFF:
- self.graphics.write(addr, value)
+ self.peripherals.graphics.write(addr, value)
+ elif addr == 0xE000:
+ self.terminal.write(value)
else:
self.ram.write(addr & 0x7FFF, value)
@@ -359,7 +363,7 @@ class Machine:
print(f"Error while executing instruction 0b{instr:>016b} (0x{instr:>04x}) at address 0x{pc_addr:>04x}", file=sys.stderr)
raise
- self.graphics.step()
+ self.peripherals.step()
def decode(self, instr: int):
opcode = (instr & 0xF000) >> 12
diff --git a/atk16_emu/peripherals.py b/atk16_emu/peripherals.py
index c11bb55..0038a33 100644
--- a/atk16_emu/peripherals.py
+++ b/atk16_emu/peripherals.py
@@ -1,7 +1,32 @@
import pygame
import sys
+import random
from .memory import RAM, ROM
+class Peripherals:
+ def __init__(self):
+ pygame.init()
+ self.graphics = Graphics()
+ self.keyboard = Keyboard()
+
+ def step(self):
+ for event in pygame.event.get():
+ if event.type == pygame.QUIT:
+ sys.exit(0)
+ elif event.type == pygame.KEYDOWN:
+ print(f"key pressed: {event.key}")
+ self.keyboard.latest_pressed = event.key
+
+ self.graphics.step()
+
+class DummyPeripherals:
+ def __init__(self):
+ self.graphics = DummyGraphics()
+ self.keyboard = DummyKeyboard()
+
+ def step(self):
+ pass
+
class TPU:
def __init__(self):
self.surface = pygame.Surface((320, 240))
@@ -29,7 +54,6 @@ class TPU:
for cx in range(2 ** 3):
sx = (tx << 3) + cx
sy = (ty << 3) + cy
- #print("cy", cy, "ty", ty, "cx", cx, "tx", tx, "text_addr", text_addr, "char_s", char_s, "char_addr", char_addr)
pixel_value_bit = (char_d >> cx) & 1
self.surface.set_at((sx, sy), (255 * pixel_value_bit, 255 * pixel_value_bit, 255))
@@ -40,7 +64,6 @@ class TPU:
class Graphics:
def __init__(self):
- pygame.init()
pygame.display.init()
surface_scale = 4
@@ -60,10 +83,6 @@ class Graphics:
def step(self):
if self.active_picture_unit:
- for event in pygame.event.get():
- if event.type == pygame.QUIT:
- sys.exit(0)
-
self.active_picture_unit.frame()
self.screen.blit(pygame.transform.scale(self.tpu.surface, self.screen.get_size()), (0, 0))
@@ -89,3 +108,22 @@ class DummyGraphics:
def step(self):
pass
+
+ def write(self, addr: int, char: int):
+ pass
+
+class Keyboard:
+ def __init__(self):
+ # mimic electronic behaviour my assigning a random value at start
+ self.latest_pressed: int = random.randrange(0, 2 ** 16)
+
+ def read(self) -> int:
+ return self.latest_pressed
+
+class DummyKeyboard:
+ def __init__(self):
+ pass
+
+ def read(self) -> int:
+ print("warning: reading from dummy keyboard")
+ return 0xFFFF