Making 1403 printer, finishing card reader, week ending February 23, 2014


I realized I can't test the strategy for focusing the serial link reads only on the first input chip during active Documation reads, to test whether the faster link operation by itself is enough to resolve the dropped card columns, because the index marker identification signals are on board 2! When I go into focus mode, I don't see the markers and don't recognize any card columns.

Removing the focused read scheme, I am back to reading but having about 1/3 of the reads drop a column. However, I am seeing the card contents deposited in memory just as I wished.

I can either rewire the signals in the existing interface box, moving the index marker (or actually the single shot long-lived pulse I create from the IM) to chip 1, in order to accomplish this test of solely the link improvement, or I can wait and build the entire new interface board I have planned. In the interests of avoiding work that may not be necessary, I will proceed with the rewiring.

My virtual 2501 - real control panel on left, Documation 600 reader on right
After doing the small rewiring of the signals in side the interface board, I was struck again by the evil demons plaguing my project. Something went wrong, a wire snapped or something, so that the darned interface doesn't work at all anymore.  Have to shoot this problem before I can get back to testing the card reader interface. After a bit of work with the scope showing good signals and the voltmeter showing good power, I first thought that my focus modification is stuck in the active mode, which starves the output box of any attention to turn on lamps and also ignores the signals coming from chip 2 which includes the NPRO, Start and Stop buttons.

Not so, however. It is an electrical problem inside the box, caused accidentally when I opened it to swap the signal lines. The most fragile part was where the two thick cables entered the box. I completely replaced that with a terminal strip and mechanical securing of the connections, but it is still nonfunctional.

I had found one wire that broke inside its insulation (!) while appearing connected, as part of replacing the fragile part. Everywhere I can check voltages they are correct, yet something is still wrong. It is this kind of random accidental breakage that wastes so many hours during this project when I should be debugging and verifying, not going backwards to repair things that had been working smoothly.

I am communicating with the chips in my main serial link loop, but not seeing any lights or output controls. Time to trace the voltages and connections in the output box that drives these, as well as putting some debugging traces on the serial link from the fpga end. Finally, I discovered a bad solder joint - looked perfect but one of the leads at the new junction was electrically isolated even though it was immersed inside the solder surface.

It works again; time to put the interface back together and resume testing. It took a while to restore all the diagnostic feeds appropriate to reading cards, now that the interface issue is resolved. The good news is that I see clean pulses from my timing device and the data values look good coming in. I had the polarity reversed but that is now corrected. The bad news is that something strange is happening with the busy signal - it arrived at almost the end of the card being read and its presence corresponded with dropping the last few columns. Also, from time to time the adapter logic refuses to drive a card through the Documation, just turning on the ready lamp but not loading a card into the virtual preread station.

I am going to look over my logic to see where the bad behavior might be occurring and what effect a delayed busy signal might have on the state machine. Based on my study, I tweaked my diagnostic traces and tested again. I can see from the trace that my timer code is wrong - it is moving the state machine forward before the pick signal has a chance to work, then timing out because the index marker will never come from an idle reader. I had to sort out the timer misfiring.

At some point I will put some capture lines on the pick, busy and IM signals inside the reader, use my logic analyzer on those three direct signals and see if there is a problem with busy at the device, or if the problem is somewhere in my cabling or interface.

The timer issue is resolved. Further, I realized that the erratic busy signal was actually the result of focusing the serial link only on chip 1 during the active column reading period. Busy is delivered on the other chip which my logic ignores until the last column is read. That is why busy popped up at the end of the card - it was probably active the entire time on chip 2, but hidden from the fpga.

At first glance, it appeared I was reading the proper number of columns from the card and delivering them into memory. However, I see that I have consistently dropped row 8 from all the stored values and dropped the 11 row quite often as well. Correct number of columns but now data validity questions.

A quick check shows that the serial link is not delivering the status of row 8 at all. This can be an electrical problem on the chip 1 board, a cabling problem from the reader connector into my interface box, a failure in the latch board in the interface box, or a defect in the Documation reader itself.

The problem was isolated by putting the logic analyzer over next to the reader and hooking up several points. I shudder every time I move, disconnect or open the card reader interface box, since I have had SO MANY unanticipated failures when I touch it. I wasn't highly motivated to do this and left it for a while.

Tracing the row 8 issue involved getting to the chip 1 board which was at the bottom of the stack of cards in the existing enclosure, requiring all the boards to be pulled out once again. This was the last straw for continuing with the current enclosure. I found an old PC chassis, stripped it down, and used it to mount the interface with plenty of room between boards. It should be easy to trace and repair with minimum removals, most fixes could be made in situ.

