Tuesday, June 30, 2020

First test of 3179 terminal in darkness


The Operator Information Area (status line) across the bottom had a symbol and the number 3, which the User Guide for the terminal gives as the error "Keyboard not attached or functional". That is indeed the condition here as I don't have a keyboard to attach. The three keyboards I have are the type with a rectangular connector to fit to the 3178, while this terminal uses a circular DIN style connector. 

Test mode but failing with keyboard missing error (3)


When I put the terminal into TEST mode using the Test/Normal switch, it beeped a few times and showed the word TEST on the status line. No characters were displayed above the blue line. Upon reading the Guide for the terminal it became obvious that the keyboard error message above stops any further testing or action. Until I bypass that error or substitute a keyboard, I won't get any further.


I do have documentation of the pin assignments for the keyboard connector, essentially it has +5V, a clock and a data signal. I imagine I can work out the details of the protocol and enough to at least convince the Logic Element that the keyboard is present and working, although it might require a microcontroller or small FPGA. 

An interesting possibility is if the keyboards I have for the 3178 use a compatible protocol, even though they have a different connector, I might be able to bridge one to the other. This is a bit more unknown that the paragraph above.

Finally, I still have an extraordinarily dim CRT at full brightness. As you can see from the picture taken with flash, with the terminal illuminated the blue line is swamped, same as with daylight. 

Blue line almost invisible in bright lighting

The 3179 terminal has arrived! Some bad news as well

The third time on the truck is the lucky trip, as the box was delivered at noon today. The packaging was intact and the terminal inside was well padded. I hauled it around to the bench to begin some testing.

The blinking light and beeps from the Logic Element that sits below the CRT suggest that this unit is working properly. The real evidence comes from what you see on the screen and how it responds over the coax cable, but this was a good start.

The bad news is that the CRT is exceedingly dim. At full brightness adjustment I can just barely see a thin blue line down near the bottom, probably a divider between the status line and the user accessible lines of the display. When I flip the test switch I don't see any characters - the screen should fill with characters to test out the character ROM mapping - but that could be due to the lack of a connected keyboard.

The most likely scenario here is that the tube is really worn out with massive oxidation on the cathode reducing electron emissions to paltry levels. There could be other failures in the Display Element or Logic Element that are causing this, but I suspect not. The reason is that the ebay listing for this had two terminals offered, and the picture showed the blue line about the same apparent brightness on both. Separate monitors and logic elements, unlikely to have the same electrical defect. 

I will turn it on at night and see what may appear in the dark while the Test switch is thrown. Again, I don't know if that would work sans keyboard. The other test I can do is to hook it up to my 3174 substitute and interrogate the terminal ID. If it responds properly that suggests at least partial correct operation of the Logic Element (base box).

Simple solution to the wrap around buffer problem


My buffer is 2000 characters, with the first 80 reserved for the status line at the bottom of the screen. The remaining 1920 characters wrap, that is location 1999 is line 24, column 80 if you move one character down you should be at location 80, line 1 column 1. This is not straightforward modulo 1920 math because of the status line at the beginning. 

In may places, my code will be moving through a field indexing from the first character position to the last. Fields can exist where the start position is high in the buffer but the field wraps around so that the end position is low. In one test case, my last field on the screen began at location 240 (line 3 column 1) and extended through the rest of the buffer. It was therefore terminated when it wrapped around and encountered the attribute character at location 81 (line 1 column 2). Thus line 1 column 1 was the last position in the field. Yes, it is a contrived example but the code must work properly for all legit cases. 


In every spot where I accept a buffer address, I handle the wrapping. That is, if I am presented an address less than 80, I add 1920 so that I have 'backed up' to the tail end of the buffer. If I see an address beyond 1999, I subtract 1920 from it so that I wrap around to the low end. 

This allows a 'for' loop to work properly marching up from a start address near the bottom of the screen and its end address being near the top. The loop will calculate indexes that move beyond the end address 1999 but my fix will cause the actual access to wrap. 

Monday, June 29, 2020

3178 terminal code fleshed out including shadow buffer


I created a Buffer class that maintains a 2000 character buffer. My code in terminal now writes to the buffer object for insertion in that shadow buffer, with the buffer object also writing a copy through to the regen buffer inside the 3178 terminal. 

Whenever data is written to the buffer object, but not by key press actions, I run a method that builds a list of tuples defining the fields found in the buffer. This is done by scanning the buffer for attributes. These field tuples also indicate whether fields are protected, numeric and when their contents were modified by key presses after it was written by the mainframe (or my fixed code in the terminal script). 

The list of fields helps in implementing the TAB, BACKTAB, HOME, ER INP and ERASE EOF keys correctly, as I can locate the unprotected fields for movement and erasure. 


The bottom line on the screen is not accessible by the application programmer or mainframe. It is used by the control unit (CU) such as the IBM 3174 to signal important information about the state of the terminal and its interaction with the mainframe.

When the terminal is considered busy or locked due to operator error, symbols appear in columns 9 to 17. I implement these to display the symbols for 'key not allowed in this cursor location', 'this location is numeric only' and 'lengthy operation underway, please wait'. 

In columns 37 to 41, the state of the terminal is displayed. The first column will have a symbol to indicate that the shift key or lock is engaged. The next column contains a symbol to show that the terminal is in insert rather than regular mode. The final columns show the characters NUM when the field is numeric only. 

I modified my terminal program so that it correctly displays the shift, insert and numeric state, as well as displaying the lock and busy conditions. 


I found some of my logic falling apart because these buffers are circular. That is, just after cell location 1999 (line 24, column 80) we wrap around to cell location 80 (line 1, column 1). Calculating lengths of fields and matching when the cursor is in a field fails in the last field since it has to wrap around.

Quite a bit of the added functionality worked well, but I found a list of other defects to address. I will keep going on this effort because I am still waiting for Andrew Kay to produce a version of oec that makes use of my keyboard and I am still waiting for my color 3179 terminal.

Fedex sent me the alert that the package was due to be delivered on June 27 by 9PM. In the early evening of that day, they changed the projection to June 28th (Sunday). I was heartened to see that it was marked as onboard the delivery truck on Sunday morning. However, suddenly in the early evening of Sunday, the status went to "Pending, no delivery date set". 

Today, Monday the 29th, I received another message claiming it would be delivered today by 9PM and once again the box was reported as onboard the truck. And, again, in the early evening the status changed to "Pending, no delivery date set". I placed a WTF call to Fedex. 

Their automated systems insisted it was on the truck and coming today. I asked for an agent to show him how it was two days in a row of sham "on the truck" followed by "Pending" but he insisted that it was going to come tonight. He offered to have me call back tomorrow if it once again didn't arrive and they would then, and only then, call their third rate Fedex Home operation that was actually supposed to delivery it, to seek answers. 

It didn't arrive tonight. The service commitment date was June 27th. It has sat in the local area since that time, sometimes pretending to be onboard a truck. Tomorrow morning I firmly expect to receive another cheery promise that it will be delivered and another baseless assertion that it is onboard the truck for delivery. And I know that when I call Fedex, they will contact Fedex Hopeless and be told that . . . it is on the truck. 

Sunday, June 28, 2020

Continuing to update my terminal code to better emulate the 3174-3178 behavior

While I am waiting for Andrew Kay to make some modifications in his oec 3174 emulator project necessary to support the keyboard on my terminal, I can improve my understanding of the terminal and have fun playing around.

I was expecting to receive my 3179 color terminal yesterday, but Fedex abruptly notified me late in the afternoon that they would deliver today rather than yesterday. I had noticed it was listed as sitting in Tracy and not on a truck all day.  I then turned to the Python code to enhance what I had been doing.

