Scanning a cortron Diablo keyboard
-
- Location: USA
- Main keyboard: logitech K800
- Favorite switch: Box Heavy Pale Blues
- DT Pro Member: -
I'm working on restoring and converting a Xerox Diablo 1660 keyboard.
it has ITW/Cortron ferrite core switches.
The board is well documented in manuals and patents.
Upon initial power-up one of the caps smoked, and took out several 74 series ICs on the board.
After desoldering several chips and soldering in sockets I got the board to start scanning the matrix.
Next problem is the MCU (and possibly sense amplifier?) requires -12V supply to work.
1640/1640 variant of the keyboard omits the -12 line to MCU and amp, not sure if this was a process change or an error, but my MCU definitely requires it.
My plan is to remove the MCU, add a socket, and use a CY8C-059 to read the matrix.
I've implemented the timing generator as described in the patents below in PSOC Creator, and attached a link to a test of the state machine below.
Plans for the future:
1. Be able to scan the matrix w/ psoc5
2a. remove all non essential logic and self power over usb
2b. remove non-essential FSM states for matrix scanning (current impl uses 33% of UDBs)
3. Increase scan freq (currently is ~100 scans /sec)
4. Remove sense amp and pulse stretcher, and use ADC to read analog value
5. Make Actuation depth configurable
6. Export PSOC Creator project as Makefile, build on linux, port QMK
Simulating the timing generator:
https://www.edaplayground.com/x/6A8t
maintenance manual/ schematics:
http://bitsavers.org/pdf/diablo/printer ... _Jul78.pdf
Some photos:
https://photos.app.goo.gl/nQNQgrNcEEAYXFCp7
Relevant Patents:
https://patents.google.com/patent/US3978474A/en
https://patents.google.com/patent/US4227163
it has ITW/Cortron ferrite core switches.
The board is well documented in manuals and patents.
Upon initial power-up one of the caps smoked, and took out several 74 series ICs on the board.
After desoldering several chips and soldering in sockets I got the board to start scanning the matrix.
Next problem is the MCU (and possibly sense amplifier?) requires -12V supply to work.
1640/1640 variant of the keyboard omits the -12 line to MCU and amp, not sure if this was a process change or an error, but my MCU definitely requires it.
My plan is to remove the MCU, add a socket, and use a CY8C-059 to read the matrix.
I've implemented the timing generator as described in the patents below in PSOC Creator, and attached a link to a test of the state machine below.
Plans for the future:
1. Be able to scan the matrix w/ psoc5
2a. remove all non essential logic and self power over usb
2b. remove non-essential FSM states for matrix scanning (current impl uses 33% of UDBs)
3. Increase scan freq (currently is ~100 scans /sec)
4. Remove sense amp and pulse stretcher, and use ADC to read analog value
5. Make Actuation depth configurable
6. Export PSOC Creator project as Makefile, build on linux, port QMK
Simulating the timing generator:
https://www.edaplayground.com/x/6A8t
maintenance manual/ schematics:
http://bitsavers.org/pdf/diablo/printer ... _Jul78.pdf
Some photos:
https://photos.app.goo.gl/nQNQgrNcEEAYXFCp7
Relevant Patents:
https://patents.google.com/patent/US3978474A/en
https://patents.google.com/patent/US4227163
- DMA
- Location: Seattle, US
- Main keyboard: T420
- Main mouse: Trackpoint
- Favorite switch: beamspring
- DT Pro Member: NaN
- Contact:
I happen to have 3 cortrons laying around. In one, I've got permission to replace the MCU and keep the driving logic because I couldn't figure out the analog part, really. Especially puzzling is the output from MCU which feeds back into the analog part depending on the previous key state.
.. I almost reversed the schematics in all 3, but work took the best part of me. I'll try to find the papers.
So, I was using a KitProg (of all things!) to drive the drivers - and was able to get almost (ALMOST) all keys working. Problem was 3-4 keys which register like 1 times out of 10 - and I can't figure out is it because I fucked up timings somewhere or the keys themselves. Lack of logic analyzer shows - just the oscillograph is not a good fit for long sequences.
2b - why do you care? You won't be mass-producing them so shoehorning into 5267 is not a realistic perspective, and otherwise - why bother?
4 - why it's even a separate item?
5 - good luck. Your main problem will be fighting EMI.
6 - why? Building firmware on linux is pointless as you can't change anything - for ANY "hardware" change you'll need Windows environment - and flashing firmware into CY8C5 is a breeze from any of mac/win/linux (not by cypress software - but you can steal my flasher).
"port QMK" - good luck, you'll need it. I started from porting TMK to PSoC5LP and quickly discovered that the part that remains after all the hardware support is literally not worth keeping.
PS: edaplayground link requires login
PPS: Have you published your PSoC creator project?
.. I almost reversed the schematics in all 3, but work took the best part of me. I'll try to find the papers.
So, I was using a KitProg (of all things!) to drive the drivers - and was able to get almost (ALMOST) all keys working. Problem was 3-4 keys which register like 1 times out of 10 - and I can't figure out is it because I fucked up timings somewhere or the keys themselves. Lack of logic analyzer shows - just the oscillograph is not a good fit for long sequences.
2b - why do you care? You won't be mass-producing them so shoehorning into 5267 is not a realistic perspective, and otherwise - why bother?
4 - why it's even a separate item?
5 - good luck. Your main problem will be fighting EMI.
6 - why? Building firmware on linux is pointless as you can't change anything - for ANY "hardware" change you'll need Windows environment - and flashing firmware into CY8C5 is a breeze from any of mac/win/linux (not by cypress software - but you can steal my flasher).
"port QMK" - good luck, you'll need it. I started from porting TMK to PSoC5LP and quickly discovered that the part that remains after all the hardware support is literally not worth keeping.
PS: edaplayground link requires login

