Rebuilding and Redesigning a Classic Thinkpad Keyboard

pjmelon

05 Feb 2014, 01:36

Am using teensy 2.0, does this still apply?

The only reference I could find to matrix_init was in the matrix.c file. Do I just put those lines in that section?

Code: Select all

void matrix_init(void)
{
    // initialize row and col
    unselect_rows();
    init_cols();

    // initialize matrix state: all keys off
    for (uint8_t i=0; i < MATRIX_ROWS; i++) {
        matrix[i] = 0;
        matrix_debouncing[i] = 0;
    }
}

pjmelon

05 Feb 2014, 03:33

Ok so gave it a shot and put it in. Didnt change anything. Double checked my connections with a multimeter and all good except for a poor solder joint.

Is there anyone who can give me some help with this, feel I am way out of my league here in terms of knowledge.

mtl

05 Feb 2014, 05:44

These are the two changes it looked like your code needed. Did you make them both?

Code: Select all

void matrix_init(void)
{
    // To use PORTF disable JTAG with writing JTD bit twice within four cycles.
    MCUCR |= (1<<JTD);
    MCUCR |= (1<<JTD);

    // initialize row and col
    unselect_rows();
    init_cols();

    // initialize matrix state: all keys off
    for (uint8_t i=0; i < MATRIX_ROWS; i++) {
        matrix[i] = 0;
        matrix_debouncing[i] = 0;
    }
}

Code: Select all

/* Row pin configuration
 * row: 0   1   2   3   4
 * pin: E6  B3  B1  B2  B0
 */
static void unselect_rows(void)
{
    // Hi-Z(DDR:0, PORT:0) to unselect
    DDRE  &= ~0b01000000;
    PORTE &= ~0b01000000;
    DDRB  &= ~0b00001111;
    PORTB &= ~0b00001111;
}

pjmelon

05 Feb 2014, 16:35

Thanks mtl, I put both of those sets of lines in and it resulted in progress. :)
So when I press keys I only get one character, however the character is not the right character and not all of the keys work.

I have a few thoughts on what is happening here. At the end of the post is my matrix layout. I followed matt3o's instructions on building the keymap.
I have used the keymap_poker.c layout as per his instructions.

Code: Select all

#include "keymap_common.h"

const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* 0: dvorak */
KEYMAP(
        GRV, 1,   2,    3,   4,   5,   6,   7,   8,   9,   0,  LBRC, RBRC, DEL, BSPC,  HOME,  PGUP, \
        ESC, TAB, QUOT, COMM,DOT, P,   Y,   F,   G,   C,   R,   L,   SLSH,EQL,  BSLS,  END,   DEL,  PGDN, \
             CAPS,A,    O,   E,   U,   I,   D,   H,   T,   N,   S,   MINS,      ENT,  \
             LSFT,SCLN, Q,   J,   K,   X,   B,   M,   W,   V,   Z,              RSFT,  UP, \
             LCTL,LGUI, LALT,     SPC,     SPC,                      RALT, RGUI, RCTL, LEFT, DOWN, RIGHT),

};

const uint16_t PROGMEM fn_actions[] = {

};
And this is based on my keymap_common.h
The only keymap I defined was the first one.

Code: Select all