It took several hours to untangle the lines, choose a mounting approach, put all the components in place and then reconnect any wires that had to be cut to separate everything. It was a chance to anchor the wire entry to the PCBs too, an area where I have been worried about breaking connections whenever I disturb the wiring. I used epoxy to hold the header pins to the PCB, then reflowed the solder to ensure the connections are solid.

New enclosure for card reader interface cards
I adopted a new connector for power and moved the output box inside with the rest of the card reader electronics, leaving me with a single external box that is the Documation/2501 controller. I mounted the 2501 control panel on the top of this box and mechanically secured the signal cable entry into the machine. Once this is working again, it should be more bulletproof as well as easier to debug and service.

I took the time to do continuity testing of every wire, including shaking the connections, to make sure this unit is really reliable. All in all this consumed about eight hours of actual shop time and most of two days of elapsed time. During breaks and at other free moments I made substantial progress on the Arduino controller for the emulated 1403 printer.

I did find a bad connection, two broken off leads and a wire with a hidden break somewhere inside the insulation, but everything passes continuity tests now. The first test with it installed did not work right, but I realized I had mis-wired the pullup resistors that are necessary for the I2C lines inside the box.

Digging further, there is something erratic in the link signal which is stopping the input board chips from operating correctly. It is intermittent, which is making it hard to chase down definitively. I put in about two hours replacing wiring, improving connections and vibration testing. It goes slowly because the link has to be restarted from the fpga to test each change of position, a real impediment to vibration testing efficiency.

When I found it, the intermittent contact was at the fpga end, not the box I had reworked. Sigh. Anyhow, the link is now working reliably once I pinned the cable down at the 1130 end. My first test worked very well, I read in the card perfectly into memory, no garbling.

Since I had removed the logic analyzer to bring it over to the reader end, I had to set it up again before I can go back to troubleshooting column loss and other possible problems with the interface. That left me with just a couple of hours on Sunday to resume testing.

Card reader interface connected to Documation, ready to run
I am seeing a bit of flickering on the signals from chip 1, visually looking at a seven segment display bank representing the values. While the reader is static, these should not move at all. I am not seeing error signals from the I2C handler, but this is either something flaky about my state machines or something happening with the chips delivering the wrong data from time to time.

I will try switching the chips out of sequential addressing mode, which is where they bump the register number between reads allowing me to read all sixteen bits as two sequential read commands. I will now select and address each bank's address discretely in front of the read, keeping the chips from changing the register address on their own.

Even with the change above, I see the flickering. It occurs with chip 1 but not chip 2 and it seems to be pretty repeatable as far as the bit that is flipping. Row 5 is the one flipping on the most when the last column latched into the latchboard is being displayed. On my test card, it is the letter 'M' which is the 11 and 4 holes - those values are displayed steadily but I get false detects/flickers of row 5 and another, less frequently, from among 12, 0 and 1. I can't tell the other one as well as I can see the more steadily misbehaving row5.

I watched the link while tapping individual boards and touching groups of wires. The latchboard itself and the board for chip 2 are rock solid, but board 1 itself is extremely sensitive to direct tapping. I know I have flaky connections and I know about where to look on the board. I will dive into this sometime during the week.


I bought an HP 2563A line printer which will connect through my adapter, behaving like an IBM 1403 printer. Although the IBM uses a rotating chain and a hydraulic mechanism to space and skip the paper, while the HP printer is a moving dot matrix head, there is enough functionality to emulate everything.

The HP printer is a pin feed 132 column printer fast enough to print at 1403 speeds. It can be sent special data streams that define the equivalent of the physical carriage control tape on a 1403 in which the user punches holes. As well, it can generate custom characters from the dot matrix head, which allows me to match the 1403 print chain font if I don't like the standard font.

HP Printer which will emulate the IBM 1403 for my 1130 system

In order to create virtual carriage control tapes and to mount a tape on the 1403 printer, I put an Arduino between the HP printer and the fpga. It has an LCD screen and control panel that I will program allowing the user to pick which tape to use, as well as to create additional tapes. It will ensure that any 1403 commands to skip to a particular printer 'channel' will be issued as the relevant HP control characters. Finally, it will convert from the 1403 print code to the ascii characters (or custom characters) on the HP device.

The fpga adapter logic has a few responsibilities. It will model a 1403 printer in order to exactly match the timing and to ensure the behavior matches what would happen on a real 1403. For example, if the user asks the printer to skip to a channel on the carriage control tape which does not have a hole punched in it, the printer will 'run away' spewing out paper. It has to work properly through the IBM Storage Access Channel that is a feature of the 1130; this is the way the 1403 is given IO commands, how it reads data from core memory via cycle stealing to accomplish the printing, and the way it presents interrupt requests and status.