PPS: Have you published your PSoC creator project?
- DMA
- Location: Seattle, US
- Main keyboard: T420
- Main mouse: Trackpoint
- Favorite switch: beamspring
- DT Pro Member: NaN
- Contact:
I've read the patent. Sorry to disappoint you - but "making actuation depth configurable" is not likely to work. According to US3978474 the key in rested state saturates the ferrite core by holding a permanent magnet close to it.
https://moluch.ru/archive/158/44626/ is (sorry for Russian. In case you're wondering - this models a very popular electricity-stealing tactics where you get a strong neodymium magnet and place it onto your electricity meter.) a description of how permanent magnet affects a current transformer (those ferrite cores _are_ current transformers). As you can see, very small variation in magnet to transformer distance causes the bulk of the change. So what we will likely see (I'll make a test harness tomorrow to see what actually happens there) is that when the key is at rest, no energy passes thru, and when we press the key slowly - it's nothing-nothing-nothing-A LOT-a lot-a lot.
https://moluch.ru/archive/158/44626/ is (sorry for Russian. In case you're wondering - this models a very popular electricity-stealing tactics where you get a strong neodymium magnet and place it onto your electricity meter.) a description of how permanent magnet affects a current transformer (those ferrite cores _are_ current transformers). As you can see, very small variation in magnet to transformer distance causes the bulk of the change. So what we will likely see (I'll make a test harness tomorrow to see what actually happens there) is that when the key is at rest, no energy passes thru, and when we press the key slowly - it's nothing-nothing-nothing-A LOT-a lot-a lot.
-
- Location: USA
- Main keyboard: logitech K800
- Favorite switch: Box Heavy Pale Blues
- DT Pro Member: -
2b. only phi1 and phi3 are driven off chip, i might not need the other states at all. This was my first attempt at writing Verilog, so I guess i just offended me that such a small component took up so much space in the PSOC.DMA wrote: 16 Jul 2019, 06:25 2b - why do you care? You won't be mass-producing them so shoehorning into 5267 is not a realistic perspective, and otherwise - why bother?
4 - why it's even a separate item?
5 - good luck. Your main problem will be fighting EMI.
6 - why? Building firmware on linux is pointless as you can't change anything - for ANY "hardware" change you'll need Windows environment - and flashing firmware into CY8C5 is a breeze from any of mac/win/linux (not by cypress software - but you can steal my flasher).
"port QMK" - good luck, you'll need it. I started from porting TMK to PSoC5LP and quickly discovered that the part that remains after all the hardware support is literally not worth keeping.
PS: edaplayground link requires login
PPS: Have you published your PSoC creator project?
4. it's separate in my head from removing logic that isn't required to read the matrix, like the output buffers and strobe generating flip-flops.
5. This one is more just to see if I can. the patents mention the phi1 off time is also important to let the capacitor that's connected to the top of the matrix recharge.
6. In general, I strongly prefer linux for development, use it for work etc. I am starting to realize that PSOC Creator is pretty awesome though.
Edaplayground code and output:
https://pastebin.com/nY34Yg0r
ChibiOS demo with USBFS Uart example hacked in:
https://github.com/kfazz/ChibiOS_demo_p ... M3-GENERIC
I've attached the current state of my psoc project to this post.
- Attachments
-
- Design01.cydsn.zip
- (14.56 KiB) Downloaded 270 times
- DMA
- Location: Seattle, US
- Main keyboard: T420
- Main mouse: Trackpoint
- Favorite switch: beamspring
- DT Pro Member: NaN
- Contact:
I tried to run creator from linux, but given up. Even if compilation environment is not really windows-specific, the UI is 
As for writing verilog for psoc - I find it easier to make the equivalent schema from components and let the creator deal with everything else - from verilog to bitstream generation.
chibios - I can't really understand why you would even need OS on things that small. Driving a screen or something like that? But there's no screen..