#define KEYMAP( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K0E, K0F,      K0H, \
    K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E, K1F, K1G, K1H, \
         K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, K2D,                     \
         K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B,      K3D,           K3G,      \
         K41, K42, K43,      K45,      K47,                K4B, K4C, K4D,      K4F, K4G, K4H  \
) { \
    { KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07, KC_##K08, KC_##K09, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D, KC_##K0E, KC_##K0F, KC_NO, KC_##K0H }, \
    { KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17, KC_##K18, KC_##K19, KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D, KC_##K1E, KC_##K1F, KC_##K1G, KC_##K1H }, \
    { KC_NO, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27, KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_NO, KC_NO, KC_NO, KC_NO }, \
    { KC_NO, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37, KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_NO, KC_##K3D, KC_NO, KC_NO, KC_##K3G, KC_NO }, \
    { KC_NO, KC_##K41, KC_##K42, KC_##K43, KC_NO, KC_##K45, KC_NO, KC_##K47, KC_NO, KC_NO, KC_NO, KC_##K4B, KC_##K4C, KC_##K4D, KC_NO, KC_##K4F, KC_##K4G, KC_##K4H }  \
}

/* ANSI valiant. No extra keys for ISO */
#define KEYMAP_ANSI( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \
    K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \
    K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B,      K2D, \
    K30, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B,           K3D, \
    K40, K41, K42,           K45,                     K4A, K4B, K4C, K4D  \
) KEYMAP( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \
    K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \
    K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, NO,  K2D, \
    K30, NO,  K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, NO,  K3D, \
    K40, K41, K42,           K45,                NO,  K4A, K4B, K4C, K4D  \
)


#define KEYMAP_HHKB( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, K49,\
    K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \
    K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B,      K2D, \
    K30, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B,      K3D, K3C, \
    K40, K41, K42,           K45,                     K4A, K4B, K4C, K4D  \
) KEYMAP( \
    K00, K01, K02, K03, K04, K05, K06, K07, K08, K09, K0A, K0B, K0C, K0D, \
    K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, \
    K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, NO,  K2D, \
    K30, NO,  K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3C, K3D, \
    K40, K41, K42,           K45,                K49, K4A, K4B, K4C, K4D  \
)

#endif
Attachments
Keyboard Map.jpg
Keyboard Map.jpg (22.52 KiB) Viewed 4095 times

pjmelon

06 Feb 2014, 18:06

Do you think it is worth trying the Phantom TMK build, it has 17 columns so is built on code designed to go above 16 columns?

User avatar
hasu

06 Feb 2014, 18:37

hmm, I think you should stick to debug your code or hardware a bit more for a while before trying Phantom code.

Add these lines in matrix_init() and check your matrix status on hid_listen.
debug_enable=true;
debug_matrix=true;

you will see matrix output like this:
r/c 01234567
00: 00000000
01: 00000000
02: 00000000
03: 00000000
04: 00000000
05: 00000000
06: 00000000
07: 00000000
08: 00000000
09: 00000000
0A: 00000000
0B: 00000000
0C: 00000000
0D: 00000000
0E: 00000000
0F: 00000000

pjmelon

06 Feb 2014, 21:31

Thanks hasu,
How do you check matrix status on hid listen?

mtl

07 Feb 2014, 02:47

The Phantom firmware uses a different method of scanning the matrix because its diodes are mounted in reverse compared to the GH60, so I don't think it would work for you.

For hid_listen, download and compile the source from the pcjr website, then run:

$ sudo ./hid_listen

It should recognize your keyboard if you enable the debug stuff hasu mentioned. It doesn't always work for me, but sometimes it would work if I disabled some firmware features (e.g., the PS/2 & Trackpoint stuff).

pjmelon

07 Feb 2014, 03:17

So put the code into the matrix.c file and ran hd_listen.
Unfortunately all I got was keyboard start and nothing more.
My trackpoint runs on another teensy and plugged that in and got four lines output.

pjmelon

07 Feb 2014, 04:40

Stupid question but would Soarer's firmware work in my case?
Maybe it is better suited to my skill set

User avatar
hasu

07 Feb 2014, 04:46

I think it definitely works.

pjmelon

07 Feb 2014, 05:19

Might give it a shot and see how it goes.
The matrix looks simple but need to figure out how to use it.
Firmware uploads no prob but need to figure how to upload the matrix.

pjmelon

08 Feb 2014, 01:40

I finally have working code. YAYAYAAYAY
Soarer's firmware worked like a charm. The only key that I am missing is my ~ (GRV) key as I dont know how it is assigned in his firmware.:)

I am putting the finishing touches together and will start a new thread and put a tutorial together. Hopefully will be useful to someone. Secretly I want to get on matt3o's build list. :)
Had a few people ask about the trackpoint as well so I can definitely help a few learn from my mistakes.

pjmelon

08 Feb 2014, 05:37

Typing on my new keyboard now. Woohhooooooooooooooooooooooooooooooooooooooooooooo
And no that wasnt a slip of my firmware.

User avatar
ماء

08 Feb 2014, 05:42

Congratz!
Please pics...

pjmelon

08 Feb 2014, 06:01

Here you go, got a few cosmetic changes but most is good to go.
Attachments
IMAG0657.jpg
IMAG0657.jpg (756.67 KiB) Viewed 4003 times
IMAG0656.jpg
IMAG0656.jpg (761.67 KiB) Viewed 4004 times

zambasdvd

09 Dec 2014, 20:14

Hi and congratulations for this wonderful scene.
I have some problems with creating the hex file to burn on my teensy.
I am trying to make a tenkeyless keyboard using alps switches from a dell at101w and a teensy 2.0.
When i try to make the hex file on cmd it says: make: Interrupt/exception caught (code = 0x00000fd, addr = 0x4217b3)
I wonder if someone can see my code and points me to the right direction please.

My code:
From matrix c(a) :



/* Column pin configuration
* col: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
* pin: B0 B1 B2 B3 B4 B5 B6 B7 D0 D1 D2 D3 D4 D5 D7 E6 C7
*/

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 |;
PORTC |= (1<<7 |;
DDRB &= ~(1<<7 |1<<6 | 1<<5 | 1<<4 | 1<<3 | 1<<2 | 1<<1 | 1<<0);
PORTB |= (1<<7 |1<<6 | 1<<5 | 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<<4) ? 0 : (1<<4)) |
(PINB&(1<<5) ? 0 : (1<<5)) |
(PINB&(1<<6) ? 0 : (1<<6)) |
(PINB&(1<<7) ? 0 : (1<<7)) |
(PIND&(1<<0) ? 0 : (1<<8)) |
(PIND&(1<<1) ? 0 : (1<<9)) |
(PIND&(1<<2) ? 0 : (1<<10)) |
(PIND&(1<<3) ? 0 : (1<<11)) |
(PIND&(1<<4) ? 0 : (1<<12)) |
(PIND&(1<<5) ? 0 : (1<<13)) |
(PIND&(1<<7) ? 0 : (1<<14)) |
(PINE&(1<<6) ? 0 : (1<<15)) |
(PINC&(1<<7) ? 0 : (1<<16)) |
;
}

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



From Matrix c(b):


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;
}
}

