From 3f0289e66678af8c2d1f001ccb9cb34ccfba7c5c Mon Sep 17 00:00:00 2001 From: tmk Date: Wed, 14 Dec 2011 12:13:32 +0900 Subject: Added protocol support for Macintosh keyboard M0110. --- m0110_usb/Makefile | 52 +++++++++++++ m0110_usb/README | 55 ++++++++++++++ m0110_usb/config.h | 62 +++++++++++++++ m0110_usb/doc/m0110.jpg | Bin 0 -> 49360 bytes m0110_usb/doc/teensy.jpg | Bin 0 -> 50081 bytes m0110_usb/keymap.c | 118 +++++++++++++++++++++++++++++ m0110_usb/led.c | 24 ++++++ m0110_usb/matrix.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 504 insertions(+) create mode 100644 m0110_usb/Makefile create mode 100644 m0110_usb/README create mode 100644 m0110_usb/config.h create mode 100755 m0110_usb/doc/m0110.jpg create mode 100755 m0110_usb/doc/teensy.jpg create mode 100644 m0110_usb/keymap.c create mode 100644 m0110_usb/led.c create mode 100644 m0110_usb/matrix.c (limited to 'm0110_usb') diff --git a/m0110_usb/Makefile b/m0110_usb/Makefile new file mode 100644 index 000000000..8c8460c80 --- /dev/null +++ b/m0110_usb/Makefile @@ -0,0 +1,52 @@ +# Target file name (without extension). +TARGET = m0110 + +# Directory common source filess exist +COMMON_DIR = .. + +# Directory keyboard dependent files exist +TARGET_DIR = . + +# keyboard dependent files +SRC = main.c \ + keymap.c \ + matrix.c \ + led.c \ + m0110.c + +CONFIG_H = config.h + + +# MCU name, you MUST set this to match the board you are using +# type "make clean" after changing this, so all files will be rebuilt +#MCU = at90usb162 # Teensy 1.0 +MCU = atmega32u4 # Teensy 2.0 +#MCU = at90usb646 # Teensy++ 1.0 +#MCU = at90usb1286 # Teensy++ 2.0 + + +# Processor frequency. +# Normally the first thing your program should do is set the clock prescaler, +# so your program will run at the correct speed. You should also set this +# variable to same clock speed. The _delay_ms() macro uses this, and many +# examples use this variable to calculate timings. Do not add a "UL" here. +F_CPU = 16000000 + + +# Build Options +# *Comment out* to disable the options. +# +#MOUSEKEY_ENABLE = yes # Mouse keys +#PS2_MOUSE_ENABLE = yes # PS/2 mouse(TrackPoint) support +#EXTRAKEY_ENABLE = yes # Audio control and System control +#NKRO_ENABLE = yes # USB Nkey Rollover + + + +#---------------- Programming Options -------------------------- +PROGRAM_CMD = teensy_loader_cli -mmcu=$(MCU) -w -v $(TARGET).hex + + + +include $(COMMON_DIR)/pjrc.mk +include $(COMMON_DIR)/common.mk diff --git a/m0110_usb/README b/m0110_usb/README new file mode 100644 index 000000000..4122edb28 --- /dev/null +++ b/m0110_usb/README @@ -0,0 +1,55 @@ +M0110 to USB keyboard converter +=============================== +This firmware converts protocol for Apple Machintosh Keybard M0110. + + +Connection +---------- +You need 4P4C plug and cable to connect Teensy into M0110. +Teensy port F0 is assigned for CLOCK line and F1 for DATA by default, you can change pin configuration with editing config.h.. + +Plug: + http://en.wikipedia.org/wiki/Modular_connector#4P4C + +Pinout: + http://www.kbdbabel.org/conn/kbd_connector_macplus.png + 1(Black): GND + 2(Red): CLOCK + 3(Green): DATA + 4(Yellow): +5V + + + +Build Frimware +-------------- +Optionally edit Makefile and config.h for build options, pin configuration or MCU. + +$ cd m0110_usb +$ make +and program your Teensy with loader. + + + +Keymap +------ +You can change a keymap by editing code of keymap.c like following. +How to define the keymap is probably obvious. You can find key symbols in usb_keycodes.h. + +This is a default keymap for M0110. +,---------------------------------------------------------. +| `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Bacpa| +|---------------------------------------------------------| +|Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| +|---------------------------------------------------------| +|CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| +|---------------------------------------------------------| +|Shift | Z| X| C| V| B| N| M| ,| ,| /|Shift | +`---------------------------------------------------------' + |Opt|Alt | Space |Alt |Opt| + `-----------------------------------------------' + + +Notes +----- + +EOF diff --git a/m0110_usb/config.h b/m0110_usb/config.h new file mode 100644 index 000000000..c12e0738d --- /dev/null +++ b/m0110_usb/config.h @@ -0,0 +1,62 @@ +/* +Copyright 2011 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +/* controller configuration */ +#include "controller_teensy.h" + + +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x0110 +#define MANUFACTURER t.m.k. +#define PRODUCT M0110 keyboard converter +#define DESCRIPTION convert M0110 keyboard to USB + + +/* matrix size */ +#define MATRIX_ROWS 8 +#define MATRIX_COLS 8 + +/* Locking Caps Lock support */ +//#define MATRIX_HAS_LOCKING_CAPS + +/* key combination for command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_LCTRL) | MOD_BIT(KB_LALT) | MOD_BIT(KB_LGUI)) || \ + keyboard_report->mods == (MOD_BIT(KB_LSHIFT) | MOD_BIT(KB_RSHIFT)) \ +) + + +/* mouse keys */ +#ifdef MOUSEKEY_ENABLE +# define MOUSEKEY_DELAY_TIME 192 +#endif + + +/* ports */ +#define M0110_CLOCK_PORT PORTF +#define M0110_CLOCK_PIN PINF +#define M0110_CLOCK_DDR DDRF +#define M0110_CLOCK_BIT 0 +#define M0110_DATA_PORT PORTF +#define M0110_DATA_PIN PINF +#define M0110_DATA_DDR DDRF +#define M0110_DATA_BIT 1 + +#endif diff --git a/m0110_usb/doc/m0110.jpg b/m0110_usb/doc/m0110.jpg new file mode 100755 index 000000000..ef9a123ab Binary files /dev/null and b/m0110_usb/doc/m0110.jpg differ diff --git a/m0110_usb/doc/teensy.jpg b/m0110_usb/doc/teensy.jpg new file mode 100755 index 000000000..96e93e7e2 Binary files /dev/null and b/m0110_usb/doc/teensy.jpg differ diff --git a/m0110_usb/keymap.c b/m0110_usb/keymap.c new file mode 100644 index 000000000..24fe6cd47 --- /dev/null +++ b/m0110_usb/keymap.c @@ -0,0 +1,118 @@ +/* +Copyright 2011 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* + * Keymap for ADB keyboard + */ +#include +#include +#include +#include "usb_keyboard.h" +#include "usb_keycodes.h" +#include "print.h" +#include "debug.h" +#include "util.h" +#include "keymap.h" + + +#define KEYCODE(layer, row, col) (pgm_read_byte(&keymaps[(layer)][(row)][(col)])) + +// Convert physical keyboard layout to matrix array. +// This is a macro to define keymap easily in keyboard layout form. +// TODO: layout for M0110A +/* M0110 */ +#define KEYMAP( \ + K32,K12,K13,K14,K15,K17,K16,K1A,K1C,K19,K1D,K1B,K18,K33, \ + K30,K0C,K0D,K0E,K0F,K11,K10,K20,K22,K1F,K23,K21,K1E,K2A, \ + K39,K00,K01,K02,K03,K05,K04,K26,K28,K25,K29,K27, K24, \ + K38,K06,K07,K08,K09,K0B,K2D,K2E,K2B,K2F,K2C, \ + K3A,K37, K31, K34 \ +) { \ + { KB_##K00, KB_##K01, KB_##K02, KB_##K03, KB_##K04, KB_##K05, KB_##K06, KB_##K07 }, \ + { KB_##K08, KB_##K09, KB_NO, KB_##K0B, KB_##K0C, KB_##K0D, KB_##K0E, KB_##K0F }, \ + { KB_##K10, KB_##K11, KB_##K12, KB_##K13, KB_##K14, KB_##K15, KB_##K16, KB_##K17 }, \ + { KB_##K18, KB_##K19, KB_##K1A, KB_##K1B, KB_##K1C, KB_##K1D, KB_##K1E, KB_##K1F }, \ + { KB_##K20, KB_##K21, KB_##K22, KB_##K23, KB_##K24, KB_##K25, KB_##K26, KB_##K27 }, \ + { KB_##K28, KB_##K29, KB_##K2A, KB_##K2B, KB_##K2C, KB_##K2D, KB_##K2E, KB_##K2F }, \ + { KB_##K30, KB_##K31, KB_##K32, KB_##K33, KB_##K34, KB_NO, KB_NO, KB_##K37 }, \ + { KB_##K38, KB_##K39, KB_##K3A, KB_NO, KB_NO, KB_NO, KB_NO, KB_NO } \ +} + + +// Assign Fn key(0-7) to a layer to which switch with the Fn key pressed. +static const uint8_t PROGMEM fn_layer[] = { + 0, // Fn0 + 0, // Fn1 + 0, // Fn2 + 0, // Fn3 + 0, // Fn4 + 0, // Fn5 + 0, // Fn6 + 0 // Fn7 +}; + +// Assign Fn key(0-7) to a keycode sent when release Fn key without use of the layer. +// See layer.c for details. +static const uint8_t PROGMEM fn_keycode[] = { + KB_NO, // Fn0 + KB_NO, // Fn1 + KB_NO, // Fn2 + KB_NO, // Fn3 + KB_NO, // Fn4 + KB_NO, // Fn5 + KB_NO, // Fn6 + KB_NO // Fn7 +}; + +static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* Default Layer: plain keymap + * ,---------------------------------------------------------. + * | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Bacpa| + * |---------------------------------------------------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| + * |---------------------------------------------------------| + * |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| + * |---------------------------------------------------------| + * |Shift | Z| X| C| V| B| N| M| ,| ,| /|Shift | + * `---------------------------------------------------------' + * |Opt|Alt | Space |Alt |Opt| + * `-----------------------------------------------' + */ + KEYMAP( + GRV, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, MINS,EQL, BSPC, + TAB, Q, W, E, R, T, Y, U, I, O, P, LBRC,RBRC,BSLS, + CAPS,A, S, D, F, G, H, J, K, L, SCLN,QUOT, ENT, + LSFT,Z, X, C, V, B, N, M, COMM,DOT, SLSH, + LGUI,LALT, SPC, RALT + ), +}; + + +uint8_t keymap_get_keycode(uint8_t layer, uint8_t row, uint8_t col) +{ + return KEYCODE(layer, row, col); +} + +uint8_t keymap_fn_layer(uint8_t fn_bits) +{ + return pgm_read_byte(&fn_layer[biton(fn_bits)]); +} + +uint8_t keymap_fn_keycode(uint8_t fn_bits) +{ + return pgm_read_byte(&fn_keycode[(biton(fn_bits))]); +} diff --git a/m0110_usb/led.c b/m0110_usb/led.c new file mode 100644 index 000000000..f76545f0b --- /dev/null +++ b/m0110_usb/led.c @@ -0,0 +1,24 @@ +/* +Copyright 2011 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#include "stdint.h" +#include "led.h" + + +void led_set(uint8_t usb_led) +{ +} diff --git a/m0110_usb/matrix.c b/m0110_usb/matrix.c new file mode 100644 index 000000000..f045920cc --- /dev/null +++ b/m0110_usb/matrix.c @@ -0,0 +1,193 @@ +/* +Copyright 2011 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +/* + * scan matrix + */ +#include +#include +#include +#include +#include "print.h" +#include "util.h" +#include "debug.h" +#include "host.h" +#include "led.h" +#include "m0110.h" +#include "matrix.h" + + +#define CAPS 0x39 +#define CAPS_UP (CAPS | 0x80) +#define ROW(key) ((key)>>3&0x0F) +#define COL(key) ((key)&0x07) + + +static bool is_modified = false; + +// matrix state buffer(1:on, 0:off) +static uint8_t *matrix; +static uint8_t _matrix0[MATRIX_ROWS]; + +#ifdef MATRIX_HAS_GHOST +static bool matrix_has_ghost_in_row(uint8_t row); +#endif +static void register_key(uint8_t key); + + +inline +uint8_t matrix_rows(void) +{ + return MATRIX_ROWS; +} + +inline +uint8_t matrix_cols(void) +{ + return MATRIX_COLS; +} + +void matrix_init(void) +{ + print_enable = true; + debug_enable = true; + debug_matrix = false; + debug_keyboard = false; + debug_mouse = false; + print("debug enabled.\n"); + + m0110_init(); + // initialize matrix state: all keys off + for (uint8_t i=0; i < MATRIX_ROWS; i++) _matrix0[i] = 0x00; + matrix = _matrix0; + return; +} + +uint8_t matrix_scan(void) +{ + uint8_t key; + + is_modified = false; + key = m0110_recv_key(); + +#ifdef MATRIX_HAS_LOCKING_CAPS + // Send Caps key up event + if (matrix_is_on(ROW(CAPS), COL(CAPS))) { + is_modified = true; + register_key(CAPS_UP); + } +#endif + if (key == M0110_NULL) { + return 0; + } else { +#ifdef MATRIX_HAS_LOCKING_CAPS + if (host_keyboard_leds() & (1<