My initial work put out a fixed screen of data and managed the fields based on hardcoded locations. Far better for me to emulate the full functionality with arbitrary screen contents and any number of fields at any locations. Thus I built a class called Buffer that would handle this for me and do write-through to the regen buffer inside the 3178.

It builds a list of field tuples upon request. This is called whenever the 'host' writes to it (or my startup where I set initial screen contents). This is a bit wasteful of processor time but safer than trying to sort out the minimum changes to the attribute list based on each write from the host. 

Having the list of attributes allows me to provide functions that validate whether a field is protected or numeric. Eventually it will allow Insert and Delete key operation which moves data but stops at the end of the current field. 

New Apollo items loaned to me including a late model EL panel

The collector who had loaned the three Apollo items to me for my display project brought over three more yesterday! I have a later model Electroluminescent Display Panel which should glow with the correct colors that were visible to the astronauts. He loaned me a second relay module which I will test out. The third item is some kind of display that marketed at auction as coming from an Apollo Command Module but we are not certain.


The new display has identifications that tie it to Marshall Space Flight Center (Huntsville Alabama), the designer and system integrator of the Saturn V and IB vehicles. The only information I could find on the contract number is that it was finalized in June of 1967. That is relatively late in the design cycle for Apollo. 

Secondly, looking closely at the frosted glass front I can't see any signs of traces to suggest this is electroluminescent, as stated in the auction and as used throughout the spacecraft due to the very low power consumption of that technology. 

Third, its connectors on the rear are a pair of circular sets of solder pins, much like only vacuum tube sockets. This kind of connector and reliance on solder would not have been used in the spacecraft.

Fourth, its body size is much taller and wider than the visible screen area. There is no location in any of the Apollo spacecraft, CM or LM, where we find a similarly shaped indicator. More importantly, no spot has reserved space free of other indicators or controls to match the tall and wide shape of this object. 

Our conclusion is that this is an indicator of some sort procured to support the Apollo program, but likely was used in some ground support equipment. I looked at images of every console in the KSC launch control room as well as all the mission control consoles at JSC, but none had that indicator attached. 

I is probably one of those displays that shows numbers by mechanically moving masks so that the incandescent bulb inside shines on the frosted screen with the pattern of the desired digit(s). Big and bulky enough to house the lamp, solenoids and moving masks. 

Connectors on mystery indicator module


I switched over to the newer EL panel module, which was boxed and appeared to be an unused spare part thus new-old-stock. When I activated it, the brightness was dramatically better. More importantly to me, it had the proper wavelength. The early version I previously had used was shifted to the blue-green while this one is a nice central green that would have been the color seen by all the astronauts and technicians. 

The COMP ACTY segment works as well, a nice bright rectangle that was illuminated when the Apollo Guidance Computer was running any code other than its idle task. Thus the flickering and percentage of time it was illuminated gave an indication of CPU busy. 

I wired up another driver circuit and the relay in the Relay Module that was used to drive this indicator. That relay is NOT a latching type. It is only energized when the input signal is on. 

New-Old-Spare display panel in operation


Next up I am going to wire up the second Relay Module to control the five digits in the R1 row on the display. Those are to the right of the sign I am already driving. This will require five new driver circuits, 93 additional pins, a new relay module plate for the connector, and lots of additional wirewrap connections. 

Normally, to drive the five digits would require five selection line drivers, five column latch drivers, and five column unlatch drivers. However, I realized that I could double the connections from my existing latch and unlatch drivers that are wired to Relay Module 1. As long as I only select the row in one of the modules at a time, this is okay as current will only flow through one relay coil at a time. Thus, I have discrete row select drivers but share the latch/unlatch outputs. 

Friday, June 26, 2020

A session playing with the quick and dirty 3174 connected to the 3178 terminal

I made use of my quick and dirty program to write some initial content into the regen buffer for display. It consists of four fields, two protected and one of them intensified. I choose the first console message of MVS 3.8 at IPL time for the first row, protected and intensified, with the rest of that line being a normal intensity unprotected field. 

I picked a common response during IPL as the second line, in a normal protected field, and set the remainder of the buffer to be a normal unprotected field.

My 3174 program should control when I can type into areas and which areas are off limits, as well as showing the desired content on the screen at all time. It is my hypothesis that the terminal itself only interprets the intensity/normal/hidden attribute, but ignores protected or numeric. Here are some screen shots to show the session. 

Data written initially by my program

Initial screen contents

Updating the screen down on line 4 and testing protected and numeric fields

I used the down arrow to advance the cursor one line lower, the typed in some text. This appeared just as I had expected. I then moved up with the arrow keys to the midst of the intensified and protected part of the first line. As I suspected, what I typed overwrote the characters on the screen. Finally, I moved to the middle of the second line, which I had marked as unprotected but numeric. Typed letters wrote right over the field. 


I haven't implemented the buffer in my CU yet, I am only writing data to the regen buffer in the terminal. Before I code up the substantial change to manage the buffer and shadow it to regen, I put some quick and dirty functions I can interrogate to ask whether a field is protected and whether it is numeric. I also have a function that gives the cursor position of the next field, allowing me to mimic the TAB key.

As I process keystrokes, but before I write them to the regen buffer, I check for protected fields. If it is protected, I write the status line section that shows the error of attempting entry in a protected field. I pseudo-lock the terminal, meaning I will only accept a RESET key to unblock it. The RESET key erases the error status on line 25.

Testing again

Updated unprotected areas and wrote 05 into numeric field

Status sign indication for protected or alpha-into-numeric field

After pressing RESET to unlock terminal

More numeric input permitted on line 2

I was generally satisfied with this recreation of functionality. I didn't get the TAB support to operate correctly but that wasn't pressing to fix. 

A tale of two buffers - 3178 terminal and the 3174 control unit

I received a question from a reader from which I realized that I wasn't clear enough in talking about the display and buffer side. This post is a quick amplification


The box under the CRT monitor is called the Logic Element. It has a 2000 character buffer inside which I call the regen buffer. The logic element is sweeping the CRT beam across the screen, left to right and stepping down after each sweep until it gets to the bottom of the screen. As the logic does this sweep, it advances the index into the regen buffer as it moves from each character cell to the next.

A character cell is a rectangular group of pixels where the pattern of the desired visible character is painted. My terminal has 80 character cells across a line and 25 lines stacked vertically. The user accessible and programmer accessible area is the first 24 lines, with the final line used for status feedback to the operator. 

The logic element begins at the top left corner of the screen, in character cell line 1 column 1. It uses the value of the byte in that first regen buffer position to look up the pixel pattern from the character ROM. Technically, the CRT scans the top row of pixels for all eighty cells then returns to sweep the second row of pixels for all eighty cells and so forth until it finishes the bottom row of the character cell. At that time it moves from line 1 to line 2, the next set of rows comprising the character cells in line 2 and begins with the top row of pixels of that line. 

The CRT is completing this sweep from top left corner to bottom right corner 60 times per second. The regen buffer is used to regenerate the pixels every 1/60 second as the phosphor fades rapidly. 

The logic element has some register that keep track of state, including the cursor position, an index in the regen buffer and thus a character cell somewhere on the screen. When the CRT sweep is moving through the cell whose position matches the cursor position, extra pixels are painted to show the cursor shape. 

A write from the control unit (CU) to the terminal will put the character(s) sent into the regen buffer starting at the current cursor position, then updating that position to just beyond the newly written characters. 

