Compare commits
11 Commits
rearchitec
...
main
| Author | SHA1 | Date |
|---|---|---|
|
|
ceb6019a1c | |
|
|
353b7d7fdc | |
|
|
82c0283b25 | |
|
|
3261b6c97a | |
|
|
f3f6a58a65 | |
|
|
0b91a71575 | |
|
|
144ae8de6c | |
|
|
dee5b4afd4 | |
|
|
e6883fbc65 | |
|
|
072d2ccdb5 | |
|
|
9f4a67770f |
|
|
@ -2,4 +2,6 @@
|
||||||
.vscode
|
.vscode
|
||||||
*.tmp.*
|
*.tmp.*
|
||||||
node_modules
|
node_modules
|
||||||
cardiograph.code-workspace
|
cardiograph.code-workspace
|
||||||
|
*venv*
|
||||||
|
*__pycache__
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,6 @@
|
||||||
[submodule "src/argparser"]
|
[submodule "src/argparser"]
|
||||||
path = src/opter
|
path = src/opter
|
||||||
url = https://git.nloewen.com/n/argv-parser.git
|
url = https://git.nloewen.com/n/argv-parser.git
|
||||||
|
[submodule "src/python/opter-py"]
|
||||||
|
path = src/python/opter-py
|
||||||
|
url = https://git.nloewen.com/n/opter-py.git
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,15 @@ Cardiograph is an imaginary computer. It has three main components:
|
||||||
|
|
||||||
## Simulator
|
## Simulator
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
Cardiograph is an imaginary computer. It has three main components:
|
||||||
|
|
||||||
|
1. the CPU, *Card* (short for 'Completely Analogue Risc Machine')
|
||||||
|
2. an input-output processor, *IO*
|
||||||
|
3. a display, *Graph*
|
||||||
|
|
||||||
|
## Simulator
|
||||||
|
|
||||||
### Dependencies
|
### Dependencies
|
||||||
|
|
||||||
- Node.js
|
- Node.js
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import board
|
||||||
|
import displayio
|
||||||
|
import vectorio
|
||||||
|
import terminalio
|
||||||
|
from adafruit_display_text import label
|
||||||
|
|
||||||
|
group = displayio.Group()
|
||||||
|
board.DISPLAY.root_group = group
|
||||||
|
|
||||||
|
text = "Hello world"
|
||||||
|
text_area = label.Label(terminalio.FONT, text=text)
|
||||||
|
text_area.x = 10
|
||||||
|
text_area.y = 10
|
||||||
|
group.append(text_area)
|
||||||
|
|
||||||
|
palette = displayio.Palette(1)
|
||||||
|
palette[0] = 0xff00ff
|
||||||
|
|
||||||
|
circle = vectorio.Circle(pixel_shader=palette, radius=5, x=5, y=5)
|
||||||
|
group.append(circle)
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
#meowbit
|
||||||
|
|
||||||
|
import keypad
|
||||||
|
import board
|
||||||
|
|
||||||
|
km = keypad.KeyMatrix(
|
||||||
|
row_pins = (board.P0, board.P1, board.P2, board.P3),
|
||||||
|
column_pins = (board.P4, board.P6, board.P8, board.P9) )
|
||||||
|
|
||||||
|
while True:
|
||||||
|
event = km.events.get()
|
||||||
|
if event:
|
||||||
|
print(event.key_number, event.released)
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
import time
|
||||||
|
import board
|
||||||
|
import neopixel
|
||||||
|
|
||||||
|
pixels = neopixel.NeoPixel(board.A3, 5*5, brightness=0.5, auto_write=True)
|
||||||
|
|
||||||
|
for i in range(50):
|
||||||
|
pixels.fill((50, 0, 0)) # red
|
||||||
|
time.sleep(0.5)
|
||||||
|
pixels.fill((0,0,50)) # blue
|
||||||
|
time.sleep(0.5)
|
||||||
|
print(i)
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,181 @@
|
||||||
|
# SPDX-FileCopyrightText: 2016 Damien P. George
|
||||||
|
# SPDX-FileCopyrightText: 2017 Scott Shawcroft for Adafruit Industries
|
||||||
|
# SPDX-FileCopyrightText: 2019 Carter Nelson
|
||||||
|
# SPDX-FileCopyrightText: 2019 Roy Hooper
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
"""
|
||||||
|
`neopixel` - NeoPixel strip driver
|
||||||
|
====================================================
|
||||||
|
|
||||||
|
* Author(s): Damien P. George, Scott Shawcroft, Carter Nelson, Rose Hooper
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import board
|
||||||
|
import digitalio
|
||||||
|
from neopixel_write import neopixel_write
|
||||||
|
|
||||||
|
import adafruit_pixelbuf
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Used only for typing
|
||||||
|
from typing import Optional, Type
|
||||||
|
from types import TracebackType
|
||||||
|
import microcontroller
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
__version__ = "6.3.15"
|
||||||
|
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_NeoPixel.git"
|
||||||
|
|
||||||
|
|
||||||
|
# Pixel color order constants
|
||||||
|
RGB = "RGB"
|
||||||
|
"""Red Green Blue"""
|
||||||
|
GRB = "GRB"
|
||||||
|
"""Green Red Blue"""
|
||||||
|
RGBW = "RGBW"
|
||||||
|
"""Red Green Blue White"""
|
||||||
|
GRBW = "GRBW"
|
||||||
|
"""Green Red Blue White"""
|
||||||
|
|
||||||
|
|
||||||
|
class NeoPixel(adafruit_pixelbuf.PixelBuf):
|
||||||
|
"""
|
||||||
|
A sequence of neopixels.
|
||||||
|
|
||||||
|
:param ~microcontroller.Pin pin: The pin to output neopixel data on.
|
||||||
|
:param int n: The number of neopixels in the chain
|
||||||
|
:param int bpp: Bytes per pixel. 3 for RGB and 4 for RGBW pixels.
|
||||||
|
:param float brightness: Brightness of the pixels between 0.0 and 1.0 where 1.0 is full
|
||||||
|
brightness
|
||||||
|
:param bool auto_write: True if the neopixels should immediately change when set. If False,
|
||||||
|
`show` must be called explicitly.
|
||||||
|
:param str pixel_order: Set the pixel color channel order. The default is GRB if bpp is set
|
||||||
|
to 3, otherwise GRBW is used as the default.
|
||||||
|
|
||||||
|
Example for Circuit Playground Express:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import neopixel
|
||||||
|
from board import *
|
||||||
|
|
||||||
|
RED = 0x100000 # (0x10, 0, 0) also works
|
||||||
|
|
||||||
|
pixels = neopixel.NeoPixel(NEOPIXEL, 10)
|
||||||
|
for i in range(len(pixels)):
|
||||||
|
pixels[i] = RED
|
||||||
|
|
||||||
|
Example for Circuit Playground Express setting every other pixel red using a slice:
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
import neopixel
|
||||||
|
from board import *
|
||||||
|
import time
|
||||||
|
|
||||||
|
RED = 0x100000 # (0x10, 0, 0) also works
|
||||||
|
|
||||||
|
# Using ``with`` ensures pixels are cleared after we're done.
|
||||||
|
with neopixel.NeoPixel(NEOPIXEL, 10) as pixels:
|
||||||
|
pixels[::2] = [RED] * (len(pixels) // 2)
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
.. py:method:: NeoPixel.show()
|
||||||
|
|
||||||
|
Shows the new colors on the pixels themselves if they haven't already
|
||||||
|
been autowritten.
|
||||||
|
|
||||||
|
The colors may or may not be showing after this function returns because
|
||||||
|
it may be done asynchronously.
|
||||||
|
|
||||||
|
.. py:method:: NeoPixel.fill(color)
|
||||||
|
|
||||||
|
Colors all pixels the given ***color***.
|
||||||
|
|
||||||
|
.. py:attribute:: brightness
|
||||||
|
|
||||||
|
Overall brightness of the pixel (0 to 1.0)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
pin: microcontroller.Pin,
|
||||||
|
n: int,
|
||||||
|
*,
|
||||||
|
bpp: int = 3,
|
||||||
|
brightness: float = 1.0,
|
||||||
|
auto_write: bool = True,
|
||||||
|
pixel_order: str = None
|
||||||
|
):
|
||||||
|
if not pixel_order:
|
||||||
|
pixel_order = GRB if bpp == 3 else GRBW
|
||||||
|
elif isinstance(pixel_order, tuple):
|
||||||
|
order_list = [RGBW[order] for order in pixel_order]
|
||||||
|
pixel_order = "".join(order_list)
|
||||||
|
|
||||||
|
self._power = None
|
||||||
|
if (
|
||||||
|
sys.implementation.version[0] >= 7
|
||||||
|
and getattr(board, "NEOPIXEL", None) == pin
|
||||||
|
):
|
||||||
|
power = getattr(board, "NEOPIXEL_POWER_INVERTED", None)
|
||||||
|
polarity = power is None
|
||||||
|
if not power:
|
||||||
|
power = getattr(board, "NEOPIXEL_POWER", None)
|
||||||
|
if power:
|
||||||
|
try:
|
||||||
|
self._power = digitalio.DigitalInOut(power)
|
||||||
|
self._power.switch_to_output(value=polarity)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
super().__init__(
|
||||||
|
n, brightness=brightness, byteorder=pixel_order, auto_write=auto_write
|
||||||
|
)
|
||||||
|
|
||||||
|
self.pin = digitalio.DigitalInOut(pin)
|
||||||
|
self.pin.direction = digitalio.Direction.OUTPUT
|
||||||
|
|
||||||
|
def deinit(self) -> None:
|
||||||
|
"""Blank out the NeoPixels and release the pin."""
|
||||||
|
self.fill(0)
|
||||||
|
self.show()
|
||||||
|
self.pin.deinit()
|
||||||
|
if self._power:
|
||||||
|
self._power.deinit()
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(
|
||||||
|
self,
|
||||||
|
exception_type: Optional[Type[BaseException]],
|
||||||
|
exception_value: Optional[BaseException],
|
||||||
|
traceback: Optional[TracebackType],
|
||||||
|
):
|
||||||
|
self.deinit()
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "[" + ", ".join([str(x) for x in self]) + "]"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def n(self) -> int:
|
||||||
|
"""
|
||||||
|
The number of neopixels in the chain (read-only)
|
||||||
|
"""
|
||||||
|
return len(self)
|
||||||
|
|
||||||
|
def write(self) -> None:
|
||||||
|
""".. deprecated: 1.0.0
|
||||||
|
|
||||||
|
Use ``show`` instead. It matches Micro:Bit and Arduino APIs."""
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
def _transmit(self, buffer: bytearray) -> None:
|
||||||
|
neopixel_write(self.pin, buffer)
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
# Open the binary file in read-binary mode
|
||||||
|
with open('test-multiply.bin', 'rb') as file:
|
||||||
|
# Read the entire file contents
|
||||||
|
binary_data = file.read()
|
||||||
|
|
||||||
|
# Convert the binary data to a string of hex bytes
|
||||||
|
hex_string = binary_data.hex()
|
||||||
|
|
||||||
|
# Print the hex string
|
||||||
|
print(hex_string)
|
||||||
|
|
||||||
|
|
||||||
|
# Open the binary file in read-binary mode
|
||||||
|
with open('test-multiply.bin', 'rb') as file:
|
||||||
|
# Read the entire file contents into a bytearray
|
||||||
|
byte_data = bytearray(file.read())
|
||||||
|
|
||||||
|
# Print the bytearray
|
||||||
|
print(byte_data)
|
||||||
|
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,10 @@
|
||||||
|
import board
|
||||||
|
import busio
|
||||||
|
from adafruit_ht16k33 import matrix
|
||||||
|
i2c = busio.I2C(board.GP17, board.GP16) # scl, sda
|
||||||
|
|
||||||
|
matrix = matrix.Matrix8x8(i2c)
|
||||||
|
matrix.fill(0) # Clear the matrix.
|
||||||
|
matrix[0, 0] = 1
|
||||||
|
matrix.brightness = 1
|
||||||
|
matrix.blink_rate = 2
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
"""Example for pi pico. Blinking LED"""
|
||||||
|
|
||||||
|
import board
|
||||||
|
import digitalio
|
||||||
|
import time
|
||||||
|
|
||||||
|
led = digitalio.DigitalInOut(board.LED)
|
||||||
|
led.direction = digitalio.Direction.OUTPUT
|
||||||
|
|
||||||
|
led.value = True
|
||||||
|
|
||||||
|
for i in range(50):
|
||||||
|
led.value = not led.value
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
"""Example for pi pico. Button-controlled LED.
|
||||||
|
|
||||||
|
Wiring: switch to ground pin on pico, and to pin 18.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import board
|
||||||
|
import digitalio
|
||||||
|
|
||||||
|
led = digitalio.DigitalInOut(board.LED)
|
||||||
|
led.direction = digitalio.Direction.OUTPUT
|
||||||
|
|
||||||
|
switch = digitalio.DigitalInOut(board.GP18)
|
||||||
|
switch.direction = digitalio.Direction.INPUT
|
||||||
|
switch.pull = digitalio.Pull.UP
|
||||||
|
|
||||||
|
while True:
|
||||||
|
led.value = not switch.value
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
# pi pico
|
||||||
|
|
||||||
|
import keypad
|
||||||
|
import board
|
||||||
|
|
||||||
|
keymatrix = keypad.KeyMatrix(
|
||||||
|
row_pins = (board.GP5, board.GP6, board.GP7, board.GP8),
|
||||||
|
column_pins = (board.GP9, board.GP10, board.GP11, board.GP12, board.GP13) )
|
||||||
|
|
||||||
|
keymap = {
|
||||||
|
15:"0", 16:"1", 17:"2", 18:"3", 19:"runhalt",
|
||||||
|
10:"4", 11:"5", 12:"6", 13:"7", 14:"step",
|
||||||
|
5:"8", 6:"9", 7:"A", 8:"B", 9:"addrdata",
|
||||||
|
0:"C", 1:"D", 2:"E", 3:"F", 4:"NA" }
|
||||||
|
|
||||||
|
while True:
|
||||||
|
event = keymatrix.events.get()
|
||||||
|
if event:
|
||||||
|
print(event.key_number, event.released, keymap[event.key_number])
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
import board
|
||||||
|
import keypad
|
||||||
|
|
||||||
|
keymatrix = keypad.KeyMatrix(
|
||||||
|
row_pins = (board.GP5, board.GP6, board.GP7, board.GP8),
|
||||||
|
column_pins = (board.GP9, board.GP10, board.GP11, board.GP12, board.GP13) )
|
||||||
|
|
||||||
|
keymap = {
|
||||||
|
15:"0", 16:"1", 17:"2", 18:"3", 19:"runhalt",
|
||||||
|
10:"4", 11:"5", 12:"6", 13:"7", 14:"step",
|
||||||
|
5:"8", 6:"9", 7:"A", 8:"B", 9:"addr",
|
||||||
|
0:"C", 1:"D", 2:"E", 3:"F", 4:"data" }
|
||||||
|
|
||||||
|
while True:
|
||||||
|
keypad_event = keymatrix.events.get()
|
||||||
|
keyPressed = True if (keypad_event and keypad_event.released ) else False
|
||||||
|
key = keymap[keypad_event.key_number] if keyPressed else False
|
||||||
|
if key:
|
||||||
|
print(key)
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
"""Example for pi pico. Blinking LED"""
|
||||||
|
|
||||||
|
import board
|
||||||
|
import digitalio
|
||||||
|
import time
|
||||||
|
from tm1637_display import TM1637Display
|
||||||
|
|
||||||
|
display_1 = TM1637Display(board.GP0, board.GP1, length=4)
|
||||||
|
display_1.print("1234")
|
||||||
|
|
||||||
|
display_2 = TM1637Display(board.GP2, board.GP3, length=4)
|
||||||
|
display_2.print("ABCD")
|
||||||
|
|
||||||
|
print("end")
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
BSD 3-Clause License
|
||||||
|
|
||||||
|
Copyright (c) 2013-2024, Kim Davies and contributors.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
||||||
|
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
@ -0,0 +1,164 @@
|
||||||
|
import time
|
||||||
|
|
||||||
|
class CPU:
|
||||||
|
def __init__(self):
|
||||||
|
self.running = False
|
||||||
|
self.IP = 254
|
||||||
|
self.acc = 0
|
||||||
|
self.flags = { 'C': False, 'Z': False, 'N': False, 'Eq': False }
|
||||||
|
self.instruction = { 'opcode': False, 'operand': False }
|
||||||
|
self.memory = False
|
||||||
|
|
||||||
|
|
||||||
|
def load_memory(self, bytes):
|
||||||
|
self.memory = bytes + bytearray(256 - len(bytes))
|
||||||
|
# print(self.memory)
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self.running = True
|
||||||
|
|
||||||
|
def step(self):
|
||||||
|
if self.IP >= 255: # TODO CHECK
|
||||||
|
self.IP = 0
|
||||||
|
print("IP:", toHex(self.IP))
|
||||||
|
self.instruction['opcode'] = self.memory[self.IP]
|
||||||
|
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:", toHex(self.instruction['opcode']), toHex(self.instruction['operand']))
|
||||||
|
print("mnem:", self.nums2mnems[self.instruction['opcode']])
|
||||||
|
print("acc:", self.acc, "N:", self.flags['N'])
|
||||||
|
print("running:", self.running)
|
||||||
|
print()
|
||||||
|
# self.print_screen()
|
||||||
|
print("byte 26 (keyboard):", self.memory[26])
|
||||||
|
print()
|
||||||
|
|
||||||
|
def hlt(self, operand):
|
||||||
|
self.running = False
|
||||||
|
|
||||||
|
def nop(self, operand):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def lda_lit(self, operand):
|
||||||
|
self.acc = operand
|
||||||
|
self.flags['Z'] = True if self.acc == 0 else False
|
||||||
|
self.flags['Eq'] = True if self.acc == operand else False
|
||||||
|
self.flags['N'] = True if self.acc > 127 else False
|
||||||
|
|
||||||
|
def lda_mem(self, operand):
|
||||||
|
self.acc = self.memory[operand]
|
||||||
|
self.flags['Z'] = True if self.acc == 0 else False
|
||||||
|
self.flags['Eq'] = True if self.acc == operand else False
|
||||||
|
self.flags['N'] = True if self.acc > 127 else False
|
||||||
|
|
||||||
|
def sta_lit(self, operand):
|
||||||
|
self.memory[operand] = self.acc
|
||||||
|
|
||||||
|
def sta_mem(self, operand):
|
||||||
|
self.memory[self.memory[operand]] = self.acc
|
||||||
|
|
||||||
|
def add_lit(self, operand):
|
||||||
|
self.acc = self.acc + operand
|
||||||
|
if self.acc > 255:
|
||||||
|
self.acc = self.acc % 256
|
||||||
|
self.flags['C'] = True
|
||||||
|
else:
|
||||||
|
self.flags['C'] = False
|
||||||
|
self.flags['Z'] = True if self.acc == 0 else False
|
||||||
|
self.flags['Eq'] = True if self.acc == operand else False
|
||||||
|
self.flags['N'] = True if self.acc > 127 else False
|
||||||
|
|
||||||
|
def add_mem(self, operand):
|
||||||
|
self.acc = self.acc + self.memory[operand]
|
||||||
|
if self.acc > 255:
|
||||||
|
self.acc = self.acc % 256
|
||||||
|
self.flags['C'] = True
|
||||||
|
else:
|
||||||
|
self.flags['C'] = False
|
||||||
|
self.flags['Z'] = True if self.acc == 0 else False
|
||||||
|
self.flags['Eq'] = True if self.acc == operand else False
|
||||||
|
self.flags['N'] = True if self.acc > 127 else False
|
||||||
|
|
||||||
|
def sub_lit(self, operand):
|
||||||
|
self.acc = self.acc - operand
|
||||||
|
if self.acc < 0:
|
||||||
|
self.acc = self.acc % 256
|
||||||
|
self.flags['C'] = True
|
||||||
|
else:
|
||||||
|
self.flags['C'] = False
|
||||||
|
self.flags['Z'] = True if self.acc == 0 else False
|
||||||
|
self.flags['Eq'] = True if self.acc == operand else False
|
||||||
|
self.flags['N'] = True if self.acc > 127 else False
|
||||||
|
|
||||||
|
def sub_mem(self, operand):
|
||||||
|
self.acc = self.acc - self.memory[operand]
|
||||||
|
if self.acc > 255:
|
||||||
|
self.acc = self.acc % 256
|
||||||
|
self.flags['C'] = True
|
||||||
|
else:
|
||||||
|
self.flags['C'] = False
|
||||||
|
self.flags['Z'] = True if self.acc == 0 else False
|
||||||
|
self.flags['Eq'] = True if self.acc == operand else False
|
||||||
|
self.flags['N'] = True if self.acc > 127 else False
|
||||||
|
|
||||||
|
def jmp_lit(self, operand):
|
||||||
|
self.IP = operand
|
||||||
|
|
||||||
|
def jmp_mem(self, operand):
|
||||||
|
self.IP = self.memory[operand]
|
||||||
|
|
||||||
|
def ske(self, operand): # FIXME
|
||||||
|
# if self.flags['Eq']:
|
||||||
|
# self.IP += 2
|
||||||
|
if self.acc == operand:
|
||||||
|
self.IP += 2
|
||||||
|
|
||||||
|
def skz(self, operand):
|
||||||
|
if self.flags['Z']:
|
||||||
|
self.IP += 2
|
||||||
|
|
||||||
|
def skn(self, operand):
|
||||||
|
if self.flags['N']:
|
||||||
|
self.IP += 2
|
||||||
|
|
||||||
|
def skc(self, operand):
|
||||||
|
if self.flags['C']:
|
||||||
|
self.IP += 2
|
||||||
|
|
||||||
|
def cst(self, operand):
|
||||||
|
self.flags['C'] = True
|
||||||
|
|
||||||
|
def ccl(self, operand):
|
||||||
|
self.flags['C'] = False
|
||||||
|
|
||||||
|
nums2mnems = {
|
||||||
|
0: hlt, # x0
|
||||||
|
1: nop, # x1
|
||||||
|
2: lda_lit, # 02
|
||||||
|
3: sta_lit, # 03
|
||||||
|
4: add_lit, # 04
|
||||||
|
5: sub_lit, # 05
|
||||||
|
6: jmp_lit, # 06
|
||||||
|
7: ske, # x7
|
||||||
|
8: skz, # x8
|
||||||
|
9: skn, # x9
|
||||||
|
10: skc, # A
|
||||||
|
11: cst, # B
|
||||||
|
12: ccl, # C
|
||||||
|
16: hlt, #
|
||||||
|
17: nop, #
|
||||||
|
18: lda_mem, # 12
|
||||||
|
19: sta_mem, # 13
|
||||||
|
20: add_mem, # 14
|
||||||
|
21: sub_mem, # 15
|
||||||
|
22: jmp_mem, # 16
|
||||||
|
23: ske,
|
||||||
|
24: skz,
|
||||||
|
25: skn,
|
||||||
|
26: skc,
|
||||||
|
27: cst,
|
||||||
|
28: ccl,
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
numericKeys = [ "0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F" ]
|
||||||
|
|
||||||
|
def toHex(n):
|
||||||
|
return "%0.2X" % n
|
||||||
|
|
||||||
|
class Monitor:
|
||||||
|
def __init__(self, cpu):
|
||||||
|
self.cpu = cpu
|
||||||
|
self.monitorMode = 'addressEntry' # or dataEntry
|
||||||
|
self.monitorAddressInput = TwoDigitHexInput()
|
||||||
|
self.monitorDataInput = TwoDigitHexInput()
|
||||||
|
|
||||||
|
# In data entry mode, when a full byte is keyed in,
|
||||||
|
# the next keypress advances to the next address and continues entering data there.
|
||||||
|
# This variable tracks whether it's time to do that or not.
|
||||||
|
self.advanceDataEntryNextPress = False
|
||||||
|
|
||||||
|
def handleKeys(self):
|
||||||
|
keypad_event = keymatrix.events.get()
|
||||||
|
keyPressed = True if (keypad_event and keypad_event.released ) else False
|
||||||
|
key = keymap[keypad_event.key_number] if keyPressed else False
|
||||||
|
numericKeyPressed = True if (keyPressed and (key in numericKeys)) else False
|
||||||
|
|
||||||
|
|
||||||
|
if self.cpu.running:
|
||||||
|
if key == "runhalt":
|
||||||
|
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 numericKeyPressed:
|
||||||
|
self.cpu.memory[26] = int(key, 16)
|
||||||
|
|
||||||
|
elif not self.cpu.running:
|
||||||
|
if key == "runhalt":
|
||||||
|
self.cpu.running = True
|
||||||
|
print("\nSTARTING")
|
||||||
|
time.sleep(0.5) # lazy debounce
|
||||||
|
|
||||||
|
if key == "addr":
|
||||||
|
self.monitorMode = 'addressEntry'
|
||||||
|
print("\nENTERING", self.monitorMode, "MODE")
|
||||||
|
self.monitorAddressInput.currentDigit = 0
|
||||||
|
time.sleep(0.5) # lazy debounce
|
||||||
|
if key == "data":
|
||||||
|
self.monitorMode = 'dataEntry'
|
||||||
|
print("\nENTERING", self.monitorMode, "MODE")
|
||||||
|
self.monitorDataInput.clear()
|
||||||
|
self.advanceDataEntryNextPress = False
|
||||||
|
time.sleep(0.5) # lazy debounce
|
||||||
|
|
||||||
|
if key == "step":
|
||||||
|
print("\nSINGLE STEP FROM MONITOR ADDR")
|
||||||
|
# self.IP = self.monitorAddressInput.value
|
||||||
|
self.cpu.step()
|
||||||
|
time.sleep(0.5) # lazy debounce
|
||||||
|
|
||||||
|
if numericKeyPressed:
|
||||||
|
if self.monitorMode == 'addressEntry':
|
||||||
|
self.monitorAddressInput.input(int(key, 16))
|
||||||
|
self.cpu.IP = self.monitorAddressInput.value
|
||||||
|
print("MA", self.cpu.IP)
|
||||||
|
|
||||||
|
if self.monitorMode == 'dataEntry':
|
||||||
|
if self.advanceDataEntryNextPress:
|
||||||
|
print("ADVANCING")
|
||||||
|
self.cpu.IP = (self.cpu.IP + 1) % 256
|
||||||
|
# self.monitorDataInput.clear() # reset .currentDigit
|
||||||
|
self.monitorDataInput.set(self.cpu.memory[self.cpu.IP])
|
||||||
|
self.advanceDataEntryNextPress = False
|
||||||
|
self.monitorDataInput.input(int(key, 16))
|
||||||
|
self.cpu.memory[self.cpu.IP] = self.monitorDataInput.value
|
||||||
|
print("MD", self.monitorDataInput.value)
|
||||||
|
if self.monitorDataInput.currentDigit == 0: # that was the second keypress, so next keypress is for the next address
|
||||||
|
self.advanceDataEntryNextPress = True
|
||||||
|
|
||||||
|
print("Acc", self.cpu.acc, "IP", self.cpu.IP, "Data", self.cpu.memory[self.cpu.IP], "\n")
|
||||||
|
|
||||||
|
|
||||||
|
def displayScreen(self):
|
||||||
|
for x in range(8):
|
||||||
|
for y in range(8):
|
||||||
|
matrix[x, y] = self.cpu.memory[x + (8*y)]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
#self.cpu.start()
|
||||||
|
t = time.time()
|
||||||
|
while (time.time() - t) < 120: # TODO: add a time delta or sth maybe so this doesn't just burn cycles
|
||||||
|
self.handleKeys()
|
||||||
|
display_1.print(toHex(self.cpu.IP) + toHex(self.cpu.memory[self.cpu.IP]))
|
||||||
|
# display_1.print(toHex(self.monitorAddressInput.value) + toHex(self.cpu.memory[self.cpu.IP]))
|
||||||
|
# display_2.print(toHex(self.cpu.IP) + toHex(self.cpu.acc))
|
||||||
|
display_2.print(toHex(self.cpu.acc))
|
||||||
|
self.displayScreen()
|
||||||
|
if self.cpu.running:
|
||||||
|
self.cpu.step()
|
||||||
|
# time.sleep(0.5) # TODO ?
|
||||||
|
print("timeout")
|
||||||
|
print(self.cpu.memory)
|
||||||
|
|
||||||
|
|
||||||
|
cpu = CPU()
|
||||||
|
monitor = Monitor(cpu)
|
||||||
|
|
||||||
|
# preamble = '00 ' * 64
|
||||||
|
# prog = preamble + '02 01 13 f0 12 f0 04 02 03 f0 12 f0 05 41 08 00 06 40 00 00' # STRIPES
|
||||||
|
# offset = 64
|
||||||
|
# prog = preamble + '02 01 13 f0 12 f0 04 02 03 f0 05 08 09 00 04 09 03 f0 07 41 06' + toHex(offset) + '00 00'
|
||||||
|
#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') # jump to addr 00
|
||||||
|
# program_with_jump = program_bytes + bytearray(254 - len(program_bytes)) + bytearray.fromhex('0640') # jump to addr 0x40 (dec 64)
|
||||||
|
|
||||||
|
with open('test-multiply2.bin', 'rb') as file:
|
||||||
|
program_bytes = bytearray(file.read())
|
||||||
|
|
||||||
|
cpu.load_memory(program_bytes)
|
||||||
|
|
||||||
|
monitor.run()
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
import cpu
|
||||||
|
|
||||||
|
c = cpu.CPU()
|
||||||
|
|
||||||
|
print(c)
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 1d98a0707c3e61e362d2d3d5413b475437b5de0e
|
|
||||||
Loading…
Reference in New Issue