Sfoglia il codice sorgente

Removed websockets

Min 4 anni fa
parent
commit
69f9623b52

+ 42 - 28
emulator/Makefile

@@ -1,71 +1,85 @@
-all: MSP430 SERVER
+CC:=gcc
+CXX:=g++
+PYDIR:= $(word 1, $(wildcard /usr/include/python3*))
+CCFLAGS:=-fPIC -DPYTHON -I$(PYDIR)
+LLFLAGS:=-s
+
+all: MSP430 SERVER _msp430emu.so
 
 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;
+	g++ -o MSP430 launcher.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;
 
-_msp430emu.so: main.o utilities.o emu_server.o registers.o memspace.o debugger.o disassembler.o \
+_msp430emu.so: py_functions.o py_interface.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 packet_queue.o bcm.o timer_a.o
-	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
+	usci.o port1.o bcm.o timer_a.o
+	$(CC) $(LLFLAGS) py_functions.o py_interface.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 \
+	-lreadline -lrt -lpthread -o _msp430emu.so -shared
+
 
 main.o : main.c
-	gcc $(CCFLAGS) -c main.c
+	$(CC) $(CCFLAGS) -c main.c
+
+py_functions.o : python/py_functions.c
+	$(CC) $(CCFLAGS) -c python/py_functions.c
+
+py_interface.o : python/py_interface.c
+	$(CC) $(CCFLAGS) -c python/py_interface.c
 
 utilities.o : devices/utilities.c
-	gcc $(CCFLAGS) -c devices/utilities.c
+	$(CC) $(CCFLAGS) -c devices/utilities.c
 
 registers.o : devices/cpu/registers.c
-	gcc $(CCFLAGS) -c devices/cpu/registers.c
+	$(CC) $(CCFLAGS) -c devices/cpu/registers.c
 
 memspace.o : devices/memory/memspace.c
-	gcc $(CCFLAGS) -c devices/memory/memspace.c
+	$(CC) $(CCFLAGS) -c devices/memory/memspace.c
 
 debugger.o : debugger/debugger.c
-	gcc $(CCFLAGS) -c debugger/debugger.c
+	$(CC) $(CCFLAGS) -c debugger/debugger.c
 
 disassembler.o : debugger/disassembler.c
-	gcc $(CCFLAGS) -c debugger/disassembler.c
+	$(CC) $(CCFLAGS) -c debugger/disassembler.c
 
 register_display.o : debugger/register_display.c
-	gcc $(CCFLAGS) -c debugger/register_display.c
+	$(CC) $(CCFLAGS) -c debugger/register_display.c
 
 decoder.o : devices/cpu/decoder.c
-	gcc $(CCFLAGS) -c devices/cpu/decoder.c
+	$(CC) $(CCFLAGS) -c devices/cpu/decoder.c
 
 flag_handler.o : devices/cpu/flag_handler.c
-	gcc $(CCFLAGS) -c devices/cpu/flag_handler.c
+	$(CC) $(CCFLAGS) -c devices/cpu/flag_handler.c
 
 formatI.o : devices/cpu/formatI.c
-	gcc $(CCFLAGS) -c devices/cpu/formatI.c
+	$(CC) $(CCFLAGS) -c devices/cpu/formatI.c
 
 formatII.o : devices/cpu/formatII.c
-	gcc $(CCFLAGS) -c devices/cpu/formatII.c
+	$(CC) $(CCFLAGS) -c devices/cpu/formatII.c
 
 formatIII.o : devices/cpu/formatIII.c
-	gcc $(CCFLAGS) -c devices/cpu/formatIII.c
+	$(CC) $(CCFLAGS) -c devices/cpu/formatIII.c
 
 bcm.o : devices/peripherals/bcm.c
-	gcc $(CCFLAGS) -c devices/peripherals/bcm.c
+	$(CC) $(CCFLAGS) -c devices/peripherals/bcm.c
 
 timer_a.o : devices/peripherals/timer_a.c
-	gcc $(CCFLAGS) -c devices/peripherals/timer_a.c
+	$(CC) $(CCFLAGS) -c devices/peripherals/timer_a.c
 
 usci.o : devices/peripherals/usci.c
-	gcc $(CCFLAGS) -c devices/peripherals/usci.c
+	$(CC) $(CCFLAGS) -c devices/peripherals/usci.c
 
 port1.o : devices/peripherals/port1.c
-	gcc $(CCFLAGS) -c devices/peripherals/port1.c
+	$(CC) $(CCFLAGS) -c devices/peripherals/port1.c
 
 emu_server.o : debugger/websockets/emu_server.c
