Przeglądaj źródła

Working version

Min 4 lat temu
rodzic
commit
347c85a630

+ 25 - 25
emulator/Makefile

@@ -3,69 +3,69 @@ all: MSP430 SERVER
 MSP430 : main.o utilities.o emu_server.o registers.o memspace.o debugger.o disassembler.o \
 	register_display.o decoder.o flag_handler.o formatI.o formatII.o formatIII.o \
 	usci.o port1.o packet_queue.o bcm.o timer_a.o
-
 	g++ -o MSP430 main.o emu_server.o utilities.o registers.o memspace.o debugger.o disassembler.o \
 	register_display.o decoder.o flag_handler.o formatI.o formatII.o formatIII.o usci.o port1.o bcm.o timer_a.o packet_queue.o -lreadline -lwebsockets -lpthread -lrt -lssl -lcrypto;
 
-libmsp430.so: main.o utilities.o emu_server.o registers.o memspace.o debugger.o disassembler.o \
+_msp430emu.so: main.o utilities.o emu_server.o registers.o memspace.o debugger.o disassembler.o \
 	register_display.o decoder.o flag_handler.o formatI.o formatII.o formatIII.o \
 	usci.o port1.o packet_queue.o bcm.o timer_a.o
-	g++ main.o emu_server.o utilities.o registers.o memspace.o debugger.o disassembler.o \
-	register_display.o decoder.o flag_handler.o formatI.o formatII.o formatIII.o usci.o port1.o bcm.o timer_a.o packet_queue.o -lreadline -lwebsockets -lpthread -lrt -lssl -lcrypto -shared -o libmsp430.so;
+	gcc $(LLFLAGS) main.o emu_server.o utilities.o registers.o memspace.o debugger.o disassembler.o \
+	register_display.o decoder.o flag_handler.o formatI.o formatII.o formatIII.o usci.o port1.o bcm.o timer_a.o packet_queue.o \
+	-lwebsockets -lreadline -lrt -lssl -lcrypto -lpthread -o _msp430emu.so -shared
 
-main.o : main.cpp
-	g++ -c -fPIC main.cpp
+main.o : main.c
+	gcc $(CCFLAGS) -c main.c
 
 utilities.o : devices/utilities.c
-	g++ -c -fPIC devices/utilities.c
+	gcc $(CCFLAGS) -c devices/utilities.c
 
 registers.o : devices/cpu/registers.c
-	g++ -c -fPIC devices/cpu/registers.c
+	gcc $(CCFLAGS) -c devices/cpu/registers.c
 
 memspace.o : devices/memory/memspace.c
-	g++ -c -fPIC devices/memory/memspace.c
+	gcc $(CCFLAGS) -c devices/memory/memspace.c
 
 debugger.o : debugger/debugger.c
-	g++ -c -fPIC debugger/debugger.c
+	gcc $(CCFLAGS) -c debugger/debugger.c
 
 disassembler.o : debugger/disassembler.c
-	g++ -c -fPIC debugger/disassembler.c
+	gcc $(CCFLAGS) -c debugger/disassembler.c
 
 register_display.o : debugger/register_display.c
-	g++ -c -fPIC debugger/register_display.c
+	gcc $(CCFLAGS) -c debugger/register_display.c
 
 decoder.o : devices/cpu/decoder.c
-	g++ -c -fPIC devices/cpu/decoder.c
+	gcc $(CCFLAGS) -c devices/cpu/decoder.c
 
 flag_handler.o : devices/cpu/flag_handler.c
-	g++ -c -fPIC devices/cpu/flag_handler.c
+	gcc $(CCFLAGS) -c devices/cpu/flag_handler.c
 
 formatI.o : devices/cpu/formatI.c
-	g++ -c -fPIC devices/cpu/formatI.c
+	gcc $(CCFLAGS) -c devices/cpu/formatI.c
 
 formatII.o : devices/cpu/formatII.c
-	g++ -c -fPIC devices/cpu/formatII.c
+	gcc $(CCFLAGS) -c devices/cpu/formatII.c
 
 formatIII.o : devices/cpu/formatIII.c
-	g++ -c -fPIC devices/cpu/formatIII.c
+	gcc $(CCFLAGS) -c devices/cpu/formatIII.c
 
 bcm.o : devices/peripherals/bcm.c
