Shop OBEX P1 Docs P2 Docs Learn Events
Combinational key matrix 4 I/O=10 keys, 8 I/O=36 keys — Parallax Forums

Combinational key matrix 4 I/O=10 keys, 8 I/O=36 keys

Peter JakackiPeter Jakacki Posts: 10,193
edited 2020-08-17 05:20 in General Discussion
We are used to simple key inputs and when we have a lot of keys we used an XY matrix. If we only have 4 I/O that gives us 4 keys or with a 2x2 matrix that still only gives us 4 keys with no advantage. But what if 4 keys were simple direct non-scanning inputs so that any one can pull down an I/O line. That's 4 of course but now we place keys across the combinations of the 4 inputs. Then by checking first that no direct button is pressed (all highs) we then pull one I/O down and check the other 3 for a low indicating a combo key is pressed?

How many other keys can we add? The answer is 6 so with the 4 in total we can have 10 keys. With 5 I/O we can have 15, with 6 we can have 21, and the scan logic is very simple.
Any of the commoned keys (directly grounded) can directly affect the I/O but the combo keys need to be scanned.

For 4 I/O labeled A B C D we get the combinations: A B C D AB AC AD BC BD CD
Even if you didn't have a ground and only 4 physical wires you could still read 6 keys.

This reminded me of Charlieplexing LEDs and so I just did a quick search for doing the same with switches but from the little I could find they seem to be using diodes.
Anyway I don't know what to call it, maybe "ultraplex" but this method is ultra-simple and your typical 4x4 matrix normally yields 16 keys but those same 8 I/O will handle 36 keys this way.

The basic formula is n*n/2+n/2 so 8*4+4 =36 or n^2/2+n/2 or just add up the sequence like this 8+7+6+5+4+3+2+1 = 36
136 keys need 16 I/O.

I will build up a circuit later and write a q&d key scanner but here is what the circuit looks like. (assume pull-ups)

d273ff2a9da7d8e9b5c84a7cb7bda4.png