-	gcc $(CCFLAGS) -c debugger/websockets/emu_server.c
+	$(CC) $(CCFLAGS) -c debugger/websockets/emu_server.c
 
 packet_queue.o : debugger/websockets/packet_queue.c
-	gcc $(CCFLAGS) -c debugger/websockets/packet_queue.c
+	$(CC) $(CCFLAGS) -c debugger/websockets/packet_queue.c
 
 # Server Program
 
@@ -80,7 +94,7 @@ clean :
 	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 \
+	formatII.o formatIII.o py_functions.o py_interface.o \
 	usci.o port1.o packet_queue.o bcm.o timer_a.o \
 	*.bin *.tmp *.elf \
-	MSP430 server;
+	MSP430 server _msp430emu.so;

+ 1 - 1
emulator/debugger/debugger.h

@@ -19,7 +19,7 @@
 #ifndef _DEBUGGER_H_
 #define _DEBUGGER_H_
 
-#include "../main.h"
+#include "../emulator.h"
 #include "../devices/cpu/registers.h"
 #include "../devices/memory/memspace.h"
 

+ 1 - 1
emulator/debugger/websockets/emu_server.c

@@ -458,7 +458,7 @@ int callback_emu (struct lws *wsi, enum lws_callback_reasons reason, void *user,
 	     return 0;
 	 }
 