-	g++ -c -fPIC devices/peripherals/bcm.c
+	gcc $(CCFLAGS) -c devices/peripherals/bcm.c
 
 timer_a.o : devices/peripherals/timer_a.c
-	g++ -c -fPIC devices/peripherals/timer_a.c
+	gcc $(CCFLAGS) -c devices/peripherals/timer_a.c
 
 usci.o : devices/peripherals/usci.c
-	g++ -c -fPIC devices/peripherals/usci.c
+	gcc $(CCFLAGS) -c devices/peripherals/usci.c
 
 port1.o : devices/peripherals/port1.c
-	g++ -c -fPIC devices/peripherals/port1.c
+	gcc $(CCFLAGS) -c devices/peripherals/port1.c
 
-emu_server.o : debugger/websockets/emu_server.cpp
-	g++ -c -fPIC debugger/websockets/emu_server.cpp
+emu_server.o : debugger/websockets/emu_server.c
+	gcc $(CCFLAGS) -c debugger/websockets/emu_server.c
 
 packet_queue.o : debugger/websockets/packet_queue.c
-	g++ -c -fPIC debugger/websockets/packet_queue.c
+	gcc $(CCFLAGS) -c debugger/websockets/packet_queue.c
 
 # Server Program
 
@@ -77,7 +77,7 @@ server.o : debugger/server/server.c
 
 
 clean :
-	rm server.o main.o utilities.o emu_server.o registers.o \
+	rm py.o server.o main.o utilities.o emu_server.o registers.o \
 	memspace.o debugger.o disassembler.o \
 	register_display.o decoder.o flag_handler.o formatI.o \
 	formatII.o formatIII.o \

+ 1 - 1
emulator/debugger/disassembler.h

@@ -23,6 +23,6 @@
 #include "../devices/cpu/decoder.h"
 #include "../devices/cpu/registers.h"
 
-void disassemble(Emulator *emu, uint16_t start_addr, uint8_t times);
+extern void disassemble(Emulator *emu, uint16_t start_addr, uint8_t times);
 
 #endif

+ 16 - 5
emulator/debugger/websockets/emu_server.cpp

@@ -16,7 +16,7 @@
   along with this program. If not, see <https://www.gnu.org/licenses/>.
 */
 
-#include <string>
+#include <string.h>
 #include "emu_server.h"
 
 #define TXIFG 0x02
