Adventures With an HP 2748B Paper Tape Reader

An denizen of the Classic Computer mailing list approached me recently about getting some paper tapes read in. These were BASIC programs from his High School days. At first I tried reading them in my PC05 paper tape read on my PDP-11/34, however that reader has a sprocket feed, and no good place to hold a rolled up tape. I tried 3D printing a spool reel holder and output guide, that that was not successful. So I decided I would try instead to use one of my two HP 2748 paper tape readers – an HP 2748B in particular.

Note that this reader has a capstan (small cylinder to the right) and a pinch roller (the larger black roller to the right) to firmly grip the tape and pull it through the read station. It works pretty well, but I do have to clean it frequently when reading oiled rolled tapes or they start to slip. Fortunately, both the capstan and the pinch roller are metal – no chance for rubber rot turning to “goo” here!

The Arduino “Sketch” described in this post, the PC side perl script, and some perl script tools for working with paper tapes for 8080 machines, PDP-11 and PDP-8 are available for download.

The jig I used to install new grain-of-wheat lamps into the read head is available on Thingiverse .

Documentation is available for this reader at

HP 2748B Front Panel
Front Panel of an HP 2748B Paper Tape Reader

A gorgeous device inside

Like many/most HP devices, this device is absolutely gorgeous inside. Gold plated printed circuit boards (the entire board, not just the contact fingers), lots of space to work inside, easy disassembly and reassembly.

HP2748B Paper Tape Reader Chassis
Top view of the HP 2748B Paper Tape Reader Chassis

A Continental Connector for the Interface

The first challenge was the connector. It is a 50 pin connector originally made by Continental. First I bought a Winchester connector off of eBay, but its pins were much too narrow. Then I purchased an AMP connector of eBay, and its pins were just a little bit too narrow. For now, I added solder to the relevant pins to ensure they make contact. Some are still a bit too wide and need some filing down so the connector mates fully, but it works well enough, for now. I will not be leaving this connector attached permanently because of the solder. But I thought it was a better than the alternative of wiring up a second interface connector.

The default logic voltages for the interface are +/- 12V. However, HP also planned for a TTL logic level interface (0 – 5V) by adding a clamping circuit on each interface connection. This clamping is activated by connecting interface pins C and H. Unfortunately, my AMP connector had a coax connector on pin C, so for now I made this connection internal to the reader. When I get some time, I’ll se if I can swap pins so I can make this connection in the way the designers intended.

My plan was to use an Arduino to drive the paper tape reader, and connect to that via TCP/IP, similar to how I did my paper tape simulator.

It’s ALWAYS a Light Bulb

The first thing I did was re-form the capacitors. This turned out to not be necessary. For one thing, most of the power supply capacitors are rated at 5 TIMES to 10 TIMES the expected voltage across them. There was almost no current flow after a minute or two of “reforming”.

The next thing I thought of (thankfully) was to check to see if the illumination in the read head was OK. Well, of course it wasn’t (though the lamps in my other HP paper tape reader, an HP 2748A, turned out to be OK).

Unlike the DEC paper tape readers, these HP readers use a grain-of-wheat lamp for each channel: 10 lamps in all, 8 for the data channels, one for the feed hole, and one additional lamp used for temperature compensation. Clearly at least one was bad, but it turned out to be much more confusing than that.

I had some lamps on hand that are ostensibly for an RK05 positions sensor, but when I tried to replace the lamp I thought was bad (and at that point, I thought it was just one), another one seemed to fail. I took out the lamp I thought was bad, and tested it – and it seemed OK. Put it back in, and it seemed bad. Eventually I figured out that what was probably going on was that the wires on the lamps were so corroded that solder wasn’t taking properly to the leads. Eventually I decided to order some likely replacements off of eBay and replace all of them.

The process of lamp replacement is sufficiently tricky and time consuming that HP service people generally were not expected to do it in the field. The bulbs aren’t listed as replaceable components. Instead, service people / customers were expected to acquire a replacement for the entire read head.

