Sunday, March 27, 2016

Converting 1442 adapter for both mirror and virtual mode, plus plotter restoration start

More distracting tasks to keep me away from the 1130 project. My daughter's car is leaking oil around the valve covers, which causes smoking oil entering the ventilation system to the detriment of the riders. I bought new gaskets and parts and did the repair myself.

A gasket on the cam chain tensioner is also a source of leaks, so I replaced that. This involved partially disassembling one of the camshafts to get access for the replacement. Two special tools, easily found on ebay, were required.


Implementing mirror 1442 reader/punch

I began coding that additional logic in the fpga first, so that I can first verify that it 'does no harm' to the existing virtual 1442 functionality. I was surprised by how lightweight the change is. Only three functions force data onto the 1130 bus - XIO Read, XIO Sense ILSW and XIO Sense Device. I used my mirror versions of these, which capture the data that is written by the real, functioning adapter electronics inside the 1131 instead of driving data onto the bus as the virtual driver must do.

Next, I have to skip over the steps in the main process which trigger the 80 emitter interrupts on IL0, since the real adapter electronics will do this. I also have to skip over the step that triggers the completion interrupt on IL4, for the same reason. One signal, which indicates whether we are in mirror or virtual mode, will direct the main FSM to take or skip these steps as appropriate.

The remaining change is in the pre-read buffer logic, which now has to capture the data written by the real adapter electronics (via my XIO Mirror Read module) and store it into the buffer. This is driven by a new mirror read process that triggers a buffer write at the end of an XIO Read.

The last little bit was the special transaction from the PC that will set or unset the mirror mode signal. I chose the Write Device Status transaction (command code 6) and the low order bit will switch the adapter to mirror mode if set, otherwise it will flip the adapter to virtual mode.


I picked up the plotter, which does appear to be complete as far as parts, with the only visible damage being the dented and bent main drum upon which the paper is carried under the pen. The tasks ahead are:
  1. Repair the drum,  returning it to a constant radius cylindrical shape
  2. Get accurate pictures and colors for the control and side panels of a 1627
  3. Repaint side panel to IBM color (IBM gray)
  4. Repaint control panels to IBM color (black)
  5. Create and attach white labels on control panels
  6. Remove Calcomp label on front bar
  7. Create and attach IBM 1627 label  and "made in america" placard to front bar
  8. Reassemble plotter
  9. Attach plotter to slave fpga board
  10. Test and adjust plotter
As far as task 2, I collected quite a few pictures that show me the colors and labeling with enough fidelity that I can paint the plotter properly and fabricate realistic labeling. I have powder coating colors corresponding to both gray and black as used by IBM in the 1130 generation. I will just need to sandblast the panels to be painted and then find a powder coating facility I can use.

Task 1 - drum repair - is going to be the most complicated part of the project. The drum has a big dent and that has also bowed the cylinder out of 'round' in a couple of places. It is an aluminum drum, this inherently soft and ductile, which might allow me to get it close enough to true. If I can, then I can spin it with an abrasive to even out very slight variations.

Another possibility is to make a form out of wood or plastic that matches the desired internal volume of the drum, allowing me to force the aluminum down over the form to true it up. I am skeptical about this method but it is worth considering. As well, I need to think of other repair methods.

Another possibility is to find a substitute aluminum hollow cylinder whose ID and OD match this one. Cutting it to length will be relatively easy and then I can simply replace the dented drum with a new equivalent. The key, of course, is to find a readily available drum with the magic combination of inner and outer diameters plus sufficient length.

I disassembled the drum to find it is a light easily bent surface that had sound deadening foam on the inside. The cylinder has small pop-riveted tips that will fit the perforated holes in any paper inserted into the plotter. These would be quite hard to move to a replacement drum surface.

Dented drum

out of round condition

Internal supports and sound deadening foam

Pins riveted into drum surface

Inside view of pop riveted pins

Saturday, March 26, 2016

Up and running on Vivado toolchain, plus work on mirror 1442 mode


Converting design to Vivado toolchain

I worked on the learning what it takes to import the logic over from ISE to Vivado, using the simpler slave fpga code first. Once that synthesized, but of course couldn't create a bit stream since the slave board fpga type (Spartan 6) is not supported in Vivado.

I moved onto the main board, where I had a FIFO whose IP had changed since I generated the module I was using. I got Vivado to upgrade it to the Artix 7 version and resynthesize. Next up was getting the UCF entries converted to some new 'XDC' format used by Vivado.

This learning curve chewed up quite a bit of time until I figured out how to build an XDC file that was equivalent to my old UCF document. Then, the actual entry of the file was an hour of tedium. I saw that the new board had the same connectors as the old board and the same number of IO connections from the fpga, but the pin numbers on the Artix 7 chip are completely different from the pin numbers of the Spartan 6 chip.

The same connector position but it requires a change of the pin number, which means changing 100 entries in the new constraint file. Sigh - another hour of tedium. Fortunately, I am getting closer to have a successful run of the toolchain through to bitstream creation. Syntax has changed to use TCL language, so a UCF entry for a std_logic_vector named FD would be FD<0> etc  but in TCL it is {FD[0]} etc.

My block RAM used as buffers for 1403 and 1442, among others, required a new IP generation to use the native BRAM on the Artix 7 chip. Once I get those straightened out and my constraints file sorted properly, I managed to run the toolchain through to a bitstream.

Implementing mirror 1442 reader/punch

Fellow 1130 system restorers have a need for a variant of my virtual 1442 functionality - a mirror adapter that will capture card images being read and/or punched on a real 1442, so that a PC based file is captured. I began the work of altering the virtual 1442 function to provide mirror capability, switchable by the user of my SAC Interface Box.

A mirror device will follow all the XIO instructions, cycle steals and interrupts that are involved with the use of a real device, shadowing the behavior in order to grab the data that is being transferred between the reader/punch and the 1130. A mirror device needs to be fast enough to have the data written or read picked up by the PC side program and put into a file, before the next card is read or written.

In order to use the virtual 1442 capabilities, the machine needs to have additional signals wired between the 1130 and my box. The SAC cable on an 1130 does not display nor trigger interrupts on level 0, which are used by the reader/punch to transfer the data for each card column. Mirror functionality doesn't actually need to see when IL0 is active, while virtual functionality needs to both observe and trigger IL0. The 1442 does not use cycle steal.

My Python program on the PC side will get a copy of the XIO Control command used to start reading a card, start punching a card, select the alternate stacker, or feed a card without reading. The Python program then writes the card image from a PC file into the pre-read station buffer of the fgpa. With mirror function, these are assumed to always be blank cards, so that is what is pushed down by the Python code.

When the real 1442 card has data approaching the solar cells, for each card column, it triggers an interrupt on IL0 and the software on the 1130 issues an XIO Read to capture the card image into core memory. I just need to grab the data word that is being written into core for each of the 80 XIO Read instructions, overwriting the pre-read buffer with those contents. At the end of the 80th column, my function will claim to the Python program that it saw an XIO Init Write instruction, to have the PC side do some things before the mirror card reader copies the contents of the pre-read buffer to the pre-punch station buffer.

For a card punching operation, the IL0 interrupts cause the software in the 1130 to issue XIO Write commands that fire punches in the current card column of the card in the pre-punch station. The mirror adapter will OR the bits from the word written by the XIO Write into the pre-punch buffer location, since a real punch will add holes atop whatever was in the card before. At the end of the cycle, it also mocks up an XIO Init Write command to have the PC side do its thing

