Overview
The idea for the OMNI-1 originally started out as a memory manager for banked CP/M 3. Then I found this wonderful Burroughs keyboard monstrosity that used hall-effect key switches. I had heard of the hall-effect before, and thought it would make a great keyboard that would never wear out. So I added the serial keyboard interface to the design. Oh, and a parallel printer port, too. As I neared the point of committing this to an actual prototype design, I thought, “What else do I need?” After changing the question to “What do I want?” I thought that a PROM programmer timing generator would get me one step closer to finally building a universal programmer. So I added that. Classic scope creep in retrospect.
The OMNI-1 has a PROM programmer controller, serial keyboard interface, and a programmable bank switched memory mapper with 20 bit addressing for the new S-100 bus specification (IEEE 696). A design innovation was the use of a pair of 74F283s as an ultra fast 8 bit magnitude comparator for the memory mapper.
Serial Keyboard Interface
The serial keyboard interface is specific to the Burroughs keyboard I had found at a surplus store. It came with schematics and specifications for the serial interface.
Parallel Printer Port
The parallel printer port is a classis write-only Centronics-compatible printer port. Nothing fancy.
Memory Manager
The memory manager was designed to be exactly what CP/M 3 wanted. A 20-bit address space of 16 64k banks, with an assignable window in the 16-bit address space for global memory. This global memory was always addressed as bank 0 and was the space where ISRs, BIOS, and part of the BDOS resided. The rest was switchable. CP/M’s usage of the banked memory was pretty much limited to one other bank for the bulk of the BDOS. The rest of the banks was used in my BIOS for disk caches and printer buffers.
PROM Programmer Interface
The PROM programmer interface is an 8-bit bidirectional parallel port with a single pulse generator. The actual PROM programmer was to contain all the level shifters, buffers, and latches necessary to implement the programmer. The pulse generator eliminated the need for software-driven timers.
Port Assignments
Click here to see the OMNI-1 schematic.
PORT 0: Serial Keyboard Data
Input
This port contains the eight bits returned from the serial keyboard after an Invitation to Interrupt or Get Command.
Output
This port is used to contain the eight bit data that is sent after a Select or Send Command. Note: This register is self-clearing, that is, the contents of the register is left zero after a command is issued. Therefore, it is not necessary to initialize this register to zero for the Invitation to interrupt or Get Commands.
PORT 1: Serial Keyboard Status
Input
Bit 0 of this port shall be true if the serial keyboard port is ready.
Output
Bits 0 through 3 specify the three bit command to be sent to the keyboard. The command, along with the data in the data register is then sent serially to the keyboard.
PORT 2: Parallel Printer Data
Output
Data output to this port is sent immediately to the printer. It is the responsibility of the driver program to insure that the printer is ready to accept the data.
PORT 3: Parallel Printer Status
Input
Bit | Function |
0 | Zero after data is output to the data port, Goes to One after the printer sends the ACK* signal. |
1 | The printer BUSY signal. |
2 | The printer PAPEND signal. |
3 | The printer SELECT signal. |
Output
Bit | Function |
0 | Sets the printer’s FAULT* signal. |
PORT 4: Extended Address Global Memory Bounds Register
Output
The low nibble (bits 0 through 3) sets the starting address of global memory, in 4096 byte increments. For example, a value of 1100 sets the beginning of global memory at C000 hex. The high nibble (bits 4 through 7) Sets the ending address of global memory. For example:
Value | Global Memory Range |
FF hex | F000 – FFFF |
8D hex | 8000 – DFFF |
10 hex | 1000 – 0FFF (no global memory) |
PORT 5: Extended Address Page Register
Output
Data output to this port is sent immediately to the printer. It is the responsibility of the driver program to insure that the printer is ready to accept the data.
PORT: 6 PROM Programmer Data Register
Input
This port contains the eight data bus lines to the PROM programmer.
Output
Data written to this port is always written to the data bus output register. However, this port is used to write to the time delay register and to the time delay scalar register, and may be enabled to do so by bits in the PROM Programmer Command Register.
Time Delay Scalar Register
Bits 0 through 3 specify one of eight time constants to be used in the time delay count.
Value | Delay per count | Range of delay |
000 | Infinite Delay | |
001 | 1 microsecond | 1µs to 255µs |
010 | 10 microseconds | 10µs to 2.55ms |
011 | 100 microseconds | 100µs to 25.5ms |
100 | 1 millisecond | 1ms to 255ms |
101 | 10 milliseconds | 10ms to 2.55s |
110 | 100 milliseconds | 100ms to 25.5s |
111 | 1 second | 1s to 255s |
Time Delay Register
The eight bit value sent to this port should contain the ones-complement representation of the delay count. A value of zero (FF hex) will result in no time delay; a value of 255 (00 hex) will result in the maximum delay count.
PORT 7: PROM Programmer Command Register
Input
Bit | Function |
0-2 | Returns the contents of the scalar register. |
7 | One if Time delay is active, zero if inactive. |
Output
Bit | Function |
0 | Low order address bit. Used with bit 1 below |
1 | High order address bit. Used with address bit 0 to address one of four eight-bit registers in the PROM Programmer. |
2 | Bus Direction bit. Zero for output to PROM Programmer, One for input from PROM Programmer. |
3 | Write bit. Positive edge causes PROM Programmer to write the data present on the data bus into the currently addressed internal register. Bus Direction bit must be zero. |
4 | Delay Register Enable. Setting this bit to a One causes data written to the data port to be written to the delay count register. |
5 | Scalar Register Enable. Setting this bit to a One causes data written to the data port to be written to the delay count scalar register. |
7 | Setting this bit to a One causes the time delay one-shot to trigger. The time delay register itself is destructive, meaning it will have to be written every time before a time delay event can take place. The time delay one-shot is non-retriggerable. |
Status
Between 1984 and 2022, the ONMI-1 prototype board existed in its original form as shown in these photographs. When I started the IMSAI Development System resurrection in 2022, I discovered that the Burroughs keyboard had developed a few bad keys, one of which was the Return key. After many hours of trying to fix it, I gave up and donated it to the recycling bin. I had also recently built and purchased device programmers that eliminated the need for the PROM programmer interface.
In 2022, the OMNI-1 underwent a radical keyboard/prom interfacectomy. The keyboard interface no longer had a keyboard to talk to. The PROM programmer interface had always just sat there generating heat. So these components were ripped out, leaving the memory mapper and the parallel printer port. The first goal is for the board to recover from the interfacectomy and function in the IMSAI Development System as it once did. The second goal is to free up room for newer additions such as a PS/2 keyboard interface, and finally spin it into a real board.