Author Topic: Model M Matrix + Teensy  (Read 3634 times)

0 Members and 1 Guest are viewing this topic.

Offline phosphorglow

  • Thread Starter
  • Posts: 39
  • Location: Indianapolis, IN
  • Model M Mechanic.
    • Phosphor Glow
Model M Matrix + Teensy
« on: Sun, 01 June 2014, 22:12:23 »
Hiyo!

I'm sure someone has already done this, but I haven't found it, so hopefully this helps. Plus my matrix diagram is so colorful you'll want to lick it.

I'm a hardware guy. I've always meant to get into coding, and this little project really gave me a nice 101 crash course. Still not entirely sure what I'm doing, but I have a fuzzy idea... :P

THANK YOU HASU FOR YOUR AWESOME WORK! ^_^
And thank you matt3o for your very awesome intro guide to his firmware!
And thank you CPTBadAss for the Teensy! Finally got around to playing with it. :)

66728-0

66730-1

Code: [Select]
#define KEYMAP_ANSI( \
    K72, K53, K54, K64, K74, K76, K78, K69, K59, K56, K46, K4B, K4C, K4F, K3F, K1E, \
    K52, K42, K43, K44, K45, K55, K57, K47, K48, K49, K4A, K5A, K58,      K66, K5C, K5E, K5D, \
    K62, K32, K33, K34, K35, K65, K67, K37, K38, K39, K3A, K6A, K68, K26, K5B, K4E, K4D, \
    K63, K22, K23, K24, K25, K75, K77, K27, K28, K29, K2A, K7A,      K16, \
    K61,      K12, K13, K14, K15, K05, K07, K17, K18, K19, K0A,      K11, K7E, \
    K50, K7F,                K06,                K0F, K10, K0E, K0B, K0C \
) { \
    { KC_NO, KC_NO,   KC_NO,    KC_NO,    KC_NO,    KC_##K05, KC_##K06, KC_##K07, KC_NO,    KC_NO,    KC_##K0A,  KC_##K0B, KC_##K0C, KC_NO,   KC_##K0E, KC_##K0F }, \
    { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17, KC_##K18, KC_##K19, KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_##K1E, KC_NO }, \
    { KC_NO,    KC_NO,    KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27, KC_##K28, KC_##K29, KC_##K2A, KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO }, \
    { KC_NO,    KC_NO,    KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_NO,    KC_##K37, KC_##K38, KC_##K39, KC_##K3A, KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_##K3F }, \
    { KC_NO,    KC_NO,    KC_##K42, KC_##K43, KC_##K44, KC_##K45, KC_##K46, KC_##K47, KC_##K48, KC_##K49, KC_##K4A, KC_##K4B, KC_##K4C, KC_##K4D, KC_##K4E, KC_##K4F }, \
    { KC_##K50, KC_NO,    KC_##K52, KC_##K53, KC_##K54, KC_##K55, KC_##K56, KC_##K57, KC_##K58, KC_##K59, KC_##K5A, KC_##K5B, KC_##K5C, KC_##K5D, KC_##K5E, KC_NO },  \
    { KC_NO,    KC_##K61, KC_##K62, KC_##K63, KC_##K64, KC_##K65, KC_##K66, KC_##K67, KC_##K68, KC_##K69, KC_##K6A, KC_NO,    KC_NO,    KC_NO,    KC_NO,    KC_NO },  \
    { KC_NO,    KC_NO,    KC_##K72,    KC_NO,    KC_##K74, KC_##K75, KC_##K76, KC_##K77, KC_##K78, KC_NO,    KC_##K7A, KC_NO,    KC_NO,    KC_NO,    KC_##K7E, KC_##K7F }  \
}

Code: [Select]
const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    /* 0: qwerty */
    KEYMAP_ANSI(
        ESC, F1,   F2,  F3,   F4,   F5,   F6,   F7,   F8,   F9,   F10,   F11,   F12,   PSCR,   SLCK,   PAUS, \
        GRV, 1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS,   EQL,   BSPC,   INS,   HOME,   PGUP, \
        TAB, Q,   W,   E,   R,   T,   Y,   U,   I,   O,   P,   LBRC,   RBRC,  BSLS, DEL, END, PGDN, \
        CAPS, A,   S,   D,   F,   G,   H,   J,   K,   L,   SCLN, QUOT, ENT, \
        LSFT, Z,   X,   C,   V,   B,   N,   M,   COMM, DOT, SLSH, RSFT, UP,\
        LCTL,   LALT,   SPC,   RALT,   RCTL,   LEFT, DOWN, RIGHT),

};

Code: [Select]
/* Column pin configuration
 * col: 0   1   2   3   4   5   6   7   8   9   10   11  12  13  14  15
 * pin: B0  B1  B2  B3  B7  D0  D1  D2  D3  C6  C7  D5  E6  D4  D7  B4 
 */
static void  init_cols(void)
{
    // Input with pull-up(DDR:0, PORT:1)
    DDRE  &= ~(1<<6);
    PORTE |=  (1<<6);
    DDRD  &= ~(1<<7 | 1<<5 | 1<<4 | 1<<3 | 1<<2 | 1<<1 | 1<<0);
    PORTD |=  (1<<7 | 1<<5 | 1<<4 | 1<<3 | 1<<2 | 1<<1 | 1<<0);
    DDRC  &= ~(1<<7 | 1<<6);
    PORTC |=  (1<<7 | 1<<6);
    DDRB  &= ~(1<< 7 | 1<<4 |1<<3 | 1<<2 | 1<<1 | 1<<0);
    PORTB |=  (1<< 7 | 1<<4 |1<<3 | 1<<2 | 1<<1 | 1<<0);
}

static matrix_row_t read_cols(void)
{
    return (PINB&(1<<0) ? 0 : (1<<0)) |
           (PINB&(1<<1) ? 0 : (1<<1)) |
           (PINB&(1<<2) ? 0 : (1<<2)) |
           (PINB&(1<<3) ? 0 : (1<<3)) |
           (PINB&(1<<7) ? 0 : (1<<4)) |
           (PIND&(1<<0) ? 0 : (1<<5)) |
           (PIND&(1<<1) ? 0 : (1<<6)) |
           (PIND&(1<<2) ? 0 : (1<<7)) |
           (PIND&(1<<3) ? 0 : (1<<8)) |
           (PINC&(1<<6) ? 0 : (1<<9)) |
           (PINC&(1<<7) ? 0 : (1<<10)) |
           (PIND&(1<<5) ? 0 : (1<<11)) |
           (PINE&(1<<6) ? 0 : (1<<12)) |
           (PIND&(1<<4) ? 0 : (1<<13)) |
           (PIND&(1<<7) ? 0 : (1<<14)) |
           (PINB&(1<<4) ? 0 : (1<<15));
}

/* Row pin configuration
 * row: 0   1   2   3   4   5   6   7
 * pin: F0  F1  F4  F5  F6  F7  B6  B5
 */
static void unselect_rows(void)
{
    // Hi-Z(DDR:0, PORT:0) to unselect
    DDRF  &= ~0b11110011;
    PORTF &= ~0b11110011;
    DDRB  &= ~0b01100000;
    PORTB &= ~0b01100000;
}

static void select_row(uint8_t row)
{
    // Output low(DDR:1, PORT:0) to select
    switch (row) {
        case 0:
            DDRF  |= (1<<0);
            PORTF &= ~(1<<0);
            break;
        case 1:
            DDRF  |= (1<<1);
            PORTF &= ~(1<<1);
            break;
        case 2:
            DDRF  |= (1<<4);
            PORTF &= ~(1<<4);
            break;
        case 3:
            DDRF  |= (1<<5);
            PORTF &= ~(1<<5);
            break;
        case 4:
            DDRF  |= (1<<6);
            PORTF &= ~(1<<6);
            break;
        case 5:
            DDRF  |= (1<<7);
            PORTF &= ~(1<<7);
            break;
        case 6:
            DDRB  |= (1<<6);
            PORTB &= ~(1<<6);
            break;
        case 7:
            DDRB  |= (1<<5);
            PORTB &= ~(1<<5);
            break;    
    }
}

I'm happily typing on my SSK at the moment. Yay!
Next up is to etch some PCB's.

Also, a couple of questions since I need to take a break from looking at code:

The number lock. I'm assuming the easiest solution would be to map a new layer with the Shift+Scroll Lock combo?

LED support! I tried changing the led file to write to the teensy's LED as an experiment, but I'm not getting anything. Which brings me to...

I2C i/o expander! I would like to be able to have control of status LED's as well as some backlighting. Sure I could get some teensy ++'s, but the regular teensy + an expander is significantly less expensive. Any experience/tips with those?

Thanks! :)

(Also, someone more talented than myself should throw some code together to utilize the speakers in the keyboards equipped with them. Each key press could sound like a Selectric typewriter... Just sayin'. :P)
« Last Edit: Sun, 01 June 2014, 22:22:30 by phosphorglow »

Offline bcg

  • Posts: 112
Re: Model M Matrix + Teensy
« Reply #1 on: Mon, 02 June 2014, 07:57:28 »

I'm happily typing on my SSK at the moment. Yay!
Next up is to etch some PCB's.

Also, a couple of questions since I need to take a break from looking at code:

The number lock. I'm assuming the easiest solution would be to map a new layer with the Shift+Scroll Lock combo?

LED support! I tried changing the led file to write to the teensy's LED as an experiment, but I'm not getting anything. Which brings me to...

I2C i/o expander! I would like to be able to have control of status LED's as well as some backlighting. Sure I could get some teensy ++'s, but the regular teensy + an expander is significantly less expensive. Any experience/tips with those?

Thanks! :)

(Also, someone more talented than myself should throw some code together to utilize the speakers in the keyboards equipped with them. Each key press could sound like a Selectric typewriter... Just sayin'. :P)

That's really nice, I've been meaning to do this myself but haven't had the time; I'm cutting down a full size Model M membrane and repairing it with wire wrapping wire and conductive glue to make a "70%" buckling spring keyboard (60% + F-keys) so I have to do this mod I think.  For the FPC connectors did you just remove those from the existing controller or were you able to order those from someplace?

How many unused pins do you have on the teensy?  I'm sure you could use an I2C component to add more IO, and that should only take 2 pins I think

Better yet the use case you're describing might be an LED driver board like this:  http://www.adafruit.com/products/1455 - it says it only requires 2 pins and you would be able to do much cooler stuff

I can't tell from the photo if you have 2 pins available though, looks like you might only have that F5 pin free

Awesome job man, I'm glad I don't have to figure all that out myself now :)
:wq!

Offline 0100010

  • Posts: 1127
  • Location: DFW, TX, US
  • Not Sure
Re: Model M Matrix + Teensy
« Reply #2 on: Mon, 02 June 2014, 11:16:35 »
Whoa.  Need more details on the membrane.
  Quoting me causes a posting error that you need to ignore.

Offline E TwentyNine

  • Posts: 884
    • Some of My Keyboards
Re: Model M Matrix + Teensy
« Reply #3 on: Mon, 02 June 2014, 11:50:27 »
Whoa.  Need more details on the membrane.

There's been a not-quite-as-colorful pdf of membrane layout available for a while now: * IBM_ModelM_SSK_Membranes-dots.PDF
Daily driver: SSK or Tenkeyless IBM AT
1984 Model M Industrial Prototype ⌨ 1992 Black Oval Industrial SSK ⌨ 1982 5251 Beam Spring ⌨ 89 Key "SSK" ⌨ M13 triplets

Offline phosphorglow

  • Thread Starter
  • Posts: 39
  • Location: Indianapolis, IN
  • Model M Mechanic.
    • Phosphor Glow
Re: Model M Matrix + Teensy
« Reply #4 on: Mon, 02 June 2014, 15:19:35 »

That's really nice, I've been meaning to do this myself but haven't had the time; I'm cutting down a full size Model M membrane and repairing it with wire wrapping wire and conductive glue to make a "70%" buckling spring keyboard (60% + F-keys) so I have to do this mod I think.  For the FPC connectors did you just remove those from the existing controller or were you able to order those from someplace?

How many unused pins do you have on the teensy?  I'm sure you could use an I2C component to add more IO, and that should only take 2 pins I think

Better yet the use case you're describing might be an LED driver board like this:  http://www.adafruit.com/products/1455 - it says it only requires 2 pins and you would be able to do much cooler stuff

I can't tell from the photo if you have 2 pins available though, looks like you might only have that F5 pin free

Awesome job man, I'm glad I don't have to figure all that out myself now :)

Hmmmm... Might have to play around with that LED driver board. Technically the only pin I have left is the one for the teensy's LED. So I'd definitely have to move two of the columns or rows to the I2C chip. Probably not a big deal. Hmmm... I might even be able to use the LED driver board for that. Aye yai yai. :P

I desoldered the connectors from a nasty controller I had, but I was looking at mouser and apparently they sell them so that's neato.

Your project sounds quite similar to hasu's Happy Buckling Keyboard which is in the tmk firmware project. I learned a bit from looking at the keymap on that.

Offline bcg

  • Posts: 112
Re: Model M Matrix + Teensy
« Reply #5 on: Mon, 02 June 2014, 22:21:06 »
I guess one nice thing about an IO expander is that since it looks like you are using 16 columns you could just use one of these to read in all of the columns at once:

http://www.adafruit.com/products/732

Then you could free up the Teensy's PWM pins and you could use those for LED effects instead of a separate LED driver board.  I'm not sure how you're planning to do backlight though, I think the teensy's pins only provide about 30-40 milliamps max so if you need more current than that for the backlight you would need some other circuitry as well

One option for backlighting could be to poke the bulbs of some small LEDs through the steel plate/membranes/barrel plate and then wire them up on the back of the steel plate.  I'm not sure if a backlight Model M is a mod I've seen before, but that will certainly be interesting :)  Actually it should look pretty f'ing sweet with your enameled barrel plate
:wq!