The PC side will see the false XIO Init Write and fetch the contents of the pre-punch buffer, which has has the N-1 card image that was read plus any new holes punched. If not punching, or simply doing a feed, the data in the pre-punch buffer is the N-1 card that was read or fed. This models the real 1442 which has multiple stations where cards sit during operation. There can be two cards sitting in the machine at any time, one ready to be read and the next, which already passed the read station via read or feed, is ready to be punched.

The PC program for the mirror 1442 will fetch the pre-punch buffer on every read/feed/punch except for the first, since the first time a new set of cards is put in the hopper, the pre-punch station was empty and nothing comes out of the hopper. The read or feed will have advanced card 1 from pre-read to pre-punch, but nothing moved from the pre-punch to the stacker. On subsequent cards, the N-1 card read will pop out into the stacker. The Non Process Run Out (NPRO) button flushes any cards inside the machine to the stacker.

I have to add a command that switches the 1442 adapter between mirror and virtual modes. The user has to pull down a signal inside the 1131 when running as a virtual device, to block the action of the real 1442 adapter circuitry, then remove that pull down if using the physical device. This should be a switch operated by the user, rather than a jumper wire.

Thursday, March 24, 2016

Various small bits of progress

I spent most of the day Wednesday at the Computer History Museum where we were struggling with the 1402 card reader/punch for the "Connecticut" machine. It was misbehaving in multiple ways and required a convocation of many of the team to figure out what was going wrong.

We had one problem in the morning that blocked the basic Non-Process Runout of the reader - which went away as I examined the wiring going into a group of cam based switches. Most likely a flaky connection but until it is failing again, nothing we can do now.

The machine was substantially out of timing - there are specific points where the clutch engages, the picker knives push a card into the machine and where the microswitches detect if a card is at various stations along the read patch. This also determines when the 1401 processor looks for holes on the card during the 12 'row' times.

No idea how it got that far out of whack, although I heard indirectly that there were some major card jams back just before this reader began misbehaving last week. I don't know if there is a way that mishandling while removing a jam could shift the timing, but we got it dialed back in. Ten minutes before the 3PM demonstration for the public, it began reading correctly. Just in time, we turned it over and the docents had a successful session demonstrating the machine.

I received my new laptop and also spent some hours updating, configuring and beginning to install the important programs and files on the machine. Like almost every laptop, it has an accursed Synoptics touchpad. I don't like and don't want to use the touchpad, I just want to use the mouse stick between G, H and B on the keyboard and the two 'mouse' buttons.

I turn off the touchpad part, work away and sometime later, I hear a sound as the damned driver turns the pad back on. It won't stay off. Discovered a 'feature' of the driver is that when touched twice in succession in the upper left corner, it turns the touchpad back on. Fortunately, a somewhat obscure setting lets me disable this behavior. Now working the way I want.

In my spare time, I converted fourteen fluorescent fixtures to use LED bulbs - a bit of rewiring inside to eliminate the ballast, otherwise pretty straightforward. A dozen regular bulbs also got the treatment. Most involved ladder work and a bit of contortion, to the chagrin of my muscles.


Switching to Vivado toolchain and preparing to use the more powerful Artix 7 fpga board

I installed the latest Xilinx toolchain, Vivado, which supports the new fpga board with the Artix chip (but will not support the Spartan 3E and Spartan 6 boards I own). I moved the SAC Interface logic for the main fpga board over to this system and began working through the compatibility issues - generated IP either out of date or missing, plus a replacement for the UCF file that previously was used).

Once this is synthesizing through to a generated bitstream, I will plan to swap the fpga boards and give this one a test. Once it works, I will have reams of space for logic functions, buffers and the ability to store major amounts of data in the 256MB of DDR3 memory onboard.

Implementing physical paper tape reader/punch (1134 and 1055 equivalents)

The dual relay board arrived which will permit me to start controlling the motors of the paper tape reader and punch mechanisms. I can't punch until I have my driver board but I can do some testing of the reader. I began wiring this up.

Tuesday, March 22, 2016

Working on high speed link and physical peripheral functionality


Debugging the resilient high speed link between fpga boards

I will go over my hamming code VHDL with a fine tooth comb, as well as the processes that do the error checking on my high speed SPI links between master and slave fpga boards. I need to find the reason for sporadic conditions that cause high error rates, usually while operating the 1130, which might be triggered by some signal from the 1130 changing which is assigned to a link bit position susceptible to some design flaw. I don't think this is the cause, but it is a precautionary check.

Another potential cause is ground bounce due to the inadequate grounding between the 1130, SAC box fpga and slave fpga. Each signal is sent over a twisted pair in the SAC cable, which isolates the signals from common mode disturbances but the cumulative effect of the signals changing may be shifting ground between the three units. This is more likely.

It was indeed the grounding - a very solid ground connection to the SAC Interface unit and nothing to the slave fpga board worked wonders - zero errors. Onward to testing at least parts of the plotter and paper tape interface.

I should be able to do diagnostics that confirm the basic process from XIO Write issuance through completion interrupt and reset. That can happen with the plotter switched off, then when the plotter logic in the slave fpga is certain to be issuing the commands to the plotter interface hardware, and similarly to the paper tape units, I can be in position to start testing with real hardware in a few days.

Implementing physical plotter (1627 equivalent)

I will set aside the work on the Strobe 100 interface that appears as a 1627 plotter, since I will be getting and restoring a Calcomp 565 which is the exact plotter that IBM sold as the IBM 1627 model 1. I was at the point of tuning the timing to suit the slower speed of the Strobe, which will not be needed

As explained above, I did continue to test just to confirm that my basic logic and interactions between master and slave worked properly. That is, I would issue an XIO Write to the plotter, see the slave receive it, see the slave fire the command signal to the plotter interface, then see the master fpga trigger the interrupt. I should see appropriate sense in the DSW, and the interrupt trigger should only go away when the reset bit is set in the XIO Sense Device command.

I loaded up diagnostics to let me see what the master was doing. The slave has LEDs displaying the commands issued to the plotter interface. With those done, I went out to the system and fired up the test. I discovered that the master set up the command and thought it had fired off the transaction to the slave, but the slave sat inert. Further, a signal on the master that should have reflected the transaction request was not active.

Changing both sides for new diagnostics increases the agonizing period of inactivity to more than 50 minutes. A quick inspiration based on test results, changes developed in just a few minutes, then 50 minutes of delay to make it happen. Fortunately, this is a pretty simple transaction.

The master raises transaction and doesn't drop it until it gets the response. The slave sees the transaction, does its thing and then raises the response. When the master sees the response, it drops the transaction. The slave goes back to wait for new transactions once it sees the previous transaction signal drop. Nicely interlocked and not timing critical.

When all was finally set, I went out to debug the transaction flow. To my chagrin, the high speed link was back to huge error rates. Back to the link - that has to be rock solid before I can move on to the peripherals.

Implementing physical paper tape reader/punch (1134 and 1055 equivalents)

The paper tape reader needs one relay activated by the slave fpga to drive the motor and multiple sensing signals which are based on simple switches. Thus, I don't need any voltage shifters or other interface, simply a relay driver circuit.

The paper tape punch has to drive a relay for the motor but also eight output signals to drive the punches. Feedback comes from simple switches, those are easy. I will build 8 transistor driver circuits to feed the punch circuitry, plus two relay drivers for the reader and punch motors. When this is ready, I can wire up the reader and punch to the slave fpga and begin debugging tests.