-                 case 0x04: { // Console Input Data
+     case 0x04: { // Console Input Data
 	     if (len > 1000) exit(1);
 
 	     buf = buf + 1;	     

+ 48 - 1
emulator/devices/cpu/registers.h

@@ -23,7 +23,54 @@
 #include <stdint.h>
 #include <string.h>
 #include <stdbool.h>
-#include "../../main.h"
+
+#include "../../emulator.h"
+
+enum {
+  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,
+
+  UPDATE_REG_R0_PACKET = 0x10,
+  UPDATE_REG_R1_PACKET = 0x11,
+  UPDATE_REG_R2_PACKET = 0x12,
+  UPDATE_REG_R3_PACKET = 0x13,
+  UPDATE_REG_R4_PACKET = 0x14,
+  UPDATE_REG_R5_PACKET = 0x15,
+  UPDATE_REG_R6_PACKET = 0x16,
+  UPDATE_REG_R7_PACKET = 0x17,
+  UPDATE_REG_R8_PACKET = 0x18,
+  UPDATE_REG_R9_PACKET = 0x19,
+  UPDATE_REG_R10_PACKET = 0x1A,
+  UPDATE_REG_R11_PACKET = 0x1B,
+  UPDATE_REG_R12_PACKET = 0x1C,
+  UPDATE_REG_R13_PACKET = 0x1D,
+  UPDATE_REG_R14_PACKET = 0x1E,
+  UPDATE_REG_R15_PACKET = 0x1F,
+  UPDATE_ALL_REGS_PACKET = 0x20,
+
+  SERVO_MOTOR = 0x21,
+};
 
 /* r2 or SR, the status register */
 typedef struct Status_reg {

+ 4 - 8
emulator/devices/peripherals/port1.c

@@ -44,19 +44,15 @@ void handle_port_1 (Emulator *emu)
     //////////////////// P1.0 ////////////////////////
 
     // Check Direction
-    if (*p->DIR & 0x01)
-    {
-        p->DIR_0 = true;         // Set P1DIR.0 flag
-
-        if (*p->OUT & 0x01)      // Check OUTPUT
+    if (*p->DIR & 0x01) {
+        p->DIR_0 = true;           // Set P1DIR.0 flag
+        if (*p->OUT & 0x01)        // Check OUTPUT
             p->OUT_0 = true;       // Set P1OUT.0 flag
         else
             p->OUT_0 = false;      // Reset P1OUT.0 flag
     }
-
     // Check INPUT 
-    else                 
-    {                                
+    else {
         p->DIR_0 = false;
     }
     

+ 3 - 3
emulator/devices/peripherals/usci.c

@@ -128,11 +128,11 @@ void handle_usci (Emulator *emu)
 
       if (c & 0xFF) {
 	if (deb->web_interface) {
-	  print_serial(emu, (char*)&str[0]);
-	  //write(sp, usci->UCA0TXBUF, 1);
+        print_serial(emu, (char*)&str[0]);
+        //write(sp, usci->UCA0TXBUF, 1);
 	}
 	else if (deb->console_interface) {
-	  //write(sp, usci->UCA0TXBUF, 1);
+        //write(sp, usci->UCA0TXBUF, 1);
 	}
 
 	*usci->UCA0TXBUF = 0;

+ 62 - 0
emulator/emulator.h

@@ -0,0 +1,62 @@
+
+#ifndef _EMULATOR_H_
+#define _EMULATOR_H_
+
+#include <stdio.h>
+#include <time.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdint.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <pthread.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#ifdef WEBSOCKETS
+#include <libwebsockets.h>
+#endif
+
+typedef struct Emulator Emulator;
+
+typedef struct Cpu Cpu;
+typedef struct Port_1 Port_1;
+typedef struct Usci Usci;
+typedef struct Bcm Bcm;
+typedef struct Timer_a Timer_a;
+typedef struct Status_reg Status_reg;
+
+typedef struct Debugger Debugger;
+typedef struct Server Server;
+typedef struct Packet Packet;
+
+#include "devices/peripherals/bcm.h"
+#include "devices/peripherals/timer_a.h"
+#include "devices/peripherals/port1.h"
+#include "devices/peripherals/usci.h"
+#include "devices/cpu/registers.h"
+#include "devices/utilities.h"
+#include "devices/memory/memspace.h"
+
+#ifdef WEBSOCKETS
+#include "debugger/websockets/emu_server.h"
+#endif
+
+#include "devices/cpu/decoder.h"
+#include "debugger/debugger.h"
+#include "debugger/register_display.h"
+#include "debugger/disassembler.h"
+
+#ifdef PYTHON
+#include "python/py_interface.h"
+#endif
+
+struct Emulator {
+    Cpu *cpu;
+    Debugger *debugger;
+};
+
+#endif

+ 77 - 122
emulator/main.c

@@ -17,154 +17,109 @@
 */
 
 #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) );
+int main(int argc, char *argv[])
+{
+    Emulator *emu = (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));
+    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));
 
-    emuInst->debugger  = (Debugger *) calloc(1, sizeof(Debugger));
-    setup_debugger(emuInst);
+    emu->debugger  = (Debugger *) calloc(1, sizeof(Debugger));
+    setup_debugger(emu);
 
-    cpu = emuInst->cpu;
-    deb = emuInst->debugger;
+    cpu = emu->cpu;
+    deb = emu->debugger;
 
     deb->server = (Server *) calloc(1, sizeof(Server));
 
     if (deb->web_interface == true)
+    {
+        if (argv[1] == NULL)
         {
-            deb->ws_port = port;
+            puts("Need port argument");
+            return(1);
+        }
 
-            pthread_t *t = &deb->web_server_thread;
+        deb->ws_port = strtoul(argv[1], NULL, 10);
 
-            if ( pthread_create(t, NULL, web_server, (void *)emuInst ) )
-            {
-                fprintf(stderr, "Error creating web server thread\n");
-                return 1;
-            }
+        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);
+        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");
+        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);
-        }
+        while (!deb->web_firmware_uploaded)
+            usleep(10000);
+    }
 
-        //register_signal(SIGINT); // Register Callback for CONTROL-c
+    //register_signal(SIGINT); // Register Callback for CONTROL-c
 
-        initialize_msp_memspace();
-        initialize_msp_registers(emuInst);
+    initialize_msp_memspace();
+    initialize_msp_registers(emu);
 
-        setup_bcm(emuInst);
-        setup_timer_a(emuInst);
-        setup_port_1(emuInst);
-        setup_usci(emuInst);
+    setup_bcm(emu);
+    setup_timer_a(emu);
+    setup_port_1(emu);
+    setup_usci(emu);
 
-        load_bootloader(0x0C00);
+    load_bootloader(0x0C00);
 
-        if (deb->web_interface)
-            load_firmware(emuInst, (char*)"tmp.bin", 0xC000);
+    if (deb->web_interface)
+        load_firmware(emu, (char*)"tmp.bin", 0xC000);
 
-        // display first round of registers
-        display_registers(emuInst);
-        disassemble(emuInst, cpu->pc, 1);
-        update_register_display(emuInst);
+    // 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)
+    // Fetch-Decode-Execute Cycle (run machine)
+    while (!deb->quit)
+    {
+        // Handle debugger when CPU is not running
+        if (!cpu->running)
         {
-            // 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);
+            usleep(10000);
+            continue;
         }
-        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;
-}
+        // Handle Breakpoints
+        handle_breakpoints(emu);
 
+        // Instruction Decoder
+        decode(emu, fetch(emu), EXECUTE);
 
-int main(int argc, char *argv[])
-{
-    if (argv[1] == NULL)
-    {
-        puts("Need port argument");
-        return(1);
+        // 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);
     }
-    return run(strtoul(argv[1], NULL, 10));
-}
+
+    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;
+}

