The following article presents a text editor for Electronics BK-0010, written around 1986. The description may sound hopelessly naive. Still, the features of our editor were quite similar to those of the state-of-the art editors K52 and Wordstar. One should keep in mind that these features were implemented in only 1754 bytes of code. With 512 initial bytes used by the firmware and data and 966 bytes of the custom nanoOS, there were 13 KBytes left for the document text. There was enough room for a paper.
The article was originally published in Russian in the Magazine ``Микропроцессорные Средства и Системы'' (Microprocessor tools and systems), N3, 1989, p. 56. The following is the close translation.
Universal text editor for the "Electronics BK-0010" personal computerAn important application for personal computers is using them as typewriters, for entering, storing and editing of various documents. For doing these tasks on the ``Electronics BK-0010'', in Kazan State University (named after V.I.Ulyanov-Lenin) has been developed a universal text editor. It lets us enter and edit text in full screen: change any character of the displayed page; shift characters on a line to the right to make room for new ones; delete characters; enter, delete and duplicate lines. There were many ways to quickly move the text cursor. One can scroll the text, and display the page with the given line number. If the cursor is at the top of the screen, pressing the UP key scrolls the text down, showing the previous text line if any. Likewise, the text scrolls up when pressing the DOWN key with the cursor on the bottom two screen lines. Any group of text lines (including one line and the whole text) can be marked as a block, and copied to a different place or deleted. It takes only two key presses to mark the current line as the beginning or the end line of the block. The cursor can be quickly positioned on the first or the last line of the marked block. To format text, one can split a text line in two at the cursor, and merge two lines. If the merged line turns out too wide, it is split in such a way that the first line is filled with whole words (not characters!).
The text in memory is a sequence of lines of varying length (up to the maximum of 63 characters); the trailing spaces are not stored. However, the user does not suspect such a tight storage: he may position the cursor at any point of the screen and insert any characters at any place. The user hence has the full impression of editing the fixed-width--line text -- just like a regular printed text. This feature distinguishes our editor from other well-known screen editors (such as K52). The what-you-see-is-what-you-get mode of our editor significantly improves the convenience of using it.
Besides the editing functions, the program lets us store the document on the magnetic tape, load the previously saved text and append it to the one in memory. The appended text can then be moved using the block copy operation. A universal driver supports printing on any printer with the IRPR [Centronics-like] interface. Printing has been tested on TPU, UVVPC-30-004, TC 7180, D100 (of the DVK System). On last two units one can print both in Cyrillic and Latin alphabets in lower and upper cases.
The editor program is written in position-independent code and takes just a bit over 3 kilobytes of main memory. The rest of the RAM of BK-0010 (13 KByte) can be used for the text.
The BK editor is somewhat like Wordstar (which I have never used, and did not know at the time). There was no on-screen menu though: the whole screen was used for text. The BK editor was also reminiscent of the K52 visual editor that DEC distributed with its OS RT-11 -- which I was familiar with and disliked. The most visible distinction of the BK editor was its WYSIWYG mode: if the newline character cannot be seen, it should not be felt. Therefore, the cursor moves vertically in a straight line, without any odd jumps. The editing feels like the `picture mode' of Emacs. Although the screen lines appear padded with spaces to fixed width, the trailing spaces were not stored. Such WYSIWYG mode was a feature of several editors developed in the USSR for bigger computers but it is hardly known in the West.
The first version of the program was entered into a BK in hexadecimal codes using a custom hexadecimal editor (quite like the HEXL mode in modern Emacs). Referenced below is the second version, which added minor improvements and was re-coded in PDP Macro-11. It was then transmitted to a BK via a custom network.
The code uses tables to quickly dispatch to keystroke handlers. The
editor also relies on the putback keystroke buffer: quite a few keystrokes
are implemented as `macros'. The previously written nanoOS provided
common services via `traps'. For example, trap 14
displays and formats
a message, trap 11
controls the magnetic tape, and trap 3
printer.
Trap 16
saves registers and trap 17
restores them and returns to
the caller of the function.
The BK Editor (sometimes called TRED) was used productively for several years and was widely distributed. It was cloned, so to speak, several times.
edwa.mac [2K]
Editor Source Code (PDP-11 Assembly):
Global data definitions
edinit.mac [6K]
Global initialization
and the handling of the main menu
edroot.mac [5K]
Text editing root module,
with the main loop dispatching to keystroke handlers
edsymb.mac [8K]
Handle simple keystrokes (page/line up, etc)
edgold.mac [11K]
Handle prefix commands with
a table-driven 1-symbol-stack automaton
edut1.mac [9K]
Utilities: displaying a block of text,
locating a line by its number, status reporting, buffer operations, etc.
lined.mac [8K]
Line editor
edwa.map [2K]
Memory map of the complete executable
BK 0010 in the Old Computer Museum
<http://oldcomputermuseum.com/elektronika_bk0010.html>
An engaging and productive course should be more interactive. Presentation and questions should be interspersed; an answer should be evaluated on the spot. If the answer is not correct, the student should get another chance or a hint. If the correct answer is still not forthcoming, there should follow alternative lessons to explain the subject more slowly. Questions should be variable and varied, preferably with non-deterministic parts. It goes without saying that the answer should be given in a free form, as an arbitrary number or a string -- rather than as a selection from a list. All in all, an engaging course should look quite like an adventure game.
It was also realized early on that writing the script of a good course, like that of a good game, is a skill, different from programming. It is unreasonable to make course authors write in Fortran or Assembly (as computers were programmed those days). They needed good tools -- a high-level language for writing course scripts. (Game industry has realized that, too). One of such early course script languages was TUTOR, developed at the University of Illinois in late 1960s.
In Soviet Union, there was a dialect/reimplementation of TUTOR for mainframes. I have encountered it when studying and then working at the Kazan State University. Taking a computer course on a mainframe was inconvenient, to say the least: mainframes were not easily accessible -- and, in the Soviet Union, they often broke down.
Personal computers, once became available, made for a better, or at least much cheaper, platform for computer tutoring. That was the motivation to write an interpreter for a TUTOR dialect on the personal computer BK-0010. The hardware was quite less capable than the mainframe. Still, my implementation had a few advantages over its mainframe counterpart.
In the original TUTOR and its dialects, presentations were created by positioning the cursor on the screen and then writing text. My implementation supported formatted output, with text and drawing. The text template to display could contain slots to be filled with the current values of numeric or string expressions. Text templates may also include screen control codes, for color, inverse video and other screen effects. There was a special operator for line drawing.
The script language was a programming language, with numeric and string computations, and string conversion, editing and matching. The latter was necessary to evaluate student responses, which were assumed to be free-form. The language offered 26 integer and 8 string variables. It also supported branching, looping and subroutines. As a dialect of TUTOR, it had dedicated operators for accepting an answer and branching on match or mismatch with respect to the given template; advancing to the next lesson, backtracking, or switching to another lesson plan. Lessons may be grouped into sets. Course scripts may be edited with the built-in full-screen editor.
The interpreter was written in PDP-11 assembly (MACRO-11). The interpreter took 3Kbytes of memory, the editor 1.5KBytes and the simple OS, 2KBytes. The rest 9.5KBytes of the main memory of BK-0010 could then be used for the course script and materials. When a course is fully written, the editor can be removed and its memory used for the course.
I realize now that the script language was good enough to write text adventure games (actually, semi-textual: it supported drawing). Alas, neither I nor any of my friends knew of `text adventure' at the time.
I have written a couple of sample courses for illustration, and planned to port a few of the existing TUTOR courses developed at the university. It seems only the interpreter code has survived, shown below.
Just the other day (in September 2018) I took an online course on personal information handling, mandated by the university. The course consisted of a video followed by a dozen of multiple-choice questions. It is sad to realize that in 1988 -- on the computer with the clock speed of mere 3MHz and the total memory million times smaller than that on my present computer -- I could have scripted and taken a much more engaging course.
paper.txt [10K]
Interpreter for training courses on the "Electronics BK-0010"
personal computer (in Russian)
This paper describing the system was published in the proceedings of
the XIII Joint Soviet-French Seminar "Designing the computer assisted
systems for the higher school on the base of personal computers",
Kazan, Oct. 10-14, 1988, p. 122-125
A wordstar-like text editor for Electronics BK-0010 in 1754 bytes
BK-0010 computer and the editor used for the course scripts
The source code of the interpreter (PDP-11 Macro-assembly), as is
I came to know the R-technology in the early 1980s from several books and articles published by the Institute of Cybernetics researchers. There was a distinct impression that anything that came from the Glushkov institute was one way or another about the R-technology. I remember looking at the diagrams (R-charts) for a complete Pascal compiler, drawn on big sheets of paper.
The R-technology is based on diagrams that depict the control-flow graph of a program. Nodes are program states and directed edges (arcs) are state transitions. Arcs are annotated with text or graphics, both above and below the arc; above is the condition/guard; below is the action to perform when the arc is followed. Arcs are laid out horizontally. When a program is in a particular state, we examine the outgoing arcs top to bottom looking for an arc whose condition is true. The action of the found arc is executed and the arc's target becomes the next program state. R-technology is closely related to flowcharts; however, what is a node in a flowchart is an annotated arc in a R-chart (and, similarly, in Harel's Statechart). We shall call an R-technology diagram an R-chart, and the abstract machine/automaton it depicts -- an R-machine, or R-tran (RTRAN).
The R-machine description above should remind one of state machines. The close similarity is no accident: Glushkov was the famous researcher in automata theory, having proposed the first algorithm to transform a regular expression into a non-deterministic finite automaton, and written the book ``Synthesis of Digital Automata'' (which brought him Lenin Prize and the membership in the Soviet Academy of Sciences). Unlike finite state automata, the condition on a R-machine state transition is not a mere test of the current input symbol; it can be arbitrarily complex. R-machine actions are also arbitrarily complex. We will see later an example: an R-machine with nominally two states. It also has mutable state, updated by its actions. Therefore, the effective number of states in unbounded. To me, an R-machine always looked like a Turing machine, but with the practical `control', whose actions go beyond the mere reading, writing and moving the tape.
R-technology diagrams are often drawn as graphs, and hence the technology is called visual programming. Nothing prevents however a (stylized) plain-text representation of the diagrams. I remember seeing in some book the form for writing R-programs. It looked somewhat like the form for entering Fortran or Cobol programs for punching. The form had four columns, for the state label, condition, action and the next label. R-programs were supposed to be entered as:
statelabelA condition1 action1 statelabelA true action2 statelabelB statelabelB condition3 action3 statelabelA ...To me, this stylized plain-text notation had the most appeal: as a way to organize thoughts about the program state and to force to consider all transitions from a given state.
Let's take an example, from a train scheduling program I wrote back in
1987 or 1988, in Algol-68. (Candidate) train schedules were
represented as a tree, whose various traversals and transformations
were programmed in the R-technology. The simplest was the tree
print-out: a depth-first tree traversal printing out data from its
nodes. The traversal was done iteratively, in constant space, without
using the stack. The train scheduling program was run on ES-1033 (the
Soviet clone of an IBM S\
360 mainframe), which had only 1MB of
memory. One had to be careful with deep recursion.
To make the tree-printing R-program easier, for the modern reader, to understand, I re-wrote it in C, as follows. Like in the original Algol-68 code, the tree is a linked data structure, whose nodes point to the right sibling, the parent and the first-born--child. One may also say that the tree is the cross-product of a single-linked list (in the sibling direction) with the double-linked list (in the parent-child direction). The payload of a node is just an integer, in our example. (The original scheduling program put more data in tree nodes.)
typedef struct _node node; /* forward declaration */ struct _node { node * up; /* parent pointer */ node * down; /* first-born child */ node * right; /* brother */ int data; /* payload: just an int in our example */ }; const node * const nil = (node *)NULL;
Below is the tree printing function, written as an R-machine. It
prints the payload of nodes as it traverses the tree depth-first. The
machine has only two states (not counting the finish
label), but
also a mutable state: the pointer to the current node n
. The actions
of the machine update n
, to point to a neighboring node. Thus the
effective number of states is unbounded.
void dump(const node * const tree) { const node * n = tree; /* current node */ enum {finish,down,right_up} state = down; /* The R-machine execution, with two states */ while(state != finish) switch(state) { case down: /* condition action next-state */ if(n->down == nil) {printf("data %d----- leaf\n",n->data); state = right_up;} else {printf("data %d\n",n->data); n = n->down; state = down;} break; case right_up: if (n->right != nil) {n = n->right; state=down;} else if (n->up == nil) {n = nil; state=finish;} else {n = n->up; state=right_up;} break; case finish: break; } }
Algol-68 had the notation for anonymous functions and sequences. Therefore, the machine itself was an ordinary procedure and an R-program -- an inline sequence of tuples, recalling the 4-columnar format I have seen in a book. The C code can be made to look similarly.
The C code also has a more interesting R-program: building a full binary tree iteratively, without using stack -- in constant memory, if we do not count the allocated tree nodes. The C code, including the more complicated tree builder, worked on the first try. I should also say that the tree builder (written for the sake of running the example and was not present in the original Algol-68 code) did take some thought: how many R-states I need, what is the point of each state, how much mutable state is enough. Writing this C code now, with the 50-year old technology, confirmed the R-technology lesson: think harder now, and debug none later.
Igor V. Velbitskiy. Graphical Programming and
Program Correctness Proof
<http://glushkov.org/wp-content/131120CSITeng.pdf>
Ushakov I., Velbitskiy I. (1993) Visual programming in R-technology:
Concepts, systems and perspectives
In: Bass L.J., Gornostaev J., Unger C. (eds)
Human-Computer Interaction. EWHCI 1993. Lecture Notes in Computer
Science, vol 753. Springer, Berlin, Heidelberg.
doi:10.1007/3-540-57433-6_48
V.M. Glushkov. The abstract theory of automata. Russian Mathematical Surveys, 1961, v16:5, 1-53. (English version) doi:10.1070/RM1961v016n05ABEH004112
bldg.bld [8K]
The R-machine in Algol-68 (one of several
implementations)
dumptree.a68 [2K]
The constant-space tree traversal, as an
R-program
rtran-traverse.c [4K]
The C version of dumptree.a68
, omitting irrelevant details
of train scheduling. The C code includes another R-program: building
a full binary tree iteratively, in constant working space (not
counting the allocated nodes).
RTRAN parsing and finding direct products in Algol-68 Another implementation of the R-machine in Algol-68
tpvoc.asm [12K]
An R-machine as an Assembler Macro (IBM
System\
360 Assembly) and a parser implemented in it
Programming in a Finite Automaton style
Advanced Finite Automaton as a simple HTML formatter
More examples of C programming in the R-tran style
Calorimeter is an instrument to measure the amount of heat emitted or absorbed during a chemical or physical process. The Setaram calorimeter was designed for studying the process of dissolving a substance (so-called solute) in a large amount of solvent. The calorimeter has two identical reaction chambers: vessels for solvent, into which were submerged a temperature sensor, a resistor and and small enclosure for solute encased in glass beads. The chambers are well insulated, which is why the calorimeter is called adiabatic. After setting-up and waiting for the chambers to come to thermal equilibrium, the operator crashes the glass beads releasing the solute, which starts dissolving. The insulation keeps the heat in the reaction chamber, which hence changes its temperature, measured by the sensor. Multiplying the total change in temperature during the reaction by the calibration coefficient (the thermal capacity) gives the amount of heat -- the caloric effect of the reaction. The calibration coefficient is obtained by calibrating before or after the main experiment: releasing a known amount of heat (by briefly passing a certain amount of current through the submerged resistor) and measuring the temperature change just like in the main experiment.
The temperature sensor is connected to a potentiometric strip chart recorder, which draws the temperature vs. time graph on the advancing long strip of paper (chart). When the system is in the equilibrium, the graph is the flat straight line: so-called baseline. When a reaction is going on, the line curves. The area under the curve is the total change in temperature. Measuring this area by hand -- manual integration -- and computing necessary corrections was the most tedious, also time consuming and error-prone, part of the experiment. I was called for help.
The developed control program automates the tedium of conducting the experiment. Only crashing the glass beads and calibration had to be done manually. Concretely, the control program continuously acquires temperature sensor readings and filters them. In the baseline mode, it fits the acquired points to the straight line to obtain the noise level and the baseline parameters. When the experiment/calibration is in progress, the control program continuously integrates the temperature curve, determines the end of the process, computes the total effect and various corrections. The control program ran on a Electronics BK-0010 computer with a color TV monitor, which continuously displays the current status and the baseline parameters. One can see at a glance what is going on and if the equilibrium is reached. The monitor also displays a screen form, whose fields tell the possible actions (such as: start monitoring an experiment, switch to another screen form to show accumulated results) and various parameters, some of which could be changed. The actions are activated by a single keyboard key press, with a visual feedback. The control program occupied 4 Kbytes, of 16 Kbytes of memory available on BK-0010.
The automation was done on the cheap, as necessary in those times, with the minimum of extra hardware. I only needed an analog-to-digital converter (ADC) and a small oscillator circuit, built by a friend of mine. The circuit sends the timer interrupt to the control program every 3 seconds. The ADC is connected to the temperature sensor and the computer, and can be queried to give the current temperature reading, in a peculiar binary-coded decimal format.
The control program runs `on the bare metal': it is the operating system, into which BK-0010 boots. As my other control programs, it is interrupt-driven, with two foreground and a background tasks. The high-priority foreground task is activated by the timer interrupt and runs to completion, thus ensuring accurate sampling frequency and no data loss. The task acquires the temperature reading, filters by the 3-point median filter, and processes according to the current mode. In the baseline mode, it fits the current point, along with some number of previous points, to the baseline. In the reaction (effect) mode, the processing is guided by a 5-state automaton (see the reference below). The lower-priority foreground task is activated by the keyboard interrupt and handles operator commands. Refreshing the display is done by a background task. Computing the caloric effect requires more computation and is also done by a background task. Such tasks are interruptible and run when all urgent processing is completed.
BK-0010, however, has only one interrupt level: interrupt priorities had to be emulated. The high-priority foreground task is run as the timer interrupt handler, with interrupts disabled, to avoid data loss. The processing is typically fast, so that interrupts remain disabled only for a short time. For any longer processing, a background job is submitted. The keyboard interrupt handler only sets a flag that the operator input is pending, and immediately exits. Reading the operator request and acting on it is done in background. The background mode scheduler is activated on return from interrupt. It first checks if keyboard input is pending, and, if so, runs the operator command task. Otherwise, other scheduled background tasks are run.
The control program is written in PDP-11 macro-assembly: Macro-11. It was developed on a "Electronics E-85" computer, a beefier PDP-11 clone; a compiled executable was then transmitted to the target computer via a custom local network.
A notable feature of the control program is structured handling of operator commands, via screen forms, or `menus'. A menu is a structure containing the text to show on screen plus the description of characters (key presses) that are accepted for this menu, and how to interpret them. Here is a typical menu:
Menu.1:: .word 7,10$ .bktext <1,16.>,<\^\g> .bktext <6,16.>,<Mode: \b\~A\~\guto or \b\~M\~\ganual> .bktext <6,17.>,<Baseline stability> .bktext <12.,18.>,<\b\~T\~\ghreshold> .bktext <6,19.>,<\b\~N\~\g scanned> .bktext <6,20.>,<Start the effect managing> .bktext <6,21.>,<for \b\~L\~\geft or \b\~R\~\gight cell> .bktext <6,23.>,<\b\~O\~\gther> .bktext ,<\r> .byte 0 .even 10$: mentry 'A,<12.,16.>,1,SetAuto mentry 'M,<22.,16.>,1,SetManual mentry 'T,<10.,18.>,2,<BLs2.thr,<23.+<18.*256.>>>,color=<\r> mentry 'N,<4,19.>,2,<Nscanned,<23.+<19.*256.>>>,color=<\r> mentry 'L,<10.,21.>,1,StinLeft mentry 'R,<20.,21.>,1,StinRight mentry 'O,<4,23.>,0,Menu.2Here,
.bktext
is a macro, whose first argument (in angular brackets)
is the screen position (column,row), and the second is the text to
show at that position. The text may include control code such as \g
for green text and \~
for toggling the inverse video mode. It should
be stressed that the BK-0010 terminal is an ordinary TV monitor
rather than a VT-100 terminal and is not controlled
by escape-codes. To position the cursor or switch colors one has
to make a dedicated BIOS call. The macro mentry
describes the key
accepted in the current screen form and what to do if it is
pressed. In Menu.1
, key 'A' invokes the SetAuto
function to set the Auto mode;
key 'T' lets the operator change
the stability threshold (whose current value is taken from the
variable BLs2.thr
and displayed in red on the same line), key 'O'
switches to Menu.2
. Compiling such code and expanding macros
took noticeable time: Macro-11 assembler felt as slow as the C
compiler. (C compilation was very slow those days.)
Not only BK-0010 had no floating-point number support -- it also did not provide integer multiplication and division. I had to use fixed-point arithmetic throughout (and implement multiplication, squaring and division). I still remember what a pain it was.
0README.dr
file. A few notable files are also
mentioned below.
heff.mac [8K]
A 5-state Finite Automaton (part of a high-priority foreground
process) that monitors the reaction (effect) in progress, handles data
points, and schedules background jobs to inform the user of the
current status
effect.def [2K]
Data structures used in effect processing
bjkbdh.mac [7K]
Receive a keyboard character and interpret it in the context
of the current screen form
bk.def [3K]
Definitions of macros to write a message or display a styled text
menu.def [3K]
Definition of the menu structure,
and the declaration of the mentry
macro
menu0.mac [3K]
Root menu of the control program
menu1.mac [2K]
Starting and stopping monitoring of effects
menu2.mac [3K]
Show and set system parameters
This project was done for a friend of mine, who was working at that time in the Institute for Biological Physics of the Academy of Sciences of USSR, in Puschino (Moscow Region). He was studying changes in neuron firing patterns in rabbit brain in response to particular external stimuli. Talking to him in the evenings in the dorm about his work and listening to his frustrations at getting a signal acquisition equipment to work for his experiment, I said one day: you don't need any dedicated equipment. An IBM PC in your lab is enough; just make an amplifier, to bring the neuron firing potential to the level of +5V. I will write the recording program. The amplifier was a piece of cake for him: after all, he has built dedicate electrodes to insert into neurons, and all recording electronics. He had very capable hands.
To record signals one would typically use signal acquisition (extension) boards, plugged into a motherboard. Obtaining such boards was not logistically or financially possible. Therefore, in this and other automation projects I used a simple, and mainly, cheap and available, signal acquisition method: relying on RS232 (serial communication) ports, typically present in many computers (for mouse, modem, etc.). On IBM PC, these were so-called COM1/COM2 ports.
Here is the general idea of signal acquisition via a serial communication RS232 port (COM device). The trick is to use auxiliary control lines such as CTS (clear-to-send) of RS232. They are all high-impedance TTL level, that is, 0 and +5V (the threshold is at around +4.5V). The useful lines are:
#define Poll_port1_no 0x3fe /* Serial Port COM1, modem status reg */ #define Poll_flag1 0x10 /* signal CTS, pin #5 of the 25 pin connector*/ #define Poll_port2_no 0x3fe /* Serial Port COM1, modem status reg */ #define Poll_flag2 0x40 /* signal RI, pin #22 of the 25 pin connector*/ int bit = inportb(Poll_port1_no) & Poll_flag1;When CTS is in the low state, the
bit
variable above gets
the value 1. If the CTS line is in the high state when the above
statement is executed, bit
will be assigned the value 0. One can
also use the port COM2, in which case replace 0x3fe
with 0x2fe
in
the above code. An RS232 port also has lines whose state (0 or +5V)
can be set programmatically, and hence used for controlling external
equipment. (One needs relays since the lines carry very little
power.)
My friend was researching neural firing patterns, and so was interested only in acquiring neurons' excitation state. This is a binary signal, which, after appropriate amplification can be connected to an auxiliary control line of an RS232 port and queried/polled by a program as described above. The program would poll several control lines (initially three) and, hence, record the state of several neurons. The run-length encoded spike data (that is, the intervals between two consecutive spikes) are written on disk, as a so-called .IMP file.
The structure of the program is common to other experiment automation programs of mine. It was interrupt-driven. One of the PC AT interval timers was programmed to deliver interrupts at the polling frequency. The interrupt handler polls the input channels: RS232 lines connected to the electrodes inserted into neurons. A spike manifests as reading 1 from the corresponding poll. The interrupt handler counts the intervals between two spikes, on each channel, and records them into a memory buffer. The interrupt-driven sampling not only keeps the polling interval more or less constant. It also lets us interleave sampling and writing: a filled buffer is written onto disk, as a `background task'.
The code was written in C (Turbo C) nominally, but used quite a bit of inline assembly for speed. I would write the code first in C, then comment it out and translate to assembly by hand. Interrupt-handling and polling were especially time-critical and had to be programmed almost entirely in assembly.
A later version of the program used the polling interval 500usec (down from 1000usec) and acquired signals on four channels.
impulses.c [3K]
The main module: initialization and the main loop
telling.h [<1K]
telling.c [4K]
The user-interface: the initial dialogue and the periodical status display
filling.h [3K]
filling.c [10K]
Handling the timer interrupt, polling the channels and filling in the current
buffer with inter-spike intervals.
This is the most time-critical part of the program, and is written
largely in hand-translated inline assembly.
writing.h [2K]
writing.c [6K]
Writing filled buffers to disk
timer.h [4K]
timer.c [5K]
A small library to control the 8253/8254 timer chip; query and set
interval timers. One of the timers was used to deliver interrupts at
the sampling frequency.
imp2m.c [9K]
A separate program to convert an .IMP file to a set of Matlab m-files
(one per channel), for loading into Matlab
Given below are general-purpose utilities and the user-interface-related code. As to the emulator proper, I do not feel I have the right to say anything more about it or the target CPU architecture. I am not aware of its further development.
I used the Modula-2 system developed by the `Interface Technologies Corporation'. The system included a smart, syntax-sensitive editor. The editor made sure that at all times the program is syntactically correct -- which sometimes was a hindrance.
Kbd
and TIO
implement low-level terminal
i/o via BIOS and DOS interrupts. TIO
also supports
character escapes and printf-like formatted output. The module
Window
lets one write text into rectangular areas
on the screen, supporting line wrap-around, scrolling, colors,
and cursor positioning. The module used BIOS interrupts and
directly accessed the videoRAM. On the top of these modules,
MWDr
implements a line editor and a menu processor.
The utility modules include Lexem
(string tokenizer) and
Set
(finite maps).
IEBUPDTE
. Even if a user had access to a machine room,
he still had to punch the updates on cards and run that batch job.
That was quite inconvenient. This trivial utility was written to help
such users fix simple errors in their source code files from the
operator console. I had used the utility on many occasions --
until our computing center got display terminals.
The code illustrates parsing via a Turing-like machine -- so called Glushkov R-Technology. I implemented what I understood from a quick glance through Glushkov's book a few years earlier.
R-Technology
More detailed description of the R-technology,
with several implementations and applications
Back in 1988 I have written the identical tool, called CHECKDS, for an IBM System/360 clone (EC-1033). The purpose was not checking for viruses however. I was alarmed by the corruption of a file on my (29 MB) disk pack. I wanted to detect such corruption early so I could correct the file or restore it from the backup. I would run CHECKDS from time to time, checking checksums of important disk files against the previously computed values.
The program CHECKDS was quite atypical System/360 program: it was opening dynamically-named files: the names of the files (called `data sets' in System/360 parlance) to check were read from another file. Normally, all files needed for a program must be reserved in advance of program execution and hence described on JCL DD-cards. In the batch-oriented System/360, the names of all files opened by a program must be statically known. Opening files whose names are computed was very rare, requiring special knowledge and administrative privilege (so-called ``zero memory key'', to modify operating system tables).
The program CHECKDS had another peculiarity: it processed so-called library files (``partitioned data sets'', in the official terminology) as if they were ordinary (i.e., sequential) data sets, which may contain records of zero length. Such records separate library members. Normally reading a record of zero length raises the end-of-data indicator. To ignore zero-size records when reading a partitioned data set, CHECKDS installs a call-back (formally called ``IO appendix'') to be executed upon the completion of IO channel operations. The call-back will check for the zero-length record and reset the error indicator. Installing IO callbacks too required zero memory key.
About a year later, working on a micro-computer, a clone of PDP-11, I had to check for corruption of disk files again. Soviet-built computers were notably unreliable. The disk controller of that particular computer broke down. A friend of mine, a remarkable electrical engineer, identified the failure in the checksum computation circuit, which he managed to disable. The computer could work again but disk data corruption could no longer be detected. I had to compensate for faulty hardware with software.
verify.c [9K]
The commented C code; DEC RT-11/XM operating system
I first saw NeWS on an SGI IRIX workstation in the office of my boss at a
lab I was visiting in mid 1991. I knew a bit of Forth and was glad
to see such an impressive application of it. I then learned PostScript from the
Adobe manual (`the red book') and played with NeWS from time to
time. When the boss wanted to present a poster about our work,
I declared that we make it in PostScript. I wrote
several PostScript functions (`words') to set up a page,
typeset lists, easily change fonts, etc. The boss
played along and even did editing of his own. Of course we
used the NeWS own PostScript interpreter (psh
) to preview the results.
Half a year later, in a different lab, presenting a poster at a
conference came up once more. Again, I chose to do it directly in
PostScript. The topic was wavelet image compression, and the poster
included equations and diagrams, for which PostScript turned out
especially convenient. Without an easy access to a workstation,
previewing was a chore however. I use that poster as an example to introduce
the postscripting.
One should be well aware that as a typesetting language, PostScript is quite low-level: by itself it does no line breaking, word placement, justification, alignment, etc. It is no TeX -- although something like TeX could well be programmed in it. Luckily, posters and slides are not supposed to contain long paragraphs of text. They should present outlines, equations and figures -- and for that, PostScript is adequate, especially with a few `words' for placement, lists, sub/superscripts, math symbols, etc.
To give the feel for manual PostScript posters, here is the beginning of the source for page 5 of the image compression poster:
(5) newpage 24 points TR (TRIMMING) showcenter newline .20 inch lineshift 18 points TR { 22 points TB ( I. Uniform ) show } locally newline indent (\267 Sets c) show (k) sups (lm) subs ( ) show s= (0) show ( if ||) show (c) show (k) sups (lm) subs ( ) show (lm) Phi (||) show ( < T, a threshold) show newline -0.10 inch lineshift (\267 Keeps only ) show { HB (significant features of the image) show } locally newline -0.10 inch lineshift indent { TBI ((contrast)) show s_product ((grain-level) > threshold) show } locally end-indent newline -0.10 inch lineshift { HB ( uniformly ) show } locally (over the entire picture) show newline .15 inch lineshift end-indentwhere
indent
increments the left margin and end-indent
decrements.
The word locally
executes a sequence of words restoring the
font settings afterwards.
Page 6 of the poster, about the discrete gradient, starts by defining the gradient operator
/Dx % Gradient Operator in x { currentfont % Put the currentfont to the stack getfontsize 1.1 mul points TBI (D) show % D stylish setfont % Restore the font that was before 0.05 inch neg 0 rmoveto (x) subs ( ) show } deflater used in a formula to compute it:
{ 22 points TB (Computation) show } locally newline ( ) show Dx (f(x,y)) show s= (M) (k=0) sum_sign ( ) show ( ) (l,m) sum_sign ( c) show (k) sups (lm) subs ( ) show Dx (lm) Phi
Page 6 also has diagrams, drawn as typically in PostScript, with
moveto
, rlineto
and stroke
(TeX native drawing facility is
similar and just as low-level, but more difficult to program).
Looking at this code 30 years later, lots of improvements come to
mind. I should have used lists and defined more `environments' like
indent
/end-indent
, borrowing ideas from LaTeX (which I barely knew
at the time). As I tried to view the complete poster in Ghostscript,
it displayed just as well as 30 years earlier, with no changes at all.
procs.ps [7K]
local_procs.ps [2K]
Typesetting words (`macros')
page.5 [2K]
page.6 [4K]
Source for pages 5 and 6 of the poster. The same directory contains
the source of the other pages:
page.1
..page.8
(The university did not have an easily accessible large-format
printer, so the poster was a collection of individual pages -- as was
common at the time.)
complete-poster.pdf [13K]
The complete poster
Spoiled by nc, when working on VAX/VMS in 1990 I wanted something similar. In fact, our VAX already had it, from a DECUS tape. DECUS was a DEC User's Society, which collected and distributed user-developed software with source code and for free. (Free and open software predates FSF and FOSS by a long shot.) I was not satisfied with that file manager however.
There was already a well-optimized text user interface on VAX/VMS, which could display full screen text in several non-overlapping windows, position the cursor and act on key presses: a text editor, EVE specifically. EVE was an extensible editor built with the VMS Text Processing Utility (TPU) -- a simple, PASCAL-like programming language with built-in data types for buffers, windows, ranges of selected text, etc. Today one may say it was just like Emacs -- which is unfair: `Emacs is like TPU' seems more appropriate; after all, Emacs includes the TPU emulation.
It was natural, to me, at least, to develop a file manager within EVE. Which is what I did over several days in 1990 and used until I had to leave the VAX environment. There is not much to say about the code: it was rather straightforward -- thanks to the power and expressivity of TPU. One cannot help but feel nostalgic after looking at the code -- and sigh over the fate of TPU, and VMS.
Incidentally, Emacs dired-mode appeared in 1985-1986, it seems, but then put on a 6-year hiatus. I was not aware of it: likely it was not part of Emacs at that point. Anyway, Emacs (and Unix in general) at that time was hardly competitive with what VAX had to offer.
ncbody.tpu [6K]
Key handlers: actions of the file manager