I selected the components that will let me build this using off the shelf boards designed for hobbyists. A twin relay board will let me drive the two motors. An 8 channel power driver board can drive up to 100ma per channel at reasonable voltages, acting as a 8 bit shift register and gated output. Level shifters allow the TTL level boards to be interfaced to the LVCMOS 3.3V fpga pins. A small box, connectors, wiring between boards and I will be ready to go. The parts will arrive in a few days.

Monday, March 21, 2016

Virtual 1403 printer function completed, moving on to a Calcomp 565 plotter restoration to create a real 1627


Implementing virtual 1403 printer

For my first test of the day, I set up latches to record bit 1 (channel 2) as it is being written into the buffer for lines 1 to 4. This should match the pattern I am sending from the Python program, 0-1-0-1 unlike the detected pattern when I looked at the output of the buffer, 0-1-1-1

One teeny flaw in the latching logic, so none of the latches worked. Thirty minutes to correct before I can retry the test. At least these tests can occur without powering up the 1130 - they are focused on actions that occur between the Python code in the PC and the logic in the fpga.

Interesting. The input to the memory for lines 1 to 4 during the write cycle when the buffer write enable is set up was 0-1-0-1, exactly what I should see. This leaves a few possibilities to explain the problems I am facing. I need to work through the cases, unfortunately in half hour or longer intervals. I say longer, because as a retired person, I have the distractability of an ADHD afflicted child. This means that while waiting for the toolchain to complete, I wander off and may not return for a while.

I saw that the buffer had the right input (bit off) at the time I was setting up to write to the memory for line 3, but when it was fetched during the carriage movement process, the bit was now on. I altered the latches to show me the bit for the cycles after it has written, also to latch if the output of the buffer is set after the writing cycle.

Line 3 is not disturbed by writing and not disturbed if I use XIO Control (space one line) commands to move past line 3. I am forced to conclude that my problem is caused only when performing carriage skip processing, although the mechanism by which this can happen is obscure. I have to think of further diagnostic tests to determine what is actually occurring.

Assumed I had a race hazard on changing of the address to the buffer memory, which I blocked by idling one cycle before changing, but the flaw is still present. This bug is so frustrating. Perhaps I am overwriting words in the buffer as part of the seven 'write special data' transactions that are needed to load the 66 word buffer, ten words at a time.

If you can't spot the race hazard, register the signal. I set the carriage tape buffer process to lock in the line number as the buffer address while the carriage movement process is in its timing loop, simulating the time delay of 1403 printer movement, well away from the cycles where it is checked against a skip command. That did the trick. I now have the virtual 1403 printer function working exactly as I wish.


My friend Bob offered a Calcomp 565 that I can try to restore. It is in pieces and the drum is dented, but there is a good chance that I could this back in operating state. IBM sold the Calcomp as the IBM 1627, for use with the 1620 and 1130 systems. If I restore this, it would replace the Strobe 100 I am currently using as a 1627 substitute.

Calcomp 565 - comes in various skin colors such as teal or black
I should consider changing the paint and labeling to be as close as possible to the IBM appearance. I will need to repaint the outer cover, paint the panels that hold the switches/knobs, and create the right decals for the labeling of panels and the front bar.

IBM 1627 - different skin and panel colors, plus changed logo

Saturday, March 19, 2016

Problem with 1403 function isolated to 'write special data' transaction from PC


Implementing virtual 1403 printer

The definitive diagnostic output was to a set of latches I set up to check the state of bit 1 of the carriage tape buffer word for various print line numbers. What I was pushing down from the Python program were the following four words for lines 1 to 4 - 0x8000 0x4000 0x2000 0x5000. These mean line 1 has only channel 1 set, line 2 has channel 2 set, line 3 has channel 3 set and line 4 has both channel 2 and channel 4 set. Bit 1 represents channel 2.

Therefore, I should have had bit 1, channel 2, set for lines 2 and 4, but not for 1 and 3. I spaced the printer through the four lines and had found bit 1 set on lines 2, 3 and 4. Not correct, as line 3 should have that channel off.

I did some more skip testing (XIO Write to skip to certain channels on the carriage control tape). I found that it behaved correctly but had a line number one higher than what should be sitting in the buffer. That is, if I was going to match a bit set in line 8 of the buffer, I would match and stop on line 9.

The proof of this was to do a skip to a channel that only existed in the last line of the buffer - such as channel 9 or 12 which I didn't set until the last line. The fpga logic had a runaway carriage - the result of looking for a channel (1 bit) when no buffer word has that bit set.

My problem is in the process that accepts the write special data transaction for the 1403 and places the data words from the transaction into the buffer. Tomorrow morning I will set the latches to watch the words being written and display the active word for given line numbers. This will freeze the transactional engine between fpga and PC, but give me the snapshots I need. At 30 minutes per tweak, it will continue to be a slow pace towards eventual success.

Friday, March 18, 2016

One nit and 1403 is complete


Implementing virtual 1403 printer

I built the test for skipping, which I can perform on the 1130 to verify that my virtual carriage control tape works properly.  I have a sequence of skips to perform, based on the default carriage control tape image for my adapter, and will check that the resulting line number is correct after each one.

My first test this morning was bad due to operator error. I forgot that my skip list for the XIO Write is offset - channel 1 is bit 4, channel 2 is bit 5, etc. I reran with the proper command and the fpga and python behavior differed. The fpga is wrong.

I was at line 1 and did a skip to channel 4, which should have stopped on line 4 since there is a channel 4 punch at every line modulo 4 (4, 8, 12, etc). It stopped on 8 in the fpga based on the displayed line number. Next, I set it to skip to channel 1 and it stopped at line 2 per the fpga.

I need to validate the contents of the tape buffer first, which I can do with my current LED assignment from the fpga board. I can see the top five bits of the buffer - channels 1 to 5. If I do XIO Control (space one line) then I will successively look at all the buffer contents and can match them to what should be present.

While I am running that test, I have the fpga synthesizing a new assignment for the LEDS, to display the top five bits of the skip command issued (XIO Write with the data word bit 4 as top bit, bit 5, the next, etc). That will let me confirm that the search word is correct for the fpga process.

Immediately, I could see that the print line number in the fpga was NOT advancing with successive XIO Control (space one line), thus I was always seeing the same buffer word. That needed to be fixed in order to complete my test validating the buffer contents.

Defect found and fixed rapidly, so a mere 30 minutes for the toolchain process before the next test. Grabbed some lunch while it synthesized. With this, I found a defect in my Python code as it loaded the buffers, corrected it and got right back to testing (not needing the glacial toolchain for the fpga).

I discovered one oddity - the displayed line number from the fpga was one higher than the actual buffer contents and one higher than the place it was stopping. I will review the fpga code to repair this. I made one operator error again - when I set the skip word to go to channel 12, I put in 0x0010 instead of 0x0001, leaving the printer on line 10 and not line 66 as I intended.

However, a retest uncovered a timing condition in my XIO handling logic, with the low bits of a word from core arriving later than the higher bits and sometimes not being latched properly.  I changed my XIO routines to give a bit more time for latching and all is good.

Skipping is working properly, so I can run a final test to produce an intended output file and verify that it produces the desired output including everything being on the proper line number.  I had made the change to the fpga to straighten out the line numbers reported, but the line number assumed by the fpga is always one past the real line number. I just can't see why this is happening.

Thursday, March 17, 2016

Down to last few tests for virtual 1403 printer

Sidenote - it may seem that after retirement, I would get more done per day than before and have plenty of idle time. That was my expectation. There are a daunting number of tasks that must be handled to convert to a retired lifestyle, however, which are demanding big chunks of time even two weeks after I stopped working.


