1
0
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:
¨Rene Richarz
2019-04-14 08:29:29 +02:00
parent 5b49d4eca4
commit 24ddb744a5
12 changed files with 94 additions and 44 deletions

View File

@@ -1,27 +1,29 @@
[![Build Status](https://travis-ci.org/rricharz/Tek4010.svg?branch=master)](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).
![screen_shot](screendump.png?raw=true "tek4010 screendump")
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.

BIN
tek4010

Binary file not shown.

View File

@@ -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);

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

45
tube.c
View File

@@ -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
View File

@@ -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;

View File

@@ -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
==========================