The HP printer is accessed through an RS232 serial link. The Arduino handles the RS232 serial protocol but only supports TTL voltage levels, not the higher voltages defined for RS232. I built a board that shifts the voltages between 'real' (EIA RS232) levels and TTL levels, allowing me to hook up the Arduino. One serial cable runs between the printer and the Arduino, another cable runs from the Arduino to the Digilent FPGA board. That board has an RS232 connector which operates at EIA RS232 voltage. My voltage shifting board implements dual RS232 connections, to hook up both cables.

Voltage conversion from TTL microcontroller to RS232 levels
I wired up the voltage shifting board and connections to the Arduino, in preparation for the code development and testing on the Arduino. By using another system, perhaps a Raspberry Pi, I can develop the Arduino and test it independently of the fpga side logic. Later, the Raspberry Pi can be used to test the fpga logic independent of the Arduino. The final full testing will be easier when I modularize and shake out each part separately.

I sketched out some test code for the microcontroller to validate my connection to the HP printer and the soundness of that link, before I introduce the code to mimic the 1403. My printer uses HP Print Control Language, which is mostly a set of escape sequences that control various actions, configurations and features of the printer, that get added into the stream along with characters to print on the page.

Running my first test sequence to the HP printer but it didn't work. The printer detected the data set ready signal I transmitted, indicating the 'modem' is online, but I wasn't seeing the signals inside the Arduino. Connecting two machines together with RS232 is always a bit of a problem because the standard was designed for a computer or device to connect to a modem, that modem using its own method to link to another modem. Eliminating the modems between the devices, using so called null modem wiring, is not a standard method. There are many possible ways, depending on how the devices use some of the control signals.

I built by board to support hardware flow control using the RTS and CTS signals, in addition to the transmit and recieve lines, but the HP printer does not use these. It always puts CTS high for the other side, instead using other methods of flow control. One is to make use of the DSR and DTR signals, sometimes the DTR and DSR are looped to each other. A flow control signal can carried to the other side on the DCD line. In addition, there are several software flow control methods, the main one being use of the XON and XOFF ASCII characters.

In this case, the printer must see the DSR line go high, but that can be a simple loopback of the DTR emitted by the printer. CTS/RTS is not used here, so I can stop managing them. I will implement XON/XOFF flow control in software. The arduino only uses the TX and RX lines, not implementing any of the other signals. I think I have straightened out the signaling that is needed and can test once I rewire for the loopback above.

The test worked perfectly at 19,200 baud. I can now code up the functionality for the HP driving side of the Arduino and begin to test it with data sent over USB to the microcontroller. So far, I have it handling the code translation, managing the flow control and buffering the stream going from CPU to printer and implementing much of the skip and space commands.

The 1403 printer uses seven bit values to encode characters, translated by lookup in the Arduino to ASCII characters. The 1130's version of the 1403 only had a 48 character print train - the alphabetics, numerals and just twelve special characters. Any value that doesn't map to one of the emulated 48 will be turned into a space.

I found one collision in the encoding, the letter 'Y' is x13 which is the same value as the flow control character XOFF. I will map any x13 coming from the fpga into the code x83, where the high order bit of the byte tells me this is not a printable character. I look for the x83 when receiving data from the fpga, translate it to the intended 'Y' and put it into the output queue.

When the 1130 requests that the printer space down one line (by issuing an XIO Control instruction), I send that on the link to the Arduino as code x80. At the receiving end, I convert this into the ASCII codes CR and LF which are placed into the output buffer in lieu of the stripped value x80.

Carriage control tape operations (skip to channel) are initiated by an XIO Write command, turned into the code x88 followed by two bytes of channel data. I push this unaltered into the output queue, then when it is time to write to the HP printer from that queue, I pull those three bytes off the queue and convert it into the appropriate HP escape sequence that spaces the paper based on the VCF (analog of the carriage control tape).

Any time the operator defines or changes a carriage control tape, I set up the VFC in the printer to match so that the HP escape sequences will make the paper advance as intended. In addition, I shadow the moves in software in the Arduino, because the 1130 behavior is different from the HP printer. When the 1130 requests a ship to channel, it sends twelve bits corresponding to the 12 tape channels. The 1403 will stop only if ALL the punched holes match the 1 bits sent over, not just stopping if any one of the channels has a hole. Thus, I must look through my software copy of the VFC to find an exact match, determine how many lines would be skipped in this case, and inform the fpga.

There are messages I will send back to the fpga, informing it of status and the number of lines that were skipped. The 1130 implementation will turn on a flipflop if the carriage control tape passes a hole in channel 9, same for holes in channel 12. When the user does an XIO Sense Device instruction, some of the bits returned tell the programmer whether those channels were detected since the last time they were reset. I have to spot this in the shadow VFC and send back appropriate status.

There may be responses from the HP printer that we need to extract from the return stream, which can easily be added into the program as I have reserved the space to do that processing; to date I see nothing in the HP documentation about messages that may be emitted by the printer.