Implementing virtual 1403 printer

I ran a test to display the first 8 bits of the virtual carriage control tape buffer at the current line. That began as line 1, which had only a punch in channel 1. It displayed correctly as x80 upon testing. Next, I set up the display to show the latched up channel seek list from an XIO Control - this should be non-zero after I issue the Skip to Channel operation (XIO Control).

The next test latched up the code I put in memory and referenced with the XIO Control - skip to channel 4 - which should have matched a number of lines in the buffer. In spite of seeing some good values in the buffer, I might not have a full and faithful copy of the carriage tape words I pushed down from the PC.

It occurred to me that my problem may be byte order differences resulting in swapping of the bytes from what I planned for in the carriage tape and what arrives to the FPGA and makes its way to the buffer memory. I had some diagnostic LEDs set to show me the high bits of the current buffer and with the print line set to 1, it displayed 0b10000 when I should have seen 0b10111 if it was correctly stored.

 Finally, I caught the problem in my process that loads the carriage control tape image into a buffer memory. I made a change and now the carriage is not running away. I have a minor problem left with synchronizing - what line the fpga thinks we stopped at versus the Python code - but I already know at least one fix.

I spotted flaws in the Python code related to the mismatch of line numbers I was seeing. Partly it is a matter of the pernicious 'off by one' problem - people think of line numbers starting at 1 but the array holding the carriage tape values is origin 0. I had to adjust the line number at the appropriate times.

It appears my skipping works right, but I need to do some careful tests that verify the line we should reach for various sequences of space and channel skips. This will take a bit of design work, to be sure I have a good test and can definitively mark the virtual 1403 as done.

Wednesday, March 16, 2016

Still battling the virtual 1403 virtual carriage control tape for skip; 1401 display panel design work


Implementing physical plotter (1627 equivalent)

I refined the process that moves the plotter to divide the time interval between a move portion and a restoration portion, thus even with a maximum rate drive of XIOs the plotter should move properly. I also tested this during my morning session.

I found an oddity that when I was doing the IO to the plotter, the high speed link went berserk, giving me a continually climbing error count. I suspect a problem in the Hamming/CRC from the slave side. It also climbs when doing certain manual operations on the 1130 such as loading core contents or setting the IAR, thus a tantalizing hint at a common cause. If it is a bit position in the data that isn't handled properly, it doesn't occur during normal 1130 operation.

The hamming calculations and the CRC logic are pointing at the same VHDL for both master and slave, so any problem is going to be a consequence of process differences in the slave or some deep flaw I hadn't found before.

Implementing virtual 1403 printer

Having corrected the flaw that kept the carriage control process from completing with an interrupt to present status, I was ready to test in the morning. Printing and spacing are working properly now, with interrupts and appropriate DSWs, but skipping to a channel produced a runaway printer in the fpga.

I set up the logic for the tape hole matching function in a different way, that I will test in one more shot today. I also updated the code for Python as that also failed to stop as intended. Now, the Python code stops but the fpga logic loops (runaway carriage for those familiar with real 1403 behavior when skipping to a channel that has no holes punched in its control tape).

I have to step through some diagnostic investigations to determine whether the tape image is correctly held in the buffer memory in the fpga and that the skip list issued by the program is properly stored in the UCW. I will work on these tomorrow.


One of the purposes of the restored 1401 systems at CHM is educational. STEM education and adult interest in understand this classic system can involve a learner stepping through instructions from the control panel. While most of the information needed to understand the behavior is displayed with lamps, one area is partially obscured.

The 1401 uses addresses which are three BCD digits each, able to address up to 16000 locations. A character in memory has (besides the parity and wordmark) six bits called B, A, 8, 4, 2 and 1. Binary coded decimal provides for up to three decimal digits, but that only addresses 1000 locations. The B and A bits on the high order address character are used to select one of four groups of 1000 locations, thus with the 'zone' bits you can address 0 to 3999. The B and A bits on the low order digit are used to select which of four blocks of 4000 characters you are addressing.

