Repairing a 1960s mainframe: Fixing the IBM 1401's core memory and power supply

A few weeks ago, I wanted to use one of the vintage IBM 1401 mainframe computers at the Computer History Museum, but the computer wasn't working.1 This article describes the multi-week repair process to get the computer working again.

The problem started when the machine was powered up at the same time someone shut down the main power, apparently causing some sort of destructive power transient. The computer's core memory completely stopped working, making the computer unusable. To fix this we had to delve into the depths of the computer's core memory circuitry and the power supplies.

The IBM 1401 computer. The card reader/punch is in the foreground. The 12K memory expansion box is partially visible to the right behind the 1401.

The IBM 1401 computer. The card reader/punch is in the foreground. The 12K memory expansion box is partially visible to the right behind the 1401.

Debugging the core memory

The IBM 1401 was a popular business computer of the early 1960s. It had 4000 characters of internal core memory with additional 12000 characters in an external expansion box.2 Core memory was a popular form of storage in this era as it was relatively fast and inexpensive. Each bit is stored in a tiny magnetized ferrite ring called a core. (If you've ever heard of a "core dump", this is what the term originally referred to.) The photo below is a magnified view of the cores, along with the red wires used to select, read and write the cores.4 The cores are wired in an X-Y grid; to access a particular address, one of the X lines is pulsed and one of the Y lines is pulsed, selecting the core where they intersect.3

Detail of the core memory in the IBM 1401. Each toroidal ferrite core stores one bit.

Detail of the core memory in the IBM 1401. Each toroidal ferrite core stores one bit.

In the 1401, there are 4000 cores in each grid, forming a core plane that stores 4000 bits. Planes are then stacked up, one for each bit in the word, to form the complete core module, as shown below.

The 4000 character core memory module from an IBM 1401 computer. Tiny ferrite cores are strung on the red wires.

The 4000 character core memory module from an IBM 1401 computer. Tiny ferrite cores are strung on the red wires.

To diagnose the memory problem, the team started probing the 1401 with an oscilloscope. They checked the signals that select the core module, the memory control signals, the incoming addresses, the clock signals and so forth, but everything looked okay.

The next step was to see if the X and Y select signals were being generated properly. These pulses are generated by two boards called "matrix switches", one for the X pulse and one for the Y pulse.5 Some address lines are decoded and fed into the X matrix switch, while the other address lines are decoded and fed into the Y matrix switch. The matrix switches then create pulses on the appropriate X and Y select lines to access the desired address in the core planes.

The photo below shows the core memory module and its supporting circuitry inside the 1401. The core memory module itself is at the bottom, with the two matrix switch boards mounted on it. Above it, three rows of circuit boards (each the size of a playing card) provide the electronics. The top row consists of inhibit drivers (used for writing memory) and the current source and current driver boards (providing current to the matrix switches). The middle row has 17 boards to decode the memory addresses. At the bottom 19 sense amplifier boards read the data signals from the cores. As you can see, core memory requires a lot of supporting electronics and wiring. Also note the heat sinks on most of these boards due to the high currents required by core memory.

Inside the IBM 1401 computer, showing the key components of the core memory system.

Inside the IBM 1401 computer, showing the key components of the core memory system.

After some oscilloscope measurements, we found that one of the matrix switches wasn't generating pulses, which explained why the memory wasn't working. We started checking the signals going into the matrix switch and found one matrix switch input line showed some ringing, apparently enough to keep the matrix switch from functioning.

Since the CHM has two 1401 computers, we decided to swap cards with the good machine to track down the fault. First we tried swapping the thermal switch board (below). One problem with core memory is that the properties of ferrite cores change with temperature. Some computers avoid this problem by heating the core memory to a constant temperature in air (as in the IBM 1620 computer) or an oil bath (as in the IBM 7090). The 1401 on the other hand uses temperature-controlled switches to adjust the current based on the ambient temperature. We swapped the "AKB" thermal switch board (below) and the associated "AKC" resistor board, with no effect.

The core memory uses a thermal switch board to adjust the current through core memory as temperature changes.  The switches open at 35°C, 29°C and 22°C.  The type of the board (AKB) is stamped into the lower left of the board.

The core memory uses a thermal switch board to adjust the current through core memory as temperature changes. The switches open at 35°C, 29°C and 22°C. The type of the board (AKB) is stamped into the lower left of the board.

Next we tried swapping the "AQW" current source boards that control current through the matrix switches.6 We swapped these board and the 1401's memory started working. Replacing the original boards one at a time, we found the bad board, shown below.

The IBM 1401 has four "AQW" cards that generate currents for the core memory switches. This card had a faulty inductor (the upper green cylinder), preventing core memory from working.

The IBM 1401 has four "AQW" cards that generate currents for the core memory switches. This card had a faulty inductor (the upper green cylinder), preventing core memory from working.

I examined the bad board and tested its components with an multimeter. There were two 1.2mH inductors on the board (the large green cylinders). I measured 3 ohms across one and 3 megaohms across the other, indicating that the second inductor had failed. With an open inductor, the board would only provide half the current. This explained why the matrix switch wasn't generating pulses, and thus why the core memory didn't work.

I gave the bad inductor to Robert Baruch of Project 5474 for analysis. He found that the connection between the lead and the inductor wire was intermittent. He dissolved the inductor's package in acid and took photographs of the winding inside the inductor.7

The faulty inductor from the IBM 1401 showing the failed connection.

The faulty inductor from the IBM 1401 showing the failed connection.

We looked in the spare board cabinet for an AQW board to replace the bad one and found several. However, the replacement boards were different from the original—they had one power transistor instead of two. (Compare the photo below with the photo of the failed card from the computer.)

The replacement AQW card had one transistor instead of two, but was supposedly compatible with the old board.

The replacement AQW card had one transistor instead of two, but was supposedly compatible with the old board.

Despite misgivings from some team members, the bad AQW card was replaced with a one-transistor AQW card and we attempted to power the system back up. Relays clicked and fans spun, but the computer refused to power up. We put the old card back (after replacing the inductor), and the computer still wouldn't start. So now we had a bigger problem. Apparently something had gone wrong with the computer's power supplies so the debugging effort switched focus.

Diagnosing the power supply problem

The power supply system for the IBM 1401 is more complex than you might expect. Curiously, the main power supplies for the system are inside the card reader; a 1250W ferro-resonant transformer in the card reader regulates the line input AC to 130V AC, which is fed to the 1401 computer itself through a thick cable under the floor. Smaller power supplies inside the 1401 then produce the necessary voltages.

Since it was built before switching power supplies became popular, the IBM 1401 uses bulky linear power supplies. The photo below shows (left to right) the +30V, -6V, +6V and -12V supplies.8 In the lower left, under the +30V supply, you can see eight relays for power sequencing. The circuit board to the right of the relays is one of the "sense cards" that checks for proper voltages. Under the +6V supply is a small "+18V differential" supply for the core memory. Foreshadowing: these components will all be important later.9

Power supplies in the IBM 1401.

Power supplies in the IBM 1401.

After measuring voltages on the multiple power supplies, the team concluded that the -6V power supply wasn't working right. This was a bit puzzling because the AQW card (the one we replaced) only uses +12 and +30 volts. Since it doesn't use -6 volts at all, I didn't see how it could mess up the -6 volt supply.

Inside the IBM 1401's -6V power supply.

Inside the IBM 1401's -6V power supply.

The team removed the -6V supply and took it to the lab. In the photo above, you can see the heavy AC transformer and large electrolytic capacitors inside the power supply. Measuring the output transistors, they found one bad transistor and some weak transistors and decided to replace all six transistors. In the photo below, you can see the new transistors, mounted on the power supply's large heat sink. These are germanium power transistors; the whole computer is pre-silicon.

The -6V power supply from the IBM 1401 uses six power transistors on a large heat sink.

The -6V power supply from the IBM 1401 uses six power transistors on a large heat sink.

The -6V power supply tested okay in the lab with the new transistors, so it was installed back in the 1401. We hit the "Power On" button on the console and... it still didn't work. We still weren't getting -6V and the computer wouldn't power up.

In the next repair session, we tried to determine why the computer wasn't powering up. Recall the eight relays mentioned earlier; these relays provide AC power to the power supplies in sequence to ensure that the supplies start up in the right order. If there is a problem with a voltage, the next relay in the sequence won't close and the power-up process will be blocked. We looked at which relays were closing and which weren't, and measured the voltages from the various power supplies. Eventually we determined that about halfway through the power-up process, relay #1 was not closing when it should, stopping the power-up sequence.

Relay #1 was driven by the +30V supply and was activated by a "sense card" that checked the +6V supply. But the +30V and +6V supplies were powering up fine and the sense card was switching on properly. Thus, the problem seemed to be a failure with the relay itself. Just before we pulled out the relay for testing, someone found an updated schematic showing the relay didn't use the regular +30V supply but instead obtained its 30 volts through the "18V differential supply".11 And the schematic for the 18V differential supply had a pencilled-in fuse.10

Could the power problem be as simple as a burnt-out fuse? We opened up the 18V differential supply, and sure enough, there was a fuse and it was burnt out. After replacing the fuse, the system powered up fine and we were back in business.

The 18V differential power supply in the IBM 1401 provides 12 volts to the core memory. The fuse is under the large electrolytic filter capacitors.

The 18V differential power supply in the IBM 1401 provides 12 volts to the core memory. The fuse is under the large electrolytic filter capacitors.

With the computer operational, I could finally run my program. After a few bug fixes, my program used the computers's reader/punch to punch a card with a special hole pattern:

A punch card with "Merry Xmas" and a tree punched into it.

A punch card with "Merry Xmas" and a tree punched into it.

Happy holidays everyone!12

Conclusion

After all this debugging, what was the root cause of the problems? As far as we can tell, the original problem was the inductor failure and it's just a coincidence that the problem occurred after the power loss during system startup. The new AQW card must have caused the fuse to blow, although we don't have a smoking gun.13 The reason the -6V power supply wasn't showing any voltage is because it was sequenced by relay #1, which didn't close because of the fuse. The bad transistors in the -6V power supply problem were apparently a pre-existing and non-critical problem; the good transistors handled enough load to keep the power supply working. The moral from all this is that keeping an old computer running is challenging and takes a talented team.

Thanks to Robert Baruch for the inductor photos. Thanks to Carl Claunch for providing analysis. The Computer History Museum in Mountain View runs demonstrations of the IBM 1401 on Wednesdays and Saturdays so check it out if you're in the area; the demo schedule is here.

Follow me on Twitter or RSS to find out about my latest blog posts.

Notes and references

  1. Although there are two IBM 1401 computers at the CHM, only one of them has the "column binary punch" feature that I needed. "Column binary" lets you punch arbitrary patterns on a punch card (to store binary) rather than being limited to the standard punch card character set of 64 characters. 

  2. Note that the 1401 has 4000 characters of memory and not 4096 because it is a decimal machine. Also, the memory stores 6-bit characters plus a (metadata) word mark and not bytes. 

  3. If you want to know more about the 1401's core memory, I've written in detail about core memory and described a core memory fix

  4. The trick that makes core memory work is that the cores have extremely nonlinear magnetic characteristics. If you pass a current (call it I) through a wire through a core, the core will become magnetized in that direction. But if you pass a smaller current (I/2) through a wire, the core doesn't change magnetization at all. The result is that you can put cores on a grid of X and Y wires. If you put current I/2 through an X wire and current I/2 through a Y wire, the core at their intersection will get enough current to change state, while the rest of the cores will remain unchanged. Thus, individual cores can be selected. 

  5. The matrix switch is another set of cores in a grid, but used to generate pulses rather than store data. The 1401's memory has 50 X lines and 80 Y lines (yielding 4000 addresses), so generating the X and Y pulses with transistors would require 50 + 80 expensive, high-current transistors. The X matrix switch has 5 row inputs and 10 column inputs, and 50 outputs—one from each core. The address is decoded to generate the current pulses for these 15 inputs. Thus, instead of using transistor circuits to decode and drive 50 lines, just 15 lines need to be decoded and driven, and the matrix switch generates the final 50 lines from these. The Y lines are similar, using a second matrix switch to drive the 80 Y lines. 

  6. Each matrix switch has two current inputs (for the row select and the column select), so there are four current source boards and four current driver boards in total. 

  7. Strangely, half the inductor is nicely wound while the winding in the other half is kind of a mess.

    The faulty inductor from the IBM 1401.

    The faulty inductor from the IBM 1401.

  8. The 1401 has more power supplies that aren't visible in the picture. They are behind the power supplies in the photo and slide out from the side for maintenance. 

  9. If you want to see the original schematics and diagrams of the 1401's power supplies, you can find them here. Core memory schematics are here

  10. The pencilled-in fused on the schematic also had a note about an IBM "engineering change". In IBM lingo, an engineering change is a modification to the design to fix a problem. Thus, it appears the the 1401 originally didn't have the fuse, but it was added later. Perhaps we weren't the first installation to have this problem, and the fuse was added to prevent more serious damage. 

  11. The 18V differential supply provides 12 volts. This seemed contradictory, but there's an explanation. The core memory circuitry is referenced to +30 volts. It needs a supply 18 volts lower, which is provided by the 18V differential supply. Thus, the voltage is +12V above ground. Unlike the regular +12V power supply, however, the differential power supply's output will move with any changes to the +30V supply, ensuring the difference is a steady 18 volts. 

  12. The "Merry Xmas" card was inspired by a tweet from @rrragan. (I had also designed a card with a menorah, but unfortunately encountered keypunch problems and couldn't get it completed in time. Maybe next year.) Punch cards normally encode characters by punching up to three holes per column. Since this decorative card required many holes per column, I needed to use the 1401's column binary feature, which allows arbitrary binary data to be punched. I ended up punching the card upside down to simplify the program:

    Front of my "Merry Xmas" punch card.

    Front of my "Merry Xmas" punch card.

  13. After carefully examining the AQW boards, we determined that one- and two-transistor cards should be compatible. The two-transistor board had the two transistors in parallel, probably using earlier transistors that couldn't handle as much current. It's possible that the filter capacitor between +30V and ground was shorted in the replacement AQW board, blowing the fuse. 

Repairing a 1960s-era IBM keypunch: controlled by mechanical tabs and bars

In this article I describe repairing an IBM 029 keypunch that wouldn't punch numbers. Keypunches were a vital component of punch card computing, recording data as holes in an 80-column card. Although keypunches have a long history, dating back to the use of punch cards in the 1890s, the IBM 029 keypunch is slightly more modern, introduced in 1964. The repair turned out to be simple, but in the process I learned about the complex mechanical process keypunches used to encode characters.

Keyboard of an IBM 029 keypunch. "Numeric" key is in the lower left. Strangely, this keyboard labels most special characters with the holes that are punched (e.g. 12-8-6) rather than the character. Compare with the photo of a different 029 keyboard later.

Keyboard of an IBM 029 keypunch. "Numeric" key is in the lower left. Strangely, this keyboard labels most special characters with the holes that are punched (e.g. 12-8-6) rather than the character. Compare with the photo of a different 029 keyboard later.

A couple weeks ago, I was using the 029 keypunch in the Computer History Museum's 1401 demo room and I found that numbers weren't punching correctly. The keyboard has a "Numeric" key that you press to punch a number or special character. (Unlike modern keyboards with a row of numbers at the top, numbers on the 029 keyboard share keys with letters.) When I tried to type a number, I got the corresponding letter; the keypunch was ignoring the "Numeric" key. The same happened with special characters that required "Numeric".

Frank King, an expert on repairing vintage IBM computers, showed me how to fix the keyboard. The first step was to remove the keyboard from the desk. This was surprisingly easy—you just rotate the keyboard clockwise and lift it up.

The keyboard of an IBM 029 keypunch can be removed from the desk simply by rotating and lifting.

The keyboard of an IBM 029 keypunch can be removed from the desk simply by rotating and lifting.

On the underside of the keyboard are several microswitches for some special function keys. The microswitches are on the left half, connected by blue wires. Also note the metal rectangles along the right; these are the "latch contacts", one for each key and will be discussed later.

The underside of the IBM 029 keypunch's keyboard.

The underside of the IBM 029 keypunch's keyboard.

Frank noticed that the keystem for the "Numeric" key wasn't pressing the microswitch, but was out of alignment and missing the microswitch's lever entirely. Thus, pressing the "Numeric" key had no effect and the wrong character was getting punched. He simply rotated the microswitch slightly so it was back into alignment with the keystem, fixing the problem. We placed the keyboard back into the desk and the keypunch was back in business. Many vintage computer repairs are difficult, but this one was quick and easy.

How the keypunch encodes characters

This repair was a good opportunity to look inside the keyboard and study the interesting techniques it uses to encode characters. On a punch card, each character is indicated by the holes punched in one of the card's 80 columns, as shown below. The digits 0 through 9 simply result in a punch in row 0 through 9. Letters are indicated by a punch in digit rows 1 through 9 combined with a punch in one of the top three rows (the "zone" rows1). Special characters usually use three punches. Since each character can have punches in any of 12 rows, you can think of cards as using a (mostly-sparse) 12-bit encoding.

An 80-column punch card stores one character in each column. The pattern of holes in the column indicates the character. From the 029 Reference Manual.

An 80-column punch card stores one character in each column. The pattern of holes in the column indicates the character. From the 029 Reference Manual.

Since each key on the keyboard has one character in alpha mode and another character in numeric mode, the keypunch must somehow determine the hole pattern for each character. With modern technology, you could simply use a tiny ROM to hold a 12-bit row value for the "alpha" mode and a second 12-bit value for the "numeric" mode. (Or use a keyboard encoding chip, digital logic, a microcontroller, etc.) But back in the keypunch era, ROMs weren't available. Instead, the keypunch uses a complex but clever mechanical technique to assign a hole pattern to each character.

The previous model: the 026 keypunch

IBM 026 keypunch. Photo by Paul Sullivan (CC BY-ND 2.0).

IBM 026 keypunch. Photo by Paul Sullivan (CC BY-ND 2.0).

Before explaining how the 029 keypunch encodes characters, I'll discuss the earlier and simpler IBM 026 keypunch, which was introduced in July 1949. The 026 used the technology of the 1940s: vacuum tubes and electromechanical relays. Encoding the hole pattern with tubes or relays would be bulky and expensive. Instead, the keypunch used a mechanical encoder with metal tabs to indicate where to punch holes.

The keyboard mechanism in the 026/029 keypunch. Pressing a key pulls the latch pull-bar. This causes the permutation bar to drop slightly. If a bail has a matching tab, the permutation bar will move the bail, closing the contact. The permutation bar also closes the key's latch contact. Based on the Maintenance Manual.

The keyboard mechanism in the 026/029 keypunch. Pressing a key pulls the latch pull-bar. This causes the permutation bar to drop slightly. If a bail has a matching tab, the permutation bar will move the bail, closing the contact. The permutation bar also closes the key's latch contact. Based on the Maintenance Manual.

The diagram above shows the keyboard mechanism in the keypunch. The basic idea is there are 12 "bail contacts" (one for each row on the card); when you press a key, the appropriate contacts are closed to punch holes in the desired rows. To implement this, each key was connected to a separate vertical "permutation bar" by a "latch pull-bar". When a key is pressed, the associated permutation bar drops down. Twelve horizontal bars, called "bails",2 ran perpendicular to the permutation bars, one bail for each row on the card. At each point where a bail crossed a key's permutation bar, the bail could have a protruding tab that meshes with the permutation bar. Pressing a key would cause the permutation bar to push the tab and rotate the bail, closing the bail contact and punching a hole in that row. Thus, the 12 bails mechanically encoded the mapping from keys to holes by the presence or absence of metal tabs along their length.

Closeup of the bails and one of the permutation bars. Four of the bails have tabs and will be triggered by the permutation bar.

Closeup of the bails and one of the permutation bars. Four of the bails have tabs and will be triggered by the permutation bar.

The photo above shows a permutation bar (right) engaging four tabs on the bails (left). In the photo below, you can see one of the bails removed from the keyboard mechanism. Note the tabs extending from the bail to engage with the permutation bars. Also note the contact on the left end of the bail.

The keyboard mechanism in the 029 keypunch. From the Maintenance Manual.

The keyboard mechanism in the 029 keypunch. From the Maintenance Manual.

There is a problem with this 12-bail mechanism: it only handles a single character per key, so it doesn't handle numbers. (The keyboard diagram below shows how numbers share keys with letters.) The obvious solution is to add 12 more bails for the second character on a key, but this would double the cost of the mechanism. However, since numbers are indicated by a single punch in a column, a shortcut is possible: use a switch on each number key to punch that row. The 026 keypunch does this, using the latch contacts shown in the earlier diagram. In numeric mode, the latch contact for the "1" key would punch row 1, and so forth for the other numbers. To handle the special characters, three additional bails were added, bringing the total number of bails to 15.5 Thus, the 026 had 12 bails used in alpha mode, 3 bails used in numeric mode for special characters, and a latch contact for each key for numbers and special characters.

Keyboard of the IBM 026 keypunch. From the IBM 24/26 Reference Manual.

Keyboard of the IBM 026 keypunch. From the IBM 24/26 Reference Manual.

The permutation bar and bail mechanism also explains why the "Numeric" key (the one we fixed) has a separate microswitch under the keyboard. The regular mechanism with permutation bars, bails and latch contacts only allows one key to be pressed at a time.3 Since "Numeric" is held down while another key is pressed, it needed a separate mechanism.4

Back to the 029 keypunch

When the 029 keypunch was introduced in 1964, it replaced the 026's vacuum tubes with transistorized circuitry and updated the keypunch's appearance from 1940's streamlining to a modernist design. However, the 029 kept most of the earlier keypunch's internal mechanical components, along with many relays.6

Keyboard from the IBM 029 keypunch. Photo by Carl Claunch.

Keyboard from the IBM 029 keypunch. Photo by Carl Claunch.

A major functional improvement over the 026 was the addition of many more special characters in the 029; almost every key on the keyboard had a special character. The three numeric mode bails used in the 026 couldn't support all these special characters. The obvious solution would be to add more bails; with 12 bails for alpha and 12 bails for numeric, any characters could be encoded. But, IBM came up with a solution for the 029 that supported the new special characters while still using the 026's 15-bail mechanical encoder. The trick was to assign the bails to rows in a way that handled most of the holes, leaving the latch contact to handle one additional "extra" hole per key.7

The diagram below shows part of the encoding mechanism, based on the keypunch schematics.8 Horizontal lines correspond to the 15 bails; the labels on the left show the row handled by each bail. Each vertical line represents the permutation bar for a key; the key labels are at the bottom. The black dots correspond to tabs on the bail, causing the bail to tripped when activated by the corresponding key. (The circles symbolize the interlock disks that keep two keys from being used simultaneously.3) Note that the 029's bails don't handle all the rows for alpha mode (unlike the 026), leaving some alpha holes to be punched by the latch contacts.

Diagram showing how keys select holes to be punched on the 029 keypunch. The complete diagram is in the schematic.

Diagram showing how keys select holes to be punched on the 029 keypunch. The complete diagram is in the schematic.

The yellow highlights on the diagram show what happens for the "W _" key. Pressing this key (bottom) will activate the "Numeric 5", "Numeric 8" and "Common 0" bails (left). In addition, the latch contact will activate "Alpha 6" (top). Putting this together, in alpha mode, rows 0 and 6 will be punched and in numeric mode, rows 0, 8 and 5 will be punched. These are the codes for "W" and "_" respectively, so the right holes get punched. The encoder works similarly for other keys, punching the appropriate holes in alpha and numeric modes. Thus, the 029 managed to extend the 026's character set with many new special characters, without requiring a redesign of the mechanical encoder.

An IBM 029 keypunch in the middle of punching cards.

An IBM 029 keypunch in the middle of punching cards.

Conclusion

For once, repairing computer equipment from the 1960s was quick and easy. Fixing the "Numeric" key didn't even require any tools. The repair did reveal the interesting mechanism used to determine which holes to punch. In the era before inexpensive ROMs, keyboard decoding was done mechanically, with tabs on metal bars indicating which holes to punch. This mechanism was inherited from the earlier 026 keypunch (1949), improved on the 029 keypunch (1964) to handle more symbols, and was finally replaced by electronic encoding when the 129 keypunch was introduced in 1971.6

Follow me on Twitter or RSS to find out about my latest blog posts.

Notes and references

  1. The card's zone rows are called 12 (on top) and 11 (below 12). Confusingly, sometimes the 0 row acts as a zone (for a letter) and sometime it acts as a digit (for a number). Also note the special characters that use 8 combined with a digit from 2 to 7; essentially this corresponds to a binary value from 10 to 15. The combination of a zone punch and digit punches encoded a 6-bit character. 

  2. "Bail" may seem like an obscure word in this context, but it's essentially a metal bar. Looking at old patents, in the early 1900s "bail" was most often used to denote a wire handle on a bucket or pot. It then got generalized to a metal bar in various mechanism, especially one that could be lifted up. If you're from the typewriter era, you might remember the "paper bail", the bar that holds the paper down. (Dictionary link.) 

  3. An interesting mechanism ensures that only one key can be pressed at a time. The keyboard mechanism contains a row of "interlock disks". When a key is pressed the latch bar slides between two of these disks. These disks slide all the other disks over, blocking the path of any other key's latch bar until the first key is released. 

  4. The other special keys that use a microswitch are "Error reset", "Multi punch", "Dup", "Feed", "Prog 1", "Prog 2" and "Alpha". 

  5. The 026 keypunch used a clever trick for some of the special characters. Note the four special character keys in the upper left. These characters were carefully assigned so each pair has the same punch except the upper one punches a 3 and the lower punches a 4. Thus, a single encoding worked for the key with the addition of a relay to switch between 3 and 4. 

  6. In 1964 IBM introduced the IBM 360 line of computers. They were built from hybrid SLT (Solid Logic Technology) modules, an alternative to integrated circuits. Although the IBM 029 keypunch was introduced along with the SLT-based IBM 360, the keypunch used older transistorized SMS boards. Even though the 029 got rid of the 026's vacuum tubes, it was still a generation behind in technology. It wasn't until the 129 keypunch was announced in 1971 (along with the 370 computer line) that keypunches moved to SLT technology.

    The 129's keyboard kept much of the mechanical structure of the older keypunches (the permutation bars and latch contacts), but got rid of the bails used to encode the keypresses. Instead, encoding in the 129 was done through digital logic SLT modules (mostly AND-OR gates) controlled by the latch contact switches. The 026 and 029 keypunches originally had model numbers 26 and 29, but with the introduction of the 129, their names were retconned to the 026 and 029. 

  7. It's not easy to design a keyboard layout that works with the 029 mechanism since the latch contact can support at most one "extra" hole per key, a hole not handled by the bails. The special characters needed to be assigned to keys in a way that would work; this probably explains the semi-random locations of the special characters on the keyboard. For instance, "(" is on "N" while ")" is on "E". Since both ")" and "E" require a hole in row 5, it made sense to put them on the same key, so the latch contact can handle the 5 punch for both. 

  8. If you want to learn more about keypunch internals, the manuals are on bitsavers.org. In particular, see the Reference Manual, Maintenance Manual and Schematics

Creating a Christmas card on a vintage IBM 1401 mainframe

I recently came across a challenge to print a holiday greeting card on a vintage computer, so I decided to make a card on a 1960s IBM 1401 mainframe. The IBM 1401 computer was a low-end business mainframe announced in 1959, and went on to become the most popular computer of the mid-1960s, with more than 10,000 systems in use. The 1401's rental price started at $2500 a month (about $20,000 in current dollars), a low price that made it possible for even a medium-sized business to have a computer for payroll, accounting, inventory, and many other tasks. Although the 1401 was an early all-transistorized computer, these weren't silicon transistors—the 1401 used germanium transistors, the technology before silicon. It used magnetic core memory for storage, holding 16,000 characters.

A greeting card with a tree and "Ho Ho Ho" inside, created on the vintage 1401 mainframe. The cards are on top of the 1403 line printer, and the 1401 mainframe is in the background.

A greeting card with a tree and "Ho Ho Ho" inside, created on the vintage 1401 mainframe. The cards are on top of the 1403 line printer, and the 1401 mainframe is in the background.

You can make a greeting card by printing a page and then folding it into quarters to make a card with text on the front and inside. The problem with a line-printer page is that when you fold it into a card shape, the printed text ends up sideways, so you can't simply print readable text. So I decided to make an image and words with sideways ASCII graphics. (Actually the 1401 predates ASCII and uses a 6-bit BCD-based character set called BCDIC, so it's really BCDIC graphics. (EBCDIC came later, extending BCDIC to 8 bits and adding lower case.)) Originally I wanted to write out "Merry Christmas", but there aren't enough characters on a page to make the word "Chrstmas" readable, so I settled on a cheery "Ho Ho Ho". I figured out how to sideways draw a tree and the words, making this file.

Closeup of a greeting card printed on the IBM 1401, with a Christmas tree on the front.

Closeup of a greeting card printed on the IBM 1401, with a Christmas tree on the front.

Next, I needed a program to print out this file. I have some experience writing assembly code for the IBM 1401 from my previous projects to perform Bitcoin mining on the 1401 and generate Mandelbrot fractals. So I wrote a short program to read in lines from punched cards and print these lines on the high-speed 1403 line printer. The simple solution would be to read a line from a card, print the line, and repeat until done. Instead, I read the entire page image into memory first, and then print the entire page. The reason is that this allows multiple greeting cards to be printed without reloading and rereading the entire card deck. The second complication is that the printer is 132 columns wide, while the punch cards are 80 columns. Instead of using two punch cards per print line, I encoded cards so a "-" in the first column indicates that the card image should be shifted to the right hand side of the page. (I could compress the data, of course, but I didn't want to go to that much effort.)

The 1401 has a strange architecture, with decimal arithmetic and arbitrary-length words, so I won't explain the above code in detail. I'll just point out that the r instruction reads a card, mcw moves characters, w writes a line to the printer, and bce branches if a character equals the specified value. (See the reference manual for details.)

The next step was to punch the code and data onto cards. Fortunately, I didn't need to type in all the cards by hand. Someone (I think Stan Paddock) attached a USB-controlled relay box to a keypunch, allowing a PC to punch cards.

A PC-controlled IBM 029 keypunch punched my card deck.

A PC-controlled IBM 029 keypunch punched my card deck.

A few minutes later I had my deck of 77 punch cards. The program itself just took 9 cards; the remainder of the cards held the lines to print.

The deck of punched cards I ran on the IBM 1401. The first few cards are the program, and the remaining cards hold the lines to print.

The deck of punched cards I ran on the IBM 1401. The first few cards are the program, and the remaining cards hold the lines to print.

Once the cards were ready, we loaded the deck into the card reader and hit "Load", causing the cards to start flying through the card reader at a dozen cards per second. Unfortunately, the reader hit an error and stopped. Apparently the alignment of the holes punched by the keypunch didn't quite match the alignment of the card reader, causing a read error.

The IBM 1401's card reader was experiencing errors, so we removed the brushes and realigned them.

The IBM 1401's card reader was experiencing errors, so we removed the brushes and realigned them.

The card reader contains sets of 80 metal brushes (one for each column of the card) that detect the presence of a hole. Computer restoration expert Frank King disassembled the card reader, removed the brush assembly from the card reader and adjusted it.

A closeup of the brush module with 80 brushes that read a card.

A closeup of the brush module with 80 brushes that read a card.

After a few tries, we got the card reader to read the program successfully and it started executing. The line printer started rapidly and noisily printing the lines of the card. We had to adjust the line printer's top-of-form a couple times so the card fit on the page, but eventually we got a successful print.

Printing a greeting card on the IBM 1403 line printer.

Printing a greeting card on the IBM 1403 line printer.

I ejected the page from the printer, tore it off, and folded the card in quarters, yielding the final greeting card. It was a fun project, but Hallmark still wins on convenience.

Greeting card created by the IBM 1401 mainframe (background).

Greeting card created by the IBM 1401 mainframe (background).

If you want to know more about the IBM 1401, I've written about its internals here. The Computer History Museum in Mountain View runs demonstrations of the IBM 1401 on Wednesdays and Saturdays. It's amazing that the restoration team was able to get this piece of history working, so if you're in the area you should definitely check it out; the demo schedule is here.

Follow me on Twitter or RSS to find out about my latest blog posts.

Decoding an air conditioner control's checksum with differential cryptanalysis

Back in 2009 I wrote an Arduino library (IRRemote) to encode and decode infrared signals for remote controls. I got an email recently from someone wanting to control an air conditioner. It turns out that air conditioner remote controls are much complicated than TV remote controls: the codes are longer and include a moderately complex checksum. My reader had collected 35 signals from his air conditioner remote control, but couldn't figure out the checksum algorithm. I decided to use differential cryptanalysis to figure out the checksum, which was overkill but an interesting exercise. In case anyone else wants to decode a similar remote control, I've written up how I found the algorithm.

My IR remote library can be used with the Arduino to send and receive signals. (This is not the air conditioner remote.)

My IR remote library can be used with the Arduino to send and receive signals. (This is not the air conditioner remote.)

The problem is to find a checksum algorithm that when given three bytes of input (left), computes the correct one byte checksum (right).

10100001 10010011 01100011 => 01110111
10100001 10010011 01100100 => 01110001
10100001 10010011 01100101 => 01110000
10100001 10010011 01100110 => 01110010
10100001 10010011 01100111 => 01110011
10100001 10010011 01101000 => 01111001
10100001 10010011 01101001 => 01111000
10100001 10010011 01101010 => 01111010
10100001 10010011 01101011 => 01111011
10100001 10010011 01101100 => 01111110
10100001 10010011 01101101 => 01111111
10100001 10010011 01101110 => 01111100
10100001 10010011 01101111 => 01111101
10100001 10010011 01110001 => 01100100
10100001 10010011 01110010 => 01100110
10100001 10010011 01110011 => 01100111
10100001 10010011 01110100 => 01100001
10100001 10010011 01110101 => 01100000
10100001 10010011 01110111 => 01100011
10100001 10010011 01110111 => 01100011
10100001 10010011 01111000 => 01101001
10100001 10010011 01101000 => 01111001
10100001 00010011 01101000 => 11111001
10100001 00010011 01101100 => 11111110
10100001 10010011 01101100 => 01111110
10100001 10010100 01111110 => 01101011
10100001 10000010 01101100 => 01100000
10100001 10000001 01101100 => 01100011
10100001 10010011 01101100 => 01111110
10100001 10010000 01101100 => 01111100
10100001 10011000 01101100 => 01110100
10100001 10001000 01101100 => 01101100
10100001 10010000 01101100 => 01111100
10100001 10011000 01101100 => 01110100
10100010 00000010 11111111 => 01111110

The idea behind differential cryptanalysis is to look at the outputs resulting from inputs that have a small difference, to see what patterns emerge (details). Finding air conditioner checksums is kind of a trivial application of differential cryptanalysis, but using differential cryptanalysis provides a framework for approaching the problem. I wrote a simple program that found input pairs that differed in one bit and displayed the difference (i.e. xor) between the corresponding checksums. The table below shows the differences.

000000000000000000000001 : 00000001
000000000000000000000010 : 00000010
000000000000000000000010 : 00000011
000000000000000000000100 : 00000100
000000000000000000000100 : 00000110
000000000000000000000100 : 00000111
000000000000000000001000 : 00001100
000000000000000000001000 : 00001110
000000000000000000001000 : 00001111
000000000000000000010000 : 00010000
000000000000100000000000 : 00001000
000000000001000000000000 : 00011000
000000001000000000000000 : 10000000

The first thing to notice is that changing one bit in the input causes a relatively small change in the output. If the checksum were something cryptographic, a single bit change would entirely change the output (so you'd see half the bits flipped on average). Thus, we know we're dealing with a simple algorithm.

The second thing to notice is the upper four bits of the checksum change simply: changing a bit in the upper four bits of an input byte changes the corresponding bit in the upper four bits of the output. This suggests that the the three bytes are simply xor'd to generate the upper four bits. In fact, my reader had already determined that the xor of the input bytes (along with 0x20) yielded the upper four bits of the checksum.

The final thing to notice is there's an unusual avalanche pattern in the lower four bits. Changing the lowest input bit changes the lowest checksum bit. Changing the second-lowest input bit changes the second-lowest checksum bit and potentially the last checksum bit. Likewise changing the fourth-lowest input bit changes the fourth-lowest checksum bit and potentially the bits to the right. And the change pattern always has 1's potentially followed by 0's, not a mixture. (1100, 1110, 1111)

What simple operation has this sort of avalanche effect? Consider adding two binary numbers. If you change a high-order bit of an input, only that bit will change in the output. If you change a low-order input bit, the low-order bit of the output will change. But maybe there will be a carry, and the next bit will change. And if there's a carry from that position, the third bit will change. Likewise, changing a bit in the middle will change that bit and potentially some of the bits to the left (due to carries). So if you change the low-order bit, the change in the output could be 0001 (no carry), or 0011, or 0111, or 1111 (all carries). This is the same pattern seen in the air conditioner checksums but backwards. This raises the possibility that the checksum is using a binary sum, but we're looking at the bits backwards.

So I made a program that reversed the bits in the input and output, and took the sum of the four bits from each byte. The output below shows the reversed input, the sum, and the 4-bit value from the correct checksum. Note that the sum and the correct value usually add up to 46 or 30 (two short of a multiple of 16). This suggested that the checksum is (-sum-2) & 0xf.

110001101100100110000101 32 14
001001101100100110000101 22 8
101001101100100110000101 30 0
011001101100100110000101 26 4
111001101100100110000101 34 12
000101101100100110000101 21 9
100101101100100110000101 29 1
010101101100100110000101 25 5
110101101100100110000101 33 13
001101101100100110000101 23 7
101101101100100110000101 31 15
011101101100100110000101 27 3
111101101100100110000101 35 11
100011101100100110000101 28 2
010011101100100110000101 24 6
110011101100100110000101 32 14
001011101100100110000101 22 8
101011101100100110000101 30 0
111011101100100110000101 34 12
111011101100100110000101 34 12
000111101100100110000101 21 9
000101101100100110000101 21 9
000101101100100010000101 21 9
001101101100100010000101 23 7
001101101100100110000101 23 7
011111100010100110000101 17 13
001101100100000110000101 15 0 *
001101101000000110000101 19 12 *
001101101100100110000101 23 7
001101100000100110000101 11 3
001101100001100110000101 12 2
001101100001000110000101 12 3 *
001101100000100110000101 11 3
001101100001100110000101 12 2
111111110100000001000101 23 7

That formula worked with three exceptions (marked with asterisks). Studying the exceptions showed that adding in byte 1 bit 3 and byte 2 bit 7 yielded the correct answer in all cases.

Conclusion

Putting this together yields the following algorithm (full code here):

inbytes = map(bitreverse, inbytes)
xorpart = (inbytes[0] ^ inbytes[1] ^ inbytes[2] ^ 0x4) & 0xf
sumpart = (inbytes[0] >> 4) + (inbytes[1] >> 4) + (inbytes[2] >> 4) +
  (inbytes[2] & 1) + ((inbytes[1] >> 3) & 1) + 1
sumpart = (-sumpart) & 0xf
result = bitreverse((sumpart << 4) | xorpart)

Is this the right formula? It gives the right checksum for all the given inputs. However, some bits never change in the input data; in particular all inputs start with "101000", so there's no way of knowing how they affect the algorithm. They could be added to the sum, for instance, replacing the constant +1. The constant 0x4 in the xor also makes me a bit suspicious. It's quite possible that the checksum formula would need to be tweaked if additional input data becomes available.

I should point out that determining the checksum formula is unnecessary for most air conditioning applications. Most users could just hard-code the checksums for the handful of commands they want to send, rather than working out the general algorithm.

Thanks to Antonio Martinez Lavin, maker of the Cuby air conditioner controller for posing this problem. If you want to use my IR library, it is on GitHub. I'm no longer actively involved with the library, so please post issues on the GitHub repository rather than on this blog post. Thanks to Rafi Kahn, who has taken over library maintenance and improvement.

Follow me on Twitter or RSS to find out about my latest blog posts.

Hands-on with the PocketBeagle: a $25 Linux computer with lots of I/O pins

The PocketBeagle is a tiny but powerful inexpensive key-fob-sized open source Linux computer. It has 44 digital I/O pins, 8 analog inputs, and supports multiple serial I/O protocols, making it very useful as a controller. In addition, its processor includes two 200-MHz microcontrollers that allow you to implement low-latency, real-time functions while still having the capabilities of a Linux system This article discusses my experience trying out different features of the PocketBeagle, along with some technical details.

The PocketBeagle is a compact Linux computer, somewhat bigger than a quarter.

The PocketBeagle is a compact Linux computer, somewhat bigger than a quarter.

You may be familiar with the BeagleBone, a credit-card sized computer. The PocketBeagle is very similar to the BeagleBone, but smaller and cheaper. Both systems use TI's 1GHz "Sitara" ARM Cortex-A8 processor, but the PocketBeagle's I/O is stripped-down with 72 header pins compared to 92 on the BeagleBone. The PocketBeagle doesn't have the BeagleBone's 4GB on-board flash; all storage is on a micro-SD card. The BeagleBone's Ethernet and HDMI ports are also dropped.

The PocketBeagle uses an interesting technology to achieve its compact size—it is built around a System-In-Package (SIP) device that has multiple dies and components in one package (see diagram below). The Octavo Systems OSD3358-SM combines the TI 3358 Sitara processor, 512MB of RAM, power management and EEPROM. 1 In the photo above, this package has a white label and dominates the circuit board.

The PocketBeagle is powered by the OSD335x, which combines a processor die, memory and other components into a single package.

The PocketBeagle is powered by the OSD335x, which combines a processor die, memory and other components into a single package.

Initializing the SD card

To use the PocketBeagle, you must write a Linux file system to a micro-SD card. The easiest way to do this is to download an image, write it to the SD card from your computer, and then pop the SD card into the PocketBeagle. Details are in the footnotes.2

You can also compile a kernel from scratch, set up U-boot, and build a file system on the SD card. the PocketBeagle. There's a bunch of information on this process at Digikey's PocketBeagle getting started page. This is the way to go if you want flexibility, but it's overkill if you just want to try out the PocketBeagle.

Starting up the PocketBeagle

Unlike the BeagleBone, which supports a keyboard and an HDMI output, the PocketBeagle is designed as a "headless" device that you ssh into. You can plug the PocketBeagle into your computer's USB port, and the PocketBeagle should appear as a network device: 192.168.6.2 on Mac/Linux and 192.168.7.2 on Windows (details). You should also see a flash-drive style file system appear on your computer under the name "BEAGLEBONE". If the PocketBeagle has the default Debian OS3, you can log in with:

ssh [email protected]
Password: temppwd

Connecting to the PocketBeagle's serial console

While ssh is the simplest way to connect to the PocketBeagle, if anything goes wrong with the boot or networking, you'll need to look at the serial console to debug the problem. The easiest solution is a UART Click board4, which gives you a serial connection over USB. You can then connect with "screen" or other terminal software: screen /dev/cu.usbserial\* 115200

Plugging a UART click board into the PocketBeagle gives access to the serial console.

Plugging a UART click board into the PocketBeagle gives access to the serial console.

You can also use a FTDI serial adapter such as the Adafruit FTDI Friend. (If you've worked with the BeagleBone, you may have one of these already.) You'll need three wires to hook it up to the PocketBeagle; it won't plug in directly as with the BeagleBone. Just connect ground, Rx and Tx between the PocketBeagle and the adapter (making sure to cross Rx to Tx).5

Accessing the PocketBeagle's serial console through an FTDI interface.

Accessing the PocketBeagle's serial console through an FTDI interface.

Pinout

The PocketBeagle has two headers that provide access to I/O functions. (These headers are different from the BeagleBone's headers, so BeagleBone "capes" won't work with the PocketBeagle.) The PocketBeagle pinout diagram (below) shows what the header pins do. The diagram may seem confusing at first, since each pin has up to three different functions shown. (Most pins actually support 8 functions, so more obscure functions have been omitted.) The diagram is color coded. Power and system pins are labeled in red. GPIO (general-purpose I/O) pins are white. USB pins are blue. Analog inputs are yellow. UART serial pins are brown. PRU microcontroller pins are cyan. Battery pins are magenta. I2C bus is purple. PWM (pulse width modulation) outputs are light green. SPI (Serial Peripheral Interface) is brown. CAN (Controller Area Network) is dark green. QEP (quadrature encoder pulse) inputs are gray.9 The dotted lines in the diagram indicate the default pin functions (except for the PRU pins, which default to GPIO).6

Pinout diagram of the PocketBeagle's headers.
USB=blue, Power=yellow, GPIO=white, PRU=cyan, SPI=orange, UART=brown, and other colors are miscellaneous.

Pinout diagram of the PocketBeagle's headers. USB=blue, Power=yellow, GPIO=white, PRU=cyan, SPI=orange, UART=brown, and other colors are miscellaneous.

Note that the diagram shows the headers from the component side of the board, not the silkscreened side of the board. Comparing the pin diagram with the board (below), you will notice everything is flipped horizontally. E.g. GPIO 59 is on the right in the diagram and on the left below. So make sure you're using the right header!

Silkscreen labeling the PocketBeagle's header pins.

Silkscreen labeling the PocketBeagle's header pins.

One tricky feature of the Sitara processor is that each pin has up to eight different functions. The motivation is that the chip supports a huge number of different I/O functions, so there aren't enough physical pins for every desired I/O. The solution is a pin mapping system that lets the user choose which functions are available on each pin. 7 If you need to change a pin assignment from the default, the config-pin command will modify pin mappings. (Some examples will be given below.) Pins can also be configured at boot time using a "U-Boot overlay".8

GPIO

The PocketBeagle exposes 45 GPIO (general purpose I/O) pins on the headers. The pins can be easily controlled by writing to pseudo-files. For example, the following shell code repeatedly blinks an LED connected to GPIO 11110 (which is accessed through header pin P1_33).

echo out > /sys/class/gpio/gpio111/direction
while :; do
> echo 1 > /sys/class/gpio/gpio111/value; sleep 1
> echo 0 > /sys/class/gpio/gpio111/value; sleep 1
> done

An LED connected to header P1 pin 33 can be controlled through GPIO 111.

An LED connected to header P1 pin 33 can be controlled through GPIO 111.

PRU

One of the most interesting features of the PocketBeagle is its PRUs, two 32-bit RISC microcontrollers that are built into the Sitara processor chip. These microcontrollers let you perform time-critical operations (such as "bit-banging" a protocol), without worrying about context switches, interrupts, or anything else interfering with your code. At the same time, the ARM processor gives high performance and a complete Linux environment. (I've made use of the BeagleBone's PRU to interface to a vintage Xerox Alto's 3 Mb/s Ethernet.)

Although the PRUs are not as easy to use as an Arduino, they can be programmed in C, using the command line or Texas Instruments' CCS development environment. I've written about PRU programming in C before (link) and the underlying library framework (link) for the 3.8.13 kernel, but since then much has changed with the way the PRUs are accessed. The PRUs are now controlled through the remoteproc framework. In addition, a messaging library (RPMsg) makes it simpler to communicate between the PRUs and the ARM processor. A "resource_table.h" file provides setup information (such as the interrupts used).

The following code will turn the LED on (by setting a bit in control register 30), wait one cycle (5ns), turn the LED off, and wait again. Note that the PRU output is controlled by modifying a bit in register R30. This will blink the LED at 40Mhz, unaffected by any other tasks, context switches or interrupts. (For the full code and details of how to run it, see my github repository.)

void main(void)
{
  while (1) {
    __R30 = __R30 | (1<<1); // Turn on output 1
    __delay_cycles(1);
    __R30 = __R30 & ~(1<<1); // Turn off output 1
    __delay_cycles(1);
  }
}

This code uses PRU0 output 1, which is accessed through header pin P1_33 (the same pin as the earlier GPIO example). Since this pin defaults to the GPIO, it must be switched to a PRU output:11

config-pin P1_33 pruout

This LED example illustrates two key advantages of using the PRU versus controlling a GPIO pin from Linux.12 First, the PRU code can operate much faster. Second, the GPIO code will produce an uneven signal if the CPU is performing some other Linux task. If you can handle milliseconds of interruption, controlling GPIO pins from Linux is fine. But if you need exact cycle-by-cycle accuracy, the PRU is the way to go.

Networking

Unlike the BeagleBone, the PocketBeagle doesn't have a built-in Ethernet port. However, there are several options for connecting the PocketBeagle to the Internet, described in the PocketBeagle FAQ. I found the easiest was to use WiFi via a WiFi adapter plugged into USB, as shown below. An alternative is to share your host computer's Ethernet, which I found more difficult to get working.14 Finally, you can add an Ethernet interface to the PocketBeagle using the expansion headers.

A USB WiFi adapter can easily be connected to the PocketBeagle.

A USB WiFi adapter can easily be connected to the PocketBeagle.

USB

You can easily connect USB devices to the PocketBeagle since the PocketBeagle has pins assigned for a second USB port. Plug a USB Micro-B breakout board into the Pocket Beagle as shown below, connect a USB OTG host cable and your USB port should be ready to go. Note that this USB port is a host (i.e. a USB device is connected to the PocketBeagle) opposite from the onboard USB port which works as a client (the PocketBeagle is connected as a device to another computer).

A closeup of how to plug the USB breakout board into the PocketBeagle. It is connected to pins P1_7 through P1_15.

A closeup of how to plug the USB breakout board into the PocketBeagle. It is connected to pins P1_7 through P1_15.

For instance, you can plug in a flash drive. (In the picture below, note that the flash drive is almost as big as the PocketBeagle.) The lsusb command will show your device, and then you can mount it with sudo mount /dev/sda1 /mnt.

Connecting a USB device (flash drive) to the PocketBeagle.

Connecting a USB device (flash drive) to the PocketBeagle.

Analog inputs

The PocketBeagle has 8 analog input pins. Six of them take an input from 0 to 1.8V, while two take an input from 0 to 3.3V. (Be careful that you don't overload the input.) The analog input value (between 0 and 4095) can be read from the file system as shown below. Change the number in voltage0 to select the input. (Inputs 5 through 7 require special handling.15)

$ cat /sys/bus/iio/devices/iio:device0/in_voltage0_raw
2510

In the photo below, I hooked up a light sensor (CdS photocell in a voltage divider) to provide a voltage to analog input 0 (header pin P1_19). The reference voltages come from header pins P1_17 (analog ground) and P1_18 (analog reference 1.8V). More light on the sensor produces a higher voltage, yielding a higher value from the input.

A photocell can be hooked up to the PocketBeagle's analog input to provide a light sensor.

A photocell can be hooked up to the PocketBeagle's analog input to provide a light sensor.

I2C / SPI

The PocketBeagle supports two SPI ports and two I2C ports. These serial protocols are popular for controlling chips and other devices.

An accelerometer board (left) can be connected to the PocketBeagle's I2C port with four wires.

An accelerometer board (left) can be connected to the PocketBeagle's I2C port with four wires.

For example, the photo above shows a cheap I2C accelerometer board connected to the PocketBeagle's SPI port. Simply wire the power, ground, SCL (clock) and SDA (data) between the accelerometer and the PocketBeagle's I2C1 port (i.e. header P2 pins 13, 15, 9, 11). Probing for I2C devices with i2cdetect will show that the device uses address 68. The device can be turned on with i2cset and the registers dumped out with i2cdump to obtain acceleration values.16

Using an I2C-based accelerometer board with the PocketBeagle.

Using an I2C-based accelerometer board with the PocketBeagle.

Conclusion

The PocketBeagle is a low-cost, compact Linux computer, able to control external devices with its I/O ports and GPIO pins. Since the PocketBeagle was released recently, there isn't a whole lot of documentation on it. Hopefully this article has shown you how to get started with the PocketBeagle and use some of its features.

New (12/2017): The PocketBeagle System Reference Manual has lots of useful information, so take a look.

For more information, see the PocketBeagle FAQ and Getting Started pages. Also remember that the PocketBeagle uses the same processor and Linux kernel as the BeagleBone, so most of the information on the BeagleBone will carry over to the PocketBeagle. I've found the book Exploring BeagleBone to be especially helpful. Thanks to Robert Nelson and DigiKey for giving a PocketBeagle tutorial at Hackaday Superconference.

Follow me on Twitter or RSS to find out about my latest blog posts.

Notes and references

  1. The Octavo package reminds me a bit of the Solid Logic Technology (SLT) modules that IBM used in the 1960s instead of integrated circuits. They consisted of small metal packages containing semiconductor dies and resistors connected together on a ceramic wafer, and were used in computers such as the IBM 360.

    Two IBM SLT modules, with a penny for scale. Each module contains semiconductors (transistors or diodes) and printed resistors wired together, an alternative to integrated circuits.

    Two IBM SLT modules, with a penny for scale. Each module contains semiconductors (transistors or diodes) and printed resistors wired together, an alternative to integrated circuits.

  2. On a Mac, I used the following procedure to write the SD card. First, download an image from beagleboard.org. I use "Stretch IoT (non-GUI) for BeagleBone and PocketBeagle via microSD card". Then unmount the SD drive and format it as FAT-32. (Replace XXX below with the right drive number; don't format your hard disk!)

    diskutil list
    diskutil umountdisk /dev/diskXXX
    sudo diskutil eraseDisk FAT32 BEAGLE MBRFormat /dev/diskXXX
    sudo diskutil unmount /dev/diskXXXs1
    
    Then write the disk image to the SD card:
    zcat /tmp/pocketbeagle.img | sudo dd of=/dev/diskXXX bs=2m
    xzcat *.xz | sudo dd of=/dev/diskXXX
    
    Writing the image took about 10 minutes with a USB to micro-SD adapter. (If it's taking hours, I recommend a different USB adapter.) When done, install the SD card in the PocketBeagle. 

  3. I'm using Debian with kernel Linux beaglebone 4.14.0-rc8 #1 Mon Nov 6 15:46:44 UTC 2017 armv7l GNU/Linux. If you use a different kernel (such as 3.8.13), many of the software features will be different. 

  4. One interesting feature of the PocketBeagle is its headers have the right pinout to support many mikroBUS boards. This is an open standard for small boards (similar to capes/shields), using a 16-pin connector. Hundreds of "click boards" are available for connectivity (e.g. Bluetooth, WiFi, Ethernet, NFC), sensors (e.g. pressure, temperature, proximity, accelerometer, seismic), security coprocessors, GPS, electronic paper, storage, and many more functions. The PocketBeagle doesn't officially support mikroBUS, but many boards "just work" (details). 

  5. For the FTDI serial connection, connect Gnd to P1_22, Rx to P1_30 (UART0 Tx) and Tx to P1_32 (UART0 Rx). 

  6. The PocketBeagle device tree file specifies the default pin mappings and names other pin mappings. But if you want to track down the actual hardware meaning of each header pin, it's complicated. The PocketBeagle schematic shows the mapping from header pins to balls on the Octavo chip package. The Octavo OSD335x documentation gives ball map to the Sitara chip. The Sitara AM335x datasheet lists the up to eight functions assigned to each pin. The Technical Reference Manual Section 9.3.1.49 describes the control register for each pin. Thus, it's possible but tedious to determine from "first principles" exactly what each PocketBeagle header pin does. 

  7. There are a couple problems you can encounter with pin mapping. First, since not all chip pins are exposed on PocketBeagle headers, you're out of luck if you want a function that isn't wired to a header. Second, if you need two functions that both use the same pin, you're also out of luck. Fortunately there's enough redundancy that you can usually get what you need. 

  8. The PocketBeagle uses U-Boot The U-Boot overlay is discussed here. For more information on device trees, see Introduction to the BeagleBone Black device tree

  9. The Technical Reference Manual is a 5041 page document describing all the feature of the Sitara architecture and how to control them. But for specifics on the AM3358 chip used in the BeagleBone, you also need to check the 253 page datasheet

  10. Note that there are two GPIO numbering schemes; either a plain number or register and number. Each GPIO register has 32 GPIOs. For example, GPIO 111 is in register 3 and also known as GPIO 3.15. (3*32+15 = 111) 

  11. To switch P1_33 back to a GPIO, use config-pin P1_33 gpio.

    Internally, config-pin writes to a pseudo-file such as /sys/devices/platform/ocp/ocp:P1_33_pinmux/state to cause the kernel to change the pin's configuration. 

  12. You can control GPIO pins from a PRU. However, there will be several cycles of latency as the control signal is delivered from the PRU to the GPIO. A PRU pin on the other hand can be read or written immediately. 

  13. WiFi on the PocketBeagle is easy to set up using a command line program called connmanctl. Instructions on configuring WiFi with connmanctl are here and also are listed in the /etc/network/interfaces file. (Don't edit that file.) When I started up connmanctl, it gave an error about VPN connections; I ignored the error. I tested WiFi with a Mini USB WiFi module and an Ourlink USB WiFi module

  14. Sharing an Internet connection with the PocketBeagle isn't as simple as I'd like. To share with Windows, I followed the instructions here and here. (Note that BeagleBone instructions should work for the PocketBeagle.) I haven't had much luck with MacOS. In any case, I recommend connecting to the serial console first since there's a good chance you'll lose any SSH connection while reconfiguring the networking. 

  15. Analog input pins 5 and 6 are shared with a GPIO pin via a voltage divider. To use one of these inputs, you must configure the shared GPIO as an input with no pullup/down so it won't affect the analog value. In addition, the input voltage is divided by 2 (so these pins can support up to 3.3V instead of 1.8V).

    # Analog input 5 (P2_35)
    $ config-pin P2_35 gpio
    $ echo in > /sys/class/gpio/gpio86/direction
    $ cat /sys/bus/iio/devices/iio:device0/in_voltage5_raw
    # Analog input 6 (P1_2)
    $ config-pin P1_2 gpio
    $ echo in > /sys/class/gpio/gpio87/direction
    $ cat /sys/bus/iio/devices/iio:device0/in_voltage6_raw
    

    Analog input 7 (P2_36) is multiplexed by the power management IC (PMIC). It supports a maximum voltage of 1.8V. To read the value, you must first configure the PMIC:

    $ sudo i2cset -y -f 0 0x24 9 5
    $ cat /sys/bus/iio/devices/iio:device0/in_voltage7_raw
    
     

  16. In the accelerometer example, the board is approximately vertical with the chip's X axis pointing up. The X, Y, and Z accelerations returned by i2cdump in the screenshot were 0x42a8, 0x02dc, and 0x1348. These are signed values, scaled so 16384 is 1G. Thus, the X acceleration was approximately 1 G (due to Earth's gravity) while the other accelerations were small. These values change if the board's orientation changes or the board is accelerated. The temperature is 0xed10, which according to the formula in the register map yields 22.3°C or 72°F. The last three words are the gyroscope values, which are approximately 0 since the board isn't rotating. For more details on the accelerometer board see the register map, the datasheet and this Arduino post