KEYPUNCH INTERFACE UNIT DEVELOPMENT
I began coding the Keypunch Interface code, although hampered because I didn't have the documentation of the pins I wired to the various signals. It did give me a chance to work out a draft protocol for users of the interface. Design objectives included the use of straightforward ASCII messages that would allow people using terminal programs to operate and test the interface.
With the lack of frames or other demarcations in a serial stream, the protocol had to allow unambiguous recognition of each message or command. Further, we didn't want to use any characters or codes that weren't sure to be available with any terminal program or connection. Marking the start and/or end of a message using only commonly available characters means that we can have that delimiter character also appear as valid data within a message. Thus, we needed a means to 'escape' the delimiter, blocking its special role to frame messages.
I was guided by the conversion table already in use at Computer History Museum to punch hollerith coded BCD characters. Since the 1401 encoding uses fewer characters than seven bit ASCII, only a subset of ASCII characters are in the table. I had the unused characters to choose among.
I somewhat arbitrarily selected the underscore ( _ ) to be the indicator of the start of a message. It would also be the escape character to use when the underscore is valid data - pairs of _ in a row are interpreted as a single data value of _ while an unmatched underscore is the start of a message.
Messages begin with _ and have a 'verb' immediately after the underscore. The message ends with the next unpaired underscore. The interface will detect error conditions such as a card punch message which has more than 80 columns of card data before the next message is recognized.
Some of the verbs are session or control functions, while others are used to punch each card or read another card. _P is followed by up to 80 columns of data and a newline to release the card. _R has no required additional content and will return the content of the next card to move through the 'dup' station of the keypunch.
The format of the data being punched or written is determined by a session state, the mode, which is changed by the verb _MODE and one of the choices ASCII, BINARY or USERTABLE. We have defined a standard or default correspondence between ASCII and Hollerith code. The binary mode we defined sends sets of four ASCII characters representing hexadecimal values, where three of the hex characters cover the twelve rows in which we can place a punch while the first or high order hex value supports release and other control characters. The user table is defined to encode a set of the twelve holes for each of the 128 valid ASCII characters.
_LOAD followed by 512 characters which are valid hex values will load the user table. Each group of four hex characters is used to determine the holes to punch or keypunch functions to actuate for a specific ASCII character. The first group of four encodes character 000 and the last group encodes character 128 (decimal).
When punching cards in the binary mode, if the characters sent are not 0-9 or a-f, a valid hexadecimal digit, an error is detected. Similarly, during the loading of the user table, any character that is not a valid hex digit will trigger an error. Finally, our default ASCII encoding will flag an error for any character that does not have a translation to a set of holes - the first of the four hex digits in the table has a value that indicates the character is an invalid character to punch.
If a newline ASCII character is in the stream of characters being punched, or the user table entry or four hex digits in binary mode specific a release, the release key of the keypunch is activated to feed the next card in position to punch a new card. It is a way of speeding up punching of cards once all the remaining columns of the card will contain blanks.
The verb _VERIFY has either ON or OFF as a valid operand. It determines whether the keypunch interface will save each punched card image and verify it when that card moves through the 'dup' station as the following card is being punched.
The interface will automatically detect when more than three holes are to be punched in one column, using the multipunch key function of the keypunch to ensure that no more than three rows are punched at any time, continuing until all the intended holes have been perforated.
The verb _CLEAR with no required additional text will activate the clear switch on the keypunch to eject all the cards in the various stations. Typically this would be done to end a punch job.
The _R read verb will space the card in the punch station which causes the preceding card to move through the 'dup' station and be sensed in the same columns. As a necessity, any deck of cards to be read must have an extra card at the end which is not read but will be used to drive reading the final data card.
The verb_R to read a card must space 80 times to pass all the columns through the sense station, Thus, when verifying with _VERIFY ON, we must be able to sense up to the last non-blank column of the card in the 'dup' station, even if the card simultaneously being punched has fewer columns and issued a release. We punch characters or spaces up to the larger of the nonblank length of the prior card or the content of the current card, to ensure that both punching and reading for verification act on all required columns.
The serial stream is 9600 baud, 8 bit, no parity, one stop bit, wired in DCE mode, full duplex and uses XON/XOFF for flow control. Note that this excludes the use of the ASCII characters XON and XOFF in any user table. Attempting to load those two positions of the table with any value except a special 'ignore' code will trigger an error.
The interface will respond with ASCII text messages to every command - both errors and a clear confirmation of the verb it received and the action undertaken. For the _R read verb, the content of the card is returned in ASCII, eighty columns terminated with a new line, when the mode is ASCII. For the user table or binary modes, 320 hex digits are returned as groups of four separated by a space, ending with an new line.
IO DEVICE INTERFACE TO 1130 USING SAC
As I continued to build out the logic design for the multiplexing interface to the storage access channel, I found myself with two directions I can take for handling interrupt requests from my attached devices. I can enforce prioritization or I can push some of the control over priority to the software for the various devices and interrupt subroutines.
I can gate the requests and the recognition of XIO Sense ILSW commands to ensure that the higher priority device on my multiplexer triggers interrupts and is serviced first by software. If more than one device on a level has conditions that request an interrupt, I would effectively poll those devices in priority sequence, selecting the top device which had a request.
Only that device's signals would be gated to the SAC. It would cause the interrupt, only that device would return a bit in the ILSW and only that device would know that the interrupt level was active. When that device's request for interrupt service dropped (the conditions were reset by an XIO Sense Device reset bit), I would poll again and pick the next highest device seeking interrupt service.
That has the downside that the interrupt handler would only see the one device at a time, not bits from all interrupting devices on the same level. The handler would be iteratively entered as each device cleared its request and we switched to another needy device. It is possible that an interrupt routine could be written that would do something special when a combination of devices were ready, different from when they sequentially request interrupts; theoretically although I don't know of any 1130 device whose software does this.
The other route I can take is to present the interrupt status and XIO Sense ILSW to all devices simultaneously, depending on the software and my assignment of bit positions in the ILSW to determine the order of servicing within a level. If more than one device on the level has interrupt requests, the XIO Sense ILSW will see all the relevant bits at once. The software will have to decide the order in which these are handled. It may be based on bit position in the ILSW, e.g. left to right as a priority scheme, or some other method.
It is possible that the interrupt routine could set flags for all the affected devices such that they would all be handled after the interrupt exit - one pass through the interrupt routine instead of multiple. If more than one configured device on an 1130 uses the same interrupt level, the IBM designed adapters use the second method, presenting all of the bits to the XIO Sense ILSW and dumping the priority issue on the coder of the software.
The uncontrolled method as used by IBM designed adapter logic is probably the purer route to take, but the 1133 Multiplexer and its support of strings of 2310 or 2311 disk drives might use the first method I posited. I have no documentation on the 1133 with which to determine that question. For the time being, I will design to the uncontrolled model.