Older blog entries for brouhaha (starting at number 64)

lcdtest

On a mailing list, someone pointed out a Windows lcd test program that was useful for adjusting the pixel clock frequency and phase of LCD monitors with analog VGA inputs (vs. DVI). It puts up alternating white and black vertical lines one pixel wide. This is useful either for auto-setup or for fine tuning.

lcdtest was able to do that, but you had to type the five key sequence ``wv0-'' to get it. So I've added the command ``a'' to do it with a single key.

I also added command line options to list the available video resolutions, select a resolution, and get help. There's a new option to display in a window, intended for debugging and example screenshots.

I now consider the program to be feature complete, so the new release is version 1.00.

lcdtest

I just replaced my aging Nokia 445Xi 21" CRT monitor with a new Samsung SyncMaster 213T 21" LCD monitor. Much easier on my aging eyes that can no longer focus close in, as the LCD face can sit much further back on my desk than the CRT face did.

I thought I'd try to count bad pixels. A Google search turned up various LCD test pattern programs for Windows and MacOS, but none for Linux. So naturally I thought I'd whip up a quick hack to fill this void.

lcdtest uses SDL for full-screen display, and in principle should work on other operating systems as well, but I've only tested it on an Athlon 64 running Fedora Core 3 Linux.

7 Apr 2005 (updated 7 Apr 2005 at 00:03 UTC) »
Nonpareil , la2vcd (new)

As mentioned in my last entry, I've been capturing microcode execution traces from an HP-97 using an HP 16500B logic analyzer, in order to reverse-engineer the additional instructions used in the Topcat series and similar HP calculators, to add those to Nonpareil. The logic analyzer provides the captured data as a set of text files, one per signal, with one data sample as binary (represented as ASCII text) per line.

That format isn't directly useful for much, so I've had to write a few translation programs. One of them that might be useful to other people is la2vcd, which will take the HP (or Agilent) logic analyzer traces, and convert them into a VCD (Value Change Dump) which is supported by most waveform-viewing software, including GTKWave.

Unfortunately extracting the data from the analyzer is a very slow process, even over Ethernet. At most I've seen a little over 10 KBytes per second. Apparently it is doing on-the-fly format conversion from its internal binary representation into the test form. The poor little 68000 in the analyzer is just too wimpy. A 2 megasample capture of five signals using a 16555A module took nearly two hours to FTP out of the analyzer. In the future I'll just tell the analyzer that all five (or more) inputs are part of a single vector, which will at least reduce the overhead somewhat.

Even with this long delay to get data out of the analyzer, it is still much better using GTKWave to inspect the results than trying to do it with the analyzer's built in display and knob. The poor thing takes over five seconds for each display update when you turn the knob one detent (which is like clicking a scroll arrow; it only scrolls a small amount of new material onto the display).

Maybe someday I'll be able to afford a used 16500C, which is 68020 based and might be less sluggish. But at least the actual acquisition capabilities of the 16500B/16555A are quite good.

I expect that the latest Agilent logic analyzers probably can directly export in VCD format, but I haven't researched it since I can't afford to buy one. If they don't, they certainly should!

Nonpareil

Hardware mystery solved:

Ever since I've been working on reverse-engineering the Woodstock/Spice era hardware, and figured out how the bank-switching works on Spice (and probably on Woodstock, though I haven't yet confirmed that), I've wondered how the multiple ROM chips all make sure they agree on the bank, and how they're forced to start in bank 0 at power-up. The mystery is that there is no reset signal going to the ROM chips (or ROM/RAM chips).

In theory it would be possible for the chips to each have their own internal power-up-reset logic, but in practice this would increase chip area and might not reliably get them all reset properly. Using 1970s technology, this would have required external RC components. It would have made even less sense for HP to put those in for each ROM than just to bus a reset signal from the ACT to the ROMs. But they didn't do either.

Studying a logic analyzer trace, I think I now know the answer. Each word cycle consists of 56 bit cycles, which are defined by the two-phase clock pulses. The various chips have to know when a word cycle begins, and they do that by watching the SYNC line, which is generated by the ACT. The SYNC line is low most of the time, but goes high for ten bit cycles of each word. Those are the ten cycles in which a ROM instruction is read out. Each chip on the bus other than the ACT has an internal counter that tracks the current bit time, and it uses the SYNC line to initialize that.

