Resurrected LED panels


I just finished building a frame for some resurrected LED panels from a decommissioned super computer. The computer was a CM-5 by Thinking Machines. It has been used at the College of Oceanography and Atmospheric Science at Oregon State for a fairly long while. A few weeks ago, its time came, and we surplussed it. I was able to get the light panels and built a frame for them at my house. This post describes a little about the process and includes some trivia about the CM-5 and the panels themselves.


The CM-5 in name alone probably doesn’t resonate with many people, but hopefully you can recognize it in the background of this photo from Jurassic Park:

Now, I don’t want to slide my glasses up my nose an snort, but the way they’re setup in this image is not at all like how would they be setup in real life. The installation engineer that setup ours had to leave half-way through to setup the Jurassic Park set. These are simply the empty chassises with the light panels. The CM-5 was also 3rd in this list of Top Ten Coolest and Most Powerful Supercomputers. The previous link has an image that shows how it would actually be setup. On top of the machine there are huge bundles of wires.

Anyway, I’m not writing this post to discuss the history of the CM-5, at least not that much, so I’ll get on with the LED panel build. It’s a really simple idea; I laid them out on the floor and measured the dimensions of their perimeter. Using these measurements, I built a simple wooden frame out of 1×2″ maple. The width of the panel is considerably less than the width between studs in my wall, so I had to secure it to a single stud on the top and bottom of the frame.

Bottom of frame and backside of one module

The location I chose for the frame covered an outlet; This not only made it easier to route the cord (I didn’t have to make a cutout), but it also looks much cleaner. Of course, I would need a way to turn it on and off. To do this, I chose an X10 transciever/switch. I covered the antenna with shrink-wrap to avoid shorting anything out. Also, I had to turn the outlet in the wall upside down because the X10 module has the plug coming out on the bottom.

X10 module installed in a reversed outlet

The next challenge was securing the power supplies into the frame. The frame was just thick enough to accommodate the supplies, but it left me little room to attach it.

Power supply against frame

There were mounting holes and a small recess in the heat sink, but the holes were far too large to thread to the hardware I was using. I tried to drill and tap new holes for 4-40 hardware.

It broke my tap!

Unfortunately, the heat sink is made of some bizarre metal that really doesn’t like to be tapped (turns out it’s aluminum). It felt very gummy, if that makes any sense. When I tried to unscrew the tap it broke right off. I tried a few different things, including sharpening the other, broken, end of the tap into a new tip. Really none of these things worked. I was practicing on a bad supply, and I decided to just take it apart and see if there was anything else I could do. When I did, I discovered that they used some strange self-tapping 4-40 screws.

Self-tapping 4-40 screws

These screws mostly did the trick.

Mounted power supplies

Once the power supplies were mounted, I attached the frame to the wall, and began wiring. Notice, in the image above, that the output ends of both supplies are near each other. This is because I wanted to use the factory wiring harnesses from the CM-5.

Low voltage DC wiring

Everything on that machine was overbuilt. Each of those supplies can source 30 Amps at 5 Volts. Each panel requires in the neighborhood 5-7 Amps, so there is almost 3x over provisioning. Not only are the supplies overbuilt, but the cabling is also a little over-the-top. It’s really a testament to the scale of the whole machine. While talking about it to those that used it, I often heard “when something costs $20 million, you expect a certain level of quality.”


Here I am testing the final wiring for a single LED module. The bottom rows are dark, not because they aren’t on, but because they’re painted black. When it’s installed in the computer, you can’t see these rows because they’re covered up, so for some reason they just painted them black. If you look close, you can see though the paint a bit at and see the lights.

Narrow margins

Here, you can see just how tight the fit of everything in the frame really is. There is barely enough room for the power connectors and cables, let alone the power supplies and X10 module.

installing modules

The modules install simply and cover up all the wiring and electronics.

All finished!

Finally, we’re all done!! The whole system looks amazing. One factoid that I find pretty interesting is that the “random and pleasing mode #7” produces exactly the same “random” pattern on every module! Next on the docket: reverse-engineering them to display messages and designs! Also, make sure to see my gallery of the process of surplussing the computer.


Someone asked about the details of the silkscreen on the LED panel.  Hopefully this image clearly displays how it was made.



Update 2:

I found some video at work of the CM5 (really, a CM500, but that’s another story) being installed.  I cut it down a bit, it was about an hour long.  I think that it was installed in 1995, but I’m not sure of the date more precisely than that.

At 4:29, you can see the edges of the CPU board.  They each have 8 banks of 4 LEDs.  I took a picture of the edge of the board for those that are curious.

Edge of the CM5 CPU board