+ 1 - 48
emulator/main.h

@@ -18,51 +18,4 @@
 
 #pragma once
 
-#include <stdio.h>
-#include <time.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <string.h>
-#include <stdint.h>
-#include <signal.h>
-#include <sys/wait.h>
-#include <errno.h>
-#include <stdbool.h>
-#include <pthread.h>
-#include <libwebsockets.h>
-#include <readline/readline.h>
-#include <readline/history.h>
-
-typedef struct Emulator Emulator;
-
-typedef struct Cpu Cpu;
-typedef struct Port_1 Port_1;
-typedef struct Usci Usci;
-typedef struct Bcm Bcm;
-typedef struct Timer_a Timer_a;
-typedef struct Status_reg Status_reg;
-
-typedef struct Debugger Debugger;
-typedef struct Server Server;
-typedef struct Packet Packet;
-
-#include "devices/peripherals/bcm.h"
-#include "devices/peripherals/timer_a.h"
-#include "devices/peripherals/port1.h"
-#include "devices/peripherals/usci.h"
-#include "devices/cpu/registers.h"
-#include "devices/utilities.h"
-#include "devices/memory/memspace.h"
-#include "debugger/websockets/emu_server.h"
-#include "devices/cpu/decoder.h"
-#include "debugger/debugger.h"
-#include "debugger/register_display.h"
-#include "debugger/disassembler.h"
-
-int run(unsigned int port);
-
-struct Emulator
-{
-    Cpu *cpu;
-    Debugger *debugger;
-};
+#include "emulator.h"

+ 123 - 0
emulator/python/py_functions.c

@@ -0,0 +1,123 @@
+#include "py_functions.h"
+// This is an ugly solution but heh
+Emulator *emuInst;
+
+void play_emu() {
+    emuInst->cpu->running = true;
+    emuInst->debugger->debug_mode = false;
+}
+
+void pause_emu() {
+    if (emuInst->cpu->running) {
+        emuInst->cpu->running = false;
+        emuInst->debugger->debug_mode = true;
+
+         // display first round of registers
+//         display_registers(emu);
+//         disassemble(emu, cpu->pc, 1);
+//         update_register_display(emu);
+    }
+}
+
+void reset_emu() {
+    emuInst->cpu->pc = 0xC000;
+    print_console(emuInst, "Resetting program counter to 0xC000\n");
+}
+
+void cmd_emu(char *line, int len) {
+    if (!emuInst->cpu->running && emuInst->debugger->debug_mode) {
+        exec_cmd(emuInst, line, len);
+//	         update_register_display(emu);
+    }
+}
+
+void stop_emu() {
+    emuInst->debugger->quit = true;
+    print_console(emuInst, "Stopping emulator..\n");
+}
+
+void start_emu(char *file) {
+    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));
+
+    initialize_msp_memspace();
+    initialize_msp_registers(emuInst);
+
+    setup_bcm(emuInst);
+    setup_timer_a(emuInst);
+    setup_port_1(emuInst);
+    setup_usci(emuInst);
+
+    load_bootloader(0x0C00);
+    load_firmware(emuInst, file, 0xC000);
+
+    display_registers(emuInst);
+    disassemble(emuInst, cpu->pc, 1);
+    update_register_display(emuInst);
+
+    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;
+}
+
+//void init_packet_queue (Emulator *emu){
+//    Server *s = emu->debugger->server;
+//    s->pending_packets_head = NULL;
+//    s->pending_packets_tail = NULL;
+//    s->packets_queued = 0;
+//    s->spin_lock = false;
+//}
+
+
+//void *emulator (void *ctxt) {
+//    emu = (Emulator *) ctxt;
+//    Debugger *deb = emu->debugger;
+//
+//    init_packet_queue(emu);
+//    printf("starting emulator...\n");
+//}

+ 16 - 0
emulator/python/py_functions.h

@@ -0,0 +1,16 @@
+
+
+#ifndef _PY_FUNCTIONS_H_
+#define _PY_FUNCTIONS_H_
+
+#include "../emulator.h"
+#include "py_interface.h"
+
+void play_emu();
+void pause_emu();
+void cmd_emu(char *line, int len);
+void start_emu(char *file);
+void stop_emu();
+void reset_emu();
+
+#endif

+ 189 - 0
emulator/python/py_interface.c

