From 19d2f125f388f5d3191446c8d2d55da60baa293f Mon Sep 17 00:00:00 2001 From: Rene Richarz Date: Sun, 3 May 2026 06:35:12 +0200 Subject: [PATCH] Fix 2s redraw gaps and continuous redraw using decay counter --- src/ards.c | 1 - src/main.c | 47 +++++++++++++++++++++++++++++++++++++++-------- src/tek4010.c | 4 +++- src/tube.c | 26 +++++++++++++++++--------- src/tube.h | 5 +++++ 5 files changed, 64 insertions(+), 19 deletions(-) diff --git a/src/ards.c b/src/ards.c index f6f1e06..50670f5 100755 --- a/src/ards.c +++ b/src/ards.c @@ -96,7 +96,6 @@ void ards_draw(cairo_t *cr, cairo_t *cr2, int first) startPaintTime = tube_mSeconds(); // start to measure time for this draw operation showCursor = 1; - isBrightSpot = 0; // clear the second surface tube_clearSecond(cr2); diff --git a/src/main.c b/src/main.c index a7fa921..cdc3684 100644 --- a/src/main.c +++ b/src/main.c @@ -27,8 +27,6 @@ * */ -#define TIME_INTERVAL 35 // time interval for timer function in msec (after last refresh) - #define GDK_DISABLE_DEPRECATION_WARNINGS #include @@ -63,6 +61,28 @@ extern int tube_doClearPersistent; static void do_drawing(cairo_t *, GtkWidget *); +#include +void debug_timer_interval(const char *where) +{ + static long last = 0; + struct timeval tv; + long now; + long diff; + + gettimeofday(&tv, NULL); + now = tv.tv_sec * 1000L + tv.tv_usec / 1000L; + + if (last != 0) { + diff = now - last; + if (diff > 100) { + printf("%s gap %ld ms\n", where, diff); + fflush(stdout); + } + } + + last = now; +} + static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, gpointer user_data) { @@ -72,9 +92,19 @@ static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, static gboolean on_timer_event(GtkWidget *widget) { - if (tube_on_timer_event()) - gtk_widget_queue_draw(widget); - return TRUE; + static int count = 0; + + count++; + if (count >= 100) { + printf("timer heartbeat\n"); + fflush(stdout); + count = 0; + } + + debug_timer_interval("timer"); + if (tube_on_timer_event()) + gtk_widget_queue_draw(widget); + return TRUE; } static gboolean clicked(GtkWidget *widget, GdkEventButton *event, gpointer user_data) @@ -95,7 +125,7 @@ static void do_drawing(cairo_t *cr, GtkWidget *widget) { static cairo_surface_t *permanent_surface, *temporary_surface; - g_source_remove(global_timeout_ref); // stop timer, in case do_drawing takes too long + // g_source_remove(global_timeout_ref); // stop timer, in case do_drawing takes too long if (global_firstcall) { // force aspect ratio by making black stripes at left and right, or top and bottom @@ -132,6 +162,7 @@ static void do_drawing(cairo_t *cr, GtkWidget *widget) printf("Cannot create drawing surfaces\n"); exit(1); } + if (argARDS) ards_draw(permanent_cr, temporary_cr, global_firstcall); else @@ -153,8 +184,8 @@ static void do_drawing(cairo_t *cr, GtkWidget *widget) cairo_destroy(permanent_cr); cairo_destroy(temporary_cr); - global_timeout_ref = g_timeout_add(TIME_INTERVAL, (GSourceFunc) on_timer_event, - (gpointer) window); + // global_timeout_ref = g_timeout_add(TIME_INTERVAL, (GSourceFunc) on_timer_event, + // (gpointer) window); } static void on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data) diff --git a/src/tek4010.c b/src/tek4010.c index 426d4d1..f4b55f8 100755 --- a/src/tek4010.c +++ b/src/tek4010.c @@ -344,6 +344,9 @@ void tek4010_draw(cairo_t *cr, cairo_t *cr2, int first) { int ch, tag; + + printf("."); + fflush(stdout); refreshCount++; @@ -359,7 +362,6 @@ void tek4010_draw(cairo_t *cr, cairo_t *cr2, int first) startPaintTime = tube_mSeconds(); // start to measure time for this draw operation showCursor = 1; - isBrightSpot = 0; // clear the second surface tube_clearSecond(cr2); diff --git a/src/tube.c b/src/tube.c index 4f26125..f951ab7 100755 --- a/src/tube.c +++ b/src/tube.c @@ -93,9 +93,9 @@ int argFast = 0; int argHalf = 0; int refresh_interval; // after this time in msec next refresh is done +int brightCounter = 0; int showCursor; // set of cursor is shown (not set in graphics mode) -int isBrightSpot = 0; // set if there is currently a bright spot on the screen int xlast, ylast; @@ -546,7 +546,10 @@ int tube_on_timer_event() printf("Process has been terminated\n"); exit(0); } - return (isBrightSpot || tube_isInput()); + if (brightCounter > 0) + brightCounter--; + + return ((brightCounter > 0) || tube_isInput()); } int tube_clicked(int button, int x, int y) @@ -596,7 +599,9 @@ void tube_clearPersistent(cairo_t *cr, cairo_t *cr2) tube_set_source_rgb(cr, NORMAL_INTENSITY, NORMAL_SATURATION); tube_set_source_rgb(cr2, BRIGHT_SPOT_INTENSITY / 2, BRIGHT_SPOT_SATURATION); cairo_paint(cr2); - isBrightSpot = 1; + printf("brightCounter reset: tubeClearPersistent\n"); + fflush(stdout); + brightCounter = BRIGHT_COUNTER_INIT; plotPointMode = 0; ltype = SOLID; xlast = 0; @@ -620,7 +625,6 @@ void tube_clearSecond(cairo_t *cr2) cairo_set_operator(cr2, CAIRO_OPERATOR_MULTIPLY); cairo_paint(cr2); cairo_set_operator(cr2, CAIRO_OPERATOR_OVER); - isBrightSpot = 1; } } @@ -821,7 +825,9 @@ void tube_drawCharacter(cairo_t *cr, cairo_t *cr2, char ch) } tube_x0 += hDotsPerChar; - isBrightSpot = 1; + printf("brightCounter reset: drawCharacter\n"); + fflush(stdout); + brightCounter = BRIGHT_COUNTER_INIT; } void tube_emulateDeflectionTime() @@ -861,8 +867,9 @@ void tube_drawPoint(cairo_t *cr, cairo_t *cr2) xlast = tube_x2; ylast = tube_y2; } - - isBrightSpot = 1; +printf("brightCounter reset: drawPoint\n"); +fflush(stdout); + brightCounter = BRIGHT_COUNTER_INIT; } void tube_crosshair(cairo_t *cr, cairo_t *cr2) @@ -913,8 +920,9 @@ void tube_drawVector(cairo_t *cr, cairo_t *cr2) cairo_line_to(cr2, tube_x2, windowHeight - tube_y2); cairo_stroke(cr2); } - - isBrightSpot = 1; // also to be set if writeThroughMode +printf("brightCounter reset: drawVector\n"); +fflush(stdout); + brightCounter = BRIGHT_COUNTER_INIT; // also to be set if writeThroughMode } void tube_setupPainting(cairo_t *cr, cairo_t *cr2, char *fontName) diff --git a/src/tube.h b/src/tube.h index 8edd1b2..a7fc3f5 100755 --- a/src/tube.h +++ b/src/tube.h @@ -30,6 +30,11 @@ extern int vDotsPerChar; extern int refresh_interval; // after this time in msec next refresh is done extern long refreshCount; +extern int brightCounter; +#define TIME_INTERVAL 35 // time interval for timer function in msec (after last refresh) +#define BRIGHT_TIME_MSEC 1000 +#define BRIGHT_COUNTER_INIT ((BRIGHT_TIME_MSEC + TIME_INTERVAL - 1) / TIME_INTERVAL) + extern int showCursor; // set of cursor is shown (not set in graphics mode) extern int isBrightSpot; // set if there is currently a bright spot on the screen extern int isGinMode; // set if GIN mode is active