Tektronix 468
Hybrid Analog/Digital Oscilloscope
The Queen of the Tektronix 400 series
|
|
|
Introduction
The Tektronix 468 Digital Storage Oscilloscope is not "pure" digital like modern digital scopes. Rather, it is a 465B analog scope with added digital storage. The analog bandwidth is 100MHz. The digital sampling rate is 25 "Megasamples" per second (40 nanoSecs per individual sample); slow by current standards, but quite useful for audio and low-speed digital signals. It can "time expand" and display a sine wave up to 10 MHz in storage mode.
Besides the usual problems that occur with Tektronix scopes from this era, like failed components, especially tantalum and filter capacitors, the Tektronix 468 has problems with "Rom Rot", meaning the Mostek Roms containing the firmware stop working. This can be fixed by replacing the 24-pin custom Mostek Roms with standard 28-pin Eproms using an adapter. The Eproms need to be programmed with the original Rom images of course. See https://vintagetek.org/468-mostek-mkb36000-rom-repairs/ for more details. I have personally used 2364 adapters from Retro Innovations.
To diagnose problems in the Digital section of the scope, Tektronix offered a "Service Rom" which replaces one of the regular Roms. It shows some diagnostics, for example the status of all switches/buttons and allows the user to do various tests involving signature analysis. This method works very well but does require a Signature Analyzer.
The Digital section of this scope contains an Intel 8085 CPU running at 2.5 Mhz, 16K bytes of Rom (the firmware), and 3.5k bytes of Static RAM (plus 1k bits static RAM for the time dot cursor). The operation of the digital section is explained in the "Theory of Operation" section of the service manual. No information is available about the firmware, the 8085 instructions that control the digital section. A small 8085 assembly program is available to test the DIP switch settings but that is all I could find.
After contacting various ex-Tektronix employees, it was discovered that the 468 firmware was written around 1980 in a higher level language called Tesla, which stands for Tektronix System Language. Tektronix had its own Tesla compiler, generating Intel sanctioned 8085 instructions, running on a CDC 6000 type mainframe. This means that the developers had to submit their code every evening for batch processing. The compilation was finished in the morning after which they could debug their code. One compilation a day! How times have changed.
The 8085 has only 7 byte registers (A, B, C, D, E, H, L) though the last 6 can be combined into 3 16-bit registers (BC, DE, HL). The 8085 has a stack but no convenient way to address locations on the stack. As a result of these limitations, the Tesla compiler only allowed very limited parameter passing and no local function variables. Thus the developers were forced to use many global variables, as the code shows. This, combined with the fact that lots of code is being executed at interrupt time to improve the responsiveness of the 468, caused a plethora of potential bugs where global variables were unexpectedly changed.
Kudos to the Tektronix 468 developers for doing a great job, especially under these circumstances.
The original source code is sadly LOST. Tektronix didn't know how to archive software at the time but saved a CDC 6000 magnetic tape with the source code. That tape was lost after the Tektronix 468 was discontinued and any warranties had expired. Given that Tektronix saved many documents on microfiche, it's a mystery why they didn't save a source listing printout on microfiche.
No information is available on the Tektronix 468 firmware and this site is an attempt to change that. The binary image of the code is not encrypted or protected and with a decoder program, it was possible to create a listing of the 8085 instructions. That by itself doesn't help much because these instructions have no labels, no comments, many errors because code based tables are shown as instructions and other ambiguities. The internal design and structure of the code is completely invisible.
Two versions of the 468 firmware were published by Tektronix. They can be distinguished from each other by a strings:
"ID TEK/468,V79.1,FV:2.0;"
Identifies Firmware V2. I have only worked with V2.
Please note that the Intel 8085 runs the instruction set of the Intel 8080 CPU, officially extended with just 2 instructions. In reality, the 8085 has a handful of undocumented instructions, present on ALL 8085 CPUs but not sanctioned by Intel. Tektronix did not use any of the undocumented instructions.
Tektronix did publish the hardware addresses and their meaning, used to control the 468 hardware, in the Service Manual so the first task in deciphering the listing was to replace all labels that matched a published address with the official name. The second task was to identify code based tables. The third task was to identify variables, addresses in the Ram area. Modifying the decoder program to do these task helped. None of these task are without guesses though. For example, when is a label a constant or when is it an address. The 8085 is not a big help here since it uses a lot of "lxi h,nnnnH" instructions which loads register pair HL with a 16 bit value, then uses HL as either a constant (e.g. "dad d") or as a memory location (e.g. mov a,m). Also, keep in mind that the 8085 code was mostly generated by the Tesla compiler so, dependent on the smartness of the compiler, it's not always obvious what the code is trying to do.
Thanks for Kevin D. Quitt for providing a sample 8085 decoder: /* DASM85.C 30-Nov-88 9:07:32 by Kevin D. Quitt */
The next step was to assemble this 8085 source code to make sure that the resulting binary image still runs the Tektronix 468 correctly. Assembling the code was done using the "Makroassembler AS v1.42" by Alfred Arnold, ported to windows in a package called "aswcurr". Conventions used by this assembler were used for the duration of the deciphering (and later development) process. For example, hexadecimal constants are listed as 0FFFFH.
As long as only labels (and some comments) were added to the code, verification is actually very easy since the only thing to do is to compare the resulting binary image with the original image; they should be identical! The resulting source code file initially used only generic labels like L0070, referring to memory location 0x0070 (hexadecimal) or a constant value of 0x0070 and no comments. Using the knowledge gathered later in my explorations, I went back to this file and gave most of the labels meaningful names; some comments were also added. This decoded listing is available on github. OLD Listing file: "rom468combined.pdf"
Of course, once changes are made, this doesn't work anymore. The resulting 8085 hex image needs to be programmed into 2 Eproms, which then need to be inserted in the Tektronix 468. The Eproms removed from the 468 need to be erased using UV light to be able to reuse them. To simplify this task, I modified the Tektronix circuit a little to allow use of an Electrically Eraseable Rom (AT28C256). This EEprom has 256K bits, equal to 32K bytes. The two Eproms in the Tektronix 468 (using an adapter) are 27C64 Eproms, 8K bytes each so the firmware size is 16K bytes. The EEprom is twice as big and was initially programmed to include 2 consecutive copies of the image. The Tektronix 468 address decoding was then interfaced using a few wires (+ diodes) and a switch to select either the lower or the upper 16K bytes of this Eeprom when addressing addresses 0..03FFFH. More hardware changes were made later to allow direct access to all of the 32KB EEprom address space.
This process was repeated to decipher more and more of the code, also using information about the interrupts as used by the 468, as well as the static memory areas used. For examples, address ranges 8000H to 83FFH and 8800H to 8BFFH are used for general purpose RAM (called System and Scratch Ram). Address range 0A000H to 0A7FFH (not a mistake) is used as Display Ram and address range 0C000H to 0C1FFH is 512 bytes acquisition memory.
Two important observations here. First of all, the range 0A000H to 0A7FFH is 2K but there is only 1K of actual RAM here (despite what the Service Manual claims). It turns out that bit 0 in this address range is ignored so the 2 bytes in this range with only address bit 0 different actually refer to the same physical location.
Secondly, the address decoding is such that various regions decode to the same physical memory. This is used on purpose by the firmware to wrap around in the acquisition memory without changing the address pointers: address 0C2000H and address 0C000H are the same physical location so there is no need to update a pointer once its value progresses above 0C1FFH. It is also used during memory testing where the code continues testing memory beyond the address range but that is obviously a bug!
After getting a good feel for the code, I started to make modifications. The reason for wanting to make modifications was to save code space and the purpose of saving code space was the desire to add debugging capabilities to the 468. To that end, an 8085 machine level software debugger called "Mon85", written by Dave Dunfield and updated by Roman Borik, was used. This debugger allows simple tasks like inspecting memory and registers, showing instructions, single stepping. It also allows for breakpoints but that is not an easy task when the code is in Rom! A special technique was developed to insert a call to RAM where a conditional breakpoint can be set. However there still is a problem: how to interact with this debugger! The 468 has no I/O facilities nor does the 8085 support a real serial interface, as used nowadays with many microcontrollers. The 8085 however has 2 pins, called SID and SOD, which can be used to create a bit-banged serial interface and both Intel and the SBC-85 development board documentation provide an example on how to do this. Of course, wires have to be soldered to these SID and SOD pins and connected to a Serial Interface board (either RS-232 or USB) to connect this port to a terminal program running on a computer.
Stage 1: through a combination of local code optimizations ("peephole optimizations"), removing redundant code, disabling Rom and Ram test code and disabling the code to support the GPIB interface, I was able to save enough code space (about 5000 bytes) to add the debugger and serial I/O code. Finding Ram space for the debugger itself was another struggle but the result is a Tektronix 468 scope that can be software debugged.
Stage 2: as I got familiar with the inner workings of the Tektronix firmware, I continued the optimization process. At some point I realized that it was possible (though not easy!) to condense the code providing complete functionality (except GPIB support) of a 468 into 8KB. This means that a 468 can run with just one Eprom, useful if the original Mostek ROMs stopped working ("Rom Rot"). I recently achieved this goal: firmware V3.C where 'C' stands for compact.
During this process I noticed that the algorithm for displaying sine waves at high frequencies could be significantly sped up and I integrated this change.
This code compression process has another benefit: there is a lot of free space available in the full 16KB (2 Eproms) version V3, allowing for an optimization called "Loop unrolling" which improves the visual appearance of the 468 screen noticeably.
I'm looking for volunteers to test this new 1 Eprom version (V3.C). Requirements are a Tektronix 468 with at least 1 Eprom adapter and the ability to erase/reprogram a 27C64 Eprom; 27C128 and 27C256 Eproms usually also work. Contact me directly if you're interested.
For suggestions and corrections, please contact me at:
![]()
![]()