Added LICENSE and README

This commit is contained in:
Seth Morabito 2018-12-15 10:58:35 -08:00
parent 2f77975f65
commit 8dd29cfa95
3 changed files with 108 additions and 24 deletions

20
LICENSE.md Normal file
View File

@ -0,0 +1,20 @@
Copyright 2018, Seth Morabito <web@loomcom.com>
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.

20
README.md Normal file
View File

@ -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 &lt;web@loomcom.com&gt;

View File

@ -1,10 +1,17 @@
#include <gtk/gtk.h>
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <stdint.h>
#include <pthread.h>
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;