Metal alignment pins at least make the removal and re-installation process relatively straight forward – takes about a minute.

HP 2747B Paper Tape Reader Read Head, Front View
HP 2747B Paper Tape Reader Read Head, Front View
HP 2748B Paper Tape Reader Read Head, Top View
HP 2748B Paper Tape Reader Read Head, Top View

To do the replacement, I removed the little PCB (left side of the photo), unsoldered everything, including the wiring to the rest of the read head, and install new lamps. I had already learned from experience that getting a single lamp into position could be tricky, so I didn’t relish trying to do what with eight of the little wee beasties. In order to assist the installation, I made a 3D printed jig that fit the boards and had a place for each bulb at an appropriate distance from the PCB based on the lead lengths of the original lamps that I had removed.

I made this jig available on Thingiverse .

3D Printed HP 2748B Lamp Installation Jig
3D Printed HP 2748B Lamp Installation Jig

It still wasn’t easy – at 70 years of age I am pretty shaky at times (and have been more shaky than average my entire life), but it worked well enough. However, since these bulbs are slightly different than the originals, I ended up adding a fixed 1/2 Watt resistor to add some additional resistance. That resistor is inside the black heat shrink tubing that goes from the adjustable resistor in the top view over to the PCB.

Then I used silicone sealant to hold the board in place, much as had been used originally – messy, but effective.

Adjustments, Adjustments

Next, I adapted the “solder enhanced” AMP connector to the tape readers interface connector. That took some trial and error in terms of how much solder to add so that I had good reliable contact. It still isn’t perfect: some are a bit too large right now.

Then I was ready to adjust the read head. Fortunately, there are good instructions in the manual (see the link at the top of this post) for how to do that. I ended up going thru that process several times, but in the end it ended up about where it was after the first time.

During this process I was also able to verify the interface signals were behaving as expected. It took a minute or ten to figure out that the read hole signal would not be present unless the READ button on the reader was engaged. Also, at first, I misunderstood the lamp/bit order – on this reader the feed holes go nearest to the front panel when inserting from left to right – the opposite of a DEC PC-05 reader.

The Arduino Interface

For this application, an Arduino Uno had sufficient interface pins, and unlike the Raspberry Pi, is supports 5V interfacing. The code was relatively straight forward, and uses the same kind of program I used for the paper tape emulator I called out earlier – the PC just makes a TCP connection and sucks up data.

The interface pins for the HP Connector, the Arduino and the Arduino digital signals are all documented at the top of the code, and symbolic constants and macros are in place for handling the Arduino port setup and usage.

There were some things I learned/ tweaked along the way:

  • At first I tried to stop the reader every time I sent a buffer of data to the PC. However, the clutch and brake on the reader don’t seem to be working quite well enough for that to succeed, so in the end I just streamed the data an “hoped” the Arduino and the TCP connection would keep up – and it seems that they do.
  • Originally I though I might have some kind of header on each buffer of data I sent, but it occurred to me that TCP is essentially doing that already. The code for that header is in SendBuffer(), but is commented out.
  • I was having problems with some extra characters, so I added a little time wasting loop to more or less ignore rapid transitions on the h0le signal. That code could probably be improved upon.

It is Working – Trust but VERIFY

After a couple of passes of tweaking the lamp positions and going through the adjustments, the reader reads a DEC test tape pretty reliably – maybe 1 error every 50,000 characters. It also handles both fan folded and wound “round” tape spools well. However, I always try and verify that tapes read correctly, so I wrote some perl scripts to do things like:

  • Verify 8080 binary tapes (the format is documented in the script)
  • Verify 8 Bit Intel HEX tapes
  • Verify Even parity text tapes
  • Verify PDP-8 binary format tapes

You can download a Zip archive with these tools, the Arduino Sketch and the PC side Perl script here.