An address with three characters of B 4 2,  8, and A 4 1 would be for 6685  (low character zone bit picks block 4000 to 7999, high character zone bit selects third of four blocks of 1000 within the 4000 group, thus 4000 + 2000 and then the 8-4-2-1 bits of each character yield 685. BCD encodes non-numeric characters by combinations of bits having nonzero zone bits. Thus, you might see the address as O8U when you look at the three address characters on the printer.

The 1401 maintains three address registers, called STARs, to hold the three characters of an address. The current instruction address is in the I STAR. The 1401 instruction format provide for two fields, as it is a memory to memory design rather than changing registers as is done on most machines. These are the A and B fields, thus our other two address registers are the A STAR and the B STAR.

On the console, there is only one set of lamps displaying an address. Which STAR you see depends on the machine operation during execution or can be changed by pushing the ISTAR, ASTAR or BSTAR buttons. You need to flip between these STARs by pushing buttons.

My auxiliary display will show all three STARS simultaneously, in three formats. You will see the BA8421 bits as they exist in core (e.g B42, 8, A41), the BCD character (e.g. O8U) and the full decimal equivalent (e.g. 6685). This will make hand debugging and learning easier.

One additional wrinkle with the 1401 is that the high bits of the middle address character are used to specify whether an index register is used - the bits coding for no register, reg 1, reg 2 or reg 3. This was an optional advanced programming option, so not all 1401 systems implement it. I intend to display the IX along with the STAR contents since it is part of an address. Thus, if we wanted our 6685 address to also include the content of index register three, we would add the B and A zone bits to the middle character. Our address in BCD is now OHU when printed.

I devised a simple circuit to convert the SMS T level signal (binary 1 is +6V, binary 0 is -6V) into CMOS levels (binary 1 is 3.3V, binary 0 is 0V). This uses a diode, four resistors and a transistor for each bit. I am tracking six bits per character, or a total of 18 bits. I intend to use an MBED, Arduino or similar microcontroller to interpret the signals and control the display.

I know where most of the signals occur in the 1401 - in frame 1, gate A7, cards C01 to C21 for all but the index register bits. I need to work on the physical aspects - cable connectors, PCB for the 18 circuits, connection to the microcontroller, power supply and mounting inside or atop the 1401. 

Sunday, March 13, 2016

Virtual 1403 printer is printing lines, skipping and spacing, but not fully correct yet


Implementing physical plotter (1627 equivalent)

I created some hand code to enter which will move the plotter pen over a detectable distance. This will be toggled into core for my testing session this morning. It was only 26 words, not very onerous. Getting them to work properly for someone who is quite rusty in whipping up 1130 machine language added a bit of time.

My attempt at testing this was not successful. I suspect that the 1130 is too quick for the plotter, taking the interrupt and firing off all the successive commands before the plotter can reset. Not certain, however, and this will require a full set of diagnostic signals before I can get to the bottom of it. My priority is to wrap up the 1403 first, since it is nearing the finish line.

Implementing virtual 1403 printer

Reviewed my logic and cleaned up a few small points prior to testing this morning. It was not successful, but I suspected it was due to contamination from the 1627 testing I had been doing. When I straightened out the testing procedure, I discovered a flaw in my character translation (from 1403 printer code, packed two columns per word, to two characters of ASCII).

With that fixed, I went back out to work on the 1403 debugging. I have two minor errors in my spec, vis a vis the functional characteristics, which I also corrected. The next test printed my line properly. I tried the XIO Write with a skip to a channel, which did add multiple lines to the output file. The XIO Control may have also worked. However, both spacing and skipping did not trigger the interrupt or present DSW status, thus I may not be processing the carriage movement in the fpga.

I added some diagnostic signals while I looked over the fpga logic, but didn't do too much because I spotted the flaw that was blocking the carriage movement process and its completion interrupt. I did display the current print line, allowing me to see what occurs in the fpga as it moves the carriage. I added diagnostic writes in the Python program to give me the line number as the PC sees it.

When I began my last test of the day, prior to an evening out with friends, I ran into some flaw that stalled the transactional engine, causing timeouts before I could issue any 1403 XIO commands. I will need a whole new set of instrumentation to debug this, unless I spot it quickly in the VHDL code, and that would cost another 45 minute+ cycle time to run the toolchain.

Possible 1403 printer enhancement

One aspect of the 1403 printer which I did not model was parity checks - the printer code uses 6 bits for the character plus a parity bit to make the total number of 1 bits odd. I look up ASCII equivalents by the full 7 bits, the character value plus the correct parity error. Any parity error or unrecognized code outside of the 48 characters plus space that are rotating on the print train, result in a space.

I could implement a parity check as I fetch and translate characters from core, detecting the error in the Python program and signalling the fpga to present a parity check error rather than a successful print result. This would catch errors in programs writing to the 1403, behaving the same as a real 1403 printer, and might be important for running the 1403 printer diagnostics.

High Speed Link Errors

I see errors on the high speed link between the fpga boards when I use the manual controls on the 1130, in addition to power-on and power-off events. I should chase these down to ensure they won't occur in normal operation.

Plotter partially working, virtual 1403 printer progress


Debugging the resilient high speed link between fpga boards

The only errors I am seeing on the link are when I power the 1130 itself up and down - I suspect that the current temporary and thin gauge wire between the SAC box, slave fpga and other boxes needs to be made more robust. The numbers never climb very high - a handful of errors - and the resulting degradation of data flow is negligible.

Implementing physical plotter (1627 equivalent)

My diagnostics showed me that I had some signals inverted in my logic - the hardware interface to the plotter works with inverted command signals, so that the idle state is 1 and we drop the signal to 0 to command an action. I could see my deliberately slowed transaction started with all six commands at 0, flipped only the desired one up to 1 and then dropped it after a second.

Polarity is correct, the plotter clanked when I issued the command, and the interrupt and DSW actions were correct afterwords. Next pass, I will try to move the carriage left or right and the pen up or down. It is hard to see a carriage or drum movement because the pitch is so small, but I can clearly see the pen move up and down.

The up and down signals for the pen are reversed, so that a pen up command drops it onto the paper and vice versa. A quick change to the slave fpga logic and that was corrected. I need to build more extensive hand code to loop and drive the plotter a fair distance.

Implementing virtual 1403 printer

I did my first test of printing a line and bumped into a bug in the Python code, which I fixed up quickly. Second test after lunch tried this again and now discovered that I am reflecting the XIO Sense DSW up to the python program, when I should not. I did see that my XIO Init Write, to print a line, completed, issued an interrupt and provided the proper DSW bits (Xfer Complete and Print Complete) on the sense, then reset properly.

The Sense command should not be stored in the 'last XIO function' field and thus never seen by the Python code. That flaw is in the main fpga logic, which I corrected and synthesized, ready for the next test shot.

My goal was to print three lines, spacing between the first and skipping to channel 8 after the second. Wrapping up with a final space, I would then examine the output, The XIO IW gave the proper interrupt, but nothing was written to the output file. The XIO Control did not trigger the interrupt or add a space. I need to set up some diagnostics to get to the bottom of this. Overall, I am making steady progress debugging the virtual 1403 (and physical 1627) functionality.

Friday, March 11, 2016

Progress on virtual 1403 - testing spacing and skipping - plus work on 1627 plotter


Implementing physical plotter (1627 equivalent)

The fpga was inert - not reacting to the XIO for the plotter device. A few changed diagnostics were configured so that I could chase this down further. I see that I now trigger the 1627 main process in the fpga, but don't get a response from the slave fpga at completion of the action. I changed out the diagnostic LEDs again with this in mind.

I saw the slave fpga run through the states when I did an XIO Write to the plotter requesting to pick the pen up off the paper. It completed, notified the master and fired off an interrupt on IL3. The sense device returned the status of 0x8000 which is what should happen. I didn't see the plotter device doing its thing, which could be a function of the time during which I assert the command signal.

To test out this theory, I will lengthen the time delays for all 1627 operations to make them palpably long. At the same time, I exposed some signals on both slave and master fpgas that will help me watch how it is operating.

Implementing virtual 1403 printer

I could see that the write special data transaction hung, with the process that does the writing looping steadily. It also appeared by carriage tape buffer process was not working properly. My suspicion lies with the writing process - needs interlocking to avoid spinning forever.

It turned out to be a simple mistake. The write special data process for the 1442 reader/punch was my template, which I copied and renamed to handle the 1403. For simplicity, imagine all the names for the 1442 had started with A and I changed all the code to start with B for the 1403 . . . except for the critical test that breaks out of the loop when the counter reaches the 10th data word in the transaction.

I was still checking the A counter, not the B counter, thus it never was incremented and I looped forever. Quick change and I verified that I now complete the 7 transactions the write the 66 lines of the virtual carriage control tape into the buffer in the fpga. After I debug the 1627 plotter support, my next tests will resume looking at the virtual 1403, to see if I am properly handling line spacing, carriage control tape skipping and writing lines of output.

I tested XIO Control, which spaces (adds a blank line), finding a bug in the Python code. I fixed it up and tested again after my 1627 diagnostic changes were synthesized. Each XIO Control added another blank line to the output file. To do more, I need to add the interrupt handler code - when an XIO is issued, there will be one or more interrupts, which need an XIO Sense Device to reset the condition and then a BOSC to leave the interrupt level. Some hand code is needed - after the 1627 is done.

Thursday, March 10, 2016

Now testing virtual 1403 printer, real 1627-substitute plotter


Implementing physical plotter (1627 equivalent)

I fired up the 1130 with the plotter connected through my slave fpga board to do some testing of XIO commands to see how it worked. I found that interrupt level 4 requests are hot from my fpga, which is probably an issue in the 1403 function as it uses that level. I need to debug that first before I begin writing to the plotter.

The problem with the hot interrupt was a mistake in assigning signals to the high speed link. The Not Ready status for the paper tape reader was connected so that it appeared to be the end operation signal which triggers an interrupt on IL4. Correcting the assignments should get rid of the undesired interrupt.

It worked and I then tried some plotter commands (XIO Write with the proper data words), but it wasn't responding. I executed XIO Sense Device and saw that my slave fpga was reporting Not Ready. I hadn't wired up the proper wire to mark it ready, but instead connected the 1627, 1134 and 1055 ready status to three of the slide switches on the slave fpga board. Now I can test as I wish.

Something is blocking response to the XIO for the plotter - I issue the XIO Write and should see a movement plus an interrupt on level 3, but even though the Not Ready bit is off, the adapter behaves as if it were still on.

Implementing physical paper tape reader/punch (1134 and 1055 equivalents)

I saw an improvement in how I would handle interrupts for the paper tape devices and began implementing it in the fpga. This treatment is consistent with the other device drives. I won't be testing the paper tape until I finish with the physical plotter and virtual 1403 types, but the changes are in place.

Implementing virtual 1403 printer

I cleaned up and tested the Python code that will load a virtual carriage control tape image from a PC file, as it is opening a print output file. If the user cancels the file open, a default tape is loaded. This tape has channel 1 in the first of 66 lines, channel 9 punched in line 65, channel 12 punched in line 66, and then a pattern for the other channels based on their numbers.I put channel 2 on every other line, channel 3 on every 3rd line, etc so that there is some degree of skipping even with the default tape. .

My testing would have been easier if the IBM diagnostic decks for the 1403 printer had been in the drawers that came with my 1130. There was a third party printer that pretended to be a 1403, but I am not sure whether the diagnostics for that depend on any behaviors that were different from an IBM 1403.

Without the 1130 or the SAC box, I can still test out the logic for opening the output file on the PC and trying to open the carriage tape image file. That all worked well but when the Python program began to write the default tape image to the buffer, my write special data transaction timed out. More debugging on my plate, along with the hot IL4 from above.

I found the problem with the write special data transaction, which was miscoded in the Python program. I fixed up this as well and went back to testing - after the 45 minutes needed to synthesize both fpga boards.

When I turn on the virtual 1403, I get an error in the first tranaction which turns off the Not Ready status to signal that programs can do IO to the printer. Something is going wrong with that or the following transaction, the one that loads the virtual carriage control tape buffer. Time to put in more diagnostics as this problem did not clear up after my first changes.

Well, I found the problem and it is something I tripped over earlier this year as well. The fpga logic looks for the transactions for the 1403 printer by matching the UCW number in the transaction. The 1403 printer is set up in the first UCW position, so its number is 00001 but the area code - the address used with the XIO program to speak to the printer - is 10101. I coded the latter value. Since I only have 20 UCWs in the current implementation, there will never be a value 21 (10101 in binary).

Thus, my logic didn't kick off and process the incoming carriage tape buffer contents and stalled the main transactional loop. I corrected the logic, surfed the internet for the half hour required to update the fpga, and then tested again. Not right, but it zoomed me in on the logic that is malfunctioning.

By the end of the day, I still hadn't found and fixed my problems, although the logic is cleaner and more solid as a result of the work so far. 

Wednesday, March 9, 2016

High speed fpga to fpga link complete, virtual 1403 printer implementation 99% done


Debugging the resilient high speed link between fpga boards

After adjusting the timeout logic quite a few times, I came to the conclusion that the link was most reliable with no timeout at all. That is, the slave automatically resets when the master drops the select line and the master will resync automatically to a dropped slave. A dropped slave may trigger an unrecoverable SECDED error, but then recover immediately; in most cases, it recovers without an error.

The highest I could get my error count, with repeated power cycling of both master and slave, was to 2 retries. The link is rock solid without timeouts and I can confidently move on to hooking many physical peripherals by using high speed links and slave FPGA boards. I will begin testing the 1627 plotter functionality over the link tomorrow.

Implementing virtual 1403 printer

I worked through the logic necessary for handling the shadowing of the virtual carriage control tape between the PC program and the fpga logic. I have one very minor tweak to make in the fpga and then some coding for the Python program.

The fpga is directly interrogating the virtual carriage control tape buffer memory when the program issues an XIO Write (skip to one/more channels on the tape). Thus, my fpga takes the correct amount of time at a rate of 16ms per line skipped then interrupts the processor with the movement completion status.

Meanwhile, the Python program sees that XIO Write command and can independently look through its copy of the virtual carriage control tape, figuring out the new line number. It will insert blank lines in the output file for every line skipped.  An XIO Control is a space command, writing out an end of line character.

Meanwhile, when the line itself is printed by the program issuing XIO Init Write, the Python program sees the command, fetches the data words from core memory using cycle steal transactions, then issues a 'get special data' transaction to tell the fpga to interrupt the processor with a transfer complete status. The fpga will continue for 200ms before interrupting again with the print complete status.

I have almost everything constructed on both sides and can move on to the debugging of it all. The remaining part is the logic to open a virtual carriage control tape file on the PC, which will load the tape buffer by 'write special data' transactions so that both fpga logic and Python have the same tape loaded. I will also set up a default tape with channel 1 at the first line, channel 9 and 12 at the 66th line, and the other channels punched at various places.

 If a channel has no hole punched in any line, then the real 1403 printer would 'run away', spewing paper continuously out of the printer as it looked in vain for a punched hole to stop the motion. Putting a hole somewhere for every channel protects against that error case.

Sunday, March 6, 2016

Fine tuning the resilient high speed fpga 2 fpga link, plus implementing virtual 1403 printer function


Debugging the resilient high speed link between fpga boards

There were a couple of minor issues with the way that the link started and restarted, having to synchronize among six FSMs split between two boards, but eventually I got it starting and recovering well. I had a counter displayed on the LEDs of the slave board to show me how many recoveries had taken place since power-up.

The link is up and running. randomly dropping either side is handled well, with immediate resync. So far I have only seen one unrecoverable hamming crc error on the slave side, which is harmless at a very low rate.

I began experimenting with timeout values - when too short, the slave would flicker an LED to show restarts forced by the master when it waited too long for the return transaction. It is slow going with a 30 minute change-synthesize-test cycle time, but if I simply put in a very long timeout then it will increase the potential delay on signal changes being sent between the boards. Some very fast peripherals might be impacted by excessive delays. Also, it is more elegant to get a close to optimum value which wastes little more than the bare minimum.

Implementing virtual 1403 printer

The first steps in implementing the virtual printer functionality were to put in the print line and carriage control tape buffer memories, with their associated logic to fetch and store respectively.

Next I set up all the FSMs to handle the simulation of printing and carriage movement. At this point I think I have all the fpga side logic complete, but I may need to add something to the carriage control tape logic once I finalize the Python side and begin testing.

many improvements and more design work on peripherals

Almost no time on Wednesday but got to do a bit more on Thursday. Fortunately I am retiring so I won't have the day job to get in the way. The only short term distraction is the need to take care of a million details, but I should be back testing by Monday.


My friend Marc is offering to mill replacement wheels for the 1442. I had cracked the ceramic rim of one wheel in the punch unit, which rendered the punch inoperative and probably the entire 1442 unusable. I am working on a repair using UV hardening material, but if that doesn't work, having a fallback is good.


Resilient High Speed Link between master and slave FPGA boards

Testing of the high speed link can be done with only the SAC box and slave FPGA active. I don't need to power up the 1130 at all. Once I get this link working to my satisfaction, I can move on to the devices connected via the first slave fpga board. I would add one or two additional slave boards when I have devices to control that each have many signals to connect.

I tested at lunchtime Thursday and see that my restart signal on the master side is steadily on. I will look to see what might be causing this, zero in with different diagnostic signals and get back to testing. My first change didn't alter things, so I have disabled the timeout, meaning that only a hamming/CRC error will trigger the restart condition.

Final tweak on the virtual 1442 functionality

I had encountered situations where a timing vulnerability allowed the FPGA side to send the XIO Control to the Python program requestng it start reading or punching, even though we had emptied the file and it was going to be closed. To protect against this, I explicitly check for the empty string that will be returned from the file read and if I see it, I warn the user and exit.

This is a benign warning, in that the DSW will soon show that the card reader is not ready. I think this only happens on programs that insist on issuing additional reads after they received a Last Card interrupt. This modification gives the program a graceful behavior whenever this race hazard allows a read to slip through.

The behavior that triggered this vulnerability has to do with the special 'last card' mode of the 1442. If the reader is Not Ready because the last card has been fed in from the hopper, the user can push Start to trigger Last Card. The machine becomes ready and lets the user issue a read. That leaves the last card in the pre-punch buffer, where it can be removed by NPRO. However, the diagnostic program documentation mentions issuing a feed to clear the last card after it has been read, which was what had triggered the flaw before.

Design work on mirror 1442 variant functionality

I intend to have the SAC Interface Box offer two styles of 1442 support - virtual and mirror. Mirror is used with a physical 1442 that is actually handling cards, allowing the mirror adapter to capture an image of the cards in a PC file as they are read and/or punched. Mirror adapters work by shadowing the real adapter logic in the 1131, snagging the data from various XIOs and cycle steals.

The key differences are that no control operations are performed - no interrupt requests, no data gated into memory for XIO Read, XIO Sense ILSW or XIO Sense DSW functions. There is no reason to load the pre-read buffer with data, it should be spaces (all zero contents). Read versus write logic is reversed for reading cards. At the XIO Read, after I snag the word transmitted by the 1442 adapter, I need to write that into the pre-read buffer.

I won't capture NPRO automatically, the operator must push my NPRO button once it is done for the physical 1442. My main feed cycle loop won't be driven by timers, it will wait for the real 1442 to do its thing. I will have a race hazard in that the Python program must check for the dummy XIO IW and fetch the data from pre-punch before the next physical feed action occurs on the real 1442, otherwise the data will be overwritten.

I am struggling to figure out how to autodetect which mode the system desires.Since the power-up of the 1442 leaves it not-read and requiring an NPRO to flush out any cards that may have been inside, I know that the Not Ready but (bit 15) of the DSW will be on, but the only way to view that is for something to issue an XIO Sense Device for the card reader, something I can't control

However, I can hijack unused bits in the XIO Control modifier word, such that if an XIO Control with that value is issued, it puts the machine into mirror mode. To compete this, I can create a boot card for the 1442 that issues the special XIO Control. Thus, when powered up, the SAC Interface box is expecting to act as the 1442 adapter, but if it sees my special instruction it reconfigures itself for the remainder of the power-on time to work as a mirror device.

My big challenge is that I don't have a fully functioning 1442 to test out the mirror mode. I have the adapter logic, permitting me to test what happens with my special boot card and the unused control bit. I can't feed, read or punch cards until the physical 1442 is restored.

Implementing virtual 1403 printer

I structured my plan for handling the virtual 1403 printer - using buffer memories much like I did with the 1442. The 1403 has two independent mechanisms - printing and carriage movement - which are modeled with fidelity to the timing of the physical printer on an 1130.

The user initiates an XIO Init Write to print, causing the 1403 to fetch up to 60 words from core containing two print columns per word of contents. When the fetch is done, the printer issues an interrupt on IL4 indicating transfer complete. It then prints those characters on the line some milliseconds later and issues another interrupt indicating print complete.

The carriage is either spaced on line or commanded to skip until a match is found on the carriage control tape, a tape which moves line by line in synchronization with the carriage (paper). To space, the user issues XIO Control. To skip, the user issues XIO Write but instead of the address part of that IOCC pointing to a word in core, it has bits 4 to 15 set to indicate a match on channels 1 to 12 respectively of the carriage control tape.

The printer moves the paper until the selected channel has a hole in the carriage control tape, when it stops. If the printer is handling an XIO IW and has not finished printing, the skip or space is held and performed once the print complete is issued for the printing operation.

My Python program will keep the printer Not Ready until an output file is opened. When the XIO IW is issued, it is reflected to the Python program which will fetch the print data. It pulls the first word from the WCA address, which is a count of words to be printed, and then fetches that many words from core to create the output line The program triggers the transer complete interrupt to the fpga, which then handles the remainder of the 'print operation'.

Once the fpga is triggered to issue transfer complete, it waits for 200ms before triggering the print complete interrupt. This corresponds to 300 LPM which is a fair but possibly a bit high rate for the faster version to actually run (nominal rate is 600LPM but all depends on character sequence for how many times the chain has to rotate). I will treat a single space as essentially zero time because its delay is built into the timing for the line print.

The XIO Control (space a line) and XIO Write (skip a line) commands are reflected to the Python program. The Python program will have a mirror of the carriage control tape that is also held in the fpga, so that the Python program can advance the output file by the appropriate number of lines independent of the action in the fpga.

In the fpga, no delay is modeled for XIO Control but for XIO Write, timing is simulated to match how long the carriage would move at its rate of 16ms per line while skipping. Once the delay (if any) is over, the fpga issues a carriage complete interrupt on IL4. The carriage is marked busy in the DSW from when the XIO Control or XIO Write is issued until the completion of the delay but also until the Python program has picked up that XIO reflection, to prevent losing any of those carriage operations.

The fpga has to maintain a carriage control tape image, pushed down by the Python program when it makes the printer 'ready'. This has 12 bits (one per channel) and a depth of 66 lines (to match an 11" form length. The DSW always reflects whether there is are 1s in channels 9 and 12, for the current line position of the carriage. A skip to channel 1 resets the line position to 1 otherwise it advances modulo 66.

Simulating a carriage skip involves waiting 16 ms per line and advancing the line position, while a space is just one such delay and advance. If the bit from the XIO Write matches a 1 in the tape buffer at the current position, we end the skip.

I will reuse logic from the push special data functions for the 1442, which pushes in groups of 10 words. This will load my 66 word memory for the carriage control tape. Since I don't foresee any design challenges, implementation is just a straight slog through VHDL and Python and then lots of debugging.

Improvement to mirror 1132 printer function

The 1132 can leverage ideas from the 1403 and 1442 logic I created to do a better job than the current implementation. Carriage control is very similar to the 1403. Printing is quite a bit different however.

The 1132 prints by starting an operation with an XIO Control command. This causes the physical printer to begin issuing interrupts on IL1. The printer has rotating print wheels, 48 characters are placed around the wheel, with a circuit that knows what character is rotating into position next. As a character comes into position, the printer issues the interrupt and waits for the program to issue an XIO Read.

The output of the XIO Read is the bit pattern of the print character that the wheels can print right now. It is up to the program to scan through the print line they want to print and determine the column numbers for every occurrence of this one print character that is ready on the print wheels.

The program sets up words beginning in a special fixed location (0x0020) in core, with a bit for each print column. Since the printer has 120 columns and we have 16 bits in a word, we need eight words, with the last word only partially used. The final bit (15) of the last word is set to 1 by the program and tested by the printer hardware. If that bit is not 1, then the printer flags a print error.

This is an interlock to ensure that the software has finished looking up all the characters in a print line and setting the bits in the words in 0x0020-0x0027 - the program sets that bit to 0 as soon as it gets the IL1 interrupt for a new character on the print wheels, then flips it on after it has completed all 120 columns. If the program doesn't get done with its work, the bit will be off and the printer detects this 'overrun' problem.

The printer uses cycle steal to fetch the eight words from location 0x0020 to 0x0027 for each position on the print wheel - about once per 11.2 ms - having first issued the IL1 to let the program reach the upcoming character value and set up the bits in core.

Our mirror drive simply watches the XIO and cycle steal operations take place, capturing the data that flows to or from core during each. Thus, the mirror adapter will have seen the upcoming print character which it captured during an XIO Read. It will see the contents of locations 0x0020 to 0x0027 by watching the cycle steal fetches as they were issued.

I can easily loop through the print buffer memory and store the latched character value for any column where the fetched word bits were 1. This builds up the characters in the print line just as they are formed on paper as a series of hammer firings for as the wheels rotate through the characters.

When I see the XIO Control wherein the program tells the 1132 to stop sending us the IL1 interrupts - thus a stop print - the reflection of that to the Python program causes it to fetch the print buffer which will have two locations per word so a total of 6 groups of 10 words each delivers the entire print line to the program. The Python code translates from 1132 code to ASCII and writes it to the output file.

Stop printer (XIO Control) is issued after printing, spacing and skipping are done,. This is reflected to the Python program. I can see that the space or skip has completed by a bit in the sensed DSW whose value I latch. I also will see if the printer didn't see the last bit as 1, causing a print scan check, so that I can behave appropriately.

It will be essential that the Python program have a mirror image of the physical carriage control tape installed on the physical 1132, since we are going to determine how many blank lines to insert in the output file by following the physical print line number with a virtual print line number in our program. We start at 1, reset to one when skipping to channel 1, and otherwise we increment this based on space operations or the lines skipped over our mirror carriage tape. I will use the fetch special data transaction to grab the print buffer, otherwise I just watch the XIO reflections to follow along.

This requires quite a bit of rip and replace, no design challenges but more slogging though VHDL and Python just to build it. I will spend time on these coding projects over the coming days.

Tuesday, March 1, 2016

Virtual 1442 booting now working and able to boot up and run diagnostics. Working on high speed link and slave peripherals


Debugging the virtual 1442 functionality

I chose a lunchtime test where I would single-step the diagnostic code and see what is returned by my adapter. Checking that against the diagnostic listing, I should be able to see where my adapter behavior diverges from what is expected.

I walked through card 7 of the one card diagnostic deck, which runs with interrupts disabled and tests the ability to boot and read from the 1442. I found that my python code gets in trouble if booting a 1 card deck since I don't gracefully handle the resulting empty file. I also see what is going wrong - my busy and busy/not ready bits (14 and 15) should be set in the DSW but are not.

I looked into the fpga logic to see where the bad DSW contents are occurring, then looked at the Python code to fix the vulnerability. Perhaps I have a problem with the setup and hold of the DSW bits, similar to what I had a week or two ago. In that case, as well, the lowest bits were not getting into memory.

I did fix up the Python program but it wasn't clear what was wrong with the DSW. I tightened up logic around the busy condition and used the LEDs for various diagnostic conditions that should be lit when I am stepping through the one card diagnostic #7.

I had time for one last test before going to bed. Good news indeed. My changes fixed the DSW issue. I booted up a card deck that had a boot card, the diagnostic monitor and the 1442 functional test program.

I hit the Boot button on my GUI, it loaded core with the boot card, I reset and pushed start and lights flashed and flashed. I saw my input deck finish and close automatically, then the typewriter began writing away with the diagnostic messages!

I ran again with the output file opened and saw all the cards copied through as they were read. I had one small flaw in my Python when a program tries to read past the end of the input file - a race hazard I suspect. Something that is not a major issue -I can fix it tomorrow.

Resilient high speed SPI link with restart

A design requirement for the high speed link is that I detect errors or lack of sync between the two sides and reliably restart the link. There needed to be a way to interlock the sides, ensuring they restart in the right sequence.

Two elements help in this quest. The master spi module has a reset input, which will force it to the initial state once reset is lifted. The master, when reset, is not selecting the slave. The slave module, when it is not selected, returns to the initial state.

I have four ways to detect a problem on the link. The input process on each side has a timer set which ensures I know that something has stalled. The CRC and hamming capability of each side can detect an uncorrected parity error.Single bit errors are corrected automatically and do not cause an error because of the SECDED (single error correcting, double error detecting) scheme built into the link.

My design challenge is to take the four cases of which mechanism detects the problem first and decide what I need to do in each case so the the two spi modules, the two input and the two output processes reset and release in the proper order.

Because of the timeout test in the master, the slave can signal problems by freezing itself (blocking the slave select line), which the master will see and react to. Thus, whether it is an uncorrectable error or a timeout of the input, the slave forces itself to reset and wait for the slave select to go active upon restart. The slave will react to the dropping of the slave select line by resetting the module, input and output processes.

The master will reset its module, input and output processes, which drop the slave select to sync the other side, then wait long enough before restarting so that the slave will be ready. The master can react as soon as it detects an error and that will cause the slave to promptly go into reset. The case of a slave detected error requires that the time for a master detected timeout must elapse, to be sure that the slave has stopped talking to the master.

A key design question is the length of the timeout test. Too long and it will introduce unacceptable delays in the high speed link that could jeopardize the behavior of higher speed physical peripherals attached to slave boards (e.g. disk drives). It should be enough longer than a real transaction to ensure we reliably catch a stall, but not much more than that.

SPI protocols add very few clock cycles surrounding an interchange, so the minimum timeout is just a bit longer than the packet size of 128 bits. The SPI clock is running slower than the FPGA clock by a ratio of 4 to 1, thus we need somewhere above 512 clocks to detect a timeout. I selected 556 clocks which is 11.6 microseconds when running on the current ztex board as master (the master generates the clock).

I will accumulate a restart count in the slave and display it on the seven segment displays since my first slave board is a Nexys2 that can display four hex digits visually. That will give me a way to quickly view the quality of the link over time as I test.

My changes for the error recovery were made to both slave and master fpga boards and that would be an easy thing to test when I got out at noon. Unfortunately, work was too heavy and I did not get out for testing until the evening. The LED segments are locked on 0000 but I don't have direct evidence that the link is operational. Some diagnostic LEDs on the slave board will reflect the 1130 state and therefore should change if the link is running.

When I got out for the last test tonight, the diagnostics showed me that something is not working properly on my modified high speed link. The data pump is not delivering any live data to the slave. It will only change the signals if a transaction completes and the hamming and CRC checks are passed. I could be timing out too early or it could be some other design flaw.

Implementing physical plotter (1627 equivalent)

The slave FPGA changes to support the 1627 were completed including the new Not Ready signal that will tell the master whether the plotter interface box is plugged into the slave board or not. The plotter is set to execute 3,000 moves per minute (50 per second) which I hope the Strobe 100 is capable of handling. A real 1627 runs four times faster.

Implementing physical paper tape reader/punch (1134 and 1055 equivalents)

I am still working on the slave side logic in light of my division of labor between master and slave. The new design with the interlocked transactions means that if the link drops while a punched character was sent, the paper tape punch will only punch a single instance and wait. If I had put the drive signal on the master side, it could have kept the reader or punch moving for as long as the link was down.

I need to study the schematics of the reader and punch in order to design any necessary interface hardware - certainly the solenoid drivers to advance the devices needs this, and probably the punch output signals, but perhaps the contacts for sensing the input needs something.

The design of the paper tape reader does not connect the eight channel contacts to the common bus while the reader is at rest. Instead, the contacts are enabled partway through the read cycle. To support this, my logic has to monitor and latch up the contacts sometime during the movement.

The user starts a read by issuing an XIO Control which clutches in the motor solenoid on the reader. My process to drive this (in the slave) holds the clutch engaged for 68 ms. I can probably trim this down to make sure I don't accidentally take a second cycle. The 68ms is the delay before the response goes back to the master fpga and becomes an operation complete interrupt.

As I start driving the motor of the reader, I reset the register holding the eight channels of data. Then, during the entire movement time, I continually OR the eight channels with the value in the register. Thus, any hole will at some point during the movement turn into a 1 in that channel of the register. Any channel without a hole will stay at 0. This register is the value that is sent back to the master fpga.

An XIO Read from the user just fetches the current value of the register that was copied over. The user issues XIO Control and XIO Read in alternation to move, latch up the register and then store the register contents into core.