Posted By
TLC on 2021-06-09 05:47:45
| Re: Let’s JoyTest! :)
Maybe I should finally sum up how/why this all works the way it does, from a hardware point of view. Probably also with a bit of history involved, since, there is (as always) a reason behind all this.
First of all, probably anyone ever programming on other platforms (also, people who converted programs from C64) have noticed that the keyboard scan method of the Plus/4 works slightly differently to either the C64 or the VIC-20 (...or, other Commodore machines). Specifically, all the other platforms lack the "sta $ff08" part in the keyboard scan method. The basic method, by itself, is always the same in any of these machines. There is a 8x8 matrix of rows and columns (wires), with key contacts at the intersection points, organized in some clever layout. There is a port circuit, usually a 6520 PIA, 6522 VIA, 6526 ACIA, where one puts out a set of row select bits by writing the value to the port register; and there is another 8-bit port, where one can "read" the columns. This can be clearly seen on both the VIC-20 schematics (see the UAB1 6522 at the upper left part, ports PA and PB), and the C64 (check U1 6526 PA/PB in the middle of the page). For physical reasons, the keyboard matrix lines are always "low active" - that is, a "0" bit (represented by a near-GND voltage level) can bring a column port input to near-GND, and (consequently) read as "0" from the column port input register, once a key contact between the activated row and some particular column is pressed. At first sight, the "TED", the 264 series, is no different. (Someone has generously made a cut-out of the keyboard part of the C16 schematics. There is U13 6529B ($fd30) supplying the row select bits, there is the keyboard matrix, and there are the K0-K7 column inputs on the TED - and that's it.) On second sight, though, there's a difference. As said, there's no equivalent of having to "write" to the input register (the column register) to trigger it to actually read something, on any of the other platforms. Simply there's no such step. But it's needed in the 264 architecture. Why is that? That one apparently goes back to the original plans, when the TED project was conceived.
As it's probably known for most people here, the TED (i.e. the machine as they called it in the early days) was originally to be a small, low-end machine, a "ZX killer", a "9-chip machine", its system properties dictated by the chip designers. 9 chips (as per Tramiel's original order), if one breaks that down, makes a CPU, TED, 2 ROMs, 2 RAMs, 2 RAM muxes, a 7406 for the serial port, and that's pretty much all. Bil Herd has regularly talked about the development of this series. For example, he told somewhere that he in fact added the "10th" chip himself (the reset circuit, a 555). ...Anybody seen the name of the 6529B keyboard port here? Nope, and that's for a reason. Bil has also talked in detail about, that the original plan used the data bus directly, as keyboard row select "port"*. With that, the designers wanted to get rid of one of the two full 8-bit ports otherwise needed for the keyboard matrix scan task. (BTW, Sinclair, for example, has been regularly using such tricks in their machines... maybe, that's also where the idea had originated from**). But, what are the consequences of a plan like that? The data bus obviously is never static. The data bus bits can change states in every bus cycles. (With a shared bus concept like in either the VIC-20, the C64, or, the Plus/4, and in its most basic case, for every CPU clock cycles, two bus cycles are performed; one for/by the CPU, and the other by the video chip). There's no way to write some "static" row select byte to the "data bus" first, and let it wait there until "something" eventually reads the columns, this is not possible. The only way for that, is some clever hack, that "captures" the column inputs' states just at some right minute. This is what's implemented in the TED keyboard input port (i.e. the port circuit behind K0-K7). The sampling of the port is triggered by writing to $ff08. So, effectively the process goes like this. 1.) CPU writes the row select byte "to" $ff08. 2.) As the last cycle of the instruction being executed, the value written to $ff08 is put onto the data bus by the CPU. 3.) This value (in this particular minute) effectively "is" on D0-D7 as voltage levels, and, with that, it's also on the keyboard matrix' row side. 4.) In just some ten- or hundred nanoseconds, the active D0-D7 outputs bring "low" all columns, where there is an active key contact between selected row and column, the voltage levels settle and become available on the K0-K7 inputs of the TED. 5.) After this some-hundred nanoseconds (timing hardwired in the TED), the TED keyboard port latches the K0-K7 inputs into an internal temporary storage. And finally 6.), a later lda $ff08 (or, any other read command) can read out the stored column value from the temporary latch. This is practically all about it .
"Aftermath". As it turned out later, the plan wasn't actually such a brilliant idea. Misusing the data bus for a keyboard matrix row port (especially, connecting long wires to the data bus) made the thing both susceptible to EMI, and made it produce a good deal of electric noise on its own (nothing good if the thing was to pass FCC inspection). The problem was eventually fixed by adding the 6529B to supply the matrix row select side, as we know it today. Interestingly, the joysticks somewhat still retain the original schema - they're not selected by 6529B port bits, they're still fed from two (now, buffered) bits from the data bus, see the U11 gate on the schematics. (With the TTL buffers added, they now prevented EMI from the long joystick wires to interfere with the data bus. I'm not that sure, though, of the RF noise produced by the construct itself.) Maybe, the V364 prototype's wiring could shed a light whether that solution was also "invented" at the time the 6529B was added to the design.***
TL;DR - the TED's keyboard port sampling nature is an artifact of the original (minimalistic) system design plan of the machine, which intended to (mis)use the data bus as keyboard matrix row select output port. The solution effectively works by sampling the K0-K7 inputs in a particular (writing) bus cycle, triggered by a write operation to the $ff08 register.
How and why it breaks? The "why" part is most likely due to ESD. The "how" part, is still unclear. As it's seen, the port still keeps working, only its "sampling" part is affected. No idea how that happens. How it works? In fact, the "sampling" part has a small additional feature, in that it not only samples (latches) the value on K0-K7, but also incorporates a "strong" pull up resistor, which is activated for a short time early in every K0-K7 sampling cycles. Maybe, this is an added feature to meet timing requirements. After all, voltages in the keyboard matrix all have to settle in a very short time, given the construct practically all clocked at the frequency of the bus cycles. This pull-up activation nature can be observed by inspecting the K0-K7 inputs on the oscilloscope, and, on a perfect TED, it evidently only happens upon $ff08 write cycles. On the other hand, with a broken TED, the activation of this pull-up can be observed on every bus cycles. It can be concluded then, that a broken TED executes the K0-K7 sampling on every bus cycles (regardless to any other factors).
All the tricks outlined to read the joysticks on a broken TED, and, to avoid the joysticks to interfere with key scan on a broken TED, are just consequences of the broken TED sampling the K0-K7 inputs on every bus cycles (plus, the nature of the port to sample the K0-K7 inputs one bus cycle prior to the value becoming available for read from the $ff08 register).
* Interview with Bil Herd , also 264/TED/Plus4 Story on cbm-hackers . BTW, if one covers the U13 6529B on the schematics of the production machine, (s)he'd pretty much get the original planned layout, with the data bus lines going straight to the keyboard connector pins. As a matter of fact, the known "developer units" like Prototype P15 and Prototype P19 from early Aug. 1983, both follow the original TED concept, i.e. neither of them have a 6529B, a PLA, nor any of the added extra ROM TTL logic. Crock's Commodore V364 prototype already has all the bells and whistles we know today (PLA, extra ROM logic, ACIA) and even more, but still only has the 6529B "dead bugged" in place of some passive components, which shows that the story of fixing the keyboard and joystick EMI problems must have happened very, very late; maybe late '83 or early 1984, and also obviously later than the invention of the fattened TED line-up models. Also, a comment found in the sources of the 264 series Kernal, http://www.zimmers.net/anonftp/pub/cbm/src/plus4/ted_kernal_basic_src.tar.gz, "** 01/17/84 mod for new keyboard port " at the $DB70 ROM routine (found beside the sta $fd30 instruction), suggests that "final" ROM support for the modified (6529B incorporated) keyboard hw layout was only added as late as January 1984, already past the 1984 Winter CES.
** At the same time, Sinclair never messed with using unbuffered system bus lines to connect joysticks, which might show why the method still worked for them, but not for Commodore.
*** Would be an interesting part to know. From Bil's story, EMI apparently only popped up as a serious problem, when they first got around to test the new (264 specific) joysticks. As he said, he invented and implemented the fix (the 6529B row buffer) in a matter of hours, and especially stressed why exactly he chose the 6529B / ruled out the use of any TTL gates for that role. Would really think the joysticks were still parallel connected to the keyboard matrix at this point, and the "fixed" prototypes simply activated them by using the 6529B.
@Mad you can detect the "broken" TED port by testing for a value change in the $ff08, while making sure that you're not doing $ff08 writes. Unfortunately, with no keys pressed / no joysticks moved, there's no activity that you could observe to change. The port problem can probably still be detected "hidden", parallel to some valid keyboard activity (at some point in your prod, where, running an additional detect routine is still not "critical").
|