@@ -0,0 +1,189 @@
+#include "py_interface.h"
+
+
+PyObject *pyOnSerial;
+PyObject *pyOnConsole;
+PyObject *pyOnControl;
+
+static PyObject *method_start(PyObject *self, PyObject *args) {
+    char *firmware_file;
+    if(!PyArg_ParseTuple(args, "s", &firmware_file)) {
+        return NULL;
+    }
+    Py_BEGIN_ALLOW_THREADS
+    start_emu(firmware_file);
+    Py_END_ALLOW_THREADS
+    return Py_None;
+}
+
+static PyObject *method_cmd(PyObject *self, PyObject *args) {
+    char *cmd;
+    int len;
+    if(!PyArg_ParseTuple(args, "s#", &cmd, &len)) {
+        return NULL;
+    }
+    cmd_emu(cmd, len);
+    return Py_None;
+}
+
+static PyObject *method_stop(PyObject *self, PyObject *args) {
+    stop_emu();
+    Py_XDECREF(pyOnSerial);
+    Py_XDECREF(pyOnConsole);
+    Py_XDECREF(pyOnControl);
+    return Py_None;
+}
+
+static PyObject *method_reset(PyObject *self, PyObject *args) {
+    reset_emu();
+    return Py_None;
+}
+
+static PyObject *method_play(PyObject *self, PyObject *args) {
+    play_emu();
+    return Py_None;
+}
+
+static PyObject *method_pause(PyObject *self, PyObject *args) {
+    pause_emu();
+    return Py_None;
+}
+
+static PyObject *method_on_serial(PyObject *self, PyObject *args) {
+    if(!PyArg_ParseTuple(args, "O", &pyOnSerial)) {
+        PyErr_SetString(PyExc_ValueError, "Invalid argument, must be single object");
+        pyOnSerial = NULL;
+        return NULL;
+    }
+    if(!PyCallable_Check(pyOnSerial)) {
+        PyErr_SetString(PyExc_ValueError, "Argument object is not callable");
+        pyOnSerial = NULL;
+        return NULL;
+    }
+    Py_INCREF(pyOnSerial);
+    return Py_None;
+}
+
+static PyObject *method_on_console(PyObject *self, PyObject *args) {
+    if(!PyArg_ParseTuple(args, "O", &pyOnConsole)) {
+        PyErr_SetString(PyExc_ValueError, "Invalid argument, must be single object");
+        pyOnControl = NULL;
+        return NULL;
+    }
+    if(!PyCallable_Check(pyOnConsole)) {
+        PyErr_SetString(PyExc_ValueError, "Argument object is not callable");
+        pyOnConsole = NULL;
+        return NULL;
+    }
+    Py_INCREF(pyOnConsole);
+    PyObject *tuple = PyTuple_New(1);
+    PyObject *pyBuf = PyUnicode_FromString("Console established..\n");
+    PyTuple_SetItem(tuple, 0, pyBuf);
+    PyObject_Call(pyOnConsole, tuple, NULL);
+    return Py_None;
+}
+
+static PyObject *method_on_control(PyObject *self, PyObject *args) {
+    if(!PyArg_ParseTuple(args, "O", &pyOnControl)) {
+        PyErr_SetString(PyExc_ValueError, "Invalid argument, must be single object");
+        pyOnSerial = NULL;
+        return NULL;
+    }
+    if(!PyCallable_Check(pyOnControl)) {
+        PyErr_SetString(PyExc_ValueError, "Argument object is not callable");
+        pyOnSerial = NULL;
+        return NULL;
+    }
+    Py_INCREF(pyOnControl);
+    return Py_None;
+}
+
+
+static PyMethodDef RunMethods[] = {
+    {"init", method_start, METH_VARARGS, "Initialise msp430 emulator"},
+    {"cmd", method_cmd, METH_VARARGS, "Send command to msp430 emulator"},
+    {"stop", method_stop, METH_NOARGS, "Stop msp430 emulator"},
+    {"play", method_play, METH_NOARGS, "Start running msp430 emulator"},
+    {"pause", method_pause, METH_NOARGS, "Pause running msp430 emulator"},
+    {"reset", method_reset, METH_NOARGS, "Reset msp430 emulator"},
+    {"on_serial", method_on_serial, METH_VARARGS, "Set emulator callback for serial"},
+    {"on_console", method_on_console, METH_VARARGS, "Set emulator callback for console"},
+    {"on_control", method_on_control, METH_VARARGS, "Set emulator callback for control"},
+    {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);
+}
+
+
+void print_serial(Emulator *emu, char *buf) {
+    if(pyOnSerial == NULL) return;
+
+    // set thread state
+    PyGILState_STATE gstate;
+    gstate = PyGILState_Ensure();
+
+    PyObject *tuple = PyTuple_New(1);
+    PyObject *pyBuf = PyUnicode_FromString(buf);
+    PyTuple_SetItem(tuple, 0, pyBuf);
+    PyObject_Call(pyOnSerial, tuple, NULL);
+
+//    Py_DECREF(pyBuf);
+//    Py_DECREF(tuple);
+    // resolve thread state
+    PyGILState_Release(gstate);
+}
+
+
+void print_console (Emulator *emu, const char *buf) {
+    if(pyOnConsole == NULL) {
+        puts(buf);
+        return;
+    }
+
+    // set thread state
+    PyGILState_STATE gstate;
+    gstate = PyGILState_Ensure();
+
+    PyObject *tuple = PyTuple_New(1);
+    PyObject *pyBuf = PyUnicode_FromString(buf);
+    PyTuple_SetItem(tuple, 0, pyBuf);
+    PyObject_Call(pyOnConsole, tuple, NULL);
+
+//    Py_DECREF(pyBuf);
+//    Py_DECREF(tuple);
+
+    // resolve thread state
+    PyGILState_Release(gstate);
+}
+
+void send_control (Emulator *emu, uint8_t opcode, void *data, size_t size) {
+    if(pyOnControl == NULL) return;
+
+    // set thread state
+    PyGILState_STATE gstate;
+    gstate = PyGILState_Ensure();
+
+    PyObject *tuple = PyTuple_New(2);
+    PyObject *pyOpcode = PyLong_FromLong(opcode);
+    PyTuple_SetItem(tuple, 0, pyOpcode);
+    PyObject *pyData = PyBytes_FromStringAndSize(data, size);
+    PyTuple_SetItem(tuple, 1, pyData);
+    PyObject_Call(pyOnControl, tuple, NULL);
+
+//    Py_DECREF(pyOpcode);
+//    Py_DECREF(pyData);
+//    Py_DECREF(tuple);
+
+    // resolve thread state
+    PyGILState_Release(gstate);
+}