One final task for the CRT sweep is to recognize attribute bytes as they are encountered in the regen buffer. They don't cause a visible character to be painted in the cell; it appears blank. However, if the attribute byte signifies an intense field, the brightness of the beam is increased while painting this character cell and all further cells until an attribute further down the buffer sets intensity back to normal. 

The 3179 color terminal interprets the attribute byte slightly differently, showing the character cell in red, blue, green or white. Optional features add more colors but use a different attribute memory, not the regen buffer. 


The CU also has a 2000 character buffer. It should be a mirror of the regen buffer. All read and write operations between the mainframe and the CU occur into the buffer in the CU, but the 3174 then copies them to the regen buffer. The two buffers should always be in sync. The CU addresses its buffer as it needs but its timing is not connected to the CRT sweep going on and the active position in the regen buffer. 

It is in the CU where keyboard and display are logically joined. The CU knows what cursor position is set in the terminal, thus it knows the field that is active at any moment. If the attributes of the field limit what can be entered to the field by the operator, it is the CU that enforces it. If a field is marked numeric, the keyboard is considered to be shifted up and the upper character of each keycap is intended when the key is pressed. The operator does not have to Up Shift in this case. If the field is marked protected, then no data can be entered into the field, which is enforced by the CU.

Movement keys are handled in the CU. For simple arrow functions it just updates the cursor position in both its and the terminal's regen buffer. If it is a TAB, the CU looks forward in the regen buffer from the current cursor position until it finds an attribute byte for a field that is unprotected. It sets the cursor position to the next cell after that attribute byte. This can move anywhere from 2 characters to almost 1920 characters depending on how far away the unprotected attribute byte is sitting. 

The attribute byte of a field has a Modified bit, which is turned off when the field is received from the mainframe and is turned on if any characters are entered in the field due to operator keypresses. This allows the CU to send back only modified fields to the mainframe, disregarding those fields that were not changed. 

Normal keypresses involve only the CU and the terminal, with characters changing on the screen and cursor movement taking place. However, a number of control keys are intended to be sent to the mainframe to indicate various operator choices. For example, the ENTER key causes the CU to respond to the mainframe with a message indicating ENTER was hit. Typically there will be an exchange between mainframe and CU at this point while the operator waits at the terminal. 

Other keys can request program actions, keys such as PF3 or PA1. These presses cause the CU to respond to the mainframe with a message indicating which of those keys was struck. This may be the only interaction between CU and mainframe or the program may decide to write some new data into the CU (and regen) buffer. 

Thursday, June 25, 2020

My quick and dirty 3174 control unit brings the 3178 terminal to life


Andrew has done a brilliant job building a substantially complete 3174 controller for use with two terminal types, a 3483 and a 3279-2, both of which he owns. However, the 3178 has a different keyboard layout, therefore a majority of the keycaps will be misinterpreted by his existing code.

I am helping build a mapping for my keyboard to fit into his code, but it will be a bit of time before it is integrated and I have the entire oec package running. In the interim, I made use of his pycoax package of utility tools and built a python program to act as a simple 3174. 


Almost all the functionality of the 3270 class terminals is implemented in the control unit (CU), such as the 3174. The terminal sends keystrokes back in response to polls from the CU but otherwise ignores the keypresses. 

The other, independent half of the terminal is a 2000 byte buffer, called the regen buffer, organized into 24 lines of 80 characters plus a special final line that is called the Operator Information Area but could casually be called the status line. The CU will write data into the regen buffer and those bytes select a character that is displayed on the screen. 

The operator is accustomed to pressing keys and seeing the character matching that keycap appear on the screen at the location where the cursor is positioned. Arrow keys allow movement of the cursor around the screen, and other control keys can effect the screen in different ways. However, the connection between keystroke and screen appearance is totally controlled by the CU.


I built a module that associates each scan code from the keyboard with its role. There are three types of scan codes that are returned to the CU - hardware events, control keys and characters that display on the screen. Control keys can be the arrow movements, TAB keys and many other types. 

The scan code for a given physical key is fixed, however the character or function associated with that key depends on two modifier conditions. The ALT key is held down to cause a given key to be interpreted as its ALT modified role. If the operator has shifted the keyboard to upper case, by use of keys like Up Shift or Caps Lock, then the scan code is interpreted as its shifted role. If the keyboard is not shifted up and the ALT key is not depressed, then the key is interpreted in its base role. 

My table for scan codes keeps track of several facts for each code. For keys that produce a displayable character, we store the regen buffer code to display the character in both the base role and the shifted role. We also store the ASCII character for base and shifted roles. For keys that produce a control function, we store the base and ALT function. A few codes represent hardware events such as Power On Reset Complete, but we can ignore these. 

My quick and dirty program loops sending POLL commands to the 3178. We receive back scan codes when a key or event has occurred. I look up the scan code and act appropriately.

If the code is a displayable character, I pick up the regen buffer code and write that character into the regen buffer. In that way, the pressed key shows up as a character on the screen. If the key is pressed while the keyboard is shifted up, I use the shifted version instead of the base version. For example, the keycap with J on it will pick up the code for a J if not shifted, but if the keyboard is shifted up, we pick up the code for 4 instead. The keycap shows J on the bottom and 4 on the top of the cap. 

I also keep track of the cursor position. The terminal maps the first 80 characters of the regen buffer to the bottom status line, then begins at position 81 with the top left position, line 1, column 1. Each time the user types a character that can be displayed, I write its code to the buffer and bump the cursor position up by 1. 

I then implement a number of the control keys, based on the key pressed and whether the ALT key is also depressed. The arrow keys increment or decrement the cursor position by 1 or 80, thus moving the cursor up, down, left or right. The HOME key moves the cursor to line 1 column 1. New Line moves the cursor to column 1 of the next line. A few others are implemented.

Many of the control keys just send a special code to the program but don't affect the displayed screen image or contents of the regen buffer. Program Function keys (PF1 to PF24), Program Action keys (PA1 to PA3), RESET, ENTER, and PRINT are examples. All I do when I receive one is print a message on my laptop screen 


The current state of my program uses the terminal as a single unformatted display. This means that there are no attributes for individual fields, such as protected from user modification. It means that the field oriented functions such as TAB are not relevant. 

I enjoyed typing text, moving the cursor about and changing text on the screen. I watched the program recognize the various control keys. It was time to up my game, so that I could implement more functionality including field behavior. 

Over the next few days I will implement a shadow 2000 character buffer in the CU, writing displayable characters in both buffers. I will recognize and implement the function of attributes. These appear as blank positions on the screen, because the terminal doesn't display a character for any regen code in the range of xC0 to xFF. Those are the ranges of value that represent attributes. Ignored by the terminal in the regen buffer but important to the CU.

When a key is pressed, the CU must pay attention to the attribute that covers the current cursor location. If the field attribute is protected, the character is NOT placed into the buffers at that location. Instead, the status line shows an error status and all keypresses are ignored until the RESET key is pressed. 

The TAB function scans forward from the current cursor position until it finds the next unprotected attribute and sets the cursor one past that byte. Keys like INS and DEL control whether a pressed key replaces the data at the cursor location, is squeezed in moving the rest to the right, or the char is removed and the remainder pulled left; all of the movements are within the current field only. 

When the attributes are written, they have the M (modified) bit off. When a keypress causes a new character to be placed in the field, the CU will switch on the M bit. Generally the mainframe is only sent fields whose M bit is on, minimizing the data transferred over comm lines or a channel. 

Wednesday, June 24, 2020

Keyboard and character set of my 3178 terminal


Data Entry Keypunch keyboard from the IBM 3178 terminal


