Description of my self build +3s. The “s” suffix comes from my nick name, Secărică.
This appears to be a never ending project, with some new ideas and solutions appearing after each previously applied ideas and solutions, with less and less time these days to advance efficiently. However, I still hope to advance anytime soon.
I started this project sometime back in 1989.
What was in my mind at that time ?
Simple things ...
... and advanced things
And the result ?
Today I have an 8 bit computer that ...
... and it has only one noticeable limitation:
There are also a few things I am still planning to do in the future. I have no idea if and which of those things will ever be done.
For example, I want to change the CP/M actual 24x80 flip screen 5x8 pixel character display to a true 24x80 8x8 pixel character. The hardware permits this, but involves a lot of work in disassembling the original CP/M routines and discover all cross interactions when changing something there.
I also want to build a real time clock circuit. At present, when booting CP/M, I am entering the date & time manually each time and I find this very annoying. I would like to automate this process.
Other thing is that I am not interested in attaching a hard drive, but I am interested in attaching a SD memory card, even as a floppy replacement, no matter how slow the access speed will result. But one of the problem is that the internet today has become too commercial, superficial and less informative from an engineering point of view: I can find tons of places where I can buy an SD memory card, I can read several stories about how to use an SD memory card, but it is more and more difficult to find a place that describes its truly technical functionality. I mean truly: timings, bus voltage tolerance, consumption in various scenarios, bus protocol instructions, etc.
There are 3 reset modes:
All ports are fully decoded.
Original +48K Spectrum used only A0 for decoding its single port for keyboard, border, beep and tape, so any other hardware who wanted to be compatible with the physical 48K model was forced to use only odd I/O port numbers (a typical example is the Kempston joystick port); later, oficial models also used only odd port numbers for their various additional I/O . Since I was convinced that no software will ever try to access any even port number other than the original #xxFE, combined with the fact that I have no way to know if or what other odd port number could already be used by some commercial (or not) interface, the full port decoding gave me complete freedom to use any custom even I/O port from the 32512 ports available in the even range (i.e. less the original #xxFE). Having said that, I had no particular reason for choosing one value or another for my custom I/O ports.
With the exception of port #1F and #FF, all ports behaves exactly the same as for the original +3, with the added bonus that input ports #1FFD and #7FFD also have read capabilities (i.e. a program can get the actual status of memory paging by issuing an IN #7FFD instruction, for example).
IN #7FFD will read the actual status of port OUT #7FFD; likewise, IN #1FFD will read the actual status of port OUT #1FFD. Additionally, originally unused bits of ports #FE, #1FFD and #7FFD are used in input to read various machine parameter status, with no interference with existing software.
port #1F (31) | ||
---|---|---|
OUT | IN | |
bit 0 | not used | * Kempston joystick - right |
bit 1 | not used | * Kempston joystick - left |
bit 2 | not used | * Kempston joystick - down |
bit 3 | not used | * Kempston joystick - up |
bit 4 | not used | * Kempston joystick - fire |
bit 5 | not used | not used |
bit 6 | not used | not used |
bit 7 | not used | not used |
* Only when Kempston joystick is enabled, via custom bit 7 / OUT #BF7E |
port #FE (254) | |||
---|---|---|---|
OUT | IN | ||
bit value = 0 (default at any RESET) |
bit value = 1 | ||
bit 0 | B border colour OFF | B border colour ON | keyboard column CSHIFT, A, Q, 1, 0, P, ENT, SPACE |
bit 1 | R border colour OFF | R border colour ON | keyboard column Z, S, W, 2, 9, O, L, SSHIFT |
bit 2 | G border colour OFF | G border colour ON | keyboard column X, D, E, 3, 8, O, K, M |
bit 3 | tape data OUT | keyboard column C, F, R, 4, 7, U, J, N | |
bit 4 | 48K beep OUT | keyboard column V, G, T, 5, 6, Y, H, B | |
bit 5 | * tape motor OFF | * tape motor ON | * keyboard column F1, F2, F3, F4, F5, F6, F7, F8 |
bit 6 | not used | not used | tape data IN |
bit 7 | not used | not used | * if 1 => video circuit oscillator is in external mode |
* Additional I/O port usage, when comparing to original +3 |
port #1FFD (8189) | |||
---|---|---|---|
OUT | IN | ||
bit value = 0 (default at any RESET, except for bit 4) |
bit value = 1 | ||
bit 0 | main RAM is in +3 Basic mode | main RAM is in CP/M mode | actual bit status |
bit 1 | see the +3 documentation for this one | actual bit status | |
bit 2 | see the +3 documentation for this one | actual bit status | |
bit 3 | FDD motor OFF | FDD motor ON | actual bit status |
bit 4 | parallel printer port n/STROBE out this bit is set at any RESET |
actual bit status | |
bit 5 | not used | not used | if 1 => 3.5 MHz CPU clock |
bit 6 | not used | not used | if 1 => 7 MHz CPU clock |
bit 7 | not used | not used | if 1 => 14 MHz CPU clock |
* Additional I/O port usage, when comparing to original +3 |
port #7FFD (32765) | |||
---|---|---|---|
OUT | IN | ||
bit value = 0 (default at any RESET) |
bit value = 1 | ||
bit 0 | see the +3 documentation for this one | actual bit status | |
bit 1 | actual bit status | ||
bit 2 | actual bit status | ||
bit 3 | in normal screen resolution display is video RAM page 5 | in normal screen resolution display is video RAM page 7 |
actual bit status |
bit 4 | see the +3 documentation for this one | actual bit status | |
bit 5 | ports #1FFD and #7FFD are unlocked | ports #1FFD and #7FFD are locked | actual bit status |
bit 6 | not used | not used | n/H_BLANK |
bit 7 | not used | not used | n/V_BLANK |
* Additional I/O port usage, when comparing to original +3 |
port #FF (255) | ||
---|---|---|
OUT | IN | |
bit 0 | not used | not used |
bit 1 | not used | not used |
bit 2 | not used | not used |
bit 3 | not used | not used |
bit 4 | not used | not used |
bit 5 | not used | not used |
bit 6 | not used | not used |
bit 7 | not used | n/ACTIVE_WINDOW (H border AND-ed with V border) |
All the other +3 ports (#0FFD for parallel printer, #2FFD & #3FFD for FDD interface and #BFFD & FFFD for PSG interface) are implemented exactly the same as on original +3.
All of these new ports have read capabilities (i.e. an IN #xxxx instruction will read the actual status of that #xxxx port).
port #7F7E (32638) | |||
---|---|---|---|
OUT | IN | ||
bit value = 0 (default at any RESET) |
bit value = 1 | ||
bit 0 | ROM page 0 at address 0000-3FFF * | RAM page 12 at address 0000-3FFF * | actual bit status |
bit 1 | ROM page 1 at address 0000-3FFF * | RAM page 13 at address 0000-3FFF * | actual bit status |
bit 2 | ROM page 2 at address 0000-3FFF * | RAM page 14 at address 0000-3FFF * | actual bit status |
bit 3 | ROM page 3 at address 0000-3FFF * | RAM page 15 at address 0000-3FFF * | actual bit status |
bit 4 | write enable RAM pages 12-15 when in ROM mode | write disable RAM pages 12-15 when in ROM mode |
actual bit status |
bit 5 | 48K lock enable | 48K lock disable | actual bit status |
bit 6 | normal H border | normal H suppressed | actual bit status |
bit 7 | normal V border | normal V suppressed | actual bit status |
* Actual ROM (or RAM in ROM mode) page at address 0000-3FFF depends on original +3 ports #1FFD and #7FFD status |
port #BF7E (49022) | |||
---|---|---|---|
OUT | IN | ||
bit value = 0 (default at any RESET) |
bit value = 1 | ||
bit 0 | write enable video RAM for first 8K of page 5 | write disable video RAM for first 8K of page 5 |
actual bit status |
bit 1 | write enable video RAM for first 8K of page 7 | write disable video RAM for first 8K of page 7 |
actual bit status |
bit 2 | write enable video RAM for second 8K of page 5 & 7 | write disable video RAM for second 8K of page 5 & 7 |
actual bit status |
bit 3 | write enable video RAM for pages 4 & 6 | write disable video RAM for pages 4 & 6 |
actual bit status |
bit 4 | write enable main RAM for pages 4-7 | write disable main RAM for pages 4-7 |
actual bit status |
bit 5 | CPU reads pages 4-7 from main RAM | CPU reads pages 4-7 from video RAM |
actual bit status |
bit 6 | normal H resolution | double H resolution | actual bit status |
bit 7 | video RAM is written by CPU | video RAM is written by external serial data |
actual bit status |
port #DF7E (57214) | |||
---|---|---|---|
OUT | IN | ||
bit value = 0 (default at any RESET) |
bit value = 1 | ||
bit 0 | currently not used | currently not used | actual bit status |
bit 1 | currently not used | currently not used | actual bit status |
bit 2 | currently not used | currently not used | actual bit status |
bit 3 | extends main RAM to 256K at address C000-FFFF (+3 mode) or 4000-7FFF (CP/M Plus mode) |
actual bit status | |
bit 4 | extends main RAM to 512K at address C000-FFFF (+3 mode) or 4000-7FFF (CP/M Plus mode) |
actual bit status | |
bit 5 | extends main RAM to 1024K at address C000-FFFF (+3 mode) or 4000-7FFF (CP/M Plus mode) |
actual bit status | |
bit 6 | extends main RAM to 2048K at address C000-FFFF (+3 mode) or 4000-7FFF (CP/M Plus mode) |
actual bit status | |
bit 7 | extends main RAM to 4096K at address C000-FFFF (+3 mode) or 4000-7FFF (CP/M Plus mode) |
actual bit status |
port #EF7E (61310) | |||
---|---|---|---|
OUT | IN | ||
bit value = 0 (default at any RESET) |
bit value = 1 | ||
bit 0 | 00 - no change, allows hardware switching 01 - force 3.5 MHz CPU clock 10 - force 7 MHz CPU clock 11 - force 14 MHz CPU clock |
actual bit status | |
bit 1 | actual bit status | ||
bit 2 | 00 - no change, allows hardware switching 01 - force local free run oscillator for video circuits 10 - force external oscillator for video circuits 11 - does nothing (considered as invalid) |
actual bit status | |
bit 3 | actual bit status | ||
bit 4 | 00 - display is 50 Hz / 313 lines 01 - display is 50 Hz / 312 lines 10 - display is 25 Hz / 625 lines interlaced (TV standard) 11 - display is 25 Hz / 625 lines interlaced (TV standard) |
actual bit status | |
bit 5 | actual bit status | ||
bit 6 | tape IN port is free | tape IN port is AND-ed with tape OUT | actual bit status |
bit 7 | Kempston joystick disable | Kempston joystick enable | actual bit status |
Screen coverage of Video RAM addresses
I was once asked about the drawings, if they are “open” or somehow otherwise available.
The drawings are “open” since long time, except that I never managed to (re)draw and organize them in a PCB-oriented application (some of them are actually drawn in Visio) and too lazy to scan the remaining hand drawn. I also find hard to believe that someone will ever care about such a hard-wired complexity in year 20xx (although not impossible), given the evolution of logic gate arrays. All I can say is that I still have a lot more fun building pure hardware logic circuit connections than making logic emulation via software array programming.
But anyway, the drawings (at least the major part of it) are as follows:
I am particularly content with my solution for processor speed clock synchronous switching (drawing 03) and the double-buffer solution for data & address buses that allows the processor to write to video RAM without using any WAIT states up to approx 9.2MHz processor clock (drawing 07 & 08).