One More Problem – There’s Always at Least One

As I started reading in tapes, starting with the DEC test tapes (MAINDEC-00-D2G2-PT and MAINDEC-00-D2G4-PT) things were fine. As I proceeded to read in some 8080 binary tapes, I started having some issues with the high order bit. That was easy to fix – the lamp was slightly miss-aligned.

I also found finding the balance between not having data errors (dropped bits) and having duplicated characters a little tricky – it took me a few passes doing the adjustment procedure described in the HP manual to get it working well.

However, I then discovered one more problem. Sometimes it would drop some of the null characters appearing in a blank area of tape after the initial leader. The HP 2748B has a special circuit that causes it to intentionally drop leader nulls – once you hit the READ button, it drops nulls until the first character. After trying this and that (including running through the adjustment procedure yet again), it occurred to me that maybe that circuit was firing, causing the reader to drop nulls.

I connected several signal lines to a connector that I thought might be useful in order to scope them (and not have to keep moving the scope probe around the board, as I have no extenders for these connectors), and quickly confirmed my suspicion. I tried a lot of things – including swapping some of the four identical transistors (two for a flip flop, and two more acting as signal inverters) so that the flip flop would have matched transistors, to no avail. I also tried replacing the capacitor that connects to +12V that resets the flip flop on power up (in case the READ button is already pressed). Nothing seemed to help.

I noticed on the oscilloscope that the length of time before the circuit fired when it shouldn’t was kind of random. Could this be noise? Connecting a .1uf bypass capacitor on the +12V line feeding the reset circuit was the first thought, but that was going to be harder to do on the board than I preferred. In the end, I hooked up the capacitor from the base of the reset signal inverter Q13, and that cured the problem.

Now the reader is generally reliable so long as I keep the read head, capstan and pinch roller clean.

IDE to SATA SSD Conversion: Adventures with a Pentium II and 1.33 GHz AMD Athlon

In early 2021, I converted the hard drives in my Pentium II computer which hosts my P/390E IBM mainframe processor card, which I call “Floppy Copy“. This machine boasts three different operating systems. Two are in support of its primary mission for copying floppies: Linux to host my Catweasel board (which may not see much future use, now that I have a Greaseweazle board), and Windows 98 for copying floppies using tools like IMD. It also has OS/2, in support of the P/390 board.

First some background: OS/2 had always acted a little wonky: I did the partitioning under Linux because OS/2 didn’t like to partition the 200GB drive. And then, having partitions of 2GB, 57GB, 57GB and 57GB, running OS/2 chkdsk on the last two 57GB partitions would sometimes clobber the first 57GB partition, for reasons I never understood – until I undertook this migration. (I still don’t quite understand why it never managed to clobber the 2GB FAT partition!)

So, off to Amazon I went, purchasing IDE to SATA adapters. The two from Startech and Kingwin worked fine. One from Sinloon worked, and the other did not work at all. In addition, I found, strangely, that the adapters would work with a 240GB drive, but not a 120GB drive. WTH?

So, then I went looking to see if the BIOS might be involved, and I found a BIOS update from Aug-17-1999 to Sep-09-2000. That cured the 120 GB problem. But then, in testing, I ran into the same kinds of issues on the 240GB drive I had seen on hard drives, with corruption after running OS/2 chkdsk.

Well, it turns out that this particular motherboard, a Chaintech 6BTM, has Ultra DMA-33 IDE ports – and only supports drives up to 137GB. Ahhh, so that was the problem.

I wanted to give OS/2 (and the P/390E) as much space as possible, so it got one 120GB drive. I tried and tried to move the drive partitions for Windows 98 and Linux over to a shared 120GB drive, but without success. The minute I created a second primary partition for Linux, Windows 98 would no longer boot. So, I simply imaged Windows 98 as is to a 120GB SSD (using only a fraction if it), OS/2 to a 120GB SSD and Linux to a 240GB SSD – because I already had it, having purchased it from before I learned about the 137GB limit.

