From 8dd29cfa9565a6efe459b33f51d7dfd8b407d3b0 Mon Sep 17 00:00:00 2001 From: Seth Morabito Date: Sat, 15 Dec 2018 10:58:35 -0800 Subject: [PATCH] Added LICENSE and README --- LICENSE.md | 20 ++++++++++++ README.md | 20 ++++++++++++ src/dmd.c | 92 ++++++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 108 insertions(+), 24 deletions(-) create mode 100644 LICENSE.md create mode 100644 README.md diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..c89f442 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,20 @@ +Copyright 2018, Seth Morabito + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..d0057b7 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# GTK DMD 5620 Emulator + +This is a GTK+ 3.0 implementation of an AT&T / Teletype DMD 5620 emulator. + +## Status + +Version: 0.1 + +This is an actively developed project, and is not ready for use yet. + +## See Also + +* [dmd_core](https://github.com/sethm/dmd_core): DMD 5620 core + implementation library, used by this project. + +## License + +MIT license. See the file [LICENSE.md](LICENSE.md) + +Copyright (c) 2018, Seth Morabito <web@loomcom.com> diff --git a/src/dmd.c b/src/dmd.c index 2a88814..af37bd2 100644 --- a/src/dmd.c +++ b/src/dmd.c @@ -1,10 +1,17 @@ #include +#include #include #include #include +#include static cairo_surface_t *surface = NULL; +static pthread_t dmd_thread; + +uint8_t last_kb_char; +uint8_t kb_pending = 0; +volatile int dmd_thread_run = 1; extern int dmd_init(); extern int dmd_reset(); @@ -53,10 +60,7 @@ static void close_window(void) { printf("[close_window]\n"); - gtk_main_quit(); - if (surface) { - cairo_surface_destroy(surface); - } + dmd_thread_run = 0; } static gboolean @@ -82,9 +86,15 @@ long get_current_time_ms() return (s * 1000) + ms; } -static void -refresh_display(GtkWidget *widget) +static gboolean +refresh_display(gpointer data) { + GtkWidget *widget = (GtkWidget *)data; + + if (widget == NULL || !GTK_IS_WIDGET(widget)) { + return FALSE; + } + GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, @@ -132,6 +142,8 @@ refresh_display(GtkWidget *widget) cairo_destroy(cr); gtk_widget_queue_draw(widget); + + return TRUE; } static gboolean @@ -148,24 +160,41 @@ button_press_event_cb(GtkWidget *widget, GdkEventButton *event, gpointer data) return TRUE; } -uint8_t last_kb_char; -uint8_t kb_pending = 0; - -static gboolean -run_dmd(gpointer user_data) +void *dmd_run(void *threadid) { - for (int i = 0; i < 40000; i++) { + long double steps = 0; + int rs; + struct timespec sleep_time_req, sleep_time_rem; + + sleep_time_req.tv_sec = 0; + sleep_time_req.tv_nsec = 10000000; + + printf("[DMD thread starting]"); + dmd_init(); + dmd_reset(); + + while (dmd_thread_run) { dmd_step(); + + // Stop every once in a while to poll for I/O and idle. + if (steps++ == 250000) { + if (kb_pending && dmd_rx_keyboard(last_kb_char)) { + printf("[DMD thread] Sent char 0x%02x\n", last_kb_char); + kb_pending = 0; + } + + steps = 0; + rs = nanosleep(&sleep_time_req, &sleep_time_rem); + if (rs) { + printf("[DMD thread] SLEEP FAILED. Result=%d\n", rs); + break; + } + } } - // Poll. - if (kb_pending && dmd_rx_keyboard(last_kb_char)) { - printf("[run_dmd] Just sent char 0x%02x\n", last_kb_char); - kb_pending = 0; - } + printf("[DMD thread exiting]\n"); - refresh_display((GtkWidget *)user_data); - return G_SOURCE_CONTINUE; + pthread_exit(NULL); } static gboolean @@ -204,7 +233,7 @@ activate(GtkApplication *app, gpointer user_data) gtk_container_add(GTK_CONTAINER(frame), drawing_area); - g_timeout_add(33, run_dmd, drawing_area); + g_timeout_add(20, refresh_display, drawing_area); /* Signals used to handle the backing surface */ g_signal_connect(drawing_area, "draw", @@ -241,11 +270,13 @@ main(int argc, char *argv[]) GtkApplication *app; int status; + long thread_id; + int rc; - dmd_init(); - dmd_reset(); - for (int i = 0; i < 1000000; i++) { - dmd_step(); + rc = pthread_create(&dmd_thread, NULL, dmd_run, (void *)thread_id); + if (rc) { + printf("ERROR: Could not create main DMD cpu thread. Status=%d\n", rc); + exit(-1); } app = gtk_application_new("com.loomcom.dmd", G_APPLICATION_FLAGS_NONE); @@ -253,6 +284,19 @@ main(int argc, char *argv[]) status = g_application_run(G_APPLICATION(app), argc, argv); + void *join_status; + rc = pthread_join(dmd_thread, &join_status); + if (rc) { + printf("ERROR: Could not join thread. Status=%d\n", rc); + exit(-1); + } + + printf("Main: DMD thread is done.\n"); + + /* if (surface) { */ + /* cairo_surface_destroy(surface); */ + /* } */ + g_object_unref(app); return status;