I installed the LCD screen 'shield' on the Arduino and began to write the user interface. It has a screen that can display six lines of fourteen characters and a four direction joystick that is also a push-in button. The joystick is analog, read by doing an analog to digital sampling which takes about .1 millisecond, during which time the Arduino won't be servicing the two 19,200 baud serial links. That wouldn't be acceptable while the printer is active, but fortunately the actions this microcontroller will allow only make sense when the printer is stopped.

Arduino control screen while printer is ready or printing
I designed it to display a static message while the printer is in the ready condition, but when the printer is stopped or not ready, a menu will appear. It will allow the operator to 1) set the page length, 2) mount a carriage control tape, 3) make or modify a carriage control tape, 4) switch the printer between 6 line per inch and 8 line per inch vertical spacing, and 5) advance the paper to the top of the next page.

Main menu when printer is stopped, allowing operator adjustment
The fpga will send a character to inform the controller of the state of the printer. x81 means the printer is stopped or not ready, x82 means it has become ready. Based on the latest character received, we will either display the static 'ready to print' message or show the menu of choices.


I use a Wright 2600 hand keypunch to build punched cards for my testing and eventual use with the completed 1130 system. Binary cards are defined in a number of formats, but they share one reality - many of the columns involve multiple rows of holes. The way this is created on the 2600 is by pushing down and holding one of the row levers, then pushing each of the other rows that must be punched. The 2600 only advances to the next column when I let up the first key, thus punching all those holes in the same column.

Wright 2600 hand keypunch
On a full sized keypunch like the IBM 029, there is a control key labeled "multipunch" which is held to allow the typist to type multiple keys for the holes in various rows, making all of those punches before moving the card to its next column position. Stan Paddock built an interface from a PC to an 029 keypunch that punches a card based on the contents of an ASCII file on the PC, but it does not currently support multipunch or binary cards, as its purpose is to create cards for the IBM 1401 systems. He is working on a utility that might allow me to provide a special format ASCII file as input to a 1401 system that has the feature permitting binary card punching on its 1402 peripheral, but that is months away.

The 1130 has a program load mode, a bootstrap mechanism, that with a push of a console button will read one card from the reader into the first 80 locations of memory, then start execution at location x0000. The cards are punched in a special format, defining how a 16 bit word is loaded by a column of a card which has only 12 rows of holes. One of the rows, row 3, will load into both bits 8 and 9 of memory. Rows 12, 11, 0, 1 and 2 load into bits 0-4, and rows 4-9 load into bits 10 to 15 of the word. That leaves zeros in bits 5, 6, and 7. For instructions, those bits are used to mark a long format (doubleword) instruction and to select index registers, but short format un-indexed instructions can be mostly represented using this encoding.

Bootstrap mode card - this one loads the disk monitor from disk
Since practical programs involve some data/constant values using bits 5-7, are best expressed with some indexed or long instructions, or need bits 8 and 9 to be 01 or 10, the typical bootstrap program must use some of its 80 word locations to set these bits, using instruction sequences involve load, store, shift, or logical operations. Most bootstrap decks are more than one card, but only the first card is read into core with the encoding of 12 rows to 16 bits I just described.

More typically, the first card of the bootstrap program defines some format for binary data on the remaining cards. One very popular scheme is called 8+8 coding, using two card columns for one word of 1130 memory. Rows 12, 11, and 0-5 are used, rows 6-9 are left blank.

Often this ends at column 72 of each card, leaving room for hollerith mode sequencing characters to identify the deck and maintain the cards in the correct order, but can also include execution data such as the address to start execution of the location that this data will begin in core. Some also put checksum information in that area, to let the loader validate that it was correctly read into memory before it transfers control to the code from those cards.

The variations mean that even with 8+8 mode binary decks, a slightly different bootstrap card or cards are needed on the front of the deck. I have punched three bootstrap card decks so far. One is for the 1130's diagnostic routines. Another is a binary loader that will take 8+8 format binary cards - for example, this is used as part of the system loader process to put the DMS2 monitor on disk.

This deck is five cards long, one in program load format and four in 8+8 with checksums. Behind this bootstrap deck would go 8+8 format decks of the diagnostic control monitor and then various diagnostic routines to exercise different parts of the system. The third is a one-card program load mode card that does a cold start of DMS2 from a disk drive selected by the console bit switch settings.

My binary decks with final card being produced in machine
The diagnostic loader uses checksums to validate correctness of the cards it has read, since it will be used on machines that may not be functioning correctly including defects that would cause wrong bit patterns in core, and allocates only two columns for hollerith hexadecimal sequencing information. The binary loader gives more space at the end of each binary card for identification and sequencing data in hollerith. The one-card program reads the bit switch values and then reads a disk drive to pull in the initial loader part of the disk monitor system.

No comments:

Post a Comment