Pentium II with SSDs for OS/2, Windows 98 and Linux (IDE to SATA adapter on OS/2 drive)

Only one of the three adapters I had supported IDE master/slave. The other two had to be alone on their cable. I am using one of those two (Kingwin) permanently.

Having gotten things tested, I went about testing the IDE to SATA adapters one at a time in order to write reviews. While testing the Kingwin adapter, though, I decided to plug it in with power on. Unfortunately I had the power connector upside down, and as soon as it touched, the computer dropped power. Worse, I could not then power it on at all — completely dead. Ohhhh nooooooooo!!!

After unplugging the power cord for a couple of minutes, I could at least try and turn it on, but it would not start up – no beep, no nothing. Fearing the worst, I tested the power supply voltages – all fine. Ohhhhhh noooooooo!!!

After 10 minutes of panic, I started testing cards from that machine in a reasonably close relative, my AMD Athlon machine with an ASUS A7M266 mother board. Video card: good. IBM P390/E even passed its diagnostics. (Whew). So then I pulled all the cards out of the Pentium II as well as the IDE to SATA adapter I had been messing with at the time of the infraction, and the machine came to life!

I put all the cards in one by one, and stopped at the POST test. All good. Then, just for giggles, I hooked up that last IDE to SATA adapter – dead in the water, apparently fried. Embarrassing: I fried an adapter. The good news: it costs less than $10. Glad I purchased four of them. (I kept the Startech out in reserve because it is the only one of the four which worked and can be set for Master or Slave.)

Having discovered that the P390/E was happy in the AMD with the A7M266 motherboard, and that the motherboard has OS/2 support as well, so in May 2021 I migrated the P/390E to the AMD machine, and upgraded to OS/2 Warp 4.52, so now I have support for the full 240GB SSD.

IBM 1410 ALD to FPGA: Volume V complete – a “quickie”

No, not that kind of “quickie”. Instead, it is about Volume V of the ALDs – now tested – in just over a week! This was due to a couple of related factors. The first 30 pages were address registers – continuation from the end of Volume IV. Then after a few more pages, the memory address register pages were up.

The second factor was a new testing technique. For cases where there are and or and/or or or gates that are similar (fed from a character of storage or another register), I started using a test vector generated from an integer counter, and then checked the results using straight-forward logic equations derived from the Instruction Logic Diagrams (ILDs), which allows me to zoom through those kinds of pages.

I also evolved how I test control signals. I typically don’t test those exhaustively with a loop (especially when they feed a latch or trigger), but I started a copy-paste routine with the variables that lets me build the tests a bit more quickly.

I really wish VHDL had a macro facility or call by name (or reference) capability, though, so I could write procedures that modify signals in a test bench. It would allow me to write generic and, and/or and or tests for various numbers of variables. Sure, I could generate the HDL with an external program, but that would actually take more time than the copy/paste technique I am currently using.

Volume V is the first volume that uses NOR (primitive DTL) for actual logic. NOR logic also shows up in gated input interface signals, but that is a different animal. I was only about 90% confident of my interpretation of some of those circuits, but so far they have been spot on.

Volume V did present a few challanges. First, another missing page: page, part of the zone adder, was missing in action. It was clearly a copy/assembly error when the drawings were assembled – page appears twice on both sides of the same sheet: one of those shoud be

Now, I could easily have just replicated the ILD as equations, but I took it a bit further than that, consistent with what I have done on other missing ALD pages. Research based on the card location chart uncovered that I had one card at 11C3A16 (type DEV) entirely dedicated to this page, though the chart only showed four of the seven gates on that card actually being used. I also discovered that the card at 11C3A17 (type DFS) had 3 gates dedicated to the cause and by elimination of a gate or two that appeared on other sheets I was able to determine which gates/pins were “available”. I struggled for a day to make it work with just 6 gates (3 from the DEV and 3 from the DFS) but I couldn’t find a way. So in the end I drafted the remaining 3 gates from DEV (which are a AND/OR triad) to complete the task. While this doesn’t agree 100% with the card location chart, who is to say that the card location chart wasn’t quite right. 😉