There are some two-word instructions, and the ACT does not raise the SYNC line while fetching the second word, so the counters in the chips are designed to "ride through" the missing SYNC period. They also know that they shouldn't try to interpret the ROM words bits that are read out when SYNC is not present as an instruction, because it's really a branch target.

I've captured a lot of logic analyzer traces in the past, but tonight I captured one from an HP-97 during initial power-up, and I think I now understand how the system-wide reset is implemented. At powerup, the ACT starts generating the clocks, and it holds the SYNC line low for about four milliseconds to allow various things in the system to stabilize. Then it starts generating narrow SYNC pulses once per clock. It generates about 30 of those, with somewhat variable width, then starts holding SYNC high. It keeps SYNC high for about 22 ms. Finally, it lowers SYNC, then begins pulsing it at the usual rate (10 bit times high out of every 56, except for the second word of two-word instructions).

So it appears that the ROMs and other "peripheral chips" are designed to reset themselves if they seen SYNC high for more than ten bits consecutively. Quite a clever solution to having a hardware reset without any extra pins.

I think the narrow SYNC pulses before the 22 ms high time are probably just an artifact of the ACT implementation; the ACT likely is not yet fully initialized yet. I doubt that any of the other chips notice these pulses at all, because they happen after the phase 2 pulse, rather than staying high throughout the phase 2 pulse.

I've also spent a little time recently on infrastructure improvements to Nonpareil, like making the word size architecture-specific (56 bits for most HPs, but 48 bits for the HP-01 watch, 64 bits for more recent Saturn-based calculators, and 8 bits for the HP-75 and Series-80 computers). I've come up with a new API to deal with memory reads and writes from the GUI task, a new API to manage multiple sparse address spaces with bank switching, and what I call a "pseudo-reflection" API for the GUI task to ask the simulator task what processor state can be accessed.

I still haven't decided whether to change the internals from using an array of 14 bytes (uint8_t) to represent a 56 bit calculator word (4 bits per byte) to using a packed value (uint64_t). The latter makes the memory API more elegant, but adds code to the simulation task.

Altogether

I've got Altogether using libgsf to read the microcode files. It works great. I wish the ISO C committee had added some way to hook into the stdio interface from the underside, i.e., to supply an alternate implementation of the functions needed to implement the FILE abstraction. Some platforms do provide this but not in a portable way. If it could be done, libgsf could allow you to use stdio calls on the components of ZIP files. As it is, libgsf provides its own read and write calls, rather than working through the GLib I/O channel API. Sigh.

glock

I needed a simpler test case to track down bugs in the Windows version of GTK+, so I wrote an analog clock program. It's fairly crude at the moment, but since I want to learn how to use SVG, I may try to draw some nicer clock faces and hands with Inkscape and use libsvrg in glock to draw them.

Nonpareil, Altogether

For some time now I've wanted to be able to read related files directly from a ZIP archive. There have been numerous libraries to do this, but each one I've looked at has had either technical or licensing problems. I just discovered libgsf, which looks like it should do the trick, and is LGPLd.

Altogether

I recently got permission from Dave Conroy to use some code from his Alto simulator, which works at the macroinstruction (Nova-like) level. So Altogether will be able to simulate at eiher microcode or macrocode level. I've started integration, but it will take a while.

18 Feb 2005 (updated 18 Feb 2005 at 08:10 UTC) »
Nonpareil

Finally found some time to work on this some more. I now have ROM dumps from real HP-25 and HP-25C calculators, and they work correctly! So the HP-25 problem I was having before was due to bugs in the printed listing I keyed in; it was apparently an interim development version.

On the other hand, the HP-34C, HP-38E, and HP-38C still are nowhere near working correctly, so there definitely are still simulator bugs.

Nonpareil is stuctured as a GUI thread and a simulator thread, using glib's thread support for portabiliy. The intent was that the simulator never touch GUI stuff. However, when I first wrote it I did not know of any portable way for the simulator thread to asynchronously notify the GUI thread that a display update should be performed, so the display updates were being done from the sim thread. I also didn't know about glib async message queues, so I used a complicated communication scheme involving both mutexes and condition variables.