Edge of the CM5 CPU board

  1. #1 by Mark on March 25, 2016 - 2:51 am


    tried that, until now no sucess, out of 64 bits if found only up to 62 identical in 4 lines.
    i searched for this from the picture on this webpage.

    int pattern1[4][16]={


    int pattern2[4][16]={


  2. #2 by iskunk on March 27, 2016 - 10:11 pm

    I tried searching for those patterns, twiddling each and every parameter and burning up quite a bit of CPU in parallelized jobs—and am afraid to report, no dice 🙁

    Barring another helpful revelation from an ex-TMC employee, I think we’ll need to settle for “close enough.”

    Any more details on your build?

  3. #3 by Mark on March 28, 2016 - 5:24 am

    Got to the same conclusion so far which is very sad considering we have a lot of information how it was done originaly. I still believe there can´t be missing much.

    For the hardware side the ebay panels from china are nearly perfect for this so there is not much to do or to say, it just works.

    There are a few seconds video from a CM5 in a Documentary on youtube “The Fantastic Mr Feynman” which i haven´t seen before. Not that this helps much but since video content of a CM5 seems rare, i wanted to mention it.

    Let´s hope someone else jumps in to help in our topic in reproducing the original blinking pattterns.

  4. #4 by iskunk on March 29, 2016 - 6:18 pm

    The Feynman video, alas, only shows the CM5 briefly at a low resolution—no way to get anything off of that. I found a few high-res photos that show the full pattern, but no telling if those are from the “random and pleasing” mode we’re after.

    I suspect the real CM5 uses 32 shift registers instead of one, since Jim said that the final XOR was added as an eleventh-hour hack to get “the effect that was desired.” The effect that wasn’t desired was probably the “dense” pattern we saw earlier, when the shift registers were displayed directly. It makes sense that the pattern was originally conceived as a bunch of shift registers shifting visibly, and modified late in the game via minimal postprocessing. But sadly, that intuition led me nowhere in my search.

    Be sure to document your build, so that even us non-hardware-hacker types can build our own pretend-CM5 ^_^

  5. #5 by Mark on March 30, 2016 - 3:45 pm

    in the mean time i tried to contact other cm5 developers, even the lead developer of the cm5. They were reacting very fast to email and tried to help, thank you very much, cm5 team, i didn´t expect so many response so quickly. But they told me that Jim is the only person who has done the microcontroller code, nobody else seems to have any insight how the random modes work.

    If you watch the Feynman video you see letter combinations like TXY and CXF scrolling which i never got with pure random data.
    This is like the LT and F letters and arrows on other videos, i´m not sure if this can be done with the random generator only.
    It is unlikely that bitmap Graphics for these Chars were inserted in the random stream. But it is not impossible to do, even on a microcontroller.

    If this really is generated randomly, only Jim can tell us what we are doing wrong not to get that same output.

  6. #6 by iskunk on March 30, 2016 - 7:19 pm

    I’m all but certain that bitmaps aren’t a part of it. Those are much more plausibly an unexpected result of the logic, rather than something the CM5 devs explicitly wanted. All they were after was a cool pattern that didn’t take much time to implement; it’s not like they had that specific an idea of what it should look like from the get-go.

    But it’s great that you’ve been able to get in touch with them! Looks like Jim is still our man. I’m sure that if you gave him that little program I wrote, he’d spend five minutes making a few edits and the mystery would be solved.

    (Here‘s the latest revision of my code, by the way. This one has the 32 unique rows instead of 128, and also displays only 106 rows, as the last 22 rows on the bottom module are painted black.)

  7. #7 by Jim on April 4, 2016 - 6:03 am

    Sorry not to get back to you sooner, but it looks like you’re having so much
    fun with this.

    The controller is an 8-bit processor, the Intel 8741. The code was written
    in Intel Macro Assembler. So the random number, RNUM, occupies two bytes.
    BTW, it doesn’t matter what seed value you use so long as it’s not all zeroes.

    There are two JTAG chains (of LEDs) on the panel. If memory serves, the top
    half is one chain, and the bottom half is the other. The JTAG chains act as
    the storage for the pattern. The code calls the RAND subroutine, and gets a
    random bit which is pushed into the top JTAG chain. Then calls RAND again, and
    pushes the next random bit into the lower JTAG chain. Note that RAND shifts
    the primitive polynomial each time it is called. After both JTAG chains get a
    new random bit, they are both shifted. When enough bits are stuffed into the
    JTAG chains for all of the LEDs, the new random pattern is latched in all of
    the LEDs simultaneously. The whole thing is timed so that the LEDs update
    every 200ms. The hardware was designed so that a logic 0 turns the LED on, a
    logic 1 turns the LED off.

    Here’s a snippit of the actual code for the random number generator.

                ;This subroutine implements a 16 bit random number generator based
                ;on the primitive polynomial:
                ;       1 + X + X^3 + X^12 + X^16
                ;The value is stored in memory as RNUM.  This subroutine returns
                ;with the low order byte of the RNUM in the accumulator and a random
                ;bit value in the Carry (C) bit.
    rand:  mov C, RNUM.0           ;get the units value of the PP
             jnb RNUM.1, rand1     ;jmp if X = 0
             cpl C                 ;else compliment C (xor)
    rand1: jnb RNUM.3, rand2       ;jmp if X^3 = 0
             cpl C                 ;else compliment C (xor)
    rand2:  jnb (RNUM+1).4, rand3  ;jmp if X^12 = 0
             cpl C                 ;else compliment C (xor)
    rand3:  mov A, RNUM+1          ;get high byte of RNUM
             rrc A                 ;and rotate down (thru accumulator)
             mov RNUM+1, A         ;save it back to memory
             mov A, RNUM           ;get low byte of RNUM
             rrc A                 ;and rotate down (thru accumulator)
             mov RNUM, A           ;save it back to memory
             orl C, RNUM.1         ;set C only 25 percent of the time
             ret                   ;return
  8. #8 by Jim on April 4, 2016 - 6:14 am

    Sorry, I couldn’t get the formatting of the subroutine correct here.

    And yes, I mis-remembered. The low two bits are ORed (not XORed).

  9. #9 by hpux735 on April 4, 2016 - 8:46 am

    I took the liberty of editing Jim’s comment to format the code block a bit. I installed markdown, so if you want to use three backticks to delimit code blocks that works more reliabily. Also, you can use the ‘pre’ and ‘code’ html tags to do the same thing.

  10. #10 by Mark on April 4, 2016 - 2:04 pm


    thank you very much for your new reply, i think iskunk and i haven´t had any hope getting more details from you anytime soon.
    your new information is pretty clear and doesn´t leave room for much further interpretation.

    Saying that you ORed at the last step and displayed the “0” bits further makes me more confident and feel that staring at the blinkenlight patterns for hours i was on the right track.

    but i have to tell you, even if i flip everything around, reverse directions, up/down the two chains etc. i can not get a 100% match of the 16×32 display, referencing to the rare seconds of video available.

    That means that

    either i am missing something or

    the polynomial in your assembler code with 2 8bit integers or iskunks latest version with 1 16bit integer is doing something different.

    Or – that in the videos we don´t see your pure random and pleasing code.
    For example, i noticed that in the “NSA” Video on youtube, on the second near machine it looks like a much denser pattern (50% on ? ) in running.
    In your description of the rotary switch of the panels, which sounds very complete, there is no mentioning of a denser scrolling pattern.

    It would be great if you can clarify these last mysteries :_) and i hope iskunk is coming with something i simply have missed.


  11. #11 by Mark on April 4, 2016 - 2:25 pm

    @dear Jim:

    after reading your last post for a few more times, it sounds to me like you are describing the pattern which replaces the whole display (every LED) with a new random pattern every cycle.

    Iskunk and i are talking about the scrolling pattern where every 4 lines are interleaved.

    I think both modes obviously use the same random generator or at least something close to it – but we were talking about the scrolling lines.


  12. #12 by iskunk on April 4, 2016 - 3:18 pm

    Okay, here’s my latest code, updated with Jim’s new information.

    I’ve done a rough translation of his assembly code into C, and my code compares the results of that with the C expression I was using earlier. There are a couple things I’ve found:

    The primitive polynomial looks like it doesn’t actually use the X^16 term. The assembly uses bits 0, 1, 3, and 12, but I don’t see that the top bit of RNUM figures into the calculation.
    The final OR is not between bits 0 and 1, but bits 0 and 2 (before the shift).

    Both of these hinge on the correctness of my C translation of Jim’s code, of course. I used this 8041 instruction set reference along the way. (The 8741 appears to be an equivalent part.) Anyone who’s interested, please review that code closely.

    One still-unknown is how this stream of random bits is mapped into the left/right shifting rows. My code starts from the top row and scans downward, inserting the new bit at the left or right end of the row depending on the direction. This seems intuitive, but of course it could be wrong.

    A few remaining nits:

    Anyone know Jim’s full name, for proper crediting?
    The comment on the ORL instruction: Shouldn’t “25 percent of the time” refer to the panel LED, not the C flag, which would presumably be true 75% of the time after this OR operation? (Assuming C=true means LED=off)
    I’m obviously not going to say Jim is wrong, but I’d really like to clear up the apparent contradictions in the information he’s provided. (Jim, pretty please? 🙂
    When the pattern starts, are the LEDs all on, or all off?

  13. #13 by Jim on April 5, 2016 - 10:42 am

    Thanks for doing the reformatting. Much easier to read now.

    In words, here’s what the subroutine does:

    XOR bits 0, 1, 3, 12 of RNUM and put the result in the carry bit.
    Right shift RNUM so that the carry bit is shifted into bit 15 of RNUM, and what
    was bit 0 of RNUM, is shifted into the carry bit.

    Remember, there is a call to RAND for each of the two JTAG chains. So each
    chain gets every other bit of the random number. That’s why the OR between
    C and rnum.1 i.e. two adjacent bits of the random number assigned to a
    particular JTAG chain. In reality, it probably doesn’t matter, but that’s what
    I did.

    Mark – I’ve been talking about mode 5 – Random and Pleasing.
    There’s also mode 7 – Interleaved Random and Pleasing.
    Not sure which one you’re trying to reproduce. Yes, they both call the same
    RAND subroutine. Regardless, I don’t have any info on what was shown in the
    movie or videos you reference. Perhaps hpux735 can clarify as he has the the
    real panels.

    iskunk – No need for my full name, I like to keep a low profile. But thanks.
    Yes, the comment “25 percent of the time” refers to the LED panel, not the
    C bit. Probably could have worded it better.

  14. #14 by iskunk on April 5, 2016 - 11:59 am

    Hi Jim!

    From my reading of the Wikipedia page on linear feedback shift registers, the least-significant bit is x^16, so your primitive polynomial would appear to be formally written as

    x^16 + x^15 + x^13 + x^4 + 1

    (I’ve reproduced the operation of your assembler code in C, and presuming I did that correctly, I have a native-C implementation of the PP that is equivalent.)

    Mode 7 is the one we’re after, as that is the most “iconic” pattern, but there’s no reason not to try for the others if it’s just a bit more doing on top of what we’ve already done.

    Fellow poster Mark is keen on an exact reproduction of the pattern, such that it will eventually match up to frame grabs from videos of real CM-5 systems. Given that the pattern operates deterministically, this would be pretty cool. (Right now, our code is already yielding a decent facsimile.)

    One detail I’m still missing is how the stream of bits is fed into the left/right moving rows, especially in light of the JTAG interface. Here is what my current code is doing:

    (top of 16x32 panel)
    <--- 1 (1st bit out of rand function)
    <--- 2 (second bit)
    <--- 3 (third bit)
    <--- 4
    5 --->
    6 --->
    7 --->
    8 --->
    <--- 9
    <--- 10
    <--- 27
    <--- 28
    29 --->
    30 --->
    31 --->
    32 --->
    (bottom of 16x32 panel)

    So I shift the rows, and then the “holes” at the left or right end of each row are filled in with the stream of random bits, going consecutively from the top row down to the bottom row. (From what you’re saying, however, this might actually be something like [from the top row down] 1, 3, 5, … 31, 2, 4, 6, … 32 ?)

    It would be helpful to have the initial seed as well, since one of the easiest ways of validating the logic is that it reproduces the first few iterations of the pattern on a real panel.

    Re name: Okay, I’ll credit you as Jim@XXX (where XXX is the acronym of your old employer), unless you have a handle you’d rather I use 🙂

  15. #15 by Mark on April 5, 2016 - 1:09 pm

    Hello Iskunk,

    we have already answers to some of these questions.

    Even that Jim described Mode 5 in more detail and we are after 7, the technical way to fill the display would be the same since it is a serial interface and it is obvious to fill it up with data as quickly as possible.

    So think JTAG 1 fills row 0-15 and JTAG 2 fills 16-31 or the reverse order.

    The most significant information i got from Jim latest post is that only one random output stream is switched between these 2 parts. He wrote:

    Remember, there is a call to RAND for each of the two JTAG chains. So each
    chain gets every other bit of the random number. That’s why the OR between
    C and rnum.1 i.e. two adjacent bits of the random number assigned to a
    particular JTAG chain.

    So this sounds to me ORs the 2 most top bits , ORs the 2 lowest bits and send one result to chain1 and the other result to chain2.
    Or he just switches the output for the parts with every iteration.

    I already tried out to just switch the output and it looks better to me but still not a full pattern match. have not tried to get both output pairs from one random value,yet.

  16. #16 by iskunk on April 5, 2016 - 1:52 pm

    Mark, there is no OR-ing of the top two bits; Jim’s code shows as much. The “rand” function is just called however many times is needed.

    Assuming that there is a single bit-generator (not two operating in parallel), and thus one stream of random bits coming out of that, the question is how those are distributed to the 32 rows.

    Incidentally, I was able to get a match on the output to the pattern in the “All finished!” photo above. Here’s the full transcribed pattern (0=dark, 1=lit):


    /* Conversion to C array: leftmost bit = most significant */
    uint16_t pattern_rows[] = {

    In order to get the match, however, I had to (1) flip all the bits, so 0=lit like Jim said; (2) mirror the bits left-to-right, so the most-significant bit is on the right, and (3) mirror the bits top-to-bottom, so rows[0] is the bottom row instead of the top.

    I get the match without knowing the initial seed value because since the function period is 65535, and we call the function 32 times for each “frame” of the pattern… 65535 and 32 are relatively prime, so eventually the pattern shifts up on the panel over time. (This means that the whole pattern repeats every 65535*32/5/3600 = 116.5 hours.) But if you want the pattern to start out the same as a real panel, and a specific frame of the pattern to come up after the same amount of time, then you need to know the seed.

    So I can’t be too sure that this is a real match, or just a fluke. But still, it sure makes one feel like they’re getting warmer!

  17. #17 by Mark on April 5, 2016 - 2:33 pm

    iskunk i can´t believe you got a full matching pattern this is absolutly amazing.

    since the random generator is “only” 16 bit, you can run all iterations without knowing the seed.
    on my computer without displaying anything it takes < 1second.

    if we compare 1-3 known sequenced frames from a video against all 16bit possibilities , shouldn´t we be able to come up with the seed?

    how much else did you change on your last code, except the mirroring and flipping?


  18. #18 by iskunk on April 5, 2016 - 3:14 pm

    You can’t determine the seed from matching frames, because the frames lack one critical bit of information: time. You don’t know if the frame (or video clip) was filmed one minute, or one hour, or one week after the pattern started up. (From the time, you can determine that a given frame is the Nth frame of the pattern—N is what you need to know to find the seed.)

    No further changes were needed to get that match, other than the search code itself. I used memcmp() to do the comparing. Let me know if it’s not working for you…

  19. #19 by Mark on April 5, 2016 - 3:39 pm

    ok i think im getting it.


    the seed also can be only a value between 0 and 65535, right?

    one full loops takes about a second.

    so if you loop from 0 to 65535 as the starting seed and then compare the output of all frames from that to about 3 or more frames known sequential frames –

    and you get matching frames – shouldn´t that find the initial seed?

    if this makes any sense, i glady share a lot of cpu time to find that if you help me with the code!


  20. #20 by iskunk on April 5, 2016 - 3:51 pm

    That won’t do it. You’ll get matches regardless of the seed you choose; I got my matches with seed=1. The question is how many iterations until the desired frame occurs. In my case, the first match came up after around 400K iterations, which would mean upwards of 22 hours after the pattern started. I don’t think Dillon was running the panel for 22 hours before photographing it.

    Our best prospect, short of Jim telling us what the seed is, is to get video of the real panel as the pattern starts up (presumably right when you turn the mode-select knob).

  21. #21 by Mark on April 5, 2016 - 4:13 pm

    i have never seen a cm5 panel starting up. but if i had programmed it, i would skip the output of the first iterations < WIDTH of the display to get a full, completly filled and nice screen with the first output filling all of the display.
    So the first visible output on the display would be then iteration 16 or 17.
    If this is reality, and the cm5 panels do so, i have no idea.

    we have to ask hpux735 if he can provide us a video of the panel starting. if it starts filling the first bits, you would have the starting seed. if it starts with a full panel, we are missing the first 16 or more steps and have starting seed+16 or 17.
    Then only Jim can help us out.

    Would you share your latest code version with me so i could take this as a new starting point to exchange information with you ? my embedded version is kind of outdated compared to the latest information from Jim you added sucessfully.

  22. #22 by hpux735 on April 5, 2016 - 4:58 pm

    You guys are killing me (in the best way!). I was working on a present for you (which I’ll still do because it should be worth it), but for now I’ll give you the first part of it. Here’s a link to a video of the first minute of the panel starting up:

  23. #23 by iskunk on April 5, 2016 - 10:20 pm

    EUREKA!!! I’ve got it!!

    Thank you very kindly Dillon, that video was just what we needed ^_^

    The seed is 0xBAD. (Oh Jim, you rascal you)

    The rows are filled like I was doing it, but starting from the bottom row consecutively up to the top row. The JTAG stuff doesn’t appear to figure into this.

    The first pattern-frame (all but 3 LEDs lit), I’ve hard-coded. Probably just an artifact of the mode-switch.

    The second pattern-frame (at 00:18), I have no idea where that comes from. It doesn’t look pseudo-randomly generated. All I know is that this frame already has the first 32 random bits inserted into the appropriate places. For now, I’ve slurped this into an initialization table, but it would be nice to suss out how it’s generated. (I doubt the real thing is using a table.)

    Here is my latest code. It successfully reproduces the entire sixty seconds of patterning in Dillon’s video. To help verify this, this revision only prints 32 rows, and calculates/prints a timestamp corresponding to the one in the video. (I used MPlayer, and stepped through the video frame-by-frame with the “.” [period] key.)

    Dillon: Bet you never thought your site would become the Internet’s clearinghouse for CM-5 random-and-pleasing blinkenlights pattern recreation, did you? 🙂

  24. #24 by Jim on April 6, 2016 - 7:05 am

    Yup, you got the seed I used. In reality though, it doesn’t matter. Any seed
    value between 0x0001 and 0xFFFF will produce the exact same string of random
    bits. The only difference is the starting point.
    As an example, look at the video, at some random time after start, and take
    16 adjacent bits from the top row. Use this as a seen in your random number
    generator. From this point on, your pattern should match the video.

  25. #25 by Mark on April 6, 2016 - 9:24 am

    Iskunk, yes this is the 1:1 output i was looking after.
    Thank you Iskunk and thank you Jim, this is just amazing.

    iskunk: don´t waste any time in searching for the “init-glitching” of the display, this is most certainly not part of the code but a pure hardware thing like that the latching of the led rows at the first step is missing or the panel isn´t fully initialized, yet.

    i can confirm that i get full matches to other video sources showing mode 7, so this is really completed:-)

    About mode 5 (the full random display without scrolling):
    I don´t like this mode so much but i´ll try out today if this is just a simplified version of mode 7 with maybe a slightly modified output. will tell you my findings later today.

  26. #26 by Mark on April 6, 2016 - 10:35 am

    For Mode 5, changing

    uint16_t rand_bit = (X | (X >> 2)) & 1;
    uint16_t rand_bit = (X | (X >> 1)) & 1;

    in the get_random_bit function might be all to get the right look.

  27. #27 by iskunk on April 6, 2016 - 10:35 am

    While any other seed would work, it would be less obvious that our code was really doing the same thing. We wanted that extra bit of authenticity 🙂

    Okay, so that “glitch” frame is basically uninitialized memory. Works for me. Can anyone confirm that this will be a different/undefined/unpredictable arrangement every time the pattern starts? (If so, storing this frame in an initialization table probably doesn’t make sense.)

    Mode 5 should be doable! It’s just a matter of determining in what sequence the panel is populated with random bits.

    Dillon, once again, thank you for the video. Props, too, for your evident care in making it—the head-on angle (which made transcription of the LEDs easier), the frame-exact timestamp, and time-basing it perfectly on the start of the pattern. Be sure to get this up on YouTube! This is a real resource, and it should be out there.

    But I’m curious about the other parts of this present you’ve been working on… ^_^

  28. #28 by iskunk on April 6, 2016 - 10:42 am


    Hmm. That’s technically changing the random function, which according to Jim is the same in the different R&P modes.

    Have you found any videos that show mode 5 in enough detail to transcribe LEDs? (I sure haven’t.) We can get something that looks “about right” easily enough, but at this point a bit-perfect reproduction should be within reach…

  29. #29 by Mark on April 6, 2016 - 10:58 am

    iskunk you´re right, this mode deserves the same care as mode 7 :_)

    I don´t have any non camera shaking videos except the installation video from the first page.

    What i have are some better photos.
    For example, this one:

    The pattern is obviously not mode 7, just by looking at it.
    further i searched for it in mode 7 and was not able to find it.

    I like these triangles in the top row.

    For populating the display, if you go the easiest way possible, means removing the &4 and just for(j=0; j<32; j++) { for(i=0; i<WIDTH; i++ ) { ….

    the output already looks very close but as you said, that is not enough 🙂

  30. #30 by iskunk on April 6, 2016 - 11:20 am

    Hunh. I thought that photo was showing mode 7, not least because that’s the mode a museum would probably want to use to make visitors go oooh and ahhh…

    As for populating the panel in mode 5, it’s not a matter of what’s easy to code. The order in which you stuff the stream of random bits into the 16×32 array directly determines what the end result looks like, and if you want that to match the real thing, then you have to follow the same order that the real thing uses.

    Now, there’s only a handful of stuffing-orders that are likely candidates here. The one you describe is among them, but given that mode 7 filled the edges of the panel starting from the bottom row, I think it’s likely that this is also the case in mode 5.

  31. #31 by Mark on April 6, 2016 - 12:35 pm

    There are a few shaky video from the museum and so far i only have seen mode 5 there.
    But if you don´t believe you can also search for the pattern in mode 7, maybe you are right!

    to keep things interesting, this is a short video of my LED display panel. These are 2 pieces, each 64×16. These panels go around 10$ on ebay.

    sorry for the screen flickering, i haven´t tuned the output for good video recording. This flicker is not visible to humans.
    And no, i will not paint the lower rows black:-) I have the power to switch them off in software:-) todays technology…

  32. #32 by Mark on April 6, 2016 - 12:40 pm

    or i could use the extra space to simulate the missing black row between the original panels:-)

  33. #33 by iskunk on April 6, 2016 - 2:18 pm

    Ohhh, nice!! You’ve got to put up a page documenting your build. I’d like to do that someday!

    One other thing that would be great is for someone to visit the National Cryptologic Museum, walk up to that CM-5, and take measurements of the panel/cabinets. It would be straightforward to build a replica out of plywood and Plexiglas, but without dimensions it’s just another kinda-sorta-looks-like guessing game.

    By the way: Should I credit you as “Mark”?

  34. #34 by Mark on April 6, 2016 - 3:42 pm

    @ Iskunk:

    The Hardware Part really isn´t that complicated today,
    you can get going with an Arduino Microcontroller for 3-4 $ or my favorite, the teensy 3.1 for < 28$ which is much more powerful.

    About the power requirements, hpux told us each of the original 3 panels is dimensioned for 5-7 Amps.
    My full display can be powered by an PC USB Port which is 0,5 Amps 🙂

    If you want to recreate the CM5 panel you only need one tiny controller since the output on all panels is the same and you can chain as many panels as you like.

    If anybody wants to do this i´m glad to share my microcontroller code and to help with questions how it is working.

    About the measurements, in the cm archive:

    you can find an installation guide with exact measurements of the machine, modules and the requirements of the room and how to get it in there and installed properly :_)
    it even shows all different installation types that are possible.

    I searched all of this documents to find clues about the panels:-)

    You can credit me as Mark or as nexuslabs if you like to do so.

    to Jim:
    I found that the older Machines, the CM1 / CM2 also had a random and pleasing mode but i´ve never seen it. Is this also your work or do you know anything about that ?

  35. #35 by Mark on April 6, 2016 - 4:03 pm

  36. #36 by Jim on April 7, 2016 - 8:21 am

    In both the CM1 and CM2, the processors themselves generated the pattern.

  37. #37 by Mark on April 7, 2016 - 10:15 am

    So there was no (Lisp?) based code provided/bundled by the manufacturer ? i have read somewhere that the term “random and pleasing” was used there also so i thought what would be somehow connected.

    And one more thing 🙂 Jim, what on earth have you done in mode 5, knowing so much about the PRNG i thought this wouldn´t be so hard to get. I tried to fill the panel in all different directions, flipping, inverting but of cause, haven´t got a match so far :_)
    any secret hint from you ?


  38. #38 by iskunk on April 7, 2016 - 4:24 pm

    Okay, a lot of ground to cover here:

    First! I transcribed a frame from that museum video, and I think I’ve nailed mode 5. Code is here. Mark, would you verify?

    Note that my program has gone multi-mode! You’ll have to invoke it with a “5” argument. Modes supported are 5, 7, 9, A and B. Though obviously, only the first two are of real interest.

    Re hardware: Non-hardware types like me will need very specific instructions, of course 🙂 I’d probably opt for a more muscular driver, to make it possible to use the panels as general information displays in addition to the CM-5 modes. (Imagine if you had four of them, arranged just so—you wouldn’t want them to only be able to do R&P patterns, would you?)

    (How big are your panels, by the way? Did you aim for a full-size recreation, or more of a scale model?)

    Re dimensions: That’s a nifty little treasure trove of docs there! I found the part you were referring to, pages 26-27 in nov06/CM-5SitePreparationGuide.pdf. Okay, so that gives the general dimensions pretty well, but you would need more than that to make a good replica—think the width of the front bezel, position and depth of grooves, depth of the LED panel glass cover and the LEDs behind that, etc. You just have to see the thing in person, and make note of a lot of incidental details like that.

    Still, the general dimensions are good to have, and that doc was good reading. Some choice excerpts:

    Is there a receiving dock? Does it have a load capacity of at least 4500 pounds?

    Verify that a separate 208 V, 100 A, 5-wire supply and circuit breaker are provided for each device cabinet.

    Not much hope of running that thing in my basement :-]

    Re credits: Does “Mark@nexuslabs” work for you?

    Re CM-[12]: This excerpt from the Wikipedia “Connection Machine” article, referring to the CM-{1,2,200}, may help:

    By default, when a processor was executing an instruction, its LED was on. In a SIMD program, the goal is to have as many processors as possible working the program at the same time – indicated by having all LEDs being steady on. Those unfamiliar with the use of the LEDs wanted to see the LEDs blink – or even spell out messages to visitors. The result was that finished programs often had superfluous operations to blink the LEDs.

    So it seems like in those early systems, the LEDs were really just utilitarian, and it was all the randos wanting blinkenlights action that led to the CM-5’s explicitly just-for-show display modes.

  39. #39 by Mark on April 7, 2016 - 5:58 pm

    well, if you look at

    all i can say, it seems you nailed it again! i swear i searched with 2,4.. 8 random values in one loop,since jim told us there are 2 panels , but it seems i only searched in the opposite,wrong panel:_) and got nothing.

    for the credits, sure, i´d like that.

    iskunk you really hacked this. there is nothing to find out any more, everything is solved. all mystery is gone:_)

    i´ll write back to you to the other parts tomorrow since it is 03:52 AM here and i really have to get some sleep:-)


  40. #40 by iskunk on April 7, 2016 - 7:48 pm

    I tried a number of different approaches with no success, but Jim’s comment on the two panel halves set me on the right path. Particularly, the idea that the random bits were assigned alternately to each half (lower, upper, lower, upper, …) instead of filling a row at a time.

    The hard part’s done… all that would be left is to correct any minor differences between the program and the panel for the non-mode-7 modes. (For example: Do all modes have that same all-but-3-LEDs-for-600ms start frame? Is the first pattern frame after that correct? Does the blinking mode update every 200ms as well?)

    I hope we can also get an answer on the “glitch” pattern at the beginning of mode 7 (is it always the same, or stochastic?), because I’d like to get rid of that table if the glitching is indeterminate.

    Sleep for now 🙂

  41. #41 by Mark on April 8, 2016 - 7:19 am

    Hello Iskunk,

    i compared 2 reference videos showing mode 5 and can confirm identical patterns and also that the output is in the same sequence over 40 iterations so i´m pretty sure it is all identical.

    We can´t know the starting seed but i think it will be the same as in mode 7. Also i do not care about this since in this mode are no lines or visual patterns that can be followed by the human viewer.

    To the hardware:
    This panel is already 16×64 so you only need 2 for a full CM5 setup.
    They are very inexpensive but by no way as big as the real thing, they are 304x76mm each, so two of them are 60,8cm x 7cm. So this in no way is a full scale replica, it is more like a CM5 on a shelf:-)

    The wireing is very easy to do since you can daisy-chain them one after another.

    For the controller i can highly recomment the teensy 3.1

    This is a little over the top for this but you would have all options, like implementing 150 more modes :_) Or display something simple as digital clocks, temperature etc. The teensy 3 already has an Real Time Clock, you only need to add an CR2032 coin cell and a Quartz.
    The Teensy is powerfull enough to drive even larger RGB LED Panels with 4096 or more colors.
    So this is an good choice if you like to do something with microcontrollers and not running out of memory space or speed anytime soon.

    Your code will run on any Arduino/Teensy with minimal modification regarding the output to the display, everything else is the same.

    To your latest Comment:

    You know i was very keen on getting the output right but simulating the startup behavior of the panel seems unimportant to me. In my opinion this is a side effect from the panel until all row are filled for the first time with correct data after startup.

    So let lean back and see if hpux comes up with any more surprises:_)

  42. #42 by iskunk on April 8, 2016 - 1:32 pm

    Thanks for checking that so thoroughly, Mark. I had no energy left for that after the logic-search!

    The starting seed is going to be the same; there’s no reason for there to be a different one. I thought maybe some initial sequence of bits might be discarded before going into the panel, but no, they go in starting from the very first one.

    Re hardware: So a full 16×128 array would be about 1.2m/48″ tall. Hmm. I see a lot of 320x160mm 32×16 panels on AliExpress, and even one 400x200mm outdoor model, but the only one available in a small lot is yellow. Man, I thought this would be easier to find…

    I’m guessing it should be straightforward to hook a RaspberryPi in to the Teensy for more informational-type stuff. It would just need to push out 256 bytes every 30ms or so for each 16×128 array.

    The Teensy-to-panel physical interconnect and protocol would be the part I’d need the most detail on; standard stuff like coding for the Teensy and getting it on there would be covered by community docs. Would there be a forthcoming blog post from you on this? 🙂

    Re startup behavior: Yes, this is getting into the nitty-gritty. But I figure, this work isn’t just about mimicking cool blinkenlights from an iconic computer system, but is also, to some extent, digital conservation. The real hardware panels may stop working someday, or become even rarer than they already are. But everyone can get their hands on this program, always, and get (hopefully) the exact same behavior as they would with hardware.

    (It’s not just that mode 7 glitch pattern, but the other modes, too. I’ve implemented my best guess at them, but I’d like to be able to say “This program has been confirmed to reproduce all modes exactly…”)

  43. #43 by Mark on April 8, 2016 - 5:51 pm

    dear iskunk,

    i wrote two of them are 60,8cm x 7cm, each has 64 LED height so this already is the full cm5 height. Of couse you could make it 2x and then just set 4 LEDs as one:-)
    So why are they so small today? I think the LEDs are about the same size as the CM5. But the spacing between them is much tighter.

    Yellow ? I don´t think i personaly would go for that. But maybe it would work if you put a red gel foil infront of it. The CM5 also has some kind of glas/plexi cover. But i assume it´s not colored at all.
    You can also go for full color panels. Much more expensive and memory intensive but no problem for the teensy.

    If you already have a RaspberryPi you can try to drive LED panels with it directly! It has more than enough pins and will be also very fast. The code changes would be about the same as for the teenys. In fact it would be identical except the adressing and numbering of the output pins.
    The disadvantages are:

    It has to boot your linux and other stuff, on the teensy your code will run instantly when you poweron.
    You should shut down the RaspberryPi or run from a read only filesystem if you don´t want to corrupt the filesystem. On the teensy the code is flashed in PGM Space and it does not matter what you do it will never get corrupted by turning it on or off and will run instantly.
    The Raspberry with linux is a multitasking system, there is no guarantee that the screen updates run exactly how you program then. but it is very fast so i have no practical experience if this might be a problem or not.

    Short version: Get some LED panel, for example the ones i suggested. They are inexpensive and will work on the teensy, arduino, Raspberry or any other modern microcontroller.
    The only Panels that MIGHT be a problem are much older produced Panels which run with 5V logic. In fact, i haven´t had any problems with these either so far. But to be sure, i would suggest to start with panels produced in this decade.

    I understand that you are stuggeling about the hardware part, specially the LED panels, since you seem not to have much experience here.

    Let me clarify this for you. I will skip a few minor details so you get the concept as whole, first.

    There are two type of LED Matrix Panels. The first one is dumb (the cheap ones) and the other are more intelligent.

    Both of them usualy adress the LEDs with shift registers. You already know these, it´s the same thing as the 16 bit random generator you did, but in hardware. Most of them are 8 bit.

    So lets asume you have a 8×8 matrix. then you have one shift register for the x axis and one for the y axis.
    With the first you fill in the bits for a row like you did in the RND code, but without the XORing stuff :_)
    You put in 1 bit after another via a pin setting on/off on the microcontroller until you have 8, then you toggle another pin on/off to display them all at once in a row.
    The second shift register is for the column. You increment this every time you wrote a new row until youre at the last row, then return to the first row.
    So in reality only one the the 8 rows are visible at once. but since youre switching so fast, for the eye it will look like at full 8×8 matrix.

    For a bigger matrix, nothing changes except the output of the x axis (first shift) register will travel to the next one and so on.

    Same thing for the y axis. There will be more shift registers daisy chained to the bits send there will travel from one chip to the next one.
    These display need fast and constant updates to make the screen visible. Usualy done with an interrupt timer that display one column and in the next iteration the next one etc.

    To the intelligent displays: They are the same but have internal memory for every bit. also they store and update the LEDs by themself so you have nothing to do if the screen doesn´t change.
    you can adress LEDs directly by code with their x,y value and do not need to fill the complete buffer with each change. It´s more or less like your computer screen but smaller:_)

    I think this sums it up roughly, tell me if you have any questions here.

    Interconnecting a Teensy/Arduino with an RaspberryPi should be no problem. I haven´t tried that myself but i assume i could do it so others will already have done this.

    Next topic, digital conservation

    Ok what i like about the CM5 are the cool patterns. The “LT” and other letters in mode 7 , the “Arrows” pointing up and down in mode 5 and these things. These visual aspects are not close in the current code, they are identical to the real thing. Absolutly identical. If there a 3 pixels stuck at the init, or the screen looks funny at the first iterations, i really don´t care. but i´m happy that you´re interested in these details and keen of getting answers there. It would not hurt if someone can experience in the year 2130, yes, this is exactly what you would get it you power on a CM5 in the year 1998 the first time 🙂 And hey, today i can run the whole sequence in 0.0000001 pico second:_)
    Only hpux can you help here since i never touched or seen an CM in person, yet.

    I hope i gave you some insight in the topics i can help with and looking forward for your first hardware attempts.

    kind regards, mark

  44. #44 by hpux735 on April 9, 2016 - 12:05 pm

    Alright, I hope this is still useful for you…

    I’ve just published a post that links to the video (though, indirectly) for Mode 5. Also, I’ve written a program to automatically transcribe the patterns into the 16-bit hex that was used in the past. This should make it very efficient to check your algorithm. I’m not 100% confident that the transcript is perfect, but it should be more than it isn’t.

  45. #45 by Mark on April 9, 2016 - 2:14 pm

    dear hpux,

    thank you very much for your effort and the great video. This output file would have been the next best thing if this had turned out to be impossible to replicate. but now, that we seem to have everything right, if we compare it the the computed output, we can see how stable your swift pattern recognition has worked .-)
    i will try this out.
    also – it should be easy to rewrite the c code in swift and compare it directly in your code against the recognition and fine tune the recognition with it 🙂

  46. #46 by iskunk on April 10, 2016 - 1:46 pm


    The whole 128 rows are 61cm tall?? Yep, that’s a scale model. Call it the CM-5/10ths :-]

    For me, part of the charm of these systems is just their size; that’s what makes them physically imposing and stately. You see a similar effect with steam locomotives—models just don’t have that same quality.

    What would you make of this model of panel? The specs indicate that it is driven by a 74HC595, which is an 8-bit register like you say, and the photos show a 16-pin connector. But it also says the working voltage is 5V. I’m guessing this should probably use a dedicated power supply?

    (There are several listings on that site for this model of LED panel, as well as other variants. This one seems to have the best combination of price, lot size, and shipping rate for a hobby project like this.)

    Using a red gel filter with a yellow panel isn’t a bad idea, but I’d worry that it would come out looking not quite right. This is the listing, FWIW. It’s also on the pricey end, albeit for ten pieces.

    A RaspberryPi wouldn’t work well for anything that requires high-speed, real-time processing. That’s why I was thinking of using one in conjuction with the Teensy. Each of those has its strengths and weaknesses, of course. But if you have the RPi interfacing with the network (e.g. a server that you submit messages to, or a Web-scraper that obtains some information from the Internet) and the Teensy driving the LED panel, then you’re using both systems to their advantage.

    I get what you’re saying about the X and Y shift registers. At the conceptual level, what’s going on is not complicated; it’s more about the nuts and bolts of e.g. how a bit is transmitted, how the “boundary” of a bit is defined on the wire (is there a clock, or some kind of special coding) what are the voltage levels, and so on. What I like about software is that you can design it so that it’s a pretty good match to the abstract concept underlying it, but with hardware, there are a lot more variables that need to be taken into account that make the picture more complicated.

    Intelligent displays sound like a good way to address flicker, but I’m not sure that any of the ones we’ve seen on eBay/AliExpress are of that kind. If the Teensy can refresh the panels at or above 120Hz, however, then flicker shouldn’t be an issue anyway. (I remember, back in the CRT days, tweaking X11 modelines to yield that refresh rate. When 75Hz was considered acceptable by the mainstream, 120Hz was soooo nice to look at for hours on end.)

    Yep, the “LT” was not likely to happen unless we figured out the pattern completely, and I’m glad you pushed for that. I didn’t think it was feasible at first, but between the information Jim provided, and the fact that the pattern was completely deterministic, it was just a puzzle waiting to be solved 🙂


    Seems one cool little project begat another! That’s a nifty bit of work you did there! I grabbed the mode 5 transcript, and have some interesting observations for you. Will comment on that new post, as this one already has comments to spare.

  47. #47 by Mark on April 10, 2016 - 3:54 pm


    the panels you have stated should not be a technical problem. one panel has a dot pitch or 10mm, the other has 12mm. The China panel that i have mentioned has about 4mm dot pitch so you should get double the size. That they have a 16pin connector and are driven by 5v is a good sign. If it says HUB Connector usualy you will find working code online without figuring out the display logic for yourself.
    It would be best if the seller can provide you a sample code. If not, when the pins at least are labeled it is a matter of minutes or a few hours to find out the logic. Basicaly, the all work very similar.

    I have not much experience with the Raspberry but i build a DIY printing plotter with it and i hadn´t much problems driving 2 stepper motors really fast with it. (abound 1000 steps per second for both motors). so this is a similar scenario and if you are allready familar with the Raspberry it is worthy to try out, you WILL get at a working display, maybe it will flicker here and there while the Pi is doing something else.

    About the power supply, if the seller states the display runs with 5v for the LEDs, it does not mean that the logic circuit also require 5v. Older Display with TTL Logic run at 5V, more modern Components at CMOS level also run at 5v but there is a difference how a “0” and and “1” are interepreted in voltage.
    But in my experience that does not matter.I think the Pi operates at 3,3v logic but it is more than enough for the Shift Register to figure out what is a 0 and a 1. To be safe, i suggest to buy only 1 panel and try out if it works out of the box. If not, you have to add either an voltage conversion, switch to a different microcontroller for the output with the right voltage or to a different panel.

    Yes, there is always a Clock pin for streaming in the bits at the Data pin.
    Don´t be afraid of that, either the Clock pin has to be set on before you set the state of the Data pin or it is the opposite way. There is a 50% Change you get it in the first try, if not you simply switch it from 0 to 1 or from 1 to 0 before and after you switch the Data pin.
    All you are sending to the display are pin states, either on or off. The pins involved are data, clock, latch and output enable (oe). Something like this:

    for (uint8_t bit = 0; bit < 8; bit++) {
    uint8_t pixels2 = ( pixels & (0x80 >> bit));
    if (pixels2) dataOn(); else dataOff();




    For the power supply for the LEDs themself it is always a good idea to power them independently from the logic circuit, even if it is the same voltage as the logic.
    For smaller displays like mine, they will run even being USB powered with 500mA, you will get more brightness if you add a stronger power supply, check what the seller suggest here for one panel.It is no problem to find a 2A or 5A power supply at 5v on ebay. When the code is done, you can of couse power the microcontroller from the same external power source. You only have to disconnect the microcontroller from it when you want to update the code via USB from your computer.

    None of the mentioned displays are “intelligent”, neither they can display “grayscale” values by themself. So you have to control the output to them in your code, either in a loop or better in an interrupt timer to get more steady refresh cycles. On/Off is pretty simply, if you want grayscales this is usualy done via PWM and requires more CPU power to turn the LEDs on/off in faster cycles to simulate the different brightness levels.
    This could be outsourced to a teensy board if the timing of the Pi is not stable enough.

    If you still have unanswered questions, please tell me. I might have missed something and will gladly help you where i can.


  48. #48 by iskunk on April 11, 2016 - 1:38 pm

    I’ll probably go ahead and order one of those panels, then. It’ll be something to mess around with. Where’s your site, by the way? “Nexuslabs” turns up a lot of unrelated hits.

    The RaspberryPi will probably work for initial testing. You’re right, even if it flickers and looks bad, it’ll be good for sussing out the protocol for later programming on a Teensy.

    I’ll have to revisit this topic when I’ve got the actual hardware in front of me, however. (As well as time to do the messing around 🙂 ) I just hope it doesn’t get to needing voltage conversion or the like. Whenever a hardware hacker starts talking op amps, I run for the hills!

    Mind if I get in touch with you a little down the line? I do want to do the quasi-full-size replica build, though it’ll be some time before I get there. And at the same time, put together an Instructables page or the like for that—because if I’ve got to figure this mess out, then I’m darn well gonna make sure it’ll be easier for the next guy/gal like me ^_^

  49. #49 by Mark on April 11, 2016 - 2:04 pm

    Dear iskunk,

    i haven´t had a website for a long time but you can contact me at nexuslabs at anytime.
    I believe with the Pi you will get faster results as you think.
    If you really setup a weblog for this, let me know, i like to help and to participate if i can help with the hardware, panel code or something else.


  50. #50 by iskunk on April 12, 2016 - 3:57 pm

    I’ll drop you a note, so you have my info too. I’m in the same boat as you are in not having a (real) Web site, which is why I’m thinking Instructables/eHow or a similar such site.

    The RaspberryPi gestalt is something I’ve been meaning to get into, since it’s just a step beyond pure Linux software hacking, and the Teensy seems like the next logical step after that. There’s a number of things I want to do, but a CM-5 LED panel replica seems like a good first project, and I’d be very happy to have you on board for that 🙂

(will not be published)

Please complete this capcha. I get almost 1000 spam comments a day! * Time limit is exhausted. Please reload CAPTCHA.