The reason that the main screen characters are restricted to the range of 0x00 to 0xBF is that the way the controller and terminal distinguishes an attribute byte from a data byte is through the high bit being 1. A screen on a 3270 is typically broken into fields, each beginning with an attribute byte. This byte specifies how the subsequent screen positions behave, up until the next attribute byte. It may protect a field from update by the operator, make the characters intensified, or restrict the typed information to be numeric. 

Screen character codes on the 3178

The bottom line of a display is a special area, called the Operator Information Area. It is always protected so that the operator cannot type in it and the arrow/tab keys won't move the cursor there. Because it is not programmable, it does not need nor use attribute bytes. Thus, for this special last line, the codes from 0xC0 to 0xFF can represent displayable characters that are only used in this area. 

Special characters for OIA line, courtesy Andrew Kay

Developing my scan code functionality for the 3178 terminal and keyboard


The 3178 sends back scan codes to its control unit, whether a real IBM 3174, some other CU, or the 3174 substitute I am working with. The CU will take such actions as writing a character on the screen that corresponds to the keycap you just pushed. It also tracks the case you are in, such as holding the 
Shift Up button or the Upper Case Lock button having been pressed. Finally, it has an ALT key that is a modifier to select an alternate function for a given key. 

The scan codes are not ASCII. They are not EBCDIC. They are not even the native character set of the display. They don't have a fixed assignment to a character; instead they represent some internal logic for how the keys are wired. 

Since the 3178 terminal can have a variety of keyboards, such as 75 or 87 key, with different arrangements of keycaps. Some are intended for Data Entry, some are considered Typewriter style, others may suit programming better. Thus, the CU has to know the specific keyboard installed on the terminal so that it can interpret a scan code. A given physical key on the keyboard may have the same scan code across all keyboard types, but its keycap and the intended character or function will vary.

I extracted all the scan codes returned by my keyboard, which has 87 keys in a version of the Data Entry Keypunch style. I will make use of this to convert the key that was pressed into the intended character. Further, some keys represent characters that will display on the screen, some represent hardware status, and some represent control functions that must be executed.

As an example of control functions, the TAB key is intended to cause the CU to move the cursor to the first position of the next field on the screen. The ENTER key is used to signal to the mainframe that all desired keystrokes have been entered into the screen and thus the application should read the typed field to begin processing. 


The 3270 style terminals use a byte to represent a character that should be displayed in each position of the screen. There are 255 possible characters, plus null, which supports a decent sized character set of upper and lower case letters, numbers, special symbols and quite a few characters for use with foreign (but latin alphabet oriented) languages. 

Of the 256 possible codes, 1/4 of them are reserved for special control symbols that are used on the bottom status line (called an Operator Information Area). The remaining 192 characters are used on the main display area, usually some multiple of 12 lines by 80 characters which depends on the terminal model. Mine is a 24 line by 80 character display.

The code used is not ASCII or EBCDIC. It is an internal code that indexes into a character ROM to choose the pixels to illuminate in each character cell. x80 encodes the lower case letter a, while xA0 is the upper case version of A. x22 encodes the numeric digit 2 while x18 represents the question mark. 


Programs on the mainframe who are sending text to place on the screen, and who are receiving the typed input from the operator, don't receive scan codes nor the internal 3270 character set. All data is translated into EBCDIC usually, unless an uncommon feature was installed that provides ASCII instead. The upper case letter A is xC0 in EBCDIC and the digit 2 is xF2.


Thus, when I hit the keycap marked A on my keyboard, it sends scan code x182. That is translated to xA0 for display on the screen and to xC0 for transmission from the CU to the mainframe host. This is layer one of the conversion required. 

Also, the role of a keycap depends on whether the operator has shifted to upper case. The keycap on my terminal represents an X in lower case and a question mark in upper case. Thus, the CU has to know whether the current state is shifted up or not. Keys such as Shift to Upper, Lock in Upper, and Shift to Lower are used to adjust that current state. These keys are unique in having two scancodes associated with each one.

When pressing Shift to Upper, the code x136 is transmitted, then when the key is released it sends x336. The CU will remember that we are in upper case based on having seen an x136 and drops back to lower when it receives the x336 code. In a similar way, the ALT key sends x13e as it is depressed and x33e when released. 

The numeric keypad on my terminal makes use of both of these. In normal mode (not upper case and not ALT), the twelve keys produce program function codes PF1 thru PF12. If ALT is active (key held down), then these produce PF13 thru PF24 instead. If instead the CU is in upper case mode then the pad produces the ten digits, decimal point and TAB. We can be in upper case mode by holding down the Shift to Upper key, or by having pressed the Lock Upper Case keycap. 

One fact that may not be obvious is that the keyboard has no way to produce lower case letters. When in lower case mode, a keycap such as B produces the upper case B character. Then shifted to upper case it represents the exclamation point (!)character. Applications can send the code x81 to display a lower case b or xA1 to display an upper case B, but the keyboard only produces capital letter codes. 


To the operator, it appears that when the cursor is blinking in a field that is not protected, any key that is pressed produces the associated character on the screen immediately. Further, movement keys such as TAB or down arrow move the cursor immediately. Control keys such as CLEAR cause the entire screen to become blank. 

None of those actions are done in the terminal. Instead, scan codes are sent to the CU which in turn makes appropriate changes to the screen in front of the operator. Pressing the keycap for a C will cause the CU to update the screen at the point of the cursor with the code xA2 and we see the C displayed. 

Pushing TAB tells the control unit to look through its buffer to find the start position of the next unprotected field and move the cursor to that point. The user sees the cursor jump. Hitting CLEAR sends the code to the CU, when then erases groups of four character positions at a time until the entire screen is cleared.

When the keycap marked B is pressed, the CU decides if it is sending a B or a ! to that screen position. It does so based on what it had last seen done with the shift keys. The keypad on the right is even more complicated. Pressing the keycap labeled PF4/4 will be interpreted as a PF4, a PF16 or a character 4 depending on whether the ALT key or the shift state is active. 

When a user has the cursor in a protected field but presses the G keycap, the CU receives that scan code but locks the terminal and displays a status character on the last line that informs the operator that data cannot be typed at the current cursor location. The scan code is still sent, it is just thrown away by the CU. 


I built a Python object that, when given a scan code, can tell us if this is a control key, a hardware status such as Power On Reset Complete, or a screen oriented keycap. Further, it can give us the 3270 native code for that scan code, to write to the screen. It can also give us the ASCII equivalent which I can use in the program for diagnostic or logical purposes.

Later we can convert the native 3270 characters to their EBCDIC equivalents for transmission back to a mainframe host, but that is not in the first version of this code. 

Serial link bug in 3174 substitute system is corrected!

