Exemple #1
0
class KeyboardTest(BaseDCPU16Test, unittest.TestCase):
    def setUp(self):
        self.device = Keyboard()
        self.cpu = DCPU16([self.device])

    def test_multiple_interrupts(self):
        self.cpu.ram[:5] = [
            # ias, :handler
            0x7d40, 0x0007,
            # turn on hardware interrupts with message "0xbeef"
            # set a, 3 / set b, 0xbeef / hwi, 0
            0x9001, 0x7c21, 0xbeef, 0x8640,
            # sub pc, 1
            0x8b83,
            # handler:
            # get the keypress from the device: set a, 1 / hwi, 0
            0x8801, 0x8640,
            # rfi 0
            0x8560
        ]
        # cycle 6 times
        for _ in xrange(6):
            self.cpu.cycle()
        # feed the keyboard "A"
        self.device.register_keypress(ord("A"))
        # cycle some more
        for _ in xrange(3):
            self.cpu.cycle()
        # make sure we got a message.
        self.assertRegister("C", ord("A"))
        # make the device interrupt again
        self.device.register_keypress(ord("B"))
        for _ in xrange(3):
            self.cpu.cycle()
        self.assertRegister("C", ord("B"))
Exemple #2
0
 def __init__(self, code):
     self.keyboard = Keyboard()
     self.display = LEM1802(self.change_font, self.change_letter,
             self.change_palette)
     # things that have changed since we last talked to the client.
     self.letters_changed = {}
     # start out by passing all of the font
     self.chars_changed = dict(enumerate(char_to_bitmap(*t) for t in
         # group them into twos and call char_to_bitmap on each pair
         zip(*[iter(self.display.font)]*2)))
     self.border_color = None
     self.errors = []
     # intialize the cpu
     self.cpu = DCPU16([self.keyboard, self.display])
     # read the code from the factory to the RAM
     self.cpu.ram[:len(code)] = code
Exemple #3
0
class DCPU16Protocol(protocol.Protocol):
    cycle_counter = 0

    def __init__(self, code):
        self.keyboard = Keyboard()
        self.display = LEM1802(self.change_font, self.change_letter,
                self.change_palette)
        # things that have changed since we last talked to the client.
        self.letters_changed = {}
        # start out by passing all of the font
        self.chars_changed = dict(enumerate(char_to_bitmap(*t) for t in
            # group them into twos and call char_to_bitmap on each pair
            zip(*[iter(self.display.font)]*2)))
        self.border_color = None
        self.errors = []
        # intialize the cpu
        self.cpu = DCPU16([self.keyboard, self.display])
        # read the code from the factory to the RAM
        self.cpu.ram[:len(code)] = code

    def change_palette(self, index, value):
        #TODO: change the palette -- not sure how this will work.
        pass

    def change_font(self, index, value):
        #TODO: change a font character.
        pass

    def change_border(self, index, value):
        #TODO: format the border color as an html/css hex color.
        pass

    def change_letter(self, index, foreground, background, blink, char):
        "This is called whenever a cell of vram is changed."
        x, y = divmod(index, 32)
        self.letters_changed[x, y] = {
            "x": x, "y": y, "char": char, "blink": blink,
            # format the background and foreground tuples as html/css colors.
            "foreground": "#%03x" % self.display.palette[foreground],
            "background": "#%03x" % self.display.palette[background],
        }

    def dataReceived(self, data):
        # get the keypresses and the number of cycles from the frontend
        keypresses, count = json.loads(data)
        for k in keypresses:
            # hand these to the keyboard
            self.keyboard.register_keypress(k)
        try:
            # cycle as many times as we're supposed to,
            for _ in xrange(count):
                self.cpu.cycle()
        # if we get any errors, let the frontend know.
        except Exception as e:
            self.errors.append(str(e))
            raise
        # and then pass everything to the frontend.
        self.write_changes()

    def write_changes(self):
        "Write the changes to the websockets client and reset."
        changes = {
            # None if there's no new background color, otherwise a color.
            "background": self.border_color,
            # the cells that have been changed since last time
            "cells": self.letters_changed.values(),
            # the characters (fonts) that have been changed
            "characters": self.chars_changed,
            # any errors we've encountered
            "errors": self.errors,
            # whether the frontend should stop.
            "halt": False,
        }
        # reset everything
        self.transport.write(json.dumps(changes))
        self.letters_changed = {}
        self.chars_changed = {}
        self.border_color = None
        self.errors = []
Exemple #4
0
 def setUp(self):
     self.device = Keyboard()
     self.cpu = DCPU16([self.device])