Diagnosing the PSU problem on my VT100.
Oh, right. I should reblog this here as well. I’m fixing the VT100 I blew up at the end of last summer.
Keni
Alisa U Zemlji Chuda
taylor price
will byers stan first human second
Cosimo Galluzzi

Discoholic 🪩
DEAR READER
we're not kids anymore.
RMH
wallacepolsom
TVSTRANGERTHINGS
No title available
Peter Solarz
Claire Keane

JVL
dirt enthusiast
tumblr dot com
Not today Justin
$LAYYYTER

祝日 / Permanent Vacation

seen from Liechtenstein

seen from Finland

seen from Sweden
seen from United States
seen from United States
seen from India
seen from Greece

seen from United States

seen from United Kingdom
seen from Hungary
seen from Czechia
seen from Belgium
seen from Brazil

seen from Malaysia

seen from United States
seen from Türkiye
seen from Israel
seen from United States

seen from United States
seen from Greece
@vt100romhax
Diagnosing the PSU problem on my VT100.
Oh, right. I should reblog this here as well. I’m fixing the VT100 I blew up at the end of last summer.
Day 32: The Least Impressive Demo of All Time
So, I’d written my VT100 emulator. I’d built out EEPROM carrier boards to emulate 8Kx8 24-DIP ROMs. I’d successfully booted modified firmware on the terminal. What’s left?
Oh, right. The screensaver.
Since I was limiting myself to the base 8K (instead of using extended memory on the AVO board), the first task was to free up space in the existing firmware for my own code. Unfortunately there’s really not a lot of room in there; there’s only 41 bytes of free storage at the end of the ROM, which isn’t a lot to play with. The trick was to see what bits of code I could cut out without reducing functionality. Two obvious candidates came to mind:
the ROM checksum code, and
the full RAM test, which zeroes memory and tests each byte with two patterns (0x55 and 0xaa).
Since a failure of either of these diagnostic checks causes the VT100 to fail at startup, I didn’t see too much harm in taking them out. I pulled out the code, clearing up an additional 100 bytes or so, plugged in some of my own code, and tested it in the emulator. It looked fine, so I burned it on a ROM and plugged it into the VT100.
It promptly crashed. This is because emulators are horrible.
Well, not horrible, but they make assumptions. In this case the simulator was essentially getting the memory zeroed for free, while the VT100 hardware’s RAM was full of noise at startup. I ended up having to re-add the memory zeroing code, bringing me down to 83 bytes freed, or a total of 124 bytes to squeeze my screensaver code into.
Ouch.
In the interest of getting it done, I dropped every feature I had planned on except for the core functionality: blank the screen after a fixed period of time, and restore it immediately on a byte coming in on the UART or a keystroke. Since the video memory is basically represented as a linked list of lines, it’s pretty easy to “blank” the screen: all you need to do is store the address of the second line in the list, and change the “next” link in the first line (which is always blank) to point to itself. On a keystroke, the address is restored, and you’re looking at the original data.
The timing is based on the vertical refresh rate. On boot, a keypress, or a byte on the UART, a fixed value is loaded into a memory location (0x22c2 if you must know), and is decremented on every vertical refresh interrupt. When it hits zero, the screensaver kicks in.
And it really was that easy. After some adjustment to get the code squeezed into the right places, the screensaver pretty much worked the first time: after waiting long enough, the screen went blank. Pressing a key restored the text.
This was, truly, the lamest victory.
Next: lessons learned of desperation.
Day 27: The Opposite of Fail
This afternoon, I loaded the custom ROM back into my programmer and ran the verification routine to ensure that the data was correct. The data matched up with the target bit for bit. Why couldn't the VT100 see my ROM? Was the extension cable too long? Was the EEPROM incapable of driving the bus? Frustrated, I tossed one of the masked ROMs into the programmer and tried to read it. And almost immediately facepalmed.
Remember the trouble I had reading the ROMs in the first place? Among other things, because the sense of the chip enable lines was not what I expected? Yeah, apparently neither did I, because when I designed the EEPROM carrier the very next day, I modeled the pinout on a 2716 PROM, which uses a more standard active-low chip enable. What the hell? Why had I thought a 2716 pinout would work? Where had that idea come from?
From the Advanced Video Option daughterboard, of course.
With the right jumper settings, the AVO can patch over individual 2K ROMs on the basic video board, or all 8K at once. And because the AVO was designed to allow patching by Mere Mortals, it's set up to accept standard 2716 parts. Take a look at the two diagrams at the bottom. The upper one is the schematic of the ROM chips on the basic video board; the lower is the schematic of the sockets on the AVO. See that little circle in front of the CS1 lines in the lower diagram? Those indicate that the signal is active low, which is how most chips (including the EEPROM on my carrier) want to interpret this sort of signal. So all I had to do is plug my ROM into the AVO E8 socket, set the dip switches to patch over the entire 8K program, and turn it on.
Presto.
Now to add a brightness indicator to my emulator, find a few spare bytes of memory, and start working on the fadeout screensaver.
Day 26: Moment of Fail
With the clock running down, it was time for the moment of truth: could I actually boot of one of my hacked-together custom ROMs? For that matter, would it even fit it in the cabinet? My first attempt, using 6" jumpers to bridge the ill-sized .9" DIP board to a set of pin headers, failed utterly. The pins just weren't going to sit in the socket, and there wasn't room in the cage for that mess of cables. Luckily, an eagle-eyed resistor found a ribbon cable with a DIP IDC header on it (similar to this). Using the correct parts was out of the question, so I found and old IDE cable, took off two of the IDC connectors, and clamped them to the ribbon. I popped some pin headers in and checked the continuity-- success! This might actually work after all!
I grabbed an old Teensy 2.0++ and hacked together some code for writing and testing the EEPROM carrier board I'd thrown together on day 24. One mess of jumpers and a stack of bits adapted from Trammell's ROM dumper code later, I had a working ROM. Multiple successes! I am unstoppable.
[cue Mozart's "Failure Dirge" on rdio right about now]
Finally, I rushed home, pried the ROMS from one of the basic video terminal boards, dropped in the custom ROM, put the AVO daughterboard back on top, slapped in the card and hit power, and got... nothing.
Thinking that perhaps I'd misconfigured the AVO, I popped it off, restarted, and was greeted with the bottom image below. Great. I figured I'd double-check my data and pop the ROM into my old ROM dumper, but surprise: it had disappeared sometime in the past week. No problem; I'd just gotten a shipment of 40-pin ZIF sockets so I could grab another Teensy and build a new one. That seemed sensible, until I got to NYCR and discovered that we were completely out of Teensy 2.0++s.
At this point, understanding the situation I was in, I retreated to the basement of my home, sat in a lotus position in front of the boiler, and intoned to myself softly:
This is all but step in the Hero's Journey.
Then I grabbed my logic analyser and got to work.
Day 24: Hacking it up
It's becoming increasingly unlikely that my second OSH Park order is going to show up before the end of the month, so I'm just going to to have to hammer this .9" square peg into this .6" round hole. Shown are the old version of the EEPROM carrier and my adapter socket. I'll be using some 6" jumpers to link them together; hopefully they'll fit semi-tidily into the VT100's card cage. Fingers crossed!
Day 18: ROM carrier fail.
My ROM carrier boards came in the other day, and no sooner had I opened the package than I realized my mistake: I'd based my footprint on a DIP24-9, not a DIP24-6, and my board was far too large. Worse yet, I wouldn't even be able to fit my flash chips on the smaller carrier.
Anyway, I quickly ordered a SOIC-28 version of the same chip and slapped together a new revision of the board. I hope it works right off the bat, because I'm running short on time. At least it wasn't a very expensive mistake.
Day 20: Qt, ncurses, massive fail and super win
Between Toorcamp, NOPE, HOPE, wedding planning and furniture shopping I haven't had time to blog my retrochallenge progress. Long story short: it's coming along!
My first attempt at an emulator was a shambling mess of Qt (top) about which the less is said, the better. So let's just skip to my second attempt (bottom), which just uses raw ncurses for the GUI.
The trickiest bit of the emulator is providing a close enough approximation to the behavior of the hardware to get it to run reliably. There are two bits in the flags buffer that represent timing-dependent values, and a third that is needed by the keyboard, all generated by the video subsystem. Two of them, LBA4 and LBA7, are address lines from the horizontal character cache. LBA7, clocking at 1/8th the rate of LBA4, is used to directly clock the non-volatile RAM chip, the 1400-bit ER1400. (Initially I thought no datasheet existed for this chip; later I discovered I'd been looking for the wrong part number, but not until after I'd reversed the protocol from the ROMs. ¯\_(ツ)_/¯) LBA4 is used to work out timing for interacting with the keyboard. The other bit is essentially the vertical refresh line, which runs about 60Hz.
It took a little doing to get the keyboard interrupt hooked up properly (and work around the debouncing code in the ROMs!), but it's currently up and running. I'm booting the ROM in the emulator, manipulating the set-up screens, etc. The next step is to emulate the UART as well, get breakpoints working properly, and finally to find unused memory to stash the screensaver code. At this point, I'll be happy to have a blanking screensaver done by the end of the month.
Day Six: Reverse engineering continues
I'm still teasing apart the ROM. 8080 assembler is getting significantly easier for me to read as I continue. I can identify stuff like this:
X1083: mov m,b inx h dcx d mov a,d ora e jnz X1083 ret
as memset pretty easily, but now I'm getting into bits of the init that are just storing magic numbers at random RAM locations. Ideally I'll have a complete enough map of scratch memory to see where I can borrow a byte here and there, but it's going to be a slog. Luckily, I've got another week until I have the parts to assemble a ROM replacement, so I can spend another few days REing the ROM in the meanwhile.
Day Five: A quick note about the emulator
I'm not going to get too much into the guts of the VT100 emulator yet, other than to mention that I'm working on one, and it's coming along nicely. I'm using Qt for the user interface (to show the character display and the keyboard LEDs) and tying it into z80pack's z80sim simulator.
So far, I've got the emulator loading the ROM, running, and driving the keyboard LEDs as expected (I've stepped it through much of the init). Unfortunately there are still some IO ports that aren't well documented that I'm going to need to nail down, and I've still got to work out how I'm going to bring in the external interrupts (most notably for the vertical refresh interrupt).
It's still very early days, but the code is up in github as usual if you want to poke around.
Day Four: ROM Checksums
The VT100 technical manual indicates that the first thing that the firmware does on boot is run checksums on the ROMs. I figured I should work out how those checksums are computed, since it would be nice to know that my dumps are correct and also because I'll need to add my own bits to the code later to ensure the checksums work out.
It's also a good exercise for me, because I've never done any 8080 work before, and it's nice to get some practice reading the mnemonics. Here's the checksum code, annotated:
;;; Run checksum on each 2K ROM, indicating with ;;; the keyboard LEDs which is being scanned. ;;; The # of the chip being scanned is stored in B. xra a ; zero A mov d,a ; zero D, L, H mov l,a mov h,a csrom: inr a ; next 2K ROM mov b,a ; store the current ROM # in B out 82h ; show current ROM on LEDs mvi c,8 ; Checksum over 8 256B blocks X004f: rlc ; Rotate A left xra m ; A <- A ^ memory inr l ; next memory address jnz X004f ; ... repeat until end of block inr h ; next block dcr c ; decrement block count jnz X004f ; ... repeat until end of chip ora a ; Check the value of the accumulator X005b: jnz X005b ; If it's not zero, hang forever mov a,b ; Put the ROM # back in the accumulator cpi 4 ; If it's not 4... jnz csrom ; repeat for the next ROM
The way the checksum works is pretty clear here: for each byte, it rotates the accumulator one bit to the left and XORs it with the byte. The accumulator is initialized with the number of the ROM being scanned (1-4) so if the wrong ROM is somehow being scanned it will fail the checksum. At the start of each chip's checksum, the number of the chip is written to the keyboard status register. The VT100 keyboard has several LEDs that are set by writing to this status register; so the current chip being checked is indicated. If a checksum fails, the terminal enters an infinite loop, and the identity of the failed chip is displayed on the keyboard LEDs. Pretty neat for thirty bytes of code.
I reimplemented the checksum in python, and sure enough, the ROMs pass. Hooray!
Day Two: The EEPROM Carrier
At some point I'm going to have to install a new physical ROM in this thing. As discussed before, the board is handily wired so that I can use a single 8Kx8 ROM instead of the four 2Kx8 chips. Unfortunately, EPROMs in a 24DIP form factor are hard to come by. Instead of attempting to hunt down an old UV-erasable chip, I've designed a simple carrier board that can plug directly into the socket and hosts an AT28C64B chip in a 32PLCC package. I'll breadboard up a circuit for programming it, and we should be good to go. The OSH park order went out on the 3rd, so the boards should be here next week. If I get really impatient I can try to mock one up on the mill.
The design is shared out on OSH park if you want to get your own, although I'd wait until I've built and tested the board first.
The VT100 Memory Map and 8080 Disassembly
Before we get into the guts of the firmware it's best to start with a basic understanding of the VT100 memory map. Leaving for the moment the AVO expansion aside, the VT100 has 8KB of ROM and 3KB of RAM. The ROM is mapped to 0x0000 and the RAM to 0x2000. The layout roughly looks like this:
Start End Size Description 0x0000 0x1fff 8K Basic ROM 0x2000 0x2012 18B Blank lines for refresh (6 x 3B) 0x2012 0x204f 61B Stack area (grows down from 0x204e) 0x204f 0x22d0 641B Scratch Pad/Setup Area(?) 0x22d0 0x2c00 2352B Screen RAM
On boot, the VT100 sets the PC to 0 and start running right from the ROM. Pretty straightforward! Now on to the firmware itself.
To disassemble the firmware, I'm using the dz80 tool from the readily-available d52 package, like so:
dz80 -8 basic.bin
The '-8' flag tells dz80 to use the 8080 mnemonics instead of the default Z80 mnemonics. (This is an actual 8080 processor after all.) Let's see if the output passes the smell test. The opening lines are:
org 0 X0000: di lxi sp,X204e jmp X003b
So the first thing it does is disable interrupts and set the stack pointer to 0x204e, exactly what we'd expect. Looking good so far!
Dumping the ROMs
On the back of the VT100 is a tall access panel affixed by four screws. Behind it is a card cage containing the Basic VT100 video card. Once the keyboard is unplugged, the video card can be easily removed by carefully pulling it out of its slot.
This VT100 has the Advanced Video Option (AVO) board installed. That's the small daughterboard you can see on top of the main board in the third picture. The VT100 ROMs are in sockets beneath the AVO board.
The VT100 shipped in two variants: with a single 8Kx8 24-DIP ROM or with 4 2Kx8 24-DIP ROMs. We have the 4 2Kx8 variant. Here's where it gets a little loopy: in the technical manual, ROM 0 is towards the middle of the board and ROM 3 is towards the edge. Confusingly, the order of the ROM chips on my (working) board was reversed! I was chalking it up to an error in the technical manual, but a few failed attempts to dump one of the ROMs later I suspected something was up. That's when I noticed the schematic above.
Rather than use a demultiplexer to select the correct ROM chip based on the high two bits of the address, the DEC engineers decided to essentially handle the demuxing in the individual ROMs themselves, with this weird three-line chip select mechanism. It's a really clever solution, since
it saves the cost of another demultiplexer chip,
you can drop in a single 8Kx8 ROM (more on that later) instead of four 2Kx8 ROMs in a later revision without having to alter the board layout, and
you can install the ROMs in any order you want, and the thing will still work.
Now that I understood how the chip select mechanism worked, I modified my dumper to set the CS1..3 lines correctly, dumped all four 2K ROMs, and assembled them into an 8K image.
Next up: disassembly.
Day 1: tools. The USB-RS232 cable is for communicating over the serial port, and the mass of death beside it is a Teensy 2.0++ attempting to be a 24-pin 8Kx8 ROM.
It's time for a better DEC VT100.
I've been toying with the idea of entering a Summer RetroChallenge for four or five years now. This summer, I finally ran out of excuses. It's on.
On Monday evening, I'm bringing home a VT100 from the massive DEC haul we scored earlier this year. On Tuesday, the chaos begins.
My goal this July is to bring enhanced capabilities to the VT100 firmware. At a minimum this means some sort of screensaver. Ideally, I want flying toasters on the display by the end of the month. It's my first time hacking an 8080 platform, so we'll see how it goes.
Anyway, it's 2014. We've waited long enough. It's time for a better VT100.
The Rough Plan
The first step is going to be dumping the current ROM. (We have a gentle introduction to ROM dumping if you're interested.) The next step will be disassembly. I'm planning on using the d52 package's dz80 disassembler. Then it's off to the VT100 technical manual to see if I can figure out what's what.
Implementing a screensaver may be fairly tricky; a lot depends on how much memory I have access to and whether or not I can find a clock. I'll most likely start by modifying or adding something to the Set-Up screens. Ideally you'll be able to use the Set-Up mechanism to configure the screensaver.
This plan will probably disintegrate on contact with reality, but I'm looking forward to seeing what I can squeeze into this thing.
It's the 21st century. You deserve a terminal with 21st century capabilities. It's time to future-proof the VT100.