Andrew Kay, the designer of the 3174 substitute project (Andrew's project page)has hunted down and exterminated the bug that caused the spurious character injection into the serial stream. It was not a flaw in his code but some undesirable behavior of the pyserial library interface with Windows drivers for the USB port and virtual COM port. Having spotted the conditions that triggered this misbehavior, he changed his code so those conditions did not occur. 

Now that this works, I can continue with two minor projects. The first is the exploration of the behavior of my 3178 terminal and experimentation with different streams of commands. The second is the installation of Andrew's full 3174 emulation package and testing with that. The package will allow me to use my physical 3178 terminal with real and virtual mainframes, particularly Hercules the mainframe emulator. 

Tuesday, June 23, 2020

Working on the issues with second digit of VERB display on DSKY panel


Initially my only problem was with the top horizontal segment (F) being absent. I did some touching and inspecting of the wiring and pin placement of the connector on the EL Panel and found that the top three segments were now blank - E, F and H.

After some probing of the wires I recovered the function of segment E, but F and H remain blanked. I already knew from logical analysis that it wasn't a problem in the Arduino or driver board. This is because the code to set up a digit is the same for all positions, the drivers that select the VERB area also control the working digit, and the drivers that control set or reset of the latching relays for the digits are the same for all digits. 

Therefore, any failure of the microcontroller or driver board would not affect just one digit position. Similarly the power supply is common for all digits and lighted segments. 

The likely suspects are:
  • Wiring between Relay Module and pins for segments F/H
  • Contact from the connector to the EL panel for those two pins
  • Failure inside the EL panel, similar to how the COMP ACTY segment doesn't work
  • Failure of relay contacts/wiring inside the Relay Module
  • Failure of the relay itself to latch or unlatch
A look at the wiring of the relays in the Relay Module shows that failure of segment H is isolated to one relay and one set of contacts, but the failure of segment F would also cause segment M to fail, which we are not seeing. plus that relay drives segments E and N. This makes the failure of the relay latching extremely unlikely, and the only internal failure in the module the could explain this is double failure of two independent wires inside the module.  

I decided to do a binary search for the cause. First step was to use my voltmeter to determine whether the pins for F and H were receiving high voltage when selected. If so, the issue was in the EL Display Panel Module or connector If not, I had to look backwards to the Relay Module. 

The result was definitive. I had full voltage on all the segment pins for that digit, so they should all be lighting. However, they weren't. This excludes many of the suspects from above and leaves a smaller list 
  • The miniWasp connector is not making good contact, even though the tail has voltage
  • Something has failed inside the EL Display Panel Module itself. 
The three failed segments (yes, I am back to all three of E, F and H being blank) are not contiguous pins on the back of the module. Two are adjacent but the third is far away. The only closeness is that they are the three upper segments of the digit, top horizontal and the two upper vertical segments. There could be a common fault in the module causing this problem.

On the other hand, I had rocked the connector block slightly to see how difficult it would be to remove when I swap for the newer EL panel. The segment defect began after that action. Thus I could have a connector/connection problem. 


The owner of the DSKY parts I am using has kindly offered to drop off two additional modules. One is a second relay module and the other is a different and newer EL Panel Module.

The second relay module would necessitate significant additional wiring and six new transistor driver circuits. It also means I have to remove the EL Panel Module connector and add 35 more pins to light the five digits of the R1 field which I can now accommodate with the added relays in the second module.

The Arduino would need six additional output pins and some minor reprogramming.

The electroluminescent panel I am currently using is the first iteration of the specs. Among other characteristics that changed for the later production panels used on missions, the wavelength of the light is 5100 angstroms, a blueish-green color.

The versions that were installed in the actual spacecraft and ground simulators were shifted to a wavelength of 5300 angstroms, more of a yellowish-green.  I am excited to receive the newer EL panel module because I will then see the display exactly as the astronauts saw them. 

The Vintage Computer Festival takes place in a number of locations each year, including the VCF-WEST out here in Silicon Valley. Due to the pandemic, it won't be feasible to have the large crowds and interactions this year. The organizers have decided to conduct a virtual festival. There will be five minute videos in place of a physical exhibit.

In past years, I have exhibited my restored IBM 1130 mainframe and a life size working replica, a restored Xerox Alto, working teletypes, and talked about our restoration of an Apollo Guidance Computer, all in person. This year I will talk about the challenges, solutions and work involved in lighting up the DSKY panel. 

Monday, June 22, 2020

Finished testing DSKY project


I did continuity tests and resistance tests for safety. All the relay coil wiring is low voltage DC (14V) while the contacts controlling the electroluminescent display are switching 275VAC 800 Hz. If the two mix, it won't be a good thing for the relay coils, diodes, nor for my driver transistor circuits and the Arduino. 


The high voltage is output from two sets of pins on the Power Supply Module, labeled 800LO and 800HI although the notion of low and high have no real meaning for alternating current. The 800LO side are connected to a pair of pins on the EL Display Panel Module that are called 'ground' but are really a common side of the many capacitors formed by the segments on the panel. 800LO is also connected to the Relay Module as it grounds segments when they don't have 800HI applied to them. 

The 800HI lines are tied directly to the pin on the EL Display Panel Module that illuminates lines and rectangles behind lettering, as well as to many input pins on the Relay Module. I suspect that having a separate 800HI for each column of the five bit relays for a digit helps with ground testing and checkout. It certainly isn't a matter of dividing up total current, because the usage of the entire display panel is quite slight. 

I took the time to clean up the small breadboard where I had built the replica of the output driver circuit inside the Apollo Guidance Computer which feeds an 800 Hz square wave into the first transformer of the Power Supply Module. On the Apollo spacecraft there is a dimmer (potentiometer) that can short part of the signal across the first transformer primary, thus reducing the output voltage and as a result, dimming the panel. I put in a 10K resistor which represents the dimmer wide open on the bright side. 


With all digits and signs off, when I applied power I saw the lines and text blocks illuminated, showing that all appeared well. I had written a simple command language for the Arduino with verbs PROG, VERB, NOUN and SIGN for the display elements I am lighting. 

Firing up a serial monitor (terminal program) to the Arduino, I commanded that all digits be set to 8 and the sign be turned to plus. This lights all segments I have wired, confirming that the Power Supply Module is able to deliver consistent brightness even with all segments on. 

With all segments active I found that I have one segment that is not lighting. The rightmost digit of the VERB section is missing its top horizontal line. It turns a 6 into a b with that segment missing, but doesn't impact digits like 1 and 4 that don't use it. Tomorrow I will check through the wiring and do more testing until I know why this is happening and what actions will restore full operation.

I then issued a mix of commands causing different digits and signs to show on the EL Display Panel Module. Once the missing segment is working, this completes the entire project to demonstrate the use of Apollo hardware producing the display output. 

As a proof of concept, I set up the display with certain digits and a sign showing, then powered everything off. When I later switched on power, the same display is visible. This is due to the use of latching relays in the Relay Module. They retain their state even across a power outage and only consume current when switching on or off. 

Sunday, June 21, 2020

Experimenting with my 3178 terminal using Andrew Kay's 3174 control unit replacement


Andrew provides a set of scripts that accomplish functions such as polling, writing data to the screen, moving the cursor location, and all the others that are available to send between an IBM control unit and a 3270 class terminal 

One of them wrote Hello world! three times across the first line of the terminal. The second one polled the terminal for responses as well as writing Be sure to drink your ovaltine on the screen. The character mapping that I had found on bitsavers wasn't helpful but Andrew took pictures of the result of all possible hex data values. 


I updated the 'ovaltine' script slightly just to experiment with the keyboard and to try out the special control characters that are displayed on the lowest (status) line of the terminal. At the end I looped doing polls of the terminal, printing out the scan code of any returned keypresses. 

Scan codes for 'hello world!' keypresses


IBM documentation on the 3270 terminals described the process of an operator entering data into fields and then hitting Enter as a local activity. It implied that you use the arrow keys to move the cursor around, then when the cursor is in an unprotected field, keys you press show up on screen and are marked as a modified field. The Enter is the only action sent on, with the mainframe program then reading modified fields to extract the newly typed data. 

It suggested that you could change it several times but only the final is seen when you hit Enter. I presumed, incorrectly, that the local process described above was done totally in the terminal and didn't involve the 3174 control unit except for when the Enter key was pressed. 

As I began to experiment, I realized that the keyboard and the display side are independent. They share a coax interface to the 3174 but nothing done on the keyboard directly affects the display on monitor.

Instead, the 3174 continuously polls the terminal and receives responses to every keypress! The 3174 is then responsible for sending an echo of the character back over coax to the display buffer. 

This explains why there is no configuration switch on the terminal to indicate which of the many keyboard types are attached. The system programmer will configure the 3174 to tell it which keyboard, such as typewriter or data entry style, so that the control unit can decide that a given scan code for a keypress is a given screen character. 

Some keyboards have the numbers across the top, others have them shifted above letters, as a consequence the 3174 has to decode the keyboard and convert that to a given 3270 character. 

A request for Terminal ID returns information about which keyboard is attached, what the size of the screen display is, and the protocol spoken. 

Much of what I thought was handled in the terminal is purely processed in the 3174. The screen has attributes at the front of each field which set the intensity, hide the data and determine if the field can be typed into. Since the KB and display buffer are independent, protecting a field is solely done in the 3174 not the terminal.

Even tabbing to get to the next field is done totally in the 3174, which maintains a shadow buffer to match the one in the terminal driving the CRT. 

Saturday, June 20, 2020

IBM 3174 Control Unit replacement is working after long painful debugging


The Python side software was generating various errors where lengths didn't match, responses didn't make sense, or other logical issues. As I had discovered, most of the issues seemed to be caused by extraneous characters injected into the serial stream (usually a hexadecimal F0 but sometimes others). I hunted the cause by replacing everything that was suspect and adding in appropriate debugging output.

I swapped USB cables, Arduino Mega machines, even moved to an older Windows 7 pro laptop, reinstalled software . . . nothing made a difference. 


I modified the code in the Arduino to simply echo back the exact message it received, nothing more. I could communicate flawlessly with the Arduino using the IDE Serial Monitor. That seemed to confirm that the USB ports, Arduino and other elements of the link were working properly. Secondarily I started the pyserial.tools.miniterm program which also proved that it was echoing correctly with no added characters.

I then tried to unwind everything that might be messing up writing from Python. The code used the SLIP library, a protocol to send packets over serial. It frames the start and end with the control character \xC0 and has various escape codes just in case the data inside the packet must be \xC0 or the escape code itself. 

I wrote a state machine to read the stream with the SLIP protocol and to write directly to pyserial's serial stream, bypassing the sliplib entirely. No change. I varied every configuration parameter or sequence of code I could, without a change. 


Finally, I realized that this corruption seemed to be introduced by the initial reset command sent from laptop down to the Arduino. I modified the code to skip that function, and the issue went away. I still don't know why it malfunctions, but I have a suitable bypass. I can move on to more interesting tasks - interacting with the 3178 terminal. 

It is late and dark out where the terminal is sitting, but I was able to interrogate the terminal ID, terminal status and to write some data on the screen. This is a great beginning.

Friday, June 19, 2020

More than 3/4 done verifying segment patterns for various codes sent to DSKY Relay Module


I found that I had skipped wiring one of the five AC high lines that feed the five columns of relays for every digit, thus the H segment of the displays was not being connected to power. I corrected that and began to get much better results.

The sign display was not switching, which I quickly traced to my omission of the Arduino code to set the pins for + and - to output mode. They began switching just like the digits and the continuity tracer showed them activated or open as appropriate. 

I began to send unique digit values to all six positions, which flagged a wiring error in the cable from the Arduino to the transistor breadboard, where two pin positions were inadvertently swapped. That was set straight.


I checked out all ten digit values for correct segment activation, including moving values between positions such as VERB to PROG. I was completely satisfied with the PROG and NOUN digits, but still have some odd behavior with the two VERB digits. Tomorrow when I get back to testing I can finalize those digits as well.


There is a fixed text/line pin and two grounds on the EL Panel that need to be wired, combined with the AC high and AC low outputs from the Power Supply Module and those connections to the Relay Module. 

I will set all segments on and check for shorts to any of the control lines, basically accomplishing the remaining checks to assure me it is safe to hook up the high voltage AC to the relays and make the entire display project work.

It shouldn't be long before I have the display lit and digits/signs dancing on it as commanded by the Arduino program. 

Using Arduino to switch the DSKY Relay Module and some QA testing


Each of my circuits is designed to be off by default, as when the Arduino is not active. They are all activated by driving the input line to +5V, which either delivers +14V for set and unset lines or grounds the row select line. I ran the wiring to the Arduino, then anchored that unit onto the board. 

Just before I connected each lead to the Arduino from the board, I tested the voltage present on that lead to be sure that I didn't have +14V leaking since that would blow the Arduino input-output circuit. This took only a few minutes and I was ready to bring it up to do some power testing.


The code in the Arduino lets me issue commands to set various values in the PROG, VERB and NOUN displays as well as setting the sign to blank, plus or minus. It has a simple command interface where I can turn the sign to + by typing sign +, then turn it off by typing simply sign. In the same way, I can put the two digits of VERB to 36 by typing verb 36 then turn them off by issuing verb with no parameter. 

To verify that I was turning on the proper segments of the display I had to first gang together the high voltage AC leads to the relay module. Each of the five columns for a digit has its own AC power line. 
There are also two low side AC lines that need to be bridged in the external wiring. 

As well, the VERB and NOUN lines require a jumper between two pins to provide AC. These two pins are connected to another relay that is flashed on and off at about 2/3 Hz or forced steadily on, based on whether those digits should flash or not. 

The bridged high AC lines are connected to the various segment outputs based on the state of the latching relays and the five bit code entered into the row that controls a digit. I can do a continuity test from high AC to the individual segments, seeing that they are turned on or off appropriately for each entered code. 

The code I ran that was expected to put 8 in every digit position, lighting all segments, instead put a 6 in as far as segment lighting. It was consistent across all six digits which means it is something that I am doing wrong. The code for 8 is 11101 while the code for 6 is 11100 thus one possibility is a fault driving the low bit. The code looks fine and the hardware worked perfectly when set manually, so I moved on to another possibility.

If I am entering the code reversed, e.g. putting in 10111 then since that is not a valid bit code value the results could well be the same as a 6, by accident.  To check this I selected two values which are symmetric opposites and set all the digits to one of them. If the segments that are active match the opposite, I would know what my problem is and how to fix it quickly. 

I chose 2 and 7 whose patterns are 11001 and 10011, thus entering the code 2 would either display 2 or 7 depending on whether I have reversed the order. The results were not what I expected. I had all the proper segments for displaying the digit 2 except that once again the H segment was inactive.

This tells me that I have something wired wrong where high AC is not getting to the relay contacts that lead to all the H segments. Off to study the schematics of the Relay Module. 

While I had all the segments active (except H) I did a sanity test, checking to be sure that the AC high and AC low lines didn't have continuity. That worked out okay, something essential for when I hook everything up and use the Power Supply Module. 

Thursday, June 18, 2020

EL Panel wired to Relay module, Relay Module wired to transistor driver breadboard, breadboard hooked to Arduino


There are 44 segments of the EL Panel Module that are switched on and off by the relay contacts in the Relay Module in order to display the two digit PROG, two digit VERB, two digit NOUN, and the sign for the R1 row. The segments for an individual digit are in a contiguous block of pins on the EL panel, but scattered across the Relay Module connector. 

I thus had first wired the segments on the EL panel and grouped them in sets of seven (one digit's segments), six of those groupings plus a pair of wires for the horizontal and vertical sign segments. I then took each group, stripped the end of the wires and used a continuity checker (beeped them) to make sure I knew exactly which segment belonged to the wire. 

After doing the wire-wrap connection, all 44 wires were hooked to their corresponding points on the Relay Module. Previously I had wired up a group of pins that provide the 275VAC 800 Hz power that causes the segments to glow. In addition, I had wired the 20 signals that select individual relays and cause them to latch or unlatch, selected in a matrix with some lines fed +14V and others pulled to ground to cause just one relay's coil to activate. 

EL Panel wired to Relay Module


I had designed and built a board that sinks current to ground to select each of the six digits or the two sign segments, as a row. Also on that board were twelve two-transistor circuits that would source +14V to either the latch or the unlatch side of a relay column. These needed to be connected to an Arduino to switch on those transistor circuits, and the output connected to the appropriate pin on the Relay Module.

The wire used to wrap the pins on the connectors of the EL Panel and Relay Module have a square tail so that as the wire is wrapped it bends and grips tightly. I did not, however, have such tails on the breadboard nor on the Arduino, so other connection methods had to be arranged.

The Arduino was easy - I used male to male cables with pins that fit both the breadboard holes and the Arduino connectors. One cable had eight lines for the row select, two others had six lines each for the column set and the column unset function. An Arduino Mega 2560 was easily able to accommodate the number of I/O pins. 

I first tried sticking in a connector post of the same type that fits into an Arduino, then doing a wirewrap on the pin. I found that the round shape of the connector post did not form that good tight grip that is possible with square tails. 

I decided on a hybrid approach. I got some hookup wire that would fit decently in the breadboard holes but also slid into the wirewrap tool. I then wrapped the wires coming from the Relay Module onto bits of bared hookup wire, soldering the connection in place and snipping off that small section. It was inserted into the breadboard for each of the twenty blue wires coming from the Relay Module.

Transistor driver circuits, Arduino cable on right and blue wires inserted on outputs


There is so much wiring to this project and a dangerous mix of high voltage AC, 14V DC and TTL level voltages. With 137 pin locations on the Relay Module and 160 locations on the EL Panel, the opportunity for error was high. Further, any inadvertent shorts might connect the AC onto the control lines and blow out my driver circuits. 

I therefore plan a set of checks and tests before full scale operation to mitigate those risks above. The first test was done by providing +14V to the transistor driver board, manually touching a +5V lead to the inputs that will eventually be driven by the Arduino, and listening for the barely audible click of the relays latching and unlatching. This let me check for proper voltages, ensure that the Arduino won't be damaged by +14V backflow, and see that all the relays click away as expected.

I selected each of the six digit rows, then while that was active I touched the latch and unlatch columns one by one to ensure I was getting switching of the relay it controlled. I then selected each of the sign segments and while it was active did a latch and unlatch of the relay. All was good.


Each digit is chosen by setting a specific pattern of latched and unlatched relays in that row. There are five columns, since the DSKY uses a five bit code to pick the value 0-9 or blank. This means that each time I want to change one of the digits, I have to select a row and then latch/unlatch five relays to choose the digit value. Doing this manually would be tedious, thus the desire to write a program for the Arduino.

I will issue simple text commands at the terminal monitor, such as PROG 63 or SIGN +, which will select each of the two digit rows and set the code in the five columns. Pretty easy for me and not much of a program for the Arduino. I am mostly done with the code, thus once it is debugged fully I can hook up the Arduino and cause digit values to be set into the Relay Module, changing them rapidly.

Wednesday, June 17, 2020

Long slow trek building and wiring up connectors for the Apollo DSKY display project


There are roughly three categories of wiring running to the Relay Module - low voltage control signals, high voltage power connections, and high voltage lines to individual segments of the EL Panel. I chose to use blue wire for the control lines and yellow for all the high voltage lines.

The first phase was to wire up all the control lines, using the blue wirewrap whose other end will go to the breadboard panel I built with all the transistors to drive +14 and ground to these lines for the purposes of latching or unlatching the individual relays in the module. I routed the wires to the right where I will place the transistor board.

Blue control wires hooked to the Relay Module connector

Second phase was to wire up the sources of 275V AC, 800 Hz which will be routed through the relays to light the segments in the display panel. These were done with yellow wire and routed out the top of the connector to be hooked to the Power Supply module and to two ground pins on the display panel. 

The final phase will be connection of the yellow wires between the display module for the individual segments and the relay contacts that power those segments. These are routed to the left where the display panel will sit. 


The connector for the Display Module has 160 male pins, but I only need to connect to 50 of those locations since I am only lighting up the PROG, VERB, and NOUN digits, the sign for the first register row, and the fixed text and legends. These are all up at the top, from pin 110 upwards.

50 female pins placed in the connector plate


I then wired all the segments with the yellow wire running to the left, so that when the display is facing forward, the wire will run to the right over to the Relay Module sitting next to it. Each digit has seven segments, thus seven wires. The three areas PROG, VERB and NOUN have two digits each.  

There are some other pins in use, two for the sign character, two for ground, and two for other purposes. I wired the digits individually, each group of seven wires routed through a shrink wrap tube. These are ready to have their other end wrapped onto the appropriate pins of the Relay Module

Yellow wires for individual segments are attached

Tuesday, June 16, 2020

Narrowing in on the communications error serial USB between Arduino and Windows virtual COM port


I hooked up my Digilent Analog Discovery and put it in protocol mode, to spy on the traffic over a serial link. I hooked the two digital lines up to pins 0 and 1 of the Arduino which are the serial port RX/TX pair. Once configured for the same 115200, 8N1 I captured what came over the port.

It should have received xC0, x00, x01, x01, x00, x00, xC0 and then sent back xC0, x00, x04, x01, x01, x02, x03, x00, x00, xC0 as the response. Instead I saw this (digilent uses h instead of x to denote a hex character):

hF0 hF0 
hC0 h00 h01 h01 h00 h00 hC0 
hC0 h00 hF0 h04 h01 h01 h02 h03 hF0 h00 h00 hC0
hF0 hF8 

There are spurious xF0 characters as well as a final xF8. The occurrence in the midst of the message coming back causes my problems. 

Now, once I figure out what is injecting these and how to turn it off, I should be able to communicate cleanly. 

Sunday, June 14, 2020

Building control system for the DSKY, based on an Arduino


The relays in the Relay Module are wired into an array, with seven rows and five columns of relays. In addition there are another column of relays used for other purposes such as lighting the sign segments For our purposes, we will use just six rows of five to light up the two PROG digits, two VERB digits and two NOUN digits. We will also make use of two relays to control the sign in front of the R1 row on the display, and use the flashing relay to make VERB and NOUN flash on and off. 

These are organized so that we select a column by pulling its control line to ground. Overly simply, select a row by feeding +14V. The relay coil at the coincidence of the energized row and column will activate. 

These are latching relays, meaning that they have both a SET and an UNSET control line for the row. To turn on a specific relay, we select its column by grounding the line and provide +14V to the SET line for the row. If we later want to turn it off, we ground the column line and provide +14V to the UNSET line for the row. 

Although each digit on the display has seven segments, the Relay Module uses only five relays to control them. There are eleven valid five bit codes that can be set into a row of relays, for the ten numeric digits and for an unlit condition. The wiring inside the relay contacts converts those five bit codes into seven discrete segment connections. 


I want to use an Arduino to programmatically set and unset the relays, forming digits to display on the Electroluminescent Panel module. That microcontroller won't tolerate 14V levels, so I need some method to control the higher voltage by sending signals at +5V. I could have set up 20 relays to drive the +14 and ground requirements for the Relay Module but decided that, due to the low current of these relays, I could use common low cost transistors. 


I set up 8 NPN and 24 PNP transistors with their bases biased to be off by default. I used a set of breadboards for convenience. Six of the NPN are used to select the six rows for the digit displays, while two are used to select the relays for the horizontal and vertical lines of the sign character. Five pairs of NPN-PNP set the bits of a display code, another five NPN-PNP pairs unset those bits, and there are two NPN-PNP pairs to set and unset the relays for the horizontal and vertical sign segments. 

The reason for using pairs of transistors with the NPN-PNP circuit is that I am switching high side +14V with an input that can't go above +5. I need a first NPN transistor with emitter at ground, biasing the base down to ground so it is by default off. When the first conducts, it pulls the base of the second (PNP) transistor down to ground, causing it to conduct. Normally the base of the second transistor is pulled up to +14V, the same as the emitter. 

I used an LED plus resistor as a load to verify that my circuit is by default off but will conduct to light the LED when +5V is delivered to the base. Similarly, I used the LED and resistor for the PNP circuits to verify that it is off by default but provides voltage to light the LED when ground is hooked to the base. 


Fortunately, one can faintly hear a click as the relays in the module are switched from set to unset or vice versa. That allowed me to check out all the control lines from my Arduino. I temporarily wired in one row with a column set and unset, verifying the sound of the relay latching and unlatching. 

Next I took some hours to carefully wire up all 32 transistors and their associated resistors and power connections. I finally had all the parts and wires set down on the breadboard, ready to begin testing.

Tested 3174 interface communications with new genuine Arduino Mega 2560, same failures

A bad board was the most likely seeming cause of the failure of the Python code in the laptop and the firmware in the Arduino to communicate correctly. Just ten minutes ago my genuine Arduino was delivered, as there were two possible causes of the problem - bad board hardware or some compatibility issue with the clone Sunfounder Arduino. 

Alas I immediately had the same error. This is frustrating because now we have to delve deeper into the workings to figure out what is wrong, since it appears to be a software defect or some kind of software configuration issue. 

Saturday, June 13, 2020

3174 interface issue narrows down to either my Arduino board or some serial communications issue


The problems I am encountering are errors found in the Arduino firmware where it finds that a length code inside a message doesn't match the actual length. To strip away possible causes and do a binary search, Andrew suggested that I remove the shield entirely and narrow down the test to a more pure communications focus.

I modified the firmware so that when it is presented the POLL command over the USB link it returns a fixed error asserting a timeout. The error remained, a length mismatch, which tells us that problem is not in the shield nor something occurring while communicating with the 3178 terminal. 

Reducing the speed of the serial link to 9600 baud from its original 11520 eliminated whatever problem we were having, because I began to get the dummy timeout error which is the correct response. Moving up to 38400 baud reintroduced the length error (garbling). 

I swapped the USB cable for another, in case there was an electrical problem with that. No change. The range of possible culprits is shrinking. Some I can think of include:
  • Windows 10 and its driver
  • The Lenovo L340 laptop USB port hardware
  • The Sunfounder Mega 2560 clone itself
  • Some unanticipated side effect of a code flaw in the firmware
  • Some corruption in the SLIP and PYSERIAL libraries used for communications
  • Some defect in the platformio toolchain that is creating defective code
The most likely is the clone Arduino. I expect to get a name brand Arduino Mega 2560 tomorrow and will repeat the test with that. 

Friday, June 12, 2020

More debugging of the 3174 interface system to drive IBM 3178 terminal


Andrew has been kind enough to spend time exchanging emails, suggestions and reviewing diagnostic results, hoping that we can get my interface working. We don't know if there is a peculiarity with the 3178, some code that could be improved in Andrew's code, or some hardware problem in my interface shield. 

He has added instrumentation, suggested changes I can make to the code and puzzled along with me at the behavior we are seeing. 


When attempting a POLL, which is a one word command issued to the terminal that either indicates it is idle or signals that some action key or other condition has occurred that should be handled by issuing further commands such as READ, we are receiving an invalid message request error. 

Having put a pause into the program, after it initializes the link down to the Arduino but before it transmits a POLL, I can see that something is triggered and we fail before even sending the POLL. A message is sent over the coax during the link initialization and receives a response from the terminal. 

In some cases, it crashes before the pause, but other times I get a chance to send the POLL. That data begins to be received by the Arduino (scoping the Rx pin) but almost immediately it sends some kind of rejection message to the laptop on Tx and we fail. There is no POLL message sent over the coax, it is blocked in the Arduino. 

Plates arrived to construct the connectors for the DSKY components


The connectors for Apollo DSKY (Display/Keyboard) are manufactured using the individual Malco mini-WASP pins pressed into holes in an aluminum or other metal plate to form some array of pins spaced .125" apart. Since mini-WASP pins are a precious commodity, I designed an alternative that would leave the pins in original condition for re-use after my project is done.

I had Ponoko.com laser-cut my design into thin maple wood, giving me a wood plate that could have the nylon holder of the mini-WASP pin pressed in without compressing or damaging the nylon. I build a stack of a plate holding the pin and an upper plate that allowed only the pin's wire-wrap post through. I could then wire-wrap to make connections and easily remove the wire after I am done. 


The plates align perfectly with the male pins on the three DSKY modules I have on hand. I tested the press fit of a mini-WASP into the plate and it was as good as I could expect. Removal leaves no damage to the pins but when pressed on it has adequate hold power. With the top plates added I have a great surface to install the wire-wrap cabling. 


My first connector construction was for the simplest of the three modules, the Power Supply Module that needs only nine pins. I quickly put it together and moved the wires over from the temporary pins. I am pleased with the connector I have constructed and its operation.


The Relay Module has space for 137 pins but for the purposes of this demonstration project I only need to install 75 of them.  They consists of three groups for different purposes:
  • 11 bring the 250 VAC 800 Hz power from the power supply
  • 20 are control inputs from the Arduino based driver to activate the relays
  • 44 deliver voltage to the segments of the EL panel

Thursday, June 11, 2020

Scoping the 3174 interface board to verify its operation


The board is fairly straightforward. The coax connector is hooked to a pulse transformer that has two far side windings, one going to the receiver circuit and one to the transmitter circuit. The receiver circuit is a DP8341 chip and the transmit circuit is a DP8340. The output of the transmit circuit goes through a DS3487 tristate line driver chip so it is not blocking the transformer when listening for incoming traffic. 

There are decoupling capacitors, several resistors to isolate inputs, plus a crystal and cap to generate the 18.867Mhz clock frequency. This is build as a shield, a board the same size as the Arduino Mega 2560, with pins that plug into the Arduino. The serial protocol from the Arduino is carried over the USB cable to a COM port on the laptop. 


No clock, no operation. Therefore, right after I verified power was provided to the three chips, I tested the clock out pin on the generating chip and the clock in pin on the other chip. The signal was correctly formed and on frequency.


I put the scope directly on the coax pin to see if the transmitter was sending out the proper bit pattern to the 3178 terminal. It appeared so. Further, I could see a response coming back from the 3178, consisting of two words. 

The program still failed with the same message length error, so I need to zoom in and make sure that the receiver side of my interface board is properly detecting, decoding and delivering the two word response. 


I then probed the signals on the DP8341 receiver chip to ensure that they were seeing, decoding and outputting the data I see arriving from the terminal. The pin Receiver Active should go high when a word is arriving, then when it is complete the Data Available pin should jump to high.

That is what I see, which indicates that the chip is seeing the word and is ready to provide it to the Arduino firmware for transmission up to the laptop. Next set of signals to monitor are the error detection pin and the output enable which controls when the chip outputs its received data. 

The Error pin never goes high, indicating that the receiver chip believes it has a properly formatted word that is ready to be presented to the Arduino. The data word received is a copy of the POLL command all bits zero except for 2 (and parity bit 0).

At this point I am going to exchange ideas with Andrew and then attempt some instrumentation to see what his software is seeing from this interchange and how it is dealing with it. Perhaps the 3178 behavior is different from the 3278 and would need some modifications in the code to work properly.