The Windows port of Nonpareil had lots of problems with the display updates, though it worked fine on Linux. I thought it might have been related to doing the display updates from a different thread than the other GUI stuff. So last weekend I rewrote all of the interface between the threads to use async message queues. And I found that another thread can wake up the GUI thread using the call g_main_context_wakeup(). But I also needed a g_source for the main loop to recognize why it has awakened. Writing a g_source didn't seem obvious from the docs, but a bit of googling turned up some messages by another developer who'd faced the same problem, and more searching led to his program Quary, a GTK-based board game GUI.

Using the Quarry code as an example, I wrote a general-purpose g_async_queue_source_add() function, which takes two async messages queues, a GMainContext (or NULL for the default), nd a callback function. The first message queue is for messages from the "other" thread to the GMainContext thread. The second is a free queue onto which the GMainContext thread recycles the messages. And a g_async_queue_source_push() function pushes a message onto the queue and wakes the GMainContext process. Maybe a simplified version of this (probably without the free queue) should be added to glib, or just integrated into the existing glib async message queue code.

Once I got all this working, I tried it on Windows again, and it worked correctly! Then I realized that I was using a newer version of GTK+ etc. on Windows than I had previously used, so I tried the old Nonpareil on the new GTK+, and that worked correctly too. So I didn't really need to do all the hacking to better separate the GUI and simulator threads, though it probably is more maintainable now.

I switched from GNU Make to SCons just after the last public release of Nonpareil. I haven't yet sorted out the packaging issues of building a new release, but I'll try to get one out soon.

asm21

The long-sought IOP microcode for HP 2000/Access Time Shared BASIC to run on the 21MX E-series minicomputer has finally been found. The ensuing discussions motivated me to finally add generation of absolute binary object files to asm21, my HP-21xx cross assembler written in Perl.

I wrote asm21 in May of 2000. I started in Awk, but quickly found things I needed to do that were very difficult in Awk. I switched to Perl, and asm21 was the first non-trivial Perl program I'd written, and I had a lot of trouble figuring out how to deal with complex data structures, such as a hash of arrays of arrays containing function references.

A few months later, I needed to write a program to decode Holerith punched card images stored in column binary format, for the IBM 1620 restoration project at the Computer History Museum. I thought that Perl would be ideal for that, so I sat down to write a program... and I quickly discovered that I'd already forgotten almost everything I'd learned about Perl.

This has happened to me every time I've wanted to write or modify a Perl script; I always spend a lot of time digging through the books and online docs. I've never had this problem with other programming or scripting languages. I attribute it to Perl's incredibly baroque syntax.

I'm switching to Python, but in the mean time I put the latest version of asm21 on my web site, and added a very brief rant about Perl. I originally had another, less inflamatory title in mind for that section of the web page, but at some point I decided to just call it "Perl Considered Harmful".

Afterward it occurred to me that there must be a lot of "Perl Considered Harmful" pages on the web, so I did a Google search. Surprisingly, there are very few. The most interesting one was actually a list of GooglePhraseWhacks, for which "Perl Considered Harmful" was number one.

Nonpareil

No progress on the software. I've been working on the ROMsucker Mark 3 hardware. I hate wirewrapping! I didn't do an adequate job of power and ground distriution, nor of filtering the switching noise from DC/DC converters, so I was getting about 0.8V peak-to-peak noise on the +/-2.5V voltage references for the DACs that set the comparator thresholds. I cleaned up the power distribution a little, and added some 220 uH inductors between the DC/DC converters and the electrolytic filter capacitors, and that's brought the noise down to about 0.06V p-p. Not great, but probably good enough.

Once the ROMsucker Mark 3 is working, I'll be able to capture the ROM code from the HP-31E and HP-33E, and execution traces from those and other models. This should enable me to fix the HP-25 and HP-34C simulation problems, and get the Voyager series (especially the HP-15C and HP-16C) working.