I did find a couple of ILD errors in this volume. On page 17 of the ILD, relating to ALD page a couple of signals are inverted and depicted as feeding OR logic. In reality, these signals are inverted on the inputs (-Y – negative active) and ANDed together. It happened because that ALD happens to depict a single NOR gate as two – one feeding the other – because that card has more inputs than can fit on a single logic block in an ALD. The symbols on the gates on the ALD do indeed imply that all the inputs are ANDed together, but if one didn’t spot that both blocks involved are the same card gate, one could easily misinterpret it. Curiously, the same thing happens on page (the previous page), but in that case the engineer who prepared the ILD interpreted it correctly.

Those same blocks on those same two gates allowed me to leverage a feature on my application. When I entered those logic blocks, I realized that they were, in both cases, the same gates. However, since they are next to each other on the ALD they were not candidates for using the “extension” capability to combine them – there would have been room for that on the page, but they were not depicted as extensions. So I moved the inputs from one of the gates of the pair to the other, and removed the output from that first one as well. When I first tried generate the HDL, the application noticed the unconnected gate and generated a (harmless) error. However, a while back I added the ability to tell the application to ignore a given logic block when generating HDL. Worked like a charm.

Another case where I ran into that sort of thing was on the real time clock, where a given switch “deck” was split in two, and also the block title — which I used to generate the name of a switch signal — was replicated between decks. In order to generate this correctly I had to tweak the logic block titles to separate them, and join the switches together in the test bench.

The ILD’s also, generally, did not include the gates for address wraparound from x9999 to 00000 for 60K and 80K – only for 20K and 40K machines. The wraparound logic was present on the ALDs however, and was easy to decipher. (Wraparound for 100K is automatic because there are only 5 digits of addressing. 10K machines to no support wraparound at all, if I recall correctly)

I discovered a typo on a signal name on page “-S AR BUS GRD OUT THP0B” — GRD should be GTD (gated).

ILD figure 24 had an error relating to page om calculating the Address Register Exit Channel “C” bit – at the least it didn’t match the ALD. In general I defer to the ALD after carefully checking the logic, figuring that the ALDs are later in the timeline than the ILDs.

I also found a case of a misleading signal name, where the signal name implies two factors in an AND, when there are actually three. However, going back I can’t seem to find it – I will update this page if I come across it.

Finally, I have come to dislike a certain idiom that has appeared on a handful of sheets, where a pair of latches are ins sequence, usually named “… Control” and “…” where the output of “…” resets “…Control”. A real pain to devise a test bench.

IBM 1410 ALD to FPGA – Punch Column Binary ALD anomaly

Came across something interesting today on Automatic Logic Diagram It refers to unit “8” – which is for punch column binary – a special feature. An 8 character is just the 8 bit – odd parity. However, to decode unit 8 per the ALD one would have to have B 8 – and no check bit – even parity- which can never happen. So, if one were going to have the column binary feature installed, it would require an actual rework to change the input to one of the pins on ALD, coordinate 3A (11DJ02) from “+S E CH U SEL REG B BIT” to “+S E CH U SEL REG NOT B BIT”. So, without this rework, the machine would simply not decode unit 8 at all – perhaps intentionally. (Of course, on the generated version, this would be an easy fix, but for now I just left it as is.)

IBM 1410 ALD to FPGA – I “got one”

I have been testing the logic generated from each Automated Logic Diagram (ALD) page, using the Instructional Logic Diagrams (ILD) were available to guide my testing. Until today I don’t recall finding any cases where I actually made a connection mistake when I entered the ALDs into the database – until today. On page, I had mis-substituted signal “-S I-O Lozenge Latch” where I should have had “+S Logic Gate E 1” as the input to the gate at coordinate 5H. The testing caught it.

