Keyboard Oddities |
Trying to reach me?
|
Just imagine you are playing on the FZ-1 when it suddenly just fries --
nothing will help but switching it off and on again.
Fortunately, there's an easy cure.
|
Suggestions, questions, acclamation, or simply curiosity about who that guy is you might want to place here:
rainer@buchty.net
|
Keyboard interface |
The keyboard scanner (MSM6200) periodically scans the 4 groups per 16 keys. Each key drives two switches in order to determine key state and velocity. Little is known about that guy, with the most comprehensive information probably contained in the HT6000 manual, that explains the general keyboard circuitry in more detail. Luckily, also someone uploaded the 8049 dump to the fantastic Synthesizer ROM Archive, so I took the change to peek into the code to deduct the inner workings in addition to what's presented in schematics and service manuals.
The keyboard controller is an 8049 microcontroller that interfaces the keyboard scanner (MSM6200) to the remaining machine. This works as follows:
- The MSM6200 is initialized by writing 0 to MSM register 8 (probably "init and start scanning") and an initial round of housekeeping by performing a write to register 8, writing/reading register 2 (presumably status; also put on the bus and flagged by P23, that however isn't used by neither FZ-1 nor HT-6000), and finally writing to register 1 (velocity) again. This probably means "halt scanning, get status, resume operation".
If the MSM6200 has a pair of key/vel data to offer, it raises an interrupt. The 8049 will then fetch it through fetching it from MSM registers 0 (key) and 1 (velocity) and put it into the ring buffer. A maximum of two pairs are fetched due to the 8049's memory limitations.
- In its main routine, the 8049 then checks whether there's data in the ring buffer. If so, the 8049 raises an interrupt towards the controlling CPU to signal that it wants to offload data, and also sets the CONT49 and SYNC49 signals accordingly.
- In the FZ-1's interrupt service routine (ISR), the CONT49 signal is checked. The 8049 lowers this for as long a full message is ready to be fetched. Otherwise, this signal is raised and the ISR is left.
- Now, the SYNC49 signal is checked. If it is raised, the key/command byte is fetched:
0x00|key means key on, 0x80|key key off. 113-key gives the true key number (as in MIDI numbering). On SYNC49==0, it's back to step #2.
- The SYNC49 signal is checked again. If it is now raised, the velocity byte is fetched. This is a 6-bit value (0-63) that serves as an index into a scaling table to get the usual 0-127 range. In case of "key off", it is zeroed. If SYNC49 went high meanwhile, 256 further access attempts are made. If the signal then is still high, the key/command byte is thrown away and we move back to step #2.
- The entire transfer phase is also flagged by the 8049's port signal P24. This, however, seemingly is neither used in the FZ-1 nor HT-6000.
- The whole message is converted to 0x90 key vel for note on or 0x90 key 0x00 for note off (looks familiar, doesn't it) and fed to the central message dispatcher that handles MIDI, keyboard, and a sequencer.
(Was there ever a native FZ-1 sequencer software? In any case, the OS is prepared ...)
- Before jumping back to the beginning of the main loop, the 8049 calls the housekeeping routine (see first step).
Channel pressure is scanned by the main machine and treated as just another control voltage like pitch bend, mod wheel, foot controller, or volume slider. The 8049 doesn't care about this, and hence it's also not part of the keyboard ISR. Furthermore, the 8049 has to be explicity reset by via the RDY signal, i.e. bit 6 of the LED pattern (using only 5 bits).
Looking at the ISR makes me shudder, to be honest, as it has some severe design issues:
- Once the ISR is entered, it can get stuck in a forever-loop in case CONT49 stays low, but SYNC49 isn't raised (as it should for indicating data ready). It takes CONT49==1 to leave this loop. This is the underlying cause enabling the fault described further down this page.
- Keys are immediately put into the keymap, but before velocity reading took place. The latter can fail, however, leaving a dead entry in the keymap until you hit that very key again. Why is this bad? Because in case of a filled keymap, the very last entry is overwritten.
- I was about to say that keycount isn't range-checked or limited, but as it's not used as an index into the keymap but instead repne scasb is used to find the entry, at least no over- or undershooting will take place.
- Only the first 6 active keys seemingly get a proper velocity reading. The remaining ones will just recycle the last reading. Bad news for people who like to play large chords. Honestly, why I see if (keycount>=6) vel=last_vel; (well, in x86 assembly) there, is beyond me.
|
|
Why does the keyboard jam anyway? |
As indicated above, the keyboard is -- from the CPU's point of view -- a read-only register in the CPU's memory area. But since the CPU has to do many things (e.g. sound playback) it doesn't have the time to permanently check this register, an interrupt is sent to the CPU by the keyboard processor. This interrupt will force the CPU to jump into the keyboard communication routine to read the (virtual) register. By doing so the interrupt flag is cleared.
What makes the FZ-1 hang is if this interrupt flag isn't cleared properly.
|
|
The Cure |
My first and obvious thought was that the interrupt flag (realized by a 74HC74) was defective. Since I didn't have a 74HC74 at hand I used a 74HCT74 as replacement -- and the FZ-1 seemed to work again. However, stress testing showed that the problem appeared just less often, but was still present. It looked like the clear signal generation was causing the problem.
And, indeed, the reset signal showed up all kinds of weirdnesses such as overshoot, undershoot and -- even worse -- spikes and breakdowns. Having a look at the schematics I realized that the address multiplexer (74HC154) was the part responsible for this signal. After replacing it with a 74HCT154 everything was fine again.
Casio obviously seems to love hide-and-seek games and thus didn't use usual part numbering, so here are the positions of the two mentioned ICs:
Location of 74HC74 and 74HC154
|
|
Nothing lasts forever... |
...even the above fixing. After several days of playing, the error showed up again. Somehow, the 74HCT154 got blown again. To prevent further blowups, I decided to secure it by a ZPD4.7 diode and a 1uF capacitor between Vcc and GND. Furthermore, pin 6 got a 100Ohm resistor in series. Future will show if this will keep the 74HCT154 alive for a longer time.
Protecting the 74HCT154
|
|