+ 13 - 0
emulator/python/py_interface.h

@@ -0,0 +1,13 @@
+
+
+#ifndef _PY_INTERFACE_H_
+#define _PY_INTERFACE_H_
+
+#include "py_functions.h"
+#include <Python.h>
+
+void print_serial (Emulator *emu, char *buf);
+void print_console (Emulator *emu, const char *buf);
+void send_control (Emulator *emu, uint8_t opcode, void *data, size_t size);
+
+#endif

+ 129 - 84
msp430emu/emulator.py

@@ -1,18 +1,9 @@
-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, mkdir, chdir
-
+from os import path
 import _msp430emu
 import wx
 
 source_dir = path.dirname(path.realpath(__file__))
-mkdir(".emulator")
-chdir(".emulator")
 
 
 class Emulator:
@@ -37,101 +28,134 @@ class Emulator:
     P1_7_ON_PACKET = 0x0E
     P1_7_OFF_PACKET = 0x0F
 
-    def __init__(self, ws_port=59981, load=None, callback=None):
+    def __init__(self, load=None, callback=None):
         # self.process = Popen([path.join(emu_dir, 'MSP430'), str(ws_port)], stdout=PIPE, stderr=PIPE)
-        self.ws_port = ws_port
-        self.process = Thread(target=self._start_emu, daemon=True)
-        self.process.start()
-        self._start_ws()
+        # self.ws_port = ws_port
+        # self._start_ws()
         self.load = load
         self.started = False
-        self.start_errors = 0
         self.callback = callback
 
+        _msp430emu.on_serial(self._on_serial)
+        _msp430emu.on_console(self._on_console)
+        _msp430emu.on_control(self._on_control)
+
+        if self.load is not None:
+            self.process = Thread(target=self._start_emu, daemon=False)
+            self.process.start()
+
+    def _on_serial(self, s):
+        self._cb(self.EVENT_SERIAL, s)
+
+    def _on_console(self, s):
+        self._cb(self.EVENT_CONSOLE, s)
+
+    def _on_control(self, opcode, data):
+        if opcode <= 0x0F:
+            self._cb(self.EVENT_GPIO, opcode)
+
+    def send_command(self, cmd):
+        if self.started:
+            _msp430emu.cmd(cmd)
+
+    def reset(self):
+        if self.started:
+            _msp430emu.reset()
+
     def _start_emu(self):
         print("starting emulator...")
-        _msp430emu.run(self.ws_port)
+        self.started = True
+        _msp430emu.init(self.load)
         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 _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)