As for writing verilog for psoc - I find it easier to make the equivalent schema from components and let the creator deal with everything else - from verilog to bitstream generation.
chibios - I can't really understand why you would even need OS on things that small. Driving a screen or something like that? But there's no screen..
- DMA
- Location: Seattle, US
- Main keyboard: T420
- Main mouse: Trackpoint
- Favorite switch: beamspring
- DT Pro Member: NaN
- Contact:
OK, I killed 2 days but now I know why reads are so unstable.
Turns out, 74145 is there for a Reason.
The Reason is all 10 outputs are essentially shorted together - well, technically, they're connected via a wire wound thru all of those ferrite cores, so there's some impedance, but inductance is low and the resistance is abysmally low, so a lot of active power is dissipated.
So much, in fact, that voltage sags to 3.8-3.9V at the USB plug, and 74145 itself is slightly warm.
RMS at the plug is 4.42-4.44V, which is very close to absolute minimum of 4.4V.
So after I finish this note, I'm into cutting some wires and direct-driving + direct-sensing. Not sure about output voltage levels - so driving first, sensing later.
Other than that - in my devices 7442 (rows) is driven normally, 0 to 9 (bits 4,5,6,7 - bit 0 being highest frequency), but 74145 is driven in an interesting way: bits 0 and 1 are coming from the MCU, but bits 2 and 3 are modulated by a NAND gate (half of 74LS00N) with positive strobe (φ2 in US3978474A AKA P1 in US4263582).
MCU drives all 16 values, but only 4,5 and 8 to 15 bring any of the outputs low. So, waveform of 1 row looks like this:
*) first 63 full periods of A (___~~~) are 70us, followed by 17 periods of 98us, giving full cycle time of 3.3+8.8=12.1 milliseconds.
The strobes themselves are a bit different from the patent - there's a positive strobe (2 lines, absolutely identical) and negative strobe. They are located in the middle of a pulse (20us + strobe + 20us or 40us + strobe + 20us) and shifted 5us front, 10us back:
Comparator (not amplifier! LM319N in my case) generates an extremely short (and very unstable because of power sag: https://www.instagram.com/p/B0Ef6aLliQX/ ) pulse - ~150ns. PFN (another half of 74LS00N) takes care of it, presenting MCU with the signal depicted as IN: on previous diagram - from the "ON" of positive strobe to the "OFF" of negative one.
I was able to poll without a single line of Verilog:
Drive and Strobe are control registers (clocked by 200kHz - same clock that drives the DriveIRQ), DrivePins are "resistive pull up" digital outputs, positive strobe (StrobePin_{0,1}) are resistive pullup too, negative strobe (StrobePin_2) is resistive pullup-pulldown.
I would make others pullup/down too - it significantly reduces spikes at the cost of 500ns to reach the logical 1/0 - but pulldown resistors only can pull the inputs down to 1.5V and this is not enough to trigger logical zero.
SensePin is digital input, CMOS, buffered.
The code pasted uses longer key scan slot as an attempt to reduce current consumption. It helps - min voltage is about 4.05V. But that's not enough, readouts are still unstable.
Turns out, 74145 is there for a Reason.
The Reason is all 10 outputs are essentially shorted together - well, technically, they're connected via a wire wound thru all of those ferrite cores, so there's some impedance, but inductance is low and the resistance is abysmally low, so a lot of active power is dissipated.
So much, in fact, that voltage sags to 3.8-3.9V at the USB plug, and 74145 itself is slightly warm.
RMS at the plug is 4.42-4.44V, which is very close to absolute minimum of 4.4V.
So after I finish this note, I'm into cutting some wires and direct-driving + direct-sensing. Not sure about output voltage levels - so driving first, sensing later.
Other than that - in my devices 7442 (rows) is driven normally, 0 to 9 (bits 4,5,6,7 - bit 0 being highest frequency), but 74145 is driven in an interesting way: bits 0 and 1 are coming from the MCU, but bits 2 and 3 are modulated by a NAND gate (half of 74LS00N) with positive strobe (φ2 in US3978474A AKA P1 in US4263582).
MCU drives all 16 values, but only 4,5 and 8 to 15 bring any of the outputs low. So, waveform of 1 row looks like this:
Code: Select all
70*us/~~~, subdivisions not to scale.
CLK: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
A: ___~~~___~~~___~~~___~~~ ___~~~___~~~___~~~___~~~
B: ______~~~~~~______~~~~~~ ______~~~~~~______~~~~~~
C: ~~~~~~~~~~~~~_~~_~~_~~_~ ~~~~~~~~~~~~~_~~_~~_~~_~
D: ~~~~~~~~~~~~~~~~~~~~~~~~ ~_~~_~~_~~_~~_~~_~~_~~_~
Out: ~~~~~~~~~~~~~_~~_~~~~~~~ ~_~~_~~_~~_~~_~~_~~_~~_~
The strobes themselves are a bit different from the patent - there's a positive strobe (2 lines, absolutely identical) and negative strobe. They are located in the middle of a pulse (20us + strobe + 20us or 40us + strobe + 20us) and shifted 5us front, 10us back:
Code: Select all
5us/~
PS: __~~~~~_
NS: ~____~~~
IN: ~~___~~~
I was able to poll without a single line of Verilog:
Code: Select all
static volatile uint8_t current_key = 0;
static volatile uint8_t drive_code = 4;
static volatile uint8_t current_stage = 0;
//static volatile uint8_t signal = 0;
#define STROBE_START 12
#define READ_POINT STROBE_START + 2
#define STROBE_END READ_POINT + 1
#define CYCLE_END STROBE_END + 12
const uint8_t column_LUT[] = {4, 5, 8, 9, 10, 11, 12, 13, 14, 15};
CY_ISR(DriveIRQ_ISR) {
// Strobe_Write(current_stage);
current_stage++;
switch (current_stage) {
case 1: {
Drive_Write(drive_code);
Strobe_Write(4);
break;
}
case STROBE_START:
Strobe_Write(0);
// signal = 0;
break;
case STROBE_START + 1:
Strobe_Write(3);
break;
case READ_POINT:
debounced_matrix_process(current_key, CyPins_ReadPin(SensePin_0) ? 0 : 1);
// The range is 0 - number of keys. So at the last key we reset to zero.
if (current_key >= 99) {
current_key = 0;
drive_code = 4;
} else {
current_key++;
}
drive_code++;
// Driver generates pulses only at positions 4, 5, 8-15.
// So we will skip non-coding positions.
if ((drive_code & 0x0f) == 6) {
// passed 5. Skip to 8.
drive_code += 2;
} else if ((drive_code & 0x0f) == 0) {
// just passed 15. Advance 4 steps to 4.
drive_code += 4;
}
break;
case STROBE_END:
Strobe_Write(7);
break;
case STROBE_END + 1:
Strobe_Write(4);
break;
case CYCLE_END:
current_stage = 0;
break;
default:
break;
}
}
I would make others pullup/down too - it significantly reduces spikes at the cost of 500ns to reach the logical 1/0 - but pulldown resistors only can pull the inputs down to 1.5V and this is not enough to trigger logical zero.

SensePin is digital input, CMOS, buffered.
The code pasted uses longer key scan slot as an attempt to reduce current consumption. It helps - min voltage is about 4.05V. But that's not enough, readouts are still unstable.
- DMA
- Location: Seattle, US
- Main keyboard: T420
- Main mouse: Trackpoint
- Favorite switch: beamspring
- DT Pro Member: NaN
- Contact:
OK, I have good news and bad news. Good news is one can sense keypress depth: https://www.instagram.com/p/B0KiNFCFydI/ - kind of.
The bad news is you have 20 mV of noise and 15 (FIFTEEN) mV of signal, for what seems to be 100 nanoseconds.
Here's non-pressed vs pressed oscillograms for 4-switches in series, loaded by:
Nothing (well, oscillograph probe is some load):
100K resistor:
Small ceramic capacitor:
Looks like capacitor is the best, but 50 nanoseconds is not really workable.
Seems like magvalve scanner will have a lot of passive components.
Need to read on direct current in transformers.
The bad news is you have 20 mV of noise and 15 (FIFTEEN) mV of signal, for what seems to be 100 nanoseconds.
Here's non-pressed vs pressed oscillograms for 4-switches in series, loaded by:
Nothing (well, oscillograph probe is some load):
Spoiler:
Spoiler:
Small ceramic capacitor:
Spoiler:
Seems like magvalve scanner will have a lot of passive components.
Need to read on direct current in transformers.
- DMA
- Location: Seattle, US
- Main keyboard: T420
- Main mouse: Trackpoint
- Favorite switch: beamspring
- DT Pro Member: NaN
- Contact:
Turns out the noise was my scope. I remembered the probes have 1x position and remeasured.
It's not that bad, but 50ns measurement window smells like OpAmps - which we have, but they only can be used on specific pins and there are only 4 of them (so either external demux OR external OpAmps OR rewiring of ALL the switches OR using 2(3?) kits and an internal USB hub.)
100KΩ load:
No load:
Capacitor load
Also it seems like external current-limiting resistors (1kΩ) will be needed - current is just too low with internal pullups to produce any meaningful output voltage:
Rectifier would save the day - but rectifying 16mV.. haven't seen diodes having forward voltage of <150mV so direct rectification is out of question.
It's not that bad, but 50ns measurement window smells like OpAmps - which we have, but they only can be used on specific pins and there are only 4 of them (so either external demux OR external OpAmps OR rewiring of ALL the switches OR using 2(3?) kits and an internal USB hub.)
100KΩ load:
Spoiler:
Spoiler:
Spoiler:
Spoiler:
- DMA
- Location: Seattle, US
- Main keyboard: T420
- Main mouse: Trackpoint
- Favorite switch: beamspring
- DT Pro Member: NaN
- Contact:
..there's this wonderful chip, cheap as dirt (about $7 for a hundred) - TA7642. It is an AM radio chip - but if you think about it, AM radio is just a very sensitive rectifier, so hooking a naked TA7642 (w/o compensating resistors - resistor between output and power, cheap diode with 100pF capacitor between output and ground) may just be the ticket.
I'll try to use the op amps - and failing that (which I kind of expect - those opamps GBW is just 3MHz), comparators - to reduce number of external components. But if I'll get sucked in by work - try TA7642, it's likely to work.
I'll try to use the op amps - and failing that (which I kind of expect - those opamps GBW is just 3MHz), comparators - to reduce number of external components. But if I'll get sucked in by work - try TA7642, it's likely to work.
- DMA
- Location: Seattle, US
- Main keyboard: T420
- Main mouse: Trackpoint
- Favorite switch: beamspring
- DT Pro Member: NaN
- Contact:
GOT THE SIGNAL.
Comparator + VDAC as reference.
VDAC 8mV - noisy resting state, solid pressed. 12mV - solid resting, noisy pressed :/
I mean debouncing is needed anyway, but would like to see something more stable.
Comparator + VDAC as reference.
VDAC 8mV - noisy resting state, solid pressed. 12mV - solid resting, noisy pressed :/
I mean debouncing is needed anyway, but would like to see something more stable.
- DMA
- Location: Seattle, US
- Main keyboard: T420
- Main mouse: Trackpoint
- Favorite switch: beamspring
- DT Pro Member: NaN
- Contact:
Made a 2-column keyboard - AMux + VDAC + comparator + SR flip-flop, @80MHz.
2-step debouncing is mostly OK, especially if you trim the comparator right between the unstable regions.
Comparators turned out to be seriously badass - can be trimmed +/-16 mV, so can easily shift 3 DAC steps if needed.
Not sure how to represent all this in configuration UI though. Probably won't - auto-trim to zero gives a threshold of ~3 on my rig.
Will make better sequencing logic tomorrow-ish to make it single-shot from the software side (Software will only need to "select column block, drive this row, read that register") and reduce pulse length to ~40-50ns so I can remove current-limiting resistors, reducing number of passive components required to zero.
2-step debouncing is mostly OK, especially if you trim the comparator right between the unstable regions.
Comparators turned out to be seriously badass - can be trimmed +/-16 mV, so can easily shift 3 DAC steps if needed.
Not sure how to represent all this in configuration UI though. Probably won't - auto-trim to zero gives a threshold of ~3 on my rig.
Will make better sequencing logic tomorrow-ish to make it single-shot from the software side (Software will only need to "select column block, drive this row, read that register") and reduce pulse length to ~40-50ns so I can remove current-limiting resistors, reducing number of passive components required to zero.
- DMA
- Location: Seattle, US
- Main keyboard: T420
- Main mouse: Trackpoint
- Favorite switch: beamspring
- DT Pro Member: NaN
- Contact:
Matrix, 4x6, doesn't work and has wildly different characteristics.
In particular, it has huge ripple at the end of the strobe - and that ripple doesn't depend on key state.
Tried some methods, was not successful.
Comparator-based thresholds suck big time - you're blind and must check all the variants.
In particular, it has huge ripple at the end of the strobe - and that ripple doesn't depend on key state.
Tried some methods, was not successful.
Comparator-based thresholds suck big time - you're blind and must check all the variants.
- DMA
- Location: Seattle, US
- Main keyboard: T420
- Main mouse: Trackpoint
- Favorite switch: beamspring
- DT Pro Member: NaN
- Contact:
OK. I've got this 2x6 piece of matrix (in background) to work.
Couldn't do it on ADCs, had to resort to comparators. Trigger levels are FOUR MILLIVOLTS. Step is 4mV, and 8mV doesn't work already - signal is too weak.
Pin placement is trickier than in original CommonSense, because there are 4 MUXes, which strains analog routing a bit. But it's nice to have 4 parallel read channels - things are faster that way.
Here's the sensor: And here's the driver/sequencer: Will try to graft to this guy over the weekend, see what happens. Today is exactly 11 months since I've got it. Hopefully Sangdrax will be typing on it before it's a year ;D
Scope is invaluable. I screwed up both in hardware (several things) and software (skipping half of the init, then shorting all rows in debouncing by passing zero instead of the row) - and the scope allowed me to figure out that OK, the scanner is now working, the problem is in firmware.Couldn't do it on ADCs, had to resort to comparators. Trigger levels are FOUR MILLIVOLTS. Step is 4mV, and 8mV doesn't work already - signal is too weak.
Pin placement is trickier than in original CommonSense, because there are 4 MUXes, which strains analog routing a bit. But it's nice to have 4 parallel read channels - things are faster that way.
Here's the sensor: And here's the driver/sequencer: Will try to graft to this guy over the weekend, see what happens. Today is exactly 11 months since I've got it. Hopefully Sangdrax will be typing on it before it's a year ;D