@@ -336,8 +336,14 @@ int callback_emu (struct lws *wsi, enum lws_callback_reasons reason, void *user,
                     puts("met bytes");
                     fclose(fp);
                    // system("msp430-objcopy -O binary tmp.elf tmp.bin");
-                    std::string ObjCopyLine = "objcopy -I elf32-little -O binary \"" + std::string(UploadFileName) + "\" tmp.bin";
-                    system(ObjCopyLine.c_str());
+                    char cmdline[255] = "objcopy -I elf32-little -O binary \"";
+                    strcat(cmdline, UploadFileName);
+                    strcat(cmdline, "\" tmp.bin");
+                    system(cmdline);
+
+//                    std::string ObjCopyLine = "objcopy -I elf32-little -O binary \"" + std::string(UploadFileName) + "\" tmp.bin";
+//                    system(ObjCopyLine.c_str());
+
 
                     deb->web_firmware_uploaded = true;
                     upload_in_progress = false;
@@ -393,8 +399,13 @@ int callback_emu (struct lws *wsi, enum lws_callback_reasons reason, void *user,
 	                    fclose(fp);
 
 	                    //system("msp430-objcopy -O binary tmp.elf tmp.bin");
-                        std::string ObjCopyLine = "objcopy -I elf32-little -O binary \"" + std::string(UploadFileName) + "\" tmp.bin";
-                        system(ObjCopyLine.c_str());
+//                        std::string ObjCopyLine = "objcopy -I elf32-little -O binary \"" + std::string(UploadFileName) + "\" tmp.bin";
+//                        system(ObjCopyLine.c_str());
+
+                        char cmdline[255] = "objcopy -I elf32-little -O binary \"";
+                        strcat(cmdline, UploadFileName);
+                        strcat(cmdline, "\" tmp.bin");
+                        system(cmdline);
 
 	                    deb->web_firmware_uploaded = true;
 	                    upload_in_progress = false;

+ 170 - 0
emulator/main.c

@@ -0,0 +1,170 @@
+/*
+  MSP430 Emulator
+  Copyright (C) 2020 Rudolf Geosits (rgeosits@live.esu.edu)
+  
+  "MSP430 Emulator" is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  "MSP430 Emulator" is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+  
+  You should have received a copy of the GNU General Public License
+  along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "main.h"
+#include <Python.h>
+
+// This is an ugly solution but heh
+Emulator *emuInst;
+
+static PyObject *method_run(PyObject *self, PyObject *args) {
+    unsigned int port;
+    if(!PyArg_ParseTuple(args, "H", &port)) {
+        return NULL;
+    }
+    Py_BEGIN_ALLOW_THREADS
+    run(port);
+    Py_END_ALLOW_THREADS
+    return Py_None;
+}
+
+static PyObject *method_stop(PyObject *self, PyObject *args) {
+    if(emuInst != NULL) {
+        emuInst->debugger->quit = true;
+    }
+    return Py_None;
+}
+
+static PyMethodDef RunMethods[] = {
+    {"run", method_run, METH_VARARGS, "Python function to start msp430 emulator"},
+    {"stop", method_stop, METH_NOARGS, "Python function to stop msp430 emulator"},
+    {NULL, NULL, 0, NULL}
+};
+
+static struct PyModuleDef msp430module = {
+    PyModuleDef_HEAD_INIT,
+    "_msp430emu",
+    "Python interface for msp430 emulator",
+    -1,
+    RunMethods
+};
+
+ PyMODINIT_FUNC PyInit__msp430emu(void) {
+    return PyModule_Create(&msp430module);
+}
+
+int run(unsigned int port) {
+
+    emuInst = (Emulator *) calloc( 1, sizeof(Emulator) );
+    Cpu *cpu = NULL; Debugger *deb = NULL;
+
+    emuInst->cpu       = (Cpu *) calloc(1, sizeof(Cpu));
+    emuInst->cpu->bcm  = (Bcm *) calloc(1, sizeof(Bcm));
+    emuInst->cpu->timer_a  = (Timer_a *) calloc(1, sizeof(Timer_a));
+    emuInst->cpu->p1   = (Port_1 *) calloc(1, sizeof(Port_1));
+    emuInst->cpu->usci = (Usci *) calloc(1, sizeof(Usci));
+
+    emuInst->debugger  = (Debugger *) calloc(1, sizeof(Debugger));
+    setup_debugger(emuInst);
+
+    cpu = emuInst->cpu;
+    deb = emuInst->debugger;
+
+    deb->server = (Server *) calloc(1, sizeof(Server));
+
+    if (deb->web_interface == true)
+        {
+            deb->ws_port = port;
+
+            pthread_t *t = &deb->web_server_thread;
+
+            if ( pthread_create(t, NULL, web_server, (void *)emuInst ) )
+            {
+                fprintf(stderr, "Error creating web server thread\n");
+                return 1;
+            }
+
+
+            while (!deb->web_server_ready)
+                usleep(10000);
+
+            print_console(emuInst, " [MSP430 Emulator]\n Copyright (C) 2020 Rudolf Geosits (rgeosits@live.esu.edu)\n");
+//            print_console(emuInst, " [!] Upload your firmware (ELF format only); Type 'h' for debugger options.\n\n");
+
+            while (!deb->web_firmware_uploaded)
+                usleep(10000);
+        }
+
+        //register_signal(SIGINT); // Register Callback for CONTROL-c
+
+        initialize_msp_memspace();
+        initialize_msp_registers(emuInst);
+
+        setup_bcm(emuInst);
+        setup_timer_a(emuInst);
+        setup_port_1(emuInst);
+        setup_usci(emuInst);
+
+        load_bootloader(0x0C00);
+
+        if (deb->web_interface)
+            load_firmware(emuInst, (char*)"tmp.bin", 0xC000);
+
+        // display first round of registers
+        display_registers(emuInst);
+        disassemble(emuInst, cpu->pc, 1);
+        update_register_display(emuInst);
+
+        // Fetch-Decode-Execute Cycle (run machine)
+        while (!deb->quit)
+        {
+            // Handle debugger when CPU is not running
+            if (!cpu->running)
+            {
+                usleep(10000);
+                continue;
+            }
+
+            // Handle Breakpoints
+            handle_breakpoints(emuInst);
+
+            // Instruction Decoder
+            decode(emuInst, fetch(emuInst), EXECUTE);
+
+            // Handle Peripherals
+            handle_bcm(emuInst);
+            handle_timer_a(emuInst);
+            handle_port_1(emuInst);
+            handle_usci(emuInst);
+
+            // Average of 4 cycles per instruction
+            mclk_wait_cycles(emuInst, 4);
+        }
+        uninitialize_msp_memspace();
+        free(cpu->timer_a);
+        free(cpu->bcm);
+        free(cpu->p1);
+        free(cpu->usci);
+        free(cpu);
+        free(deb->server);
+        free(deb);
+        free(emuInst);
+
+        return 0;
+}
+
+
+int main(int argc, char *argv[])
+{
+    if (argv[1] == NULL)
+    {
+        puts("Need port argument");
+        return(1);
+    }
+    return run(strtoul(argv[1], NULL, 10));
+}

+ 0 - 127
emulator/main.cpp

@@ -1,127 +0,0 @@
-/*
-  MSP430 Emulator
-  Copyright (C) 2020 Rudolf Geosits (rgeosits@live.esu.edu)
-  
-  "MSP430 Emulator" is free software: you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation, either version 3 of the License, or
-  (at your option) any later version.
-
-  "MSP430 Emulator" is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-  GNU General Public License for more details.
-  
-  You should have received a copy of the GNU General Public License
-  along with this program. If not, see <https://www.gnu.org/licenses/>.
-*/
-
-#include "main.h"
-
-int run(unsigned int port) {
-
-    Emulator *emu = (Emulator *) calloc( 1, sizeof(Emulator) );
-    Cpu *cpu = NULL; Debugger *deb = NULL;
-
-    emu->cpu       = (Cpu *) calloc(1, sizeof(Cpu));
-    emu->cpu->bcm  = (Bcm *) calloc(1, sizeof(Bcm));
-    emu->cpu->timer_a  = (Timer_a *) calloc(1, sizeof(Timer_a));
-    emu->cpu->p1   = (Port_1 *) calloc(1, sizeof(Port_1));
-    emu->cpu->usci = (Usci *) calloc(1, sizeof(Usci));
-
-    emu->debugger  = (Debugger *) calloc(1, sizeof(Debugger));
-    setup_debugger(emu);
-
-    cpu = emu->cpu;
-    deb = emu->debugger;
-
-    deb->server = (Server *) calloc(1, sizeof(Server));
-
-    if (deb->web_interface == true)
-        {
-            pthread_t *t = &deb->web_server_thread;
-
-            if ( pthread_create(t, NULL, web_server, (void *)emu ) )
-            {
-                fprintf(stderr, "Error creating web server thread\n");
-                return 1;
-            }
-
-            while (!deb->web_server_ready)
-                usleep(10000);
-
-            print_console(emu, " [MSP430 Emulator]\n Copyright (C) 2020 Rudolf Geosits (rgeosits@live.esu.edu)\n");
-//            print_console(emu, " [!] Upload your firmware (ELF format only); Type 'h' for debugger options.\n\n");
-
-            while (!deb->web_firmware_uploaded)
-                usleep(10000);
-        }
-
-        //register_signal(SIGINT); // Register Callback for CONTROL-c
-
-        initialize_msp_memspace();
-        initialize_msp_registers(emu);
-
-        setup_bcm(emu);
-        setup_timer_a(emu);
-        setup_port_1(emu);
-        setup_usci(emu);
-
-        load_bootloader(0x0C00);
-
-        if (deb->web_interface)
-            load_firmware(emu, (char*)"tmp.bin", 0xC000);
-
-        // display first round of registers
-        display_registers(emu);
-        disassemble(emu, cpu->pc, 1);
-        update_register_display(emu);
-
-        // Fetch-Decode-Execute Cycle (run machine)
-        while (!deb->quit)
-        {
-            // Handle debugger when CPU is not running
-            if (!cpu->running)
-            {
-                usleep(10000);
-                continue;
-            }
-
-            // Handle Breakpoints
-            handle_breakpoints(emu);
-
-            // Instruction Decoder
-            decode(emu, fetch(emu), EXECUTE);
-
-            // Handle Peripherals
-            handle_bcm(emu);
-            handle_timer_a(emu);
-            handle_port_1(emu);
-            handle_usci(emu);
-
-            // Average of 4 cycles per instruction
-            mclk_wait_cycles(emu, 4);
-        }
-        uninitialize_msp_memspace();
-        free(cpu->timer_a);
-        free(cpu->bcm);
-        free(cpu->p1);
-        free(cpu->usci);
-        free(cpu);
-        free(deb->server);
-        free(deb);
-        free(emu);
-
-        return 0;
-}
-
-
-int main(int argc, char *argv[])
-{
-    if (argv[1] == NULL)
-    {
-        puts("Need port argument");
-        return(1);
-    }
-    return run(strtoul(argv[1], NULL, 10));
-}

+ 2 - 0
emulator/main.h

@@ -59,6 +59,8 @@ typedef struct Packet Packet;
 #include "debugger/register_display.h"
 #include "debugger/disassembler.h"
 
+int run(unsigned int port);
+
 struct Emulator
 {
     Cpu *cpu;

+ 1 - 0
msp430emu/__init__.py

@@ -0,0 +1 @@
+from . import emulator

+ 14 - 0
msp430emu/__main__.py

@@ -0,0 +1,14 @@
+from msp430emu import emulator
+import sys
+import os
+
+if __name__ == '__main__':
+    load = None
+    if len(sys.argv) >= 2:
+        if os.path.exists(sys.argv[1]):
+            load = sys.argv[1]
+        else:
+            print(f"File '{sys.argv[1]}' does not exist")
+    app = emulator.wx.App(False)
+    frame = emulator.EmulatorWindow(None, "MSP430 Emulator", load)
+    app.MainLoop()

+ 119 - 65
emulator.py

@@ -1,48 +1,71 @@
 import sys
 # from http.server import BaseHTTPRequestHandler, HTTPServer
 # from subprocess import PIPE, Popen
+from subprocess import Popen, PIPE
 from threading import Thread
 from time import sleep
 import websocket
-from os import path, chdir
-import ctypes
+from os import path, mkdir, chdir
 
+import _msp430emu
 import wx
 
-pwd = path.dirname(path.realpath(__file__))
-chdir(pwd)
-libmsp430 = ctypes.cdll.LoadLibrary(path.join(pwd, "libmsp430.so"))
-run_emu = libmsp430.run
-run_emu.restype = ctypes.c_int
-run_emu.argtypes = [ctypes.c_uint]
+source_dir = path.dirname(path.realpath(__file__))
+mkdir(".emulator")
+chdir(".emulator")
 
 
 class Emulator:
     EVENT_CONSOLE = 0
     EVENT_SERIAL = 1
-
-    def __init__(self, emu_dir, ws_port=59981, load=None, callback=None):
+    EVENT_GPIO = 2
+
+    P1_0_ON_PACKET = 0x00
+    P1_0_OFF_PACKET = 0x01
+    P1_1_ON_PACKET = 0x02
+    P1_1_OFF_PACKET = 0x03
+    P1_2_ON_PACKET = 0x04
+    P1_2_OFF_PACKET = 0x05
+    P1_3_ON_PACKET = 0x06
+    P1_3_OFF_PACKET = 0x07
+    P1_4_ON_PACKET = 0x08
+    P1_4_OFF_PACKET = 0x09
+    P1_5_ON_PACKET = 0x0A
+    P1_5_OFF_PACKET = 0x0B
+    P1_6_ON_PACKET = 0x0C
+    P1_6_OFF_PACKET = 0x0D
+    P1_7_ON_PACKET = 0x0E
+    P1_7_OFF_PACKET = 0x0F
+
+    def __init__(self, ws_port=59981, load=None, callback=None):
         # self.process = Popen([path.join(emu_dir, 'MSP430'), str(ws_port)], stdout=PIPE, stderr=PIPE)
-        self.process = Thread(target=run_emu, args=(ws_port, ))
+        self.ws_port = ws_port
+        self.process = Thread(target=self._start_emu, daemon=True)
         self.process.start()
-        sleep(3)
-        self.ws = websocket.WebSocketApp(f"ws://127.0.0.1:{ws_port}",
-                                         subprotocols={"emu-protocol"},
-                                         on_open=self._ws_open,
-                                         on_data=self._ws_msg,
-                                         on_error=self._ws_err,
-                                         on_close=self._ws_close
-                                        )
+        self._start_ws()
         self.load = load
         self.started = False
         self.start_errors = 0
         self.callback = callback
-        Thread(target=self.ws.run_forever).start()
 
-    def wait(self):
-        self.process.wait()
+    def _start_emu(self):
+        print("starting emulator...")
+        _msp430emu.run(self.ws_port)
+        print("stopping emulator...")
+
+    def _start_ws(self):
+        self.ws = websocket.WebSocketApp(
+            f"ws://127.0.0.1:{self.ws_port}",
+            subprotocols={"emu-protocol"},
+            on_open=self._ws_open,
+            on_data=self._ws_msg,
+            on_error=self._ws_err,
+            on_close=self._ws_close
+        )
+        Thread(target=self.ws.run_forever).start()
 
     def load_file(self, fname):
+        print("loading " + fname)
         with open(fname, 'rb') as f:
             fdata = f.read()
             name = path.basename(fname)
@@ -52,7 +75,12 @@ class Emulator:
             payload += name.encode() + fdata
             self.ws.send(payload, websocket.ABNF.OPCODE_BINARY)
 
+    def _cb(self, ev, data):
+        if callable(self.callback):
+            self.callback(ev, data)
+
     def _ws_open(self):
+        print("connection established...")
         self.started = True
         if self.load is not None:
             self.load_file(self.load)
@@ -60,19 +88,17 @@ class Emulator:
     def _ws_msg(self, data, frame, x):
         opcode = data[0]
         if opcode == 0:
-            return
+            if len(data) == 2 and data[1] <= 15:
+                self._cb(self.EVENT_GPIO, data[1])
+
         elif opcode == 1:
             message = data[1:-1].decode()
-            if "Type 'h' for" in message:
-                return
-            if callable(self.callback):
-                self.callback(self.EVENT_CONSOLE, message)
-            print(message, end=None)
+            self._cb(self.EVENT_CONSOLE, message)
+            # print(message, end=None)
             return
         elif opcode == 2:
             message = data[1:-1].decode()
-            if callable(self.callback):
-                self.callback(self.EVENT_SERIAL, message)
+            self._cb(self.EVENT_SERIAL, message)
             return
         else:
             pass
@@ -83,7 +109,7 @@ class Emulator:
             if self.start_errors < 5:
                 print(f"Failed to connect to emulator backend attempt {self.start_errors}")
                 sleep(1)
-                self.ws.run_forever()
+                self._start_ws()
             raise ConnectionError("Failed to connect to emulation backend after 5 tries")
         raise err
 
@@ -102,31 +128,40 @@ class Emulator:
         self.ws.send(b'\x01', websocket.ABNF.OPCODE_BINARY)
 
     def close(self):
+        print("connection ended...")
         self.ws.close()
-        self.process.join()
+        # _msp430emu.stop()
+        # self.process.join(1)
 
 
 class EmulatorWindow(wx.Frame):
-    def __init__(self, parent, title):
+    def __init__(self, parent, title, load=None):
         wx.Frame.__init__(self, parent, title=title)
         self.control = wx.TextCtrl(self, size=wx.Size(400, 450),
                                    style=wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_DONTWRAP)
+        self.control.Hide()
+
         self.serial = wx.TextCtrl(self, size=wx.Size(400, 450), style=wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_DONTWRAP)
         self.serial_input = wx.TextCtrl(self, style=wx.TE_DONTWRAP)
 
         self.CreateStatusBar()  # A Statusbar in the bottom of the window
 
-        filemenu = wx.Menu()
-
-        menuFile = filemenu.Append(wx.ID_OPEN, "&Firmware", " Open firmware")
-        menuReset = filemenu.Append(wx.ID_CLOSE_ALL, "&Reset", " Reset Emulator")
-        menuExit = filemenu.Append(wx.ID_EXIT, "E&xit", " Terminate the program")
+        file_menu = wx.Menu()
+        menuFile = file_menu.Append(wx.ID_OPEN, "&Firmware", " Open firmware")
         self.Bind(wx.EVT_MENU, self.OnOpen, menuFile)
+        menuReset = file_menu.Append(wx.ID_CLOSE_ALL, "&Reset", " Reset Emulator")
         self.Bind(wx.EVT_MENU, self.RestartEmulator, menuReset)
+        menuExit = file_menu.Append(wx.ID_EXIT, "E&xit", " Terminate the program")
         self.Bind(wx.EVT_MENU, self.OnExit, menuExit)
 
+        view_menu = wx.Menu()
+        view_console = view_menu.AppendCheckItem(101, "View Console", "Show/Hide Emulator debug console")
+        self.Bind(wx.EVT_MENU, self.ToggleConsole, view_console)
+
         menuBar = wx.MenuBar()
-        menuBar.Append(filemenu, "&File")
+        menuBar.Append(file_menu, "&File")
+        menuBar.Append(view_menu, "&View")
+
         self.SetMenuBar(menuBar)
 
         self.sizer2 = wx.BoxSizer(wx.HORIZONTAL)
@@ -149,7 +184,7 @@ class EmulatorWindow(wx.Frame):
         self.sizer0.Add(self.sizer3, 0, wx.EXPAND)
 
         panel = wx.Panel(self, size=wx.Size(275, 375))
-        img = wx.Bitmap("msp430.png", wx.BITMAP_TYPE_PNG)
+        img = wx.Bitmap(path.join(source_dir, "msp430.png"), wx.BITMAP_TYPE_PNG)
         wx.StaticBitmap(panel, -1, img, (0, 0), (img.GetWidth(), img.GetHeight()))
         self.diagram = DrawRect(panel, -1, size=wx.Size(275, 375))
         #
@@ -158,7 +193,6 @@ class EmulatorWindow(wx.Frame):
         # dc.SetBrush(wx.WHITE_BRUSH)
         # dc.DrawRectangle(50, 50, 500, 500)
 
-
         self.sizer1 = wx.BoxSizer(wx.HORIZONTAL)
         self.sizer1.Add(panel, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL)
         self.sizer1.Add(self.control, 1, wx.EXPAND)
@@ -173,39 +207,51 @@ class EmulatorWindow(wx.Frame):
         self.Show()
 
         self.control.WriteText("Initialising Emulator..\n")
-        self.load = None
-        if len(sys.argv) >= 2:
-            if path.exists(sys.argv[1]):
-                self.load = sys.argv[1]
-        self.emu = Emulator('emulator', load=self.load, callback=self.callback)
+        self.load = load
+        self.emu = Emulator(load=self.load, callback=self.callback)
 
     def callback(self, event, data):
         if event == Emulator.EVENT_CONSOLE:
             wx.CallAfter(self.control.AppendText, data)
-        if event == Emulator.EVENT_SERIAL:
+        elif event == Emulator.EVENT_SERIAL:
             wx.CallAfter(self.serial.AppendText, data)
+        elif event == Emulator.EVENT_GPIO:
+            self.diagram.port1[data // 2] = data % 2 == 0
+            wx.CallAfter(self.diagram.Refresh)
 
     def RestartEmulator(self, e):
         self.control.AppendText("Stopping Emulator..")
         self.emu.close()
         self.control.Clear()
         self.serial.Clear()
-        self.control.WriteText("Initialising Emulator..\n")
-        self.emu = Emulator('emulator', load=self.load, callback=self.callback)
+
+    def ToggleConsole(self, e):
+        if e.Int == 0:
+            self.control.Hide()
+            self.Layout()
+        else:
+            self.control.Show()
+            self.Layout()
 
     def OnOpen(self, e):
-        with wx.FileDialog(self, "Open Firmware", wildcard="ELF files (*.elf)|*.elf",
+        with wx.FileDialog(self, "Open Firmware File", wildcard="ELF files (*.elf)|*.elf",
                            style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog:
             if fileDialog.ShowModal() == wx.ID_CANCEL:
                 return
             self.load = fileDialog.GetPath()
-            self.RestartEmulator(None)
+            self.emu.load_file(self.load)
+            self.diagram.power = False
+            # self.RestartEmulator(None)
 
     def OnPause(self, e):
         self.emu.emulation_pause()
+        self.diagram.power = False
+        self.diagram.Refresh()
 
     def OnStart(self, e):
         self.emu.emulation_start()
+        self.diagram.power = True
+        self.diagram.Refresh()
 
     def OnExit(self, e):
         self.emu.close()
@@ -214,27 +260,35 @@ class EmulatorWindow(wx.Frame):
 
 class DrawRect(wx.Panel):
     """ class MyPanel creates a panel to draw on, inherits wx.Panel """
+    RED = wx.Colour(255, 0, 0, wx.ALPHA_OPAQUE)
+    GREEN = wx.Colour(0, 255, 0, wx.ALPHA_OPAQUE)
+
     def __init__(self, parent, id, **kwargs):
         # create a panel
         wx.Panel.__init__(self, parent, id, **kwargs)
         # self.SetBackgroundColour("white")
         self.Bind(wx.EVT_PAINT, self.OnPaint)
+        self.power = False
+        self.port1 = [False, False, False, False, False, False, False, False]
 
     def OnPaint(self, evt):
         """set up the device context (DC) for painting"""
         self.dc = wx.PaintDC(self)
-        self.dc.SetPen(wx.Pen("green",style=wx.TRANSPARENT))
-        self.dc.SetBrush(wx.Brush("green", wx.SOLID))
-        # set x, y, w, h for rectangle
-        self.dc.DrawRectangle(83, 356, 8, 15)
-
-        self.dc.SetPen(wx.Pen("red",style=wx.TRANSPARENT))
-        self.dc.SetBrush(wx.Brush("red", wx.SOLID))
-        self.dc.DrawRectangle(70, 356, 8, 15)
-        del self.dc
 
-
-if __name__ == '__main__':
-    app = wx.App(False)
-    frame = EmulatorWindow(None, "MSP430 Emulator")
-    app.MainLoop()
+        if self.power:
+            self.dc.SetPen(wx.Pen(self.GREEN, style=wx.TRANSPARENT))
+            self.dc.SetBrush(wx.Brush(self.GREEN, wx.SOLID))
+            # set x, y, w, h for rectangle
+            self.dc.DrawRectangle(39, 110, 8, 15)
+
+        if self.port1[6]:
+            self.dc.SetPen(wx.Pen(self.GREEN, style=wx.TRANSPARENT))
+            self.dc.SetBrush(wx.Brush(self.GREEN, wx.SOLID))
+            # set x, y, w, h for rectangle
+            self.dc.DrawRectangle(83, 356, 8, 15)
+
+        if self.port1[0]:
+            self.dc.SetPen(wx.Pen(self.RED, style=wx.TRANSPARENT))
+            self.dc.SetBrush(wx.Brush(self.RED, wx.SOLID))
+            self.dc.DrawRectangle(70, 356, 8, 15)
+        del self.dc

msp430.png → msp430emu/msp430.png


+ 2 - 0
requirements.txt

@@ -0,0 +1,2 @@
+websocket_client
+wxPython>=4

+ 18 - 9
setup.py

@@ -1,14 +1,12 @@
 #!/usr/bin/env python
-
 from distutils.core import setup, Extension
 
 emulator_files = [
-    'emulator/main.cpp',
+    'emulator/main.c',
     'emulator/devices/utilities.c',
     'emulator/devices/cpu/registers.c',
     'emulator/devices/memory/memspace.c',
     'emulator/debugger/debugger.c',
-    'emulator/debugger/disassembler.c',
     'emulator/debugger/register_display.c',
     'emulator/devices/cpu/decoder.c',
     'emulator/devices/cpu/flag_handler.c',
@@ -19,17 +17,28 @@ emulator_files = [
     'emulator/devices/peripherals/timer_a.c',
     'emulator/devices/peripherals/usci.c',
     'emulator/devices/peripherals/port1.c',
-    'emulator/debugger/websockets/emu_server.cpp',
+    'emulator/debugger/websockets/emu_server.c',
     'emulator/debugger/websockets/packet_queue.c',
+    'emulator/debugger/disassembler.c',
+]
+libraries = [
+    'websockets',
+    'readline',
+    'rt',
+    'ssl',
+    'crypto',
+    'pthread'
 ]
-# emulator_files.reverse()
+ext_mod = Extension(
+    '_msp430emu', emulator_files, libraries=libraries, extra_compile_args=["-w"]
+)
 
 setup(name='msp430emu',
       version='1.0',
       description='MSP 430 Emulator',
       author_email='zceemja@ucl.ac.uk',
-      # packages=['msp430emu'],
-      # package_dir={'msp430emu': '', 'emulator': 'emulator'},
-      # libraries=['wx', 'websocket'],
-      ext_modules=[Extension('emulator', emulator_files)]
+      packages=['msp430emu'],
+      package_dir={'msp430emu': 'msp430emu'},
+      package_data={'msp430emu': ['*.png']},
+      ext_modules=[ext_mod],
       )