-            payload = b'\x00'  # opcode
-            payload += len(fdata).to_bytes(2, byteorder='big')
-            payload += len(name).to_bytes(2, byteorder='big')
-            payload += name.encode() + fdata
-            self.ws.send(payload, websocket.ABNF.OPCODE_BINARY)
+        self.load = fname
+        self.process = Thread(target=self._start_emu, daemon=False)
+        self.process.start()
+    #     with open(self.load, 'rb') as f:
+    #         self.firmware = fname
+    #         fdata = f.read()
+    #         name = path.basename(fname)
+    #         payload = b'\x00'  # opcode
+    #         payload += len(fdata).to_bytes(2, byteorder='big')
+    #         payload += len(name).to_bytes(2, byteorder='big')
+    #         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)
-
-    def _ws_msg(self, data, frame, x):
-        opcode = data[0]
-        if opcode == 0:
-            if len(data) == 2 and data[1] <= 15:
-                self._cb(self.EVENT_GPIO, data[1])
-
-        elif opcode == 1:
-            message = data[1:-1].decode()
-            self._cb(self.EVENT_CONSOLE, message)
-            # print(message, end=None)
-            return
-        elif opcode == 2:
-            message = data[1:-1].decode()
-            self._cb(self.EVENT_SERIAL, message)
-            return
-        else:
-            pass
-
-    def _ws_err(self, err):
-        if not self.started:
-            self.start_errors += 1
-            if self.start_errors < 5:
-                print(f"Failed to connect to emulator backend attempt {self.start_errors}")
-                sleep(1)
-                self._start_ws()
-            raise ConnectionError("Failed to connect to emulation backend after 5 tries")
-        raise err
-
-    def _ws_close(self):
-        if not self.started:
-            return
-        pass
+    # def _ws_open(self):
+    #     self.started = True
+    #     if self.load is not None:
+    #         self.load_file(self.load)
+    #
+    # def _ws_msg(self, data, frame, x):
+    #     opcode = data[0]
+    #     if opcode == 0:
+    #         if len(data) == 2 and data[1] <= 15:
+    #             self._cb(self.EVENT_GPIO, data[1])
+    #
+    #     elif opcode == 1:
+    #         message = data[1:-1].decode()
+    #         self._cb(self.EVENT_CONSOLE, message)
+    #         # print(message, end=None)
+    #         return
+    #     elif opcode == 2:
+    #         message = data[1:-1].decode()
+    #         self._cb(self.EVENT_SERIAL, message)
+    #         return
+    #     else:
+    #         pass
+
+    # def _ws_err(self, err):
+    #     if not self.started:
+    #         self.start_errors += 1
+    #         if self.start_errors < 5:
+    #             print(f"Failed to connect to emulator backend attempt {self.start_errors}")
+    #             sleep(1)
+    #             self._start_ws()
+    #         raise ConnectionError("Failed to connect to emulation backend after 5 tries")
+    #     raise err
+    #
+    # def _ws_close(self):
+    #     if not self.started:
+    #         return
+    #     pass
 
     def __del__(self):
         self.close()
 
     def emulation_pause(self):
-        self.ws.send(b'\x02', websocket.ABNF.OPCODE_BINARY)
+        if self.started:
+            _msp430emu.pause()
+        # if self.load is not None:
+        #     self.ws.send(b'\x02', websocket.ABNF.OPCODE_BINARY)
 
     def emulation_start(self):
-        self.ws.send(b'\x01', websocket.ABNF.OPCODE_BINARY)
+        if self.started:
+            _msp430emu.play()
+        # if self.load is not None:
+        #     self.ws.send(b'\x01', websocket.ABNF.OPCODE_BINARY)
 
     def close(self):
-        print("connection ended...")
-        self.ws.close()
+        if self.started:
+            _msp430emu.stop()
         # _msp430emu.stop()
-        # self.process.join(1)
+            self.process.join(5)
 
 
 class EmulatorWindow(wx.Frame):
@@ -165,9 +189,9 @@ class EmulatorWindow(wx.Frame):
         self.SetMenuBar(menuBar)
 
         self.sizer2 = wx.BoxSizer(wx.HORIZONTAL)
-        btn_start_emu = wx.Button(self, -1, "S&tart")
+        btn_start_emu = wx.Button(self, -1, "Start")
         self.Bind(wx.EVT_BUTTON, self.OnStart, btn_start_emu)
-        btn_stop_emu = wx.Button(self, -1, "P&ause")
+        btn_stop_emu = wx.Button(self, -1, "Pause")
         self.Bind(wx.EVT_BUTTON, self.OnPause, btn_stop_emu)
         self.sizer2.Add(btn_start_emu, 1, wx.EXPAND)
         self.sizer2.Add(btn_stop_emu, 1, wx.EXPAND)
