|
Heath8080A — Product Design : H-19 Terminal |
Page last updated |
|
21-December-2002 |
|
|
On this page
overview Related links |
H-19 Terminal This page describes the emulator's implementation of the H-19 terminal. A complete emulation of the H-19 was not completed; the device has a number of capabilities, such as the ability to interpret a set of ANSI escape sequences, that were not implemented. Refer to limitations for a complete list. H-19 Overview The H-19 Emulator supports the following capabilities. Power-on configuration
All but Heath-mode escape sequences can be overridden by escape sequences after the emulator is started. Tabs will be fixed at columns 9, 17, 25, 33, 41, 49, 57, 65, 73, 74, 75, 76, 77, 78, 79 and 80. A tab from column 80 will not move the cursor. Block Diagram Note: The words "transmit" and "receive" are used from the viewpoint of the H8, not the H-19.
In order to support "scroll mode," characters are received into a buffer. The H-19 issues Xoff when the buffer is 80% full and Xon when the buffer is 25% full. Mac keystrokes are translated and passed into a pacing buffer so that multiple-character sequences don't overrun the serial port (remember, we don't have an actual, slow serial line to slow things naturally). Incoming characters are paced at a rate of 200 cps. The emulator can put characters into the receiver buffer in two cases:
As of release 5.3.2, you can paste text from the clipboard into the H-19 window. This text is sent to the H8 as if it were typed at the keyboard. The paste buffer is not passed through the receiver buffer; rather, the emulator bypasses the receiver buffer when pasting text. Pasted text and text coming from the keyboard or H-19 buffer will not intermingle. The H-19 terminal window has a "spring open" feature. If the terminal window has not been displayed since the emulator was started, the first printable character output will cause the window to open in front of the PAM/8 GUI. This allows the user to key the boot address and press "go" and be able to use the H-19 immediately without fooling around with emulator menus. When booting an HDOS 1.6 disk or a newly-sysgened HDOS 2.0 disk, HDOS will sound PAM/8's alarm and display "SPACE" in the front-panel LEDs to prompt the user to press the space key so HDOS can determine the terminal baud rate. In this instance, the user will have to manually display the terminal window before pressing space. Keyboard Mapping Keyboard Processing Overview The Macintosh key-down event record contains both an ASCII character code and a virtual key code. While several keys on the keyboard may produce the same ASCII character — there are two "=" keys, for example — there is a one-to-one mapping between physical keys and virtual key codes that is consistent across all Macintosh keyboard layouts. It's most convenient to use the virtual key code to identify keys to be mapped to H-19 emulation functions. In the documentation that follows, "virtual key code" refers to the unique key identifier and "ASCII character code" refers to the normal ASCII value of the keystroke. The main body of the Macintosh keyboard has virtual key codes less than 0x41. All other key codes are equal to or greater than 0x41. This is actually a quite convenient bit of luck, in that it improves keyboard translation performance on the touch-typing keys. In pseudo-code, keyboard translation proceeds as follows:
if (virtual key code is less than 0x41)
if (the option key is down)
translate key code against main keyboard function key table
(option-1 = F1, etc.)
if ( no hit in table )
if ( virtual key code = scroll key or break key )
handle these keys locally
else
send the ASCII character code to the H8 serial port
else // virtual key code must be >= 0x41
if ( virtual key code = the clear key )
handle clear locally
else if ( virtual key code = top row F9 )
handle scroll locally
else if (virtual key code = top row F12)
handle break locally
else
if ((shift_mode xor shift_key) == '1')
translate key code against the shifted keypad table
(cursor keys, insert/delete char, etc.)
if (no hit in table)
if (virtual key code = IC key)
if ( we are in insert-character mode )
send exit-insert-character-mode sequence
else send enter-insert-character-mode sequence
else if (alternate keypad mode set)
translate key code against the alternate keypad table
else
translate key code against the normal keypad table
end
The search tables have the following format:
typedef struct {
unsigned char vkc; // virtual key code
char *str; // output string
} keyXlateTab, *keyXlateTabPtr;
Each table is sorted in virtual key code order. The last vkc in the table is 0xff. If there is no match in the table, and with the exception of the keys handled separately as noted in the pseudo code above, the keystroke will be ignored. Keyboard Translation The "keyboard translation" function (ref. h-19 overview) will perform the following mappings:
Notes:
We have a number of additional keys available on the Mac extended keyboard that we might as well take advantage of. These keys will be supported as follows:
Finally, there are eight command keys with local functionality. Note that the command key is held down to activate each key.
The scroll command keys effectively duplicate the functionality of the H-19 window scroll bar. H-19 Graphics Character Generation The emulator uses a modified a copy of the Monaco 10-point font which contains the H-19 graphic characters. The font is named "Heath 10." The graphic characters replace the special characters at ASCII offset 336Q through 376Q in the font set ("Q" indicates octal notation). To display a graphics character, add 200Q to the corresponding ASCII character. Example: The first graphics character is the raised dot, corresponding with the ^ character, which is ASCII 136Q. 136Q + 200Q = 336Q or 222D, which is where the raised dot is in the font. Here is the full set of graphics characters along with the octal and graphic representation of the corresponding normal character.
Character Pacing As noted in H-19 Overview, all characters to be sent to the H8 are placed into a receive buffer. H8 input must be paced so that we don't exceed around 500 characters per second. The mechanism used is the 1ms emulation clock tick. On every other tick, we check to see whether there's a character in the buffer. If so, that character is placed on the UART via a call to ioPutSerialData. For any given keystroke, there is a delay of up to 2ms before it appears on the UART. At present, there's a delay of up to 25ms before we get that keystroke from the Mac Event Manager, and this extra delay isn't noticeable. (The original plan had been to input at a rate of around 1,000 cps. In testing this proved to be too fast for the emulated H8, which lost the occasional leading ESC character in a function key sequence. Slowing the rate to 500 cps has proven to be 100% reliable.) Starting with release 4.1, outbound characters are paced so that output does not exceed 2,000 characters per second. Again, this is done using the 1ms emulation clock tick. On each tick, a 2-character output quota is refreshed. h19Status (ref. I/O Package) will return transmitterEmpty status only if this count is non-zero. Output Character Processing Note — Output, in this case, refers to characters sent by the H8 to the H-19 terminal. Logic H-19 terminal output processing is table driven, using a series of tables that taken together denote the state of the output data stream. Each time a character is output, the current table is searched and the appropriate action taken. The tables are defined as follows:
typedef struct {
unsigned char outputChar; // output by the H8
int nextTableNdx; // next table ndx
void (*procRoutine) (void); // processing routine
} outXlateTab, *outXlateTabPtr;
outXlateTabPtr nextTable[] = { outNormal, outEsc, ... };
If the processing routine is nil, none will execute. But the table address will change to the next table. The last entry, outputChar = 0xff, will match any character output. Let's process one easy example. The initial state has the current table set to the default table.
The cascading order of tables effectively parses the output and sees that the correct function is performed for each character or escape sequence. Output Escape Sequences The characters following "esc" in the following tables are case sensitive. Esc is, of course, 033q (27d).
Additional information:
Additional information:
The following Configuration Modes replace the [n] in the HSM and HRM sequences above.
Additional information:
Additional information:
Additional information:
Cursor Display H-19 emulation spends an extraordinary amount of time drawing and undrawing the cursor. This was mitigated to a degree by batching character output; the cursor is removed and drawn for each small batch of characters instead of for each character output. But when there's a long, fast burst of output, all that cursor drawing is just unnecessary overhead. QuickDraw is blazing fast, but overhead is overhead. This overhead was removed by delaying the drawing of the cursor on the screen. The amount of delay could have been anything, really, but testing showed that at 25ms a human operator can actually see the delay. I settled on 10ms because cursor motion is uniform and smooth when typing or moving the cursor by hand, and yet it's long enough to ride over small gaps in a burst of output. Cursor display is now done in the 1ms clock tick processing routine, and is controlled by three variables: int h19CursorDisplayed; // cursor has been drawn int h19CursorDesired; // cursor should be drawn int h19CursorTimer; // 10ms delay timer H-19 processing routines call insertCursor and removeCursor to put the cursor on the screen and take it off, respectively.
Note — Regardless, the cursor is never displayed on screen if the cursor has been disabled (h19ModeCursor = 0) by an output escape sequence. The cursor itself defaults to an underline, and can be configured as a block. The underline cursor is a black line drawn using modeXor so that it is visible in both reverse and normal video. The cursor is erased by simply redrawing the cursor. The block cursor is drawn using the PaintRect function, with a drawing mode of patXor. As such, it shows on a normal screen as a black box with a reverse-video character inside, and is reversed on a reverse-video character. When the cursor is idle, it blinks at a rate of: on for one second, off for one-half second. The blink is accomplished simply by calling removeCursor and insertCursor. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||