I have a good-condition HP-10C, but didn't want to tear that one apart to dump the ROM because the HP-10C is fairly rare, resulting in high prices on eBay when they can be found at all. I don't think I'm likely to damage it when I dump the ROM, but I'd rather not risk it. Fortunately I recently found my beat-up HP-10C, so I'll use that one instead. I doubt that many people really want an HP-10C simuluation, since it was one of the most basic RPN scientific calculators, but somehow it seems nice to have as complete a set available in simulation as possible.

The models that will be difficult if not impossible to get running in simulation are the HP-01 watch and the HP-10 (no "C") non-RPN four-banger, because there is no obvious way to extract the ROM code. The HP-01 has the chips inside a hermetically sealed hybrid module, and the HP-10 has a single 40-pin chip that apparently contains the CPU, ROM, and RAM.

PDP-1 Restoration Project

We were pretty excited yesterday when we were able to verify that the player control inputs for Spacewar seem to work correctly. I bought some arcade buttons from HAPP Controls in order to build new player control boxes, since the originals cannot be found. These will be intended for demo use, as they won't particularly resemble the original control boxes. We might also try to build some replicas of the originals.

The power supplies of the Type 30 Precision CRT Display are currently being restored, so it shouldn't be too much longer before we can try to test the display. If we're lucky, we may have Spacewar up and running soon!

The new web site using Plone, Zope, and Zwiki seems to work pretty well. I had a lot of trouble getting everything set up on Fedora Core 1 and had just about given up on that, but on Fedora Core 2 it all Just Works (tm).

20 Jul 2004 (updated 20 Jul 2004 at 08:26 UTC) »
Bram:

If all the contacts for the domain ignore the transfer request email, the transfer will fail in five days. I don't know French, but that's how Tucows/OpenSRS handles transfer confirmation, and when I put the email text through Altavista's translator, it seemed to confirm that. (That's the only thing I use Altavista for any more.)

However, it appears that Marcus Oesterwinter of Central Registrar Inc. is the tech contact for bitconjurer.org, so make sure that he/they don't approve it. I'd recommend making yourself the tech contact for that domain.

If you haven't already done so, lock your domains through your Tucows reseller. That makes it much harder for someone to do an unauthorized transfer. If Domain Monger/Central Registrar Inc. doesn't allow locking, you might want to transfer to another Tucows/OpenSRS reseller. I happen to be one, and have lower rates than Domain Monger, but there are plenty of other choices.

BTW, keep up the good work on Bittorrent. It's awesome. I use it to get Fedora Core releases; most recently I was able to get the FC3test1 ISO images within two hours of the torrent announcement. I normally leave the client running past the download completion until the total upload byte count is at least twice the download; is that considered a reasonable amount?

12 Jul 2004 (updated 12 Jul 2004 at 18:19 UTC) »
Nonpareil

Found a serious bug in the Woodstock simulation that was causing the selftest on several Spice models to pass the first time and fail on following invocations. This turned out to be a cut-and-paste error when I was creating the op_clear_regs() function from the Classic version. The broken code was:

  for (i = 0; i < WSIZE; i++)
     sim->env->a [i] = sim->env->b [i] = sim->env->c [i] = sim->env->y [i] = 	     
       sim->env->z [i] = sim->env->t [i];
I'd hoped that fixing this might fix other problems such as the logarithmic and exponential functions of the HP-25, but no such luck.

Computer History Museum PDP-1 Restoration Project

At the last meeting, I wrote pdp1dump, a simple program to dump PDP-1 RIM and BIN format paper tapes in human-readable form, and verify the checksums of BIN format. At least one of the PDP-1 tape images in Al's Bitsavers PDP-1 Archive is corrupted, possibly due to flow control issues between the paper tape reader and the Sun Al was using to read the tapes, so I need to check the rest of the tape images with pdp1dump and give Al a list of tapes to be reread.

For a while now I've been running a wiki for the PDP-1 Restoration Project. It's using Kwiki version 0.18, which has worked out fairly well for simple stuff. There were a few rough edges, like being unable to delete blog entries, which wouldn't have been a problem except that it's easy to accidentally get the same page listed in the blog multiple times. And users complained that they couldn't upload photos into the wiki.