@@ -193,8 +217,23 @@ class EmulatorWindow(wx.Frame):
         # dc.SetBrush(wx.WHITE_BRUSH)
         # dc.DrawRectangle(50, 50, 500, 500)
 
+        self.sizer_key_rst = wx.BoxSizer(wx.HORIZONTAL)
+        btn_key = wx.Button(self, -1, "Press Key")
+        self.Bind(wx.EVT_BUTTON, self.OnKeyPress, btn_key)
+        btn_rst = wx.Button(self, -1, "Reset")
+        self.Bind(wx.EVT_BUTTON, self.OnKeyReset, btn_rst)
+        self.sizer_key_rst.Add(btn_key, 1, wx.EXPAND)
+        self.sizer_key_rst.Add(btn_rst, 1, wx.EXPAND)
+
+        self.sizer_diagram = wx.BoxSizer(wx.VERTICAL)
+        self.sizer_diagram.Add(panel, 1, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL)
+        #
+        self.sizer_left = wx.BoxSizer(wx.VERTICAL)
+        self.sizer_left.Add(self.sizer_diagram, 1, wx.EXPAND)
+        self.sizer_left.Add(self.sizer_key_rst, 0, wx.ALIGN_BOTTOM)
+
         self.sizer1 = wx.BoxSizer(wx.HORIZONTAL)
-        self.sizer1.Add(panel, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALIGN_CENTER_VERTICAL)
+        self.sizer1.Add(self.sizer_left, 0, wx.EXPAND)
         self.sizer1.Add(self.control, 1, wx.EXPAND)
         self.sizer1.Add(self.sizer0, 1, wx.EXPAND)
 
@@ -220,10 +259,10 @@ class EmulatorWindow(wx.Frame):
             wx.CallAfter(self.diagram.Refresh)
 
     def RestartEmulator(self, e):
-        self.control.AppendText("Stopping Emulator..")
         self.emu.close()
         self.control.Clear()
         self.serial.Clear()
+        self.emu = Emulator(load=self.load, callback=self.callback)
 
     def ToggleConsole(self, e):
         if e.Int == 0:
@@ -234,7 +273,7 @@ class EmulatorWindow(wx.Frame):
             self.Layout()
 
     def OnOpen(self, e):
-        with wx.FileDialog(self, "Open Firmware File", wildcard="ELF files (*.elf)|*.elf",
+        with wx.FileDialog(self, "Open Firmware File", wildcard="BIN files (*.bin)|*.bin",
                            style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog:
             if fileDialog.ShowModal() == wx.ID_CANCEL:
                 return
@@ -257,6 +296,12 @@ class EmulatorWindow(wx.Frame):
         self.emu.close()
         self.Close(True)
 
+    def OnKeyPress(self, e):
+        pass
+
+    def OnKeyReset(self, e):
+        self.emu.reset()
+
 
 class DrawRect(wx.Panel):
     """ class MyPanel creates a panel to draw on, inherits wx.Panel """

+ 0 - 1
requirements.txt

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

+ 9 - 8
setup.py

@@ -2,7 +2,6 @@
 from distutils.core import setup, Extension
 
 emulator_files = [
-    'emulator/main.c',
     'emulator/devices/utilities.c',
     'emulator/devices/cpu/registers.c',
     'emulator/devices/memory/memspace.c',
@@ -17,20 +16,22 @@ emulator_files = [
     'emulator/devices/peripherals/timer_a.c',
     'emulator/devices/peripherals/usci.c',
     'emulator/devices/peripherals/port1.c',
-    'emulator/debugger/websockets/emu_server.c',
-    'emulator/debugger/websockets/packet_queue.c',
+    # 'emulator/debugger/websockets/emu_server.c',
+    # 'emulator/debugger/websockets/packet_queue.c',
     'emulator/debugger/disassembler.c',
+    'emulator/python/py_functions.c',
+    'emulator/python/py_interface.c',
 ]
 libraries = [
-    'websockets',
+    # 'websockets',
     'readline',
     'rt',
-    'ssl',
-    'crypto',
-    'pthread'
+    'pthread',
+    # 'ssl',
+    # 'crypto',
 ]
 ext_mod = Extension(
-    '_msp430emu', emulator_files, libraries=libraries, extra_compile_args=["-w"]
+    '_msp430emu', emulator_files, libraries=libraries, extra_compile_args=["-w", "-DPYTHON"]
 )
 
 setup(name='msp430emu',