Move meowbit CPU to its own dir + get screen going
This commit is contained in:
parent
6bea93308c
commit
4c605e92c5
|
|
@ -1,13 +1,3 @@
|
|||
# from sys import exit
|
||||
import time
|
||||
import board
|
||||
import displayio
|
||||
# import vectorio
|
||||
import terminalio # for font
|
||||
from adafruit_display_text import label
|
||||
import keypad
|
||||
from digitalio import DigitalInOut, Direction, Pull
|
||||
|
||||
# TO USE KEYPAD TO MANIPULATE DATA:
|
||||
#
|
||||
# A button: run/halt
|
||||
|
|
@ -18,24 +8,16 @@ from digitalio import DigitalInOut, Direction, Pull
|
|||
# Data entry: likewise. After you press the second digit, it will automatically go to the next address.
|
||||
|
||||
|
||||
import time
|
||||
import board
|
||||
import displayio
|
||||
import vectorio
|
||||
import terminalio # for font
|
||||
from adafruit_display_text import label
|
||||
import keypad
|
||||
from digitalio import DigitalInOut, Direction, Pull
|
||||
|
||||
# to list board features: print(board.__dir__)
|
||||
|
||||
btna = DigitalInOut(board.BTNA)
|
||||
btna.direction = Direction.INPUT
|
||||
btna.pull = Pull.UP # down doesn't work
|
||||
|
||||
btnb = DigitalInOut(board.BTNB)
|
||||
btnb.direction = Direction.INPUT
|
||||
btnb.pull = Pull.UP # down doesn't work
|
||||
|
||||
btnr = DigitalInOut(board.RIGHT)
|
||||
btnr.direction = Direction.INPUT
|
||||
btnr.pull = Pull.UP # down doesn't work
|
||||
|
||||
km = keypad.KeyMatrix(
|
||||
row_pins = (board.P0, board.P1, board.P2, board.P3),
|
||||
column_pins = (board.P4, board.P6, board.P8, board.P9) )
|
||||
|
||||
|
||||
class TwoDigitHexInput:
|
||||
|
|
@ -55,13 +37,6 @@ class TwoDigitHexInput:
|
|||
print(self.digits)
|
||||
|
||||
|
||||
group = displayio.Group()
|
||||
board.DISPLAY.root_group = group
|
||||
text_area = label.Label(terminalio.FONT, text="")
|
||||
text_area.x = 10
|
||||
text_area.y = 10
|
||||
group.append(text_area)
|
||||
|
||||
class CPU:
|
||||
def __init__(self):
|
||||
self.running = False
|
||||
|
|
@ -70,9 +45,6 @@ class CPU:
|
|||
self.flags = { 'C': False, 'Z': False, 'N': False, 'Eq': False }
|
||||
self.instruction = { 'opcode': False, 'operand': False }
|
||||
self.memory = False
|
||||
self.monitorMode = 'addressEntry' # dataEntry
|
||||
self.monitorAddressInput = TwoDigitHexInput()
|
||||
self.monitorDataInput = TwoDigitHexInput()
|
||||
|
||||
|
||||
def load_memory(self, bytes):
|
||||
|
|
@ -84,73 +56,6 @@ class CPU:
|
|||
def start(self):
|
||||
self.running = True
|
||||
|
||||
def print_screen(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
# print(f"{i}-{j}", end=" ")
|
||||
# print(self.memory[(i*5)+j], end=" ")
|
||||
memory_index = (i * 5) + j
|
||||
if self.memory[memory_index] > 0:
|
||||
print("#", end=" ")
|
||||
else:
|
||||
print("_", end=" ")
|
||||
print()
|
||||
|
||||
def print_monitor(self):
|
||||
text1 = "IP " + str(self.IP) + " DATA " + str(self.memory[self.IP]) # + "ACC " + str(self.acc)
|
||||
print(text1)
|
||||
text_area.text = text1
|
||||
|
||||
|
||||
|
||||
|
||||
def read_keys(self):
|
||||
keypad_event = km.events.get()
|
||||
if keypad_event and keypad_event.released:
|
||||
print(keypad_event.key_number)
|
||||
|
||||
if self.running:
|
||||
if btna.value == False:
|
||||
self.running = False
|
||||
print("HALT PRESSED")
|
||||
time.sleep(0.5) # lazy debounce
|
||||
# km.events.clear() # don't track keypresses from during the run
|
||||
if keypad_event and keypad_event.released:
|
||||
self.memory[26] = keypad_event.key_number
|
||||
print("mem26", self.memory[26])
|
||||
|
||||
|
||||
else: # halted
|
||||
if btna.value == False:
|
||||
self.running = True
|
||||
print("\nSTARTING")
|
||||
time.sleep(0.5) # lazy debounce
|
||||
if btnb.value == False:
|
||||
self.monitorMode = 'addressEntry' if self.monitorMode != 'addressEntry' else 'dataEntry'
|
||||
print("\nENTERING", self.monitorMode, "MODE")
|
||||
self.monitorDataInput.currentDigit = 0
|
||||
self.monitorAddressInput.currentDigit = 0
|
||||
time.sleep(0.5) # lazy debounce
|
||||
if btnr.value == False:
|
||||
print("\nSINGLE STEP FROM MONITOR ADDR")
|
||||
# self.IP = self.monitorAddressInput.value
|
||||
self.step()
|
||||
time.sleep(0.5) # lazy debounce
|
||||
if keypad_event and keypad_event.released:
|
||||
if self.monitorMode == 'addressEntry':
|
||||
self.monitorAddressInput.input(keypad_event.key_number)
|
||||
self.IP = self.monitorAddressInput.value
|
||||
print("MA", self.IP)
|
||||
else:
|
||||
self.monitorDataInput.input(keypad_event.key_number)
|
||||
self.memory[self.IP] = self.monitorDataInput.value
|
||||
print("MD", self.monitorDataInput.value)
|
||||
if self.monitorDataInput.currentDigit == 0: # that was the second keypress, so go to the next addresss
|
||||
self.IP = (self.IP + 1) % 256
|
||||
print("ADVANCING")
|
||||
print("Acc", self.acc, "IP", self.IP, "Data", self.memory[self.IP], "\n")
|
||||
|
||||
|
||||
def step(self):
|
||||
if self.IP >= 256:
|
||||
self.IP = 0
|
||||
|
|
@ -159,29 +64,16 @@ class CPU:
|
|||
self.IP = self.IP+1
|
||||
self.instruction['operand'] = self.memory[self.IP]
|
||||
self.IP = self.IP+1
|
||||
self.nums2mnems[self.instruction['opcode']](self, self.instruction['operand'])
|
||||
|
||||
print("instr:", self.instruction['opcode'], self.instruction['operand'])
|
||||
print("mnem:", self.nums2mnems[self.instruction['opcode']])
|
||||
self.nums2mnems[self.instruction['opcode']](self, self.instruction['operand'])
|
||||
print("acc:", self.acc)
|
||||
print("running:", self.running)
|
||||
print()
|
||||
# self.print_screen()
|
||||
print("byte 26 (keyboard):", self.memory[26])
|
||||
print()
|
||||
# if not self.running:
|
||||
# exit()
|
||||
|
||||
def run(self):
|
||||
self.start()
|
||||
t = time.time()
|
||||
while (time.time() - t) < 30:
|
||||
self.read_keys()
|
||||
if self.running:
|
||||
self.step()
|
||||
self.print_monitor()
|
||||
time.sleep(0.5)
|
||||
print("timeout")
|
||||
print(self.memory)
|
||||
|
||||
def hlt(self, operand):
|
||||
self.running = False
|
||||
|
|
@ -302,16 +194,134 @@ class CPU:
|
|||
28: ccl,
|
||||
}
|
||||
|
||||
cpu = CPU()
|
||||
|
||||
prog = '04 FF 04 01 14 01 00 00'
|
||||
### MEOWBIT-SPECIFIC STUFF ###
|
||||
|
||||
# to list board features: print(board.__dir__)
|
||||
|
||||
btna = DigitalInOut(board.BTNA)
|
||||
btna.direction = Direction.INPUT
|
||||
btna.pull = Pull.UP # down doesn't work
|
||||
|
||||
btnb = DigitalInOut(board.BTNB)
|
||||
btnb.direction = Direction.INPUT
|
||||
btnb.pull = Pull.UP # down doesn't work
|
||||
|
||||
btnr = DigitalInOut(board.RIGHT)
|
||||
btnr.direction = Direction.INPUT
|
||||
btnr.pull = Pull.UP # down doesn't work
|
||||
|
||||
km = keypad.KeyMatrix(
|
||||
row_pins = (board.P0, board.P1, board.P2, board.P3),
|
||||
column_pins = (board.P4, board.P6, board.P8, board.P9) )
|
||||
|
||||
# This is global because that way you can update the text by just altering text_area.text
|
||||
displayGroup = displayio.Group()
|
||||
board.DISPLAY.root_group = displayGroup
|
||||
text_area = label.Label(terminalio.FONT, text="")
|
||||
text_area.x = 10
|
||||
text_area.y = 10
|
||||
displayGroup.append(text_area)
|
||||
|
||||
palette = displayio.Palette(1)
|
||||
palette[0] = 0xff00ff
|
||||
|
||||
|
||||
class Monitor:
|
||||
def __init__(self, cpu):
|
||||
self.cpu = cpu
|
||||
self.monitorMode = 'addressEntry' # or dataEntry
|
||||
self.monitorAddressInput = TwoDigitHexInput()
|
||||
self.monitorDataInput = TwoDigitHexInput()
|
||||
|
||||
def handleKeys(self):
|
||||
keypad_event = km.events.get()
|
||||
keyPressed = True if (keypad_event and keypad_event.released) else False
|
||||
key = keypad_event.key_number if keyPressed else False
|
||||
|
||||
if self.cpu.running:
|
||||
if btna.value == False:
|
||||
print("HALT PRESSED")
|
||||
self.cpu.running = False
|
||||
time.sleep(0.5) # lazy debounce
|
||||
# km.events.clear() # don't track keypresses from during the run
|
||||
|
||||
if keyPressed:
|
||||
self.cpu.memory[26] = key
|
||||
|
||||
elif not self.cpu.running:
|
||||
if btna.value == False:
|
||||
self.cpu.running = True
|
||||
print("\nSTARTING")
|
||||
time.sleep(0.5) # lazy debounce
|
||||
|
||||
if btnb.value == False:
|
||||
self.monitorMode = 'addressEntry' if self.monitorMode != 'addressEntry' else 'dataEntry'
|
||||
print("\nENTERING", self.monitorMode, "MODE")
|
||||
self.monitorDataInput.currentDigit = 0
|
||||
self.monitorAddressInput.currentDigit = 0
|
||||
time.sleep(0.5) # lazy debounce
|
||||
|
||||
if btnr.value == False:
|
||||
print("\nSINGLE STEP FROM MONITOR ADDR")
|
||||
# self.IP = self.monitorAddressInput.value
|
||||
self.cpu.step()
|
||||
time.sleep(0.5) # lazy debounce
|
||||
|
||||
if keypad_event and keypad_event.released:
|
||||
if self.monitorMode == 'addressEntry':
|
||||
self.monitorAddressInput.input(keypad_event.key_number)
|
||||
self.cpu.IP = self.monitorAddressInput.value
|
||||
print("MA", self.IP)
|
||||
|
||||
else:
|
||||
self.monitorDataInput.input(keypad_event.key_number)
|
||||
self.cpu.memory[self.IP] = self.monitorDataInput.value
|
||||
print("MD", self.monitorDataInput.value)
|
||||
if self.monitorDataInput.currentDigit == 0: # that was the second keypress, so go to the next addresss
|
||||
self.cpu.IP = (self.cpu.IP + 1) % 256
|
||||
print("ADVANCING")
|
||||
print("Acc", self.cpu.acc, "IP", self.cpu.IP, "Data", self.cpu.memory[self.cpu.IP], "\n")
|
||||
|
||||
def printMonitor(self):
|
||||
text = "IP " + str(self.cpu.IP) + "\tDATA " + str(self.cpu.memory[self.cpu.IP]) + "\tACC " + str(self.cpu.acc) + "\nRunning: " + str(self.cpu.running)
|
||||
text_area.text = text
|
||||
|
||||
|
||||
def printScreen(self):
|
||||
for i in range(5):
|
||||
for j in range(5):
|
||||
memory_index = (i * 5) + j
|
||||
if self.cpu.memory[memory_index] > 0:
|
||||
print("#", end=" ")
|
||||
circle = vectorio.Circle(pixel_shader=palette, radius=8, x=(10 + (j * 20)), y=(40 + (i * 20)))
|
||||
displayGroup.append(circle)
|
||||
else:
|
||||
print("_", end=" ")
|
||||
print()
|
||||
|
||||
def run(self):
|
||||
self.cpu.start()
|
||||
t = time.time()
|
||||
while (time.time() - t) < 30:
|
||||
self.handleKeys()
|
||||
if self.cpu.running:
|
||||
self.cpu.step()
|
||||
self.printMonitor()
|
||||
# self.printScreen()
|
||||
time.sleep(0.5)
|
||||
print("timeout")
|
||||
print(self.cpu.memory)
|
||||
|
||||
|
||||
cpu = CPU()
|
||||
monitor = Monitor(cpu)
|
||||
|
||||
prog = '04 FF 04 01 14 01 00 00 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01 01'
|
||||
#prog = '00'
|
||||
program_bytes = bytearray.fromhex(prog.replace(" ", ""))
|
||||
# Add jmp at addr 254:
|
||||
program_with_jump = program_bytes + bytearray(254 - len(program_bytes)) + bytearray.fromhex('0600')
|
||||
cpu.load_memory(program_with_jump)
|
||||
|
||||
# cpu.start()
|
||||
# cpu.step()
|
||||
|
||||
cpu.run()
|
||||
monitor.run()
|
||||
Loading…
Reference in New Issue