When I entered data for each sheet, I tracked usage of each signal count. I had a “2” written next to “+S Logic Gate E1” — as I should have. I must have missed that when I checked the signal usage counts after entry (“-S I-O Lozenge Latch” had the two instead). The latter is right below the former on the left side of the ALD, which made the mistake not unlikely, and made it easier to mis-interpret where I had written the signal count of 2. I even circled the 2, meaning I checked it. Oops.

Instructional Logic Diagrams and Automated Logic Diagrams

As part of my project to create a Field Programmable Gate Array implementation (FPGA) of the IBM 1410 Data Processing System based on Automated Logic Diagrams (ALDs), I decided to look at using the Instructional Logic Diagrams (ILDs) to guide my testing, rather than using the ALDs directly.

The ILDs are written completely in “positive logic”. Going in, I sort of expected a pretty imperfect match – that the ILDs would not have all the signals, and be somewhat superficial in their treatment of the logic. For the IBM 1410, the circuits were:

  • AND
  • OR
  • Inverter
  • Indicator (Lamp)
  • Single Shot
  • Latch (Reset/Set)
  • Trigger (Flip Flop)

To my surprise I found that the ILDs are very accurate, and a great testing guide, providing a second view of the logic – a kind of redundancy check against my entry of ALD data into my system. They are good enough that they have given me considerable confidence that I can use them to help “fill in the blanks” related to the handful of ALD pages I am missing, and also for some of the IBM 1414 peripheral controllers for which I do not have ALDs.

Updated 6/28/2020, I discovered that not all of the ALDs are represented in the ILDs. I also had an interesting case where I thought, for a while, an ALD and the ILD that represents it were mismatched, but I was incorrect – the ILD matched the logic perfectly.

In 1962 IBM published an article in the IEEE Transactions “Information Processing — from Engineering Drawing to Manufacture” by R. K. Grim that describes how the data the ended up generated ALDs was entered and the ALDs produced, but it does not mention where the ILDs come from. They are definitely artwork – not machine generated per se. The article did not address ILDs.

I have corresponded with IBM to see if they might have, in their archives, the data from these 1960s era engineering systems, but it seems that they do not (or have lost the pointers to them.)

It seems that the SMS automation was first done using an IBM 709, then they later added IBM 7090 and IBM 1401 systems (which of course could not have been there for the original design of the IBM 7090 and 1401, which used the SMS system), using tape files. The article also describes future plans to use a 1301 disk drive attached to an IBM 1410 for remote (tele-processing) access (which was supported by the IBM 1410-PR155 operating system.

The accuracy of the ILDs is such that I expect that they evolved along with the design of the machine and entry of the data used for the ALDs. I’d expect that doing it after the fact, from the ALDs, would be quite error prone — besides the one difference I have found is in the signal names, which do not always exactly match those used in the ALDs, but are close enough that the intent is obvious. But I don’t know the timing: which came first — the ILDs or the ALDs, or did they perhaps begin together in some form and co-evolve?

In summary, it seems to me that one could do a pretty decent positive logic implementation of IBM machines of that era using these ILDs. This was a real eye-opener.

Hello world!

Welcome to my website, which I have just released in November, 2019. This is my Blog section – if you are looking for something else, then see the menu at the top of the page, or visit my home page.

My website used to be at . However Charter (now Spectrum) stopped supporting subscriber webpages, so I moved it to a linode system. Their prices are great, and support has been availability has been great as well.

The site has been restructured, although quite a few similarities exist between this site and my old one. One obvious difference is the sidebar over on the right hand side, and the existence of “posts” — a capability provided by WordPress (a link for which is at the bottom of the pages in the website).

You can visit this link to see what the old one looked like.