Comments

  • Are you sure this will work if more than one key is pressed at a time? Humans are unpredictable that way. :)

    -Phil
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2020-08-17 07:12
    Are you sure this will work if more than one key is pressed at a time? Humans are unpredictable that way. :)

    -Phil

    Not really worried about multiple key presses although some obviously would be valid. This is mainly for those times when we have 4 I/0 for example and more than 4 keys to handle. Invalid key combinations are invalid combinations, no problems. These small keypads and button inputs aren't being handled by a 2 handed touch typist but are normally by means of the George Jetson index finger.

  • Cluso99Cluso99 Posts: 18,069
    How many years have we waited for this discovery???

    I thought I had done something similar back in the 80's to save using diodes. I just checked and no. I freed up enough pins on the micro to read them directly.
    While looking I found my circuit diagram done with LisaDraw back in '83 :sunglasses:
  • I couldn't find anything similar at all and I was just thinking about a way to add an extra key to 4 I/O and then of course other combinations are possible. I will make this up later on and write a couple of lines of code and test it out. If it is new, I think I will call it ultraplexing.

    btw, a conventional 4x4 keypad matrix can only read 16 keys and up to 4 keys can be pressed at the same time as long as they don't conflict. With ultraplexing those 8 I/O can read up to 36 keys and the 8 direct keys can be operated at the same time, as well as other combinations.
  • AwesomeCronkAwesomeCronk Posts: 1,055
    edited 2020-08-17 11:17
    Very interesting thought and definitely worth investigating!

    Can help poke at your math... it looks like your formula breaks down to n! (n factorial). :tongue:
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2020-08-17 12:04
    Very interesting thought and definitely worth investigating!

    Can help poke at your math... it looks like your formula breaks down to n! (n factorial). :tongue:

    Factorial of 4 is 24 = 4x3x2x1 whereas this is 4+3+2+1 = 10
    sum not product - so maybe a sigmaplex
  • Very clever.

    It's possible to get the occasional wrong scan code, I think, when the user presses a key just after the program has read the "simple keys" and decided that it needs to scan. But this is probably easy to cater for by making the key debounce testing (which is always required for switch contacts) look for consecutive scans returning the same result before registering the initial 'key down' event.
  • ceptimus wrote: »
    Very clever.

    It's possible to get the occasional wrong scan code, I think, when the user presses a key just after the program has read the "simple keys" and decided that it needs to scan. But this is probably easy to cater for by making the key debounce testing (which is always required for switch contacts) look for consecutive scans returning the same result before registering the initial 'key down' event.

    Even simple button presses need some kind of debounce, and this would be no different. Read a code, wait, reread and verify. Direct keys that are grounded don't need scanning and work just like simple push-buttons switches would anyway. But when all is quiet then the indirect keys can be scanned and debounced too.
  • Call it PeterPlexing!
  • JRoark wrote: »
    Call it PeterPlexing!

    Hey, I thought of that too seeing Charlie somebody got perplexed about what to call his stuff. If Ultraplex or sigmaplex falls through, then why not have a PeterPlexed keypad! :smile:
  • ceptimusceptimus Posts: 135
    edited 2020-08-17 12:14
    ceptimus wrote: »
    Very clever.

    It's possible to get the occasional wrong scan code, I think, when the user presses a key just after the program has read the "simple keys" and decided that it needs to scan. But this is probably easy to cater for by making the key debounce testing (which is always required for switch contacts) look for consecutive scans returning the same result before registering the initial 'key down' event.

    Even simple button presses need some kind of debounce, and this would be no different. Read a code, wait, reread and verify. Direct keys that are grounded don't need scanning and work just like simple push-buttons switches would anyway. But when all is quiet then the indirect keys can be scanned and debounced too.

    Yes - but for the fastest response with a normal matrix keyboard, you don't necessarily have to debounce the 'contact made' events - only the 'contact released' ones. With your improved system, you need to 'debounce' both edges of the signals - but that's a small price to pay for being able to scan lots of extra keys with the same number of I/O.

    As I said, you always need a debounce routine for mechanical contacts. Some standard matrix keyboard scanning routines probably already debounce the 'make' as well as 'break' edges, and I agree that adding such an extra check, if needed, is trivial to do.
  • If you flip those inputs into ADC mode and feed each set of 4 switches from a voltage divider, you could have hundreds of switches on 4 lines for the price of a few SMD passives.
  • Cluso99Cluso99 Posts: 18,069
    edited 2020-08-17 13:09
    JRoark wrote: »
    If you flip those inputs into ADC mode and feed each set of 4 switches from a voltage divider, you could have hundreds of switches on 4 lines for the price of a few SMD passives.
    I discussed this with Chip for the P2 power up switch options.

    Peterplexed keypad +1
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2020-08-17 13:40
    I think that if the ADC was nailed down then this might have been possible. There were a lot of uncertain things that you couldn't really test which is why we played it safe with the ROM and so we wouldn't want to find that the P2 wasn't booting the way we wanted because of some unknowns about the ADC. Besides, the A/D wasn't really usable in RevA and when we made changes for RevB we didn't want to risk anything and kept those changes to minimal sure and certains.

    BTW, I used the A/D technique on vending machines decades ago where I wanted to reduce the wiring harness to the front door and used resistors and also diodes. Later I even designed a long sensor strip pcb with large copper sensor pads that could detect cards being vended just by the variation in capacitance and having one section as a reference. No A/D required there, it just needed a comparator and a pulse and some timing. I could tell how far in or out the card was unlike the troublesome microswitches or lever trigger opto-switches that it replaced. The sensor strip had its own tiny AVR just for the job.
  • ceptimusceptimus Posts: 135
    edited 2020-08-17 14:23
    In principle, with A/D and resistors, you can read thousands of keys with just one I/O point. All you need is a pair of resistors for each key, holding one of its contacts at a certain voltage level, unique for that key, and the other contact connected (in common with one contact of all the other keys) to the A/D input.

    If you have a 12-bit resolution A/D, you could in theory read up to 4095 keys, but probably 500 keys would be enough for most! And the contact resistance of the key doesn't matter much, because it's just connecting a potential divider (the resistor pair) to the A/D input - any contact resistance is likely negligible compared to the input impedance of the A/D.

    If you chose the values of the resistors carefully, you'd also be able to decode two (possibly more) keys pressed at the same time!

    A resistor ladder, rather than a pair for each key, would cut down the number of resistors to the same as the number of keys (plus one or two for the final rungs of the ladder to VCC and/or GND).
  • YanomaniYanomani Posts: 1,524
    edited 2020-08-17 14:35
    By keeping the circuit within the digital domain, one could make use of the Digital Filters for Smart Pins and ensure minimum acceptable values for the contacts break/make.

    This will easy a lot any debouncing logic, mostly avoiding timeout-waiting-related dead times.

    Also, by properlly adjusting filtering values, to ensure minimum bit-timings, I believe (though I'm not sure yet) you could even leverage from the use of some Pulse Position Modulation protocol, to ease the identification of wich pins are interconnected, if any.

    Sure, that would tottaly dismiss the use of any direct-connection to GND, but would otherwise enable the possibility of using an asynchronous serial protocol, where each received symbol would reflect the interconnection paths.

    Must put it onto some timing charts, just to be sure it's feasible, but, if it works, would immediatelly show how far we can reach with P2 and its smart pins.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2020-08-18 06:33
    I made up a keypad last night and checked it out with TAQOZ. Works perfectly and even though it is a bit of q&d coding, the maximum scan time is around 30us. The PPK@ (PeterPlexed Keypad Fetch) routine returns with an ASCII code or a null.

    This is a console test and the result when I press the buttons from left to right and back again.
    BEGIN PPK@ ?DUP IF EMIT BEGIN PPK@ 0= UNTIL THEN 20 ms KEY UNTIL --- 0123456789876543210
    
    The test waits for a valid key then emits that to the console then waits for a release and continues until a console key is pressed

    The code (194 bytes). It sets up the pins as 1K5 pullups with an active sink to allow it to drive it low. The keys can be on any port and I used a method to read all pins in one operation so it had to know which port it was on, but this could be done differently. If no direct grounded keys are found, it will then scan for the bridged keys. Any key found is converted to a code which is then translated to ascii in a lookup table (an ascii string actually).
    btw - I made a mistake initially with not writing pullup modes to the pins and found that I can draw 63.5ma from a shorted pin :)
    TAQOZ
    
    pub *PPKEYS*        PRINT" PeterPlexed keypad demonstration 200818.0000 " ;
    
    --- constants
    #P16                := KEYPAD       --- first I/O line of keypad 
    4                   := KEYS         --- number of I/O lines for direct keys
    KEYS |< 1-          := KEYM         --- internal mask
    KEYPAD 5 >> INA +   := KEYP         --- internal port to use
    
    pub READ_PPK  ( --- inputs )
    --- set all I/O        as pullup  drive low set 
        KEYPAD KEYS PINS   1K5 PULLUP CMOS SINK 0 WRFNC  H
    --- read port A or B and extract the 4 bits
        KEYP COG@ KEYPAD >> KEYM XOR >N 
        ;
    --- scan for bridged keys that may be pressed
    pub SCAN_PPK ( -- code )
    --- Q&D loop through combinations and return with a code if found
    --- 1st pin range-1    
        KEYPAD  KEYS 1- 
    ---       pin low then scan remainder (25 COG@ to read the loop limit or final i/o line)
    
          ADO I LOW    $25 COG@ 1+ I 1+ 
    ---        pin low?  yes, create a code                 with offset and quit loops   or keep looping
            DO I PIN@ 0= IF J KEYM AND 2 <<   I KEYM AND +   KEYS +   UNLOOP UNLOOP EXIT THEN LOOP 
          LOOP 0
        ;
    pub PPK@ ( -- code )
    --- read direct and encode else scan keys
        READ_PPK ?DUP IF >| 1+ ELSE SCAN_PPK THEN
    --- translate 4-bit code to ascii
        DUP IF " ?0123456??78???9" + C@ THEN
        ;
    
    END
    
    { 
    --- interactive testing will print the code - ascend and descend keypad
    BEGIN PPK@ ?DUP IF EMIT BEGIN PPK@ 0= UNTIL THEN 20 ms KEY UNTIL --- 0123456789876543210
    
    --- timing how long it takes to scan all with no result 
    TAQOZ# LAP PPK@ LAP .LAP --- 6,049 cycles= 30,245ns @200MHz ok
    }
    
    4618 x 3464 - 725K
  • Very interesting thought and definitely worth investigating! Can help poke at your math... it looks like your formula breaks down to n! (n factorial). :tongue:

    Factorial of 4 is 24 = 4x3x2x1 whereas this is 4+3+2+1 = 10
    sum not product - so maybe a sigmaplex

    So a triangular number then.

    X = (n * (n+1)) / 2
Sign In or Register to comment.