I decided a while back that I really wanted something with more sophisticated wiki, blog, and calendar functions. After a cursory evaluation of some possibilities, I tried Zope, Plone, and ZWiki. For a while I had trouble getting these installed and working on Fedora Core 1. Now that I'm running Fedora Core 2, I tried again, and it all basically just works. It's currently up and running at the temporary URL http://plone.brouhaha.com/.

The museum wants the site moved to a URL somewhere under its domain name; I'm somewhat resisting that because wiki.pdp-1.org is shorter and easier to type than something.computerhistory.org. And in fact, since it can easily absorb the content previously on www.pdp-1.org, it might move to that URL or even just pdp-1.org (with no "www"). I'm not trying to take any credit for the project away from the museum; I just think that having the URL in their subdomain isn't really going to tell the user anything that the museum's logo at the top of each web page doesn't.

The museum also has a 1401 Restoration Project that is just taking off, and I was asked to set up a wiki for that as well. Assuming that the 1401 team likes the new Plone site for the PDP-1, I'll set up the same thing for them.

For photo albums in Plone I installed CMFPhoto and CMFPhotoAlbum. They aren't nearly as fancy as Gallery, which I use for my own personal photo album, but since they integrate nicely with Plone I'm willing to give up a few features. I filed a bug report on one annoying misfeature; if you have an album that contains nested albums, but does not directly contain any photos, it is listed as being empty. That will make users think that there is nothing to see in the album. It would be nice if rather than saying it contains 0 photos, instead it would say that it contains 0 photos and 2 nested albums.

I haven't yet tried any blogging addons for Plone, such as SimpleBlog. I've been considering installing WordPress for my own personal blogging, and maybe some of my friends might want to use it. But for the PDP-1 and 1401 projects, again it's probably best to use something that integrates with Plone.

If I do set up my own WordPress, I'll probably crosspost my free software related blog entries here, since I don't expect many people will read my site. Is blog crossposting like that, done in moderation, a breach of etiquette?

8 Jul 2004 (updated 8 Jul 2004 at 21:14 UTC) »
Nonpareil

I wrote the brute-force CRC polynomial finder program. It takes six minutes to try all CRC polynomials of order three through sixteen over two buffers of 1024 ROM words, on my Athlon XP 1900+ system.

It appears that the Spice-series calculator selftest uses either a CRC-10 (x^10 + x^9 + x^5 + x^4 + x + 1), or the reverse of that (x^10 + x^9 + x^6 + x^5 + x + 1). The direction of a CRC polynomial has always been confusing to me, because some books and web pages show them shifting one way, and some another, and the whole GF(2) polynomial division concept still seems tricky. I've seen some references that claim that the reverse of a CRC polynomial is effectively as good as the normal one, but nothing authoritative. Any CRC experts out there care to look at my crc.c program and tell me which polynomial it really is?

CRC-10 would have been my first guess, since they are computing it over 10-bit words, so I suppose I could have saved time and just tried it. Though I'm not sure I would have thought to try the reverse polynomial.

I've verified that it works for the HP-32E, HP-33C, and HP-37E, as well as the non-bank-switched banks of the HP-34C, HP-38E, and HP-38C. I'll need to hack my program a bit to handle the bank switched ones, because the bank-switch instruction actually does toggle the bank even when it is fetched by the self-test instruction. That's why the bank-switch instruction is always present in identical locations in both banks, and there are always an even number of them so that the self-test instruction completes with the original bank selected.

Anyhow, I'll put the CRC verification code in the next release of Nonpareil, although I don't yet know how the self-test instruction indicates a failure, so I won't actually get it hooked in. But I can have it put up a warning dialog at startup if the ROM CRCs are bad.

In case anyone wants to see it, here is the brute-force polynomial finder program: gencrc.c. I suppose it might be useful for reverse-engineering proprietary protocols.

Googling for information on CRCs turned up an interesting recent paper (PDF format): Cyclic Redundancy Code (CRC) Polynomial Selection For Embedded Networks. It turns out that some of the old standbys aren't really all that great:

Update: I added a function to munge the ROM images for bank switching, and now I can verify that the HP-34C, HP-38E, and HP-38C ROMs also all have the same CRC. I still need to dump the ROMs of the HP-31E and HP-33E; when I tried before I ran into technical difficulties.

55 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!