led:




void led_set(uint8_t usb_led)
{
if (usb_led & (1<<USB_LED_CAPS_LOCK)) {
// output low
DDRC |= (1<<6);
PORTC &= ~(1<<6);
} else {
// Hi-z
DDRC |= (1<<6);
PORTC &= ~(1<<6);
}


From config. h:

#ifndef CONFIG_H
#define CONFIG_H


/* USB Device descriptor parameter */
#define VENDOR_ID 0xFEED
#define PRODUCT_ID 0x6060
#define DEVICE_VER 0x0001
#define MANUFACTURER ZAMBAS
#define PRODUCT OMONOIA
#define DESCRIPTION tenkeyless keyboard firmware for OMONOIA

/* key matrix size */
#define MATRIX_ROWS 6
#define MATRIX_COLS 17

/* define if matrix has ghost */
//#define MATRIX_HAS_GHOST

/* Set 0 if debouncing isn't needed */
#define DEBOUNCE 5

/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */
#define LOCKING_SUPPORT_ENABLE
/* Locking resynchronize hack */
#define LOCKING_RESYNC_ENABLE

/* key combination for command */
#define IS_COMMAND() ( \
keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \
)


From make file:


# Target file name (without extension).
TARGET = gh60_lufa

# Directory common source filess exist
TOP_DIR = ../..

# Directory keyboard dependent files exist
TARGET_DIR = .

# project specific files
SRC = keymap_common.c \
matrix.c \
led.c

ifdef KEYMAP
SRC := keymap_$(KEYMAP).c $(SRC)
else
SRC := keymap_poker.c $(SRC)
endif

CONFIG_H = config.h


# MCU name
#MCU = at90usb1287
MCU = atmega32u4

# Processor frequency.
# This will define a symbol, F_CPU, in all source code files equal to the
# processor frequency in Hz. You can then use this symbol in your source code to
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
# automatically to create a 32-bit value in your source code.
#
# This will be an integer division of F_USB below, as it is sourced by
# F_USB after it has run through any CPU prescalers. Note that this value
# does not *change* the processor frequency - it should merely be updated to
# reflect the processor speed set externally so that the code can use accurate
# software delays.
F_CPU = 16000000


#
# LUFA specific
#
# Target architecture (see library "Board Types" documentation).
ARCH = AVR8

# Input clock frequency.
# This will define a symbol, F_USB, in all source code files equal to the
# input clock frequency (before any prescaling is performed) in Hz. This value may
# differ from F_CPU if prescaling is used on the latter, and is required as the
# raw input clock is fed directly to the PLL sections of the AVR for high speed
# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
# at the end, this will be done automatically to create a 32-bit value in your
# source code.
#
# If no clock division is performed on the input clock inside the AVR (via the
# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
F_USB = $(F_CPU)

# Interrupt driven control endpoint task(+60)
OPT_DEFS += -DINTERRUPT_CONTROL_ENDPOINT


# Boot Section Size in *bytes*
# Teensy halfKay 512
# Teensy++ halfKay 1024
# Atmel DFU loader 4096
# LUFA bootloader 4096
# USBaspLoader 2048
OPT_DEFS += -DBOOTLOADER_SIZE=4096


# Build Options
# comment out to disable the options.
#
BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration(+1000)
MOUSEKEY_ENABLE = yes # Mouse keys(+4700)
EXTRAKEY_ENABLE = yes # Audio control and System control(+450)
CONSOLE_ENABLE = yes # Console for debug(+400)
COMMAND_ENABLE = yes # Commands for debug and configuration
#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend
#NKRO_ENABLE = yes # USB Nkey Rollover - not yet supported in LUFA


# Optimize size but this may cause error "relocation truncated to fit"
#EXTRALDFLAGS = -Wl,--relax

# Search Path
VPATH += $(TARGET_DIR)
VPATH += $(TOP_DIR)

