mirror of
https://github.com/rricharz/Tek4010.git
synced 2026-02-26 08:53:35 +00:00
Tektronix emulation complete, including greyscale
This commit is contained in:
33
README.md
33
README.md
@@ -1,27 +1,29 @@
|
||||
[](https://travis-ci.org/rricharz/Tek4010)
|
||||
|
||||
# Tektronix 4010 and 4014 Terminal Emulator
|
||||
# Tektronix 4010 and 4014 Storage Tube Terminal Emulator
|
||||
|
||||
This is a [Tektronix 4010 and 4014](https://en.wikipedia.org/wiki/Tektronix_4010) terminal emulator
|
||||
for the Raspberry Pi and other Linux systems. It can also be used on Windows and Macintosh systems
|
||||
with [Virtualbox](https://www.virtualbox.org/) and [Ubuntu](https://www.ubuntu.com/).
|
||||
|
||||
It can also display historical data for the
|
||||
[MIT Project MAC](https://en.wikipedia.org/wiki/MIT_Computer_Science_and_Artificial_Intelligence_Laboratory#Project_MAC)
|
||||
's ARDS (Advanced Remote Display Station).
|
||||
|
||||

|
||||
|
||||
It attempts to emulate the storage tube display of the Tektronix 4010, including the bright
|
||||
drawing spot.
|
||||
It attempts to emulate the [storage tube display](https://en.wikipedia.org/wiki/Storage_tube)
|
||||
of the Tektronix 4010, including the bright drawing spot.
|
||||
|
||||
To the best of my knowledge this is the only Tektronix 4010 emulator, which makes an effort
|
||||
to emulate the storage tube behavior of the 4010. If the look and feel is not important, you can
|
||||
use ["xterm"](https://en.wikipedia.org/wiki/Xterm) instead. "xterm" does not support the
|
||||
"write through" mode.
|
||||
|
||||
This tek4010 emulator is currently in beta-testing and updated frequently.
|
||||
To the best of my knowledge this is the only Tektronix 4010/4014 emulator, which makes an effort
|
||||
to emulate the storage tube behavior. If the look and feel is not important, you can
|
||||
use ["xterm"](https://en.wikipedia.org/wiki/Xterm) instead. "xterm" does not support all
|
||||
graphics modes of the 4014.
|
||||
|
||||
It can be used to log into a historical Unix system such as
|
||||
[2.11 BSD](https://en.wikipedia.org/wiki/Berkeley_Software_Distribution) on the
|
||||
[pidp11](http://obsolescence.wixsite.com/obsolescence/pidp-11)
|
||||
or a real historical system.
|
||||
or a real historical system. At can also be used to display historical plot data.
|
||||
|
||||
This [video of a tek4010 demo](https://youtu.be/ioYiu6oUT88) was generated using
|
||||
[simplescreenrecorder](https://www.maartenbaert.be/simplescreenrecorder). There is also a
|
||||
@@ -232,7 +234,9 @@ tek4010 has the following options:
|
||||
-full in this mode the tek4010 emulator creates a full screen window, and
|
||||
uses the full resolution of the 4014 with the enhanced graphics module
|
||||
installed, scaled down to the actual window size. Use control-q to
|
||||
close the tek4010 window. This option is experimental.
|
||||
close the tek4010 window. This option is experimental.
|
||||
|
||||
-ARDS display ARDS data
|
||||
|
||||
**Reporting problems**
|
||||
|
||||
@@ -277,4 +281,11 @@ There is a make file in the repo.
|
||||
|
||||
See [versions.txt](versions.txt)
|
||||
|
||||
**Contributors**
|
||||
|
||||
The storage tube emulator and the Tektronix 4010/4014 decoder were witten by Rene Richarz.
|
||||
The ARDS decoder was written by Lars Brinkhoff.
|
||||
The historical plot data for the Tektronix 4014 was obtained from Jos Dreesen.
|
||||
Thanks to many others who contributed important ideas and helped with the debugging.
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
43
tek4010.c
43
tek4010.c
@@ -73,6 +73,16 @@ static long startPaintTime;
|
||||
static int xh,xl,yh,yl,xy4014;
|
||||
static long todo;
|
||||
|
||||
// table for special plot point mode
|
||||
// 4014 manual page F-9
|
||||
int intensityTable[] = {14,16,17,19, 20,22,23,25, 28,31,34,38, 41,33,47,50,
|
||||
56,62,69,75, 81,88,94,100, 56,62,69,75, 81,88,96,100,
|
||||
0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3,
|
||||
4, 4, 4, 5, 5, 5, 6, 6, 7, 8, 9,10, 11,12,12,13,
|
||||
14,16,17,19, 20,22,23,25, 28,31,34,38, 41,44,47,50,
|
||||
56,62,69,75, 81,88,94,100, 56,63,69,75, 81,88};
|
||||
|
||||
|
||||
void tek4010_checkLimits()
|
||||
/* check whether char is in visibel space */
|
||||
{
|
||||
@@ -147,9 +157,12 @@ void tek4010_escapeCodeHandler(cairo_t *cr, cairo_t *cr2, int ch)
|
||||
break;
|
||||
|
||||
// modes 27 and 29 - 31 are identical in all modes
|
||||
case 28: // record sepatator
|
||||
if (DEBUG) printf("Special point plot mode not supported, ignored\n");
|
||||
mode = 50;
|
||||
case 28: // record separator
|
||||
/*if (DEBUG)*/ printf("Special point plot mode, mode=%d\n",savemode);
|
||||
mode = 50; // for the intensity/focus character
|
||||
specialPlotMode = 1;
|
||||
double intensity = 1.0;
|
||||
int defocussed = 0;
|
||||
break;
|
||||
|
||||
case '8': tube_changeCharacterSize(cr, cr2, 74, 35, (int)(efactor * 18)); break;
|
||||
@@ -215,6 +228,7 @@ int tek4010_checkReturnToAlpha(int ch)
|
||||
todo = 0;
|
||||
}
|
||||
plotPointMode = 0;
|
||||
specialPlotMode = 0;
|
||||
return 1;
|
||||
}
|
||||
else return 0;
|
||||
@@ -225,7 +239,7 @@ void tek4010_draw(cairo_t *cr, cairo_t *cr2, int first)
|
||||
// cr is used for persistent drawing, cr2 for temporary drawing
|
||||
|
||||
{
|
||||
int ch;
|
||||
int ch, tag;
|
||||
|
||||
refreshCount++;
|
||||
|
||||
@@ -332,7 +346,7 @@ void tek4010_draw(cairo_t *cr, cairo_t *cr2, int first)
|
||||
plotPointMode = 0;
|
||||
goto endDo;
|
||||
case 30: // record separator >> incremental plot mode
|
||||
if (DEBUG) printf("Incremental point plot mode not supported, ignored\n");
|
||||
if (DEBUG) printf("Incremental point plot mode\n");
|
||||
penDown = 1;
|
||||
mode = 40;
|
||||
goto endDo;
|
||||
@@ -346,7 +360,7 @@ void tek4010_draw(cairo_t *cr, cairo_t *cr2, int first)
|
||||
// this cannot be done in switch(mode) below, because multiple bytes
|
||||
// can be skipped and the current byte must be executed after a mode change
|
||||
|
||||
int tag = (ch >> 5) & 3;
|
||||
tag = (ch >> 5) & 3;
|
||||
|
||||
if ((mode >= 1) && (mode <= 8)) {
|
||||
|
||||
@@ -483,9 +497,9 @@ void tek4010_draw(cairo_t *cr, cairo_t *cr2, int first)
|
||||
showCursor = 0;
|
||||
|
||||
tube_x0 = tube_x2; // prepare for additional vectors
|
||||
tube_y0 = tube_y2;
|
||||
mode = 5;
|
||||
|
||||
tube_y0 = tube_y2;
|
||||
if (specialPlotMode) mode = 50; // another intensity/focus char follows
|
||||
else mode = 5;
|
||||
break;
|
||||
case 30: // escape code handler
|
||||
tek4010_escapeCodeHandler(cr, cr2, ch);
|
||||
@@ -507,8 +521,15 @@ void tek4010_draw(cairo_t *cr, cairo_t *cr2, int first)
|
||||
}
|
||||
else if (DEBUG) printf("Illegal byte 0x%02X in incremental plot\n", ch);
|
||||
break;
|
||||
case 50: // special plot mode, not implemented
|
||||
tek4010_checkReturnToAlpha(ch); // check for exit
|
||||
case 50:// special plot mode, not implemented
|
||||
// ignore the value for now
|
||||
tag = ch >> 5;
|
||||
if ((ch < 32) || (ch >= 126)) return;
|
||||
if (DEBUG) printf("intensity/focus control = %c: %d: ", ch, tag);
|
||||
defocussed = (tag == 1);
|
||||
intensity = intensityTable[ch - 32];
|
||||
if (DEBUG) printf("defocussed = %d, intensity = %d%%\n", defocussed, intensity);
|
||||
mode = 5; // coordinates follow
|
||||
break;
|
||||
case 101:
|
||||
if (DEBUG) printf("Ignore until group separator, ch = %02x\n", ch);
|
||||
|
||||
2
tektests/greyscaletest.plt
Normal file
2
tektests/greyscaletest.plt
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB |
45
tube.c
45
tube.c
@@ -30,8 +30,8 @@
|
||||
#define WRITE_TROUGH_INTENSITY 0.5 // green only
|
||||
#define NORMAL_INTENSITY 0.8
|
||||
#define CURSOR_INTENSITY 0.8
|
||||
#define BRIGHT_SPOT_COLOR 1.0,1.0,1.0
|
||||
#define BRIGHT_SPOT_COLOR_HALF 0.3,0.6,0.3
|
||||
#define BRIGHT_SPOT_COLOR 1.0
|
||||
#define BRIGHT_SPOT_COLOR_HALF 0.6
|
||||
#define BLACK_COLOR 0.0,0.08,0.0 // effect of flood gun
|
||||
|
||||
#define _GNU_SOURCE
|
||||
@@ -76,6 +76,10 @@ int plotPointMode = 0; // plot point mode
|
||||
int writeThroughMode = 0; // write through mode
|
||||
int tube_doClearPersistent;
|
||||
|
||||
int specialPlotMode = 0;
|
||||
int defocussed = 0;
|
||||
int intensity = 100;
|
||||
|
||||
int tube_x0, tube_x2,tube_y0, tube_y2;
|
||||
|
||||
static int debugCount = 0;
|
||||
@@ -177,7 +181,7 @@ void tube_init(int argc, char* argv[])
|
||||
char *argv2[20];
|
||||
size_t bufsize = 127;
|
||||
int firstArg = 1;
|
||||
printf("tek4010 version 1.1 - branch split\n");
|
||||
printf("tek4010 version 1.2\n");
|
||||
windowName = "Tektronix 4010/4014 emulator";
|
||||
if ((argc<2) || (argc>19)) {
|
||||
printf("Error:number of arguments\n");
|
||||
@@ -409,13 +413,16 @@ void tube_clearPersistent(cairo_t *cr, cairo_t *cr2)
|
||||
tube_y2 = tube_y0;
|
||||
leftmargin = 0;
|
||||
cairo_set_source_rgb(cr, 0, NORMAL_INTENSITY, 0);
|
||||
cairo_set_source_rgb(cr2, BRIGHT_SPOT_COLOR);
|
||||
cairo_set_source_rgb(cr2, BRIGHT_SPOT_COLOR, BRIGHT_SPOT_COLOR, BRIGHT_SPOT_COLOR);
|
||||
cairo_paint(cr2);
|
||||
isBrightSpot = 1;
|
||||
plotPointMode = 0;
|
||||
ltype = SOLID;
|
||||
xlast = 0;
|
||||
ylast = 0;
|
||||
ylast = 0;
|
||||
specialPlotMode = 0;
|
||||
defocussed = 0;
|
||||
intensity = 100;
|
||||
}
|
||||
|
||||
void tube_clearSecond(cairo_t *cr2)
|
||||
@@ -475,12 +482,12 @@ void tube_drawCharacter(cairo_t *cr, cairo_t *cr2, char ch)
|
||||
|
||||
else {
|
||||
// draw the character
|
||||
cairo_set_source_rgb(cr, 0, NORMAL_INTENSITY, 0);
|
||||
cairo_set_source_rgb(cr, 0, (NORMAL_INTENSITY * intensity) / 100, 0);
|
||||
cairo_move_to(cr, tube_x0 + eoffx, windowHeight - tube_y0);
|
||||
cairo_show_text(cr, s);
|
||||
|
||||
// draw the bright spot
|
||||
cairo_set_source_rgb(cr2, BRIGHT_SPOT_COLOR);
|
||||
cairo_set_source_rgb(cr2, BRIGHT_SPOT_COLOR, BRIGHT_SPOT_COLOR, BRIGHT_SPOT_COLOR);
|
||||
cairo_move_to(cr2, tube_x0 + eoffx, windowHeight - tube_y0);
|
||||
cairo_show_text(cr2, s);
|
||||
}
|
||||
@@ -504,7 +511,8 @@ void tube_emulateDeflectionTime()
|
||||
void tube_drawPoint(cairo_t *cr, cairo_t *cr2)
|
||||
{
|
||||
#define PI2 6.283185307
|
||||
cairo_set_source_rgb(cr, 0, NORMAL_INTENSITY, 0);
|
||||
cairo_set_line_width (cr, 1 + defocussed);
|
||||
cairo_set_source_rgb(cr, 0, (NORMAL_INTENSITY * intensity) / 100, 0);
|
||||
cairo_move_to(cr, tube_x2 + eoffx, windowHeight - tube_y2);
|
||||
cairo_line_to(cr, tube_x2 + 1 + eoffx, windowHeight - tube_y2);
|
||||
cairo_stroke (cr);
|
||||
@@ -515,10 +523,11 @@ void tube_drawPoint(cairo_t *cr, cairo_t *cr2)
|
||||
if (((tube_x2 - xlast) > 2) || ((xlast - tube_x2) > 2) ||
|
||||
((tube_y2 - ylast) > 2) || ((ylast - tube_y2) > 2)) {
|
||||
|
||||
// draw the bright spot, higher intensity
|
||||
// draw the bright spot
|
||||
cairo_set_line_width (cr2, 0.1);
|
||||
cairo_set_source_rgb(cr2, BRIGHT_SPOT_COLOR);
|
||||
cairo_arc(cr2, tube_x2 + eoffx, windowHeight - tube_y2, 2, 0, PI2);
|
||||
double bsc = (BRIGHT_SPOT_COLOR * intensity) / 100;
|
||||
cairo_set_source_rgb(cr2, bsc, bsc, bsc);
|
||||
cairo_arc(cr2, tube_x2 + eoffx, windowHeight - tube_y2, 2 + defocussed, 0, PI2);
|
||||
cairo_fill(cr2);
|
||||
|
||||
xlast = tube_x2;
|
||||
@@ -549,23 +558,25 @@ void tube_drawVector(cairo_t *cr, cairo_t *cr2)
|
||||
|
||||
else {
|
||||
// draw the actual vector on permanent surface
|
||||
cairo_set_line_width (cr, 1);
|
||||
cairo_set_source_rgb(cr, 0, NORMAL_INTENSITY, 0);
|
||||
cairo_set_line_width (cr, 1 + defocussed);
|
||||
cairo_set_source_rgb(cr, 0, (NORMAL_INTENSITY * intensity) / 100, 0);
|
||||
tube_line_type(cr, cr2, ltype);
|
||||
cairo_move_to(cr, tube_x0 + eoffx, windowHeight - tube_y0);
|
||||
cairo_line_to(cr, tube_x2 + eoffx, windowHeight - tube_y2);
|
||||
cairo_stroke (cr);
|
||||
|
||||
//draw the bright spot, half intensity
|
||||
cairo_set_line_width (cr2, 6);
|
||||
cairo_set_source_rgb(cr2, BRIGHT_SPOT_COLOR_HALF);
|
||||
cairo_set_line_width (cr2, 6 + 2 * defocussed);
|
||||
double bsc = (BRIGHT_SPOT_COLOR_HALF * intensity) / 100;
|
||||
cairo_set_source_rgb(cr2, bsc, bsc, bsc);
|
||||
cairo_move_to(cr2, tube_x0 + eoffx, windowHeight - tube_y0);
|
||||
cairo_line_to(cr2, tube_x2 + eoffx, windowHeight - tube_y2);
|
||||
cairo_stroke (cr2);
|
||||
|
||||
// draw the bright spot, high intensity
|
||||
cairo_set_line_width (cr2, 3);
|
||||
cairo_set_source_rgb(cr2, BRIGHT_SPOT_COLOR);
|
||||
cairo_set_line_width (cr2, 3 + 2 * defocussed);
|
||||
bsc = (BRIGHT_SPOT_COLOR * intensity) / 100;
|
||||
cairo_set_source_rgb(cr2, bsc, bsc, bsc);
|
||||
cairo_move_to(cr2, tube_x0 + eoffx, windowHeight - tube_y0);
|
||||
cairo_line_to(cr2, tube_x2 + eoffx, windowHeight - tube_y2);
|
||||
cairo_stroke(cr2);
|
||||
|
||||
4
tube.h
4
tube.h
@@ -20,6 +20,10 @@ extern long refreshCount;
|
||||
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 specialPlotMode;
|
||||
extern int defocussed;
|
||||
extern int intensity;
|
||||
|
||||
extern int plotPointMode;
|
||||
extern int writeThroughMode;
|
||||
|
||||
|
||||
11
versions.txt
11
versions.txt
@@ -1,12 +1,13 @@
|
||||
Next version t.b.b
|
||||
==================
|
||||
Next version t.b.d.
|
||||
===================
|
||||
New features
|
||||
- variable character size, set with ESC sequencies, reset if screen is cleared
|
||||
- incremental plot implemented
|
||||
- variable character size
|
||||
- incremental plot mode
|
||||
- ARDS mode
|
||||
- special plot mode with greyscale
|
||||
Bug fixes
|
||||
- vertical position of characters corrected
|
||||
- full implementation of Tektronix 4014 decoder
|
||||
Appearance:
|
||||
|
||||
Version 1.1 April 12, 2019
|
||||
==========================
|
||||
|
||||
Reference in New Issue
Block a user