include $(TOP_DIR)/protocol/lufa.mk
include $(TOP_DIR)/common.mk
include $(TOP_DIR)/rules.mk


From keymap common. h:

/* gh60 keymap definition macro
* K2C, K31 and K3C are extra keys for ISO
*/
#define KEYMAP( \
K00, K01, K02, K03, K04, K05, K06, K07 K08, K0A, K0B, K0C, K0D, K0E, K0F, K0G, \
K10, K11, K12, K13, K14, K15, K16, K17, K18, K19, K1A, K1B, K1C, K1D, K1E, K1F, K1G, \
K20, K21, K22, K23, K24, K25, K26, K27, K28, K29, K2A, K2B, K2C, K2D, K2E, K2F, K2G, \
K30, K31, K32, K33, K34, K35, K36, K37, K38, K39, K3A, K3B, K3D, \
K40, K42, K43, K44, K45, K46, K47, K48, K49, K4A, K4B, K4D, K4F, \
K50, K51, K52, K56, K59, K5B, K5C, K5D, K5E, K5F, K5G, \
) { \
{ KC_##K00, KC_##K01, KC_##K02, KC_##K03, KC_##K04, KC_##K05, KC_##K06, KC_##K07, KC_##K08, KC_NO, KC_##K0A, KC_##K0B, KC_##K0C, KC_##K0D, KC_##K0E, KC_##K0F, KC_##K0G,}, \
{ KC_##K10, KC_##K11, KC_##K12, KC_##K13, KC_##K14, KC_##K15, KC_##K16, KC_##K17, KC_##K18, KC_##K19, KC_##K1A, KC_##K1B, KC_##K1C, KC_##K1D, KC_##K1E, KC_##K1F, KC_##K1G,}, \
{ KC_##K20, KC_##K21, KC_##K22, KC_##K23, KC_##K24, KC_##K25, KC_##K26, KC_##K27, KC_##K28, KC_##K29, KC_##K2A, KC_##K2B, KC_##K2C, KC_##K2D, KC_##K2E, KC_##K2F, KC_##K2G,}, \
{ KC_##K30, KC_##K31, KC_##K32, KC_##K33, KC_##K34, KC_##K35, KC_##K36, KC_##K37, KC_##K38, KC_##K39, KC_##K3A, KC_##K3B, KC_NO, KC_##K3D, KC_NO, KC_NO, KC_NO, }, \
{ KC_##K40, KC_NO, KC_##K42, KC_##K43, KC_##K44, KC_##K45,,KC_##K46, KC_##K47, KC_##K48, KC_##K49, KC_##K4A, KC_##K4B, KC_NO, KC_##K4D, KC_NO, KC_##K4F, KC_NO, }, \
{ KC_##K50, KC_##K51, KC_##K52, KC_NO, KC_NO, KC_NO, KC_##K56, KC_NO, KC_NO, KC_##K59, KC_##K5A, KC_##K5B, KC_##K5C, KC_##K5D, KC_##K5E, KC_##K5F, KC_##K5G,} \
}

#endif



From keymap poker. c:


#include "keymap_common.h"

const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
/* 0: qwerty */
KEYMAP(ESC, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, PSCR,SLCK,BRK, \
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, \
FN0, 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,LGUI,LALT, SPC, RALT,RGUI,CALC,RCTL, LEFT,DOWN,RGHT),
};

const uint16_t PROGMEM fn_actions[] = {
[0] = ACTION_LAYER_MOMENTARY(1),
/* 1: FN 1 */
KEYMAP (MUTE, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,MSTP,MPLY,MPRV,MNXT,MSEL, TRNS,TRNS,TRNS, \
TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, TRNS, \
TRNS, TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS, CAPS, VOLU, \
TRNS,TRNS,TRNS, TRNS, TRNS,TRNS,TRNS,TRNS, TRNS,VOLD,TRNS),

pjmelon

11 Dec 2014, 04:20

If you have problems with this firmware I would recommend using Soarer's firmware. I ended up using this after I had problems with the firmware type that you are using.

zambasdvd

12 Dec 2014, 00:12

pjmelon wrote: If you have problems with this firmware I would recommend using Soarer's firmware. I ended up using this after I had problems with the firmware type that you are using.
I did and everything works ok with soarer's fw. I am typing right now :)
The only thing if you know where do i connect the led? one pin to analog pin on teensy and another on ground? Because i connect like this the caps lock led and it lights in reverse , when not in caps mode, and it lights very very faint...
It lights the same with 680 ohms resistor, 510 ohms, 30 ohms and even without resistor!!
Edit: Nevermind man i left the polarity to negative. Little by little i get it
I've never touch programming before even this 'easy